LCOV - code coverage report
Current view: top level - test/cctest - test-api.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 13468 13539 99.5 %
Date: 2019-04-17 Functions: 1116 1177 94.8 %

          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             : #include "test/cctest/wasm/wasm-run-utils.h"
      69             : #include "test/common/wasm/wasm-macro-gen.h"
      70             : 
      71             : static const bool kLogThreading = false;
      72             : 
      73             : using ::v8::Array;
      74             : using ::v8::Boolean;
      75             : using ::v8::BooleanObject;
      76             : using ::v8::Context;
      77             : using ::v8::Extension;
      78             : using ::v8::Function;
      79             : using ::v8::FunctionTemplate;
      80             : using ::v8::HandleScope;
      81             : using ::v8::Local;
      82             : using ::v8::Maybe;
      83             : using ::v8::Message;
      84             : using ::v8::MessageCallback;
      85             : using ::v8::Module;
      86             : using ::v8::Name;
      87             : using ::v8::None;
      88             : using ::v8::Object;
      89             : using ::v8::ObjectTemplate;
      90             : using ::v8::Persistent;
      91             : using ::v8::PropertyAttribute;
      92             : using ::v8::Script;
      93             : using ::v8::StackTrace;
      94             : using ::v8::String;
      95             : using ::v8::Symbol;
      96             : using ::v8::TryCatch;
      97             : using ::v8::Undefined;
      98             : using ::v8::V8;
      99             : using ::v8::Value;
     100             : 
     101             : 
     102             : #define THREADED_PROFILED_TEST(Name)                                 \
     103             :   static void Test##Name();                                          \
     104             :   TEST(Name##WithProfiler) {                                         \
     105             :     RunWithProfiler(&Test##Name);                                    \
     106             :   }                                                                  \
     107             :   THREADED_TEST(Name)
     108             : 
     109          30 : void RunWithProfiler(void (*test)()) {
     110          30 :   LocalContext env;
     111          60 :   v8::HandleScope scope(env->GetIsolate());
     112          30 :   v8::Local<v8::String> profile_name = v8_str("my_profile1");
     113          30 :   v8::CpuProfiler* cpu_profiler = v8::CpuProfiler::New(env->GetIsolate());
     114          30 :   cpu_profiler->StartProfiling(profile_name);
     115          30 :   (*test)();
     116          30 :   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
     117          30 :   cpu_profiler->Dispose();
     118          30 : }
     119             : 
     120             : 
     121             : static int signature_callback_count;
     122             : static Local<Value> signature_expected_receiver;
     123        3900 : static void IncrementingSignatureCallback(
     124             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     125        3900 :   ApiTestFuzzer::Fuzz();
     126        3900 :   signature_callback_count++;
     127       11700 :   CHECK(signature_expected_receiver->Equals(
     128             :                                        args.GetIsolate()->GetCurrentContext(),
     129             :                                        args.Holder())
     130             :             .FromJust());
     131       11700 :   CHECK(signature_expected_receiver->Equals(
     132             :                                        args.GetIsolate()->GetCurrentContext(),
     133             :                                        args.This())
     134             :             .FromJust());
     135             :   v8::Local<v8::Array> result =
     136        3900 :       v8::Array::New(args.GetIsolate(), args.Length());
     137        7020 :   for (int i = 0; i < args.Length(); i++) {
     138        6240 :     CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
     139             :                       v8::Integer::New(args.GetIsolate(), i), args[i])
     140             :               .FromJust());
     141             :   }
     142             :   args.GetReturnValue().Set(result);
     143        3900 : }
     144             : 
     145             : 
     146         205 : static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
     147             :   info.GetReturnValue().Set(42);
     148         205 : }
     149             : 
     150             : 
     151             : // Tests that call v8::V8::Dispose() cannot be threaded.
     152       26644 : UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
     153           5 :   CHECK(v8::V8::Initialize());
     154           5 :   CHECK(v8::V8::Dispose());
     155           5 : }
     156             : 
     157             : 
     158             : // Tests that call v8::V8::Dispose() cannot be threaded.
     159       26644 : UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
     160          20 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     161          20 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
     162          20 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     163          20 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
     164          20 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     165           5 : }
     166             : 
     167             : // Tests that Smi::kZero is set up properly.
     168       26644 : UNINITIALIZED_TEST(SmiZero) { CHECK_EQ(i::Smi::kZero, i::Smi::kZero); }
     169             : 
     170       26645 : THREADED_TEST(Handles) {
     171          12 :   v8::HandleScope scope(CcTest::isolate());
     172             :   Local<Context> local_env;
     173             :   {
     174           6 :     LocalContext env;
     175             :     local_env = env.local();
     176             :   }
     177             : 
     178             :   // Local context should still be live.
     179           6 :   CHECK(!local_env.IsEmpty());
     180           6 :   local_env->Enter();
     181             : 
     182           6 :   v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
     183           6 :   CHECK(!undef.IsEmpty());
     184           6 :   CHECK(undef->IsUndefined());
     185             : 
     186             :   const char* source = "1 + 2 + 3";
     187           6 :   Local<Script> script = v8_compile(source);
     188           6 :   CHECK_EQ(6, v8_run_int32value(script));
     189             : 
     190           6 :   local_env->Exit();
     191           6 : }
     192             : 
     193             : 
     194       26645 : THREADED_TEST(IsolateOfContext) {
     195          12 :   v8::HandleScope scope(CcTest::isolate());
     196           6 :   v8::Local<Context> env = Context::New(CcTest::isolate());
     197             : 
     198           6 :   CHECK(!env->GetIsolate()->InContext());
     199           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     200           6 :   env->Enter();
     201           6 :   CHECK(env->GetIsolate()->InContext());
     202           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     203           6 :   env->Exit();
     204           6 :   CHECK(!env->GetIsolate()->InContext());
     205           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     206           6 : }
     207             : 
     208         420 : static void TestSignatureLooped(const char* operation, Local<Value> receiver,
     209             :                                 v8::Isolate* isolate) {
     210             :   i::ScopedVector<char> source(200);
     211             :   i::SNPrintF(source,
     212             :               "for (var i = 0; i < 10; i++) {"
     213             :               "  %s"
     214             :               "}",
     215         420 :               operation);
     216         420 :   signature_callback_count = 0;
     217         420 :   signature_expected_receiver = receiver;
     218             :   bool expected_to_throw = receiver.IsEmpty();
     219         840 :   v8::TryCatch try_catch(isolate);
     220             :   CompileRun(source.start());
     221         420 :   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
     222         420 :   if (!expected_to_throw) {
     223         300 :     CHECK_EQ(10, signature_callback_count);
     224             :   } else {
     225         600 :     CHECK(v8_str("TypeError: Illegal invocation")
     226             :               ->Equals(isolate->GetCurrentContext(),
     227             :                        try_catch.Exception()
     228             :                            ->ToString(isolate->GetCurrentContext())
     229             :                            .ToLocalChecked())
     230             :               .FromJust());
     231             :   }
     232         420 : }
     233             : 
     234         420 : static void TestSignatureOptimized(const char* operation, Local<Value> receiver,
     235             :                                    v8::Isolate* isolate) {
     236             :   i::ScopedVector<char> source(200);
     237             :   i::SNPrintF(source,
     238             :               "function test() {"
     239             :               "  %s"
     240             :               "}"
     241             :               "try { test() } catch(e) {}"
     242             :               "try { test() } catch(e) {}"
     243             :               "%%OptimizeFunctionOnNextCall(test);"
     244             :               "test()",
     245         420 :               operation);
     246         420 :   signature_callback_count = 0;
     247         420 :   signature_expected_receiver = receiver;
     248             :   bool expected_to_throw = receiver.IsEmpty();
     249         840 :   v8::TryCatch try_catch(isolate);
     250             :   CompileRun(source.start());
     251         420 :   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
     252         420 :   if (!expected_to_throw) {
     253         300 :     CHECK_EQ(3, signature_callback_count);
     254             :   } else {
     255         600 :     CHECK(v8_str("TypeError: Illegal invocation")
     256             :               ->Equals(isolate->GetCurrentContext(),
     257             :                        try_catch.Exception()
     258             :                            ->ToString(isolate->GetCurrentContext())
     259             :                            .ToLocalChecked())
     260             :               .FromJust());
     261             :   }
     262         420 : }
     263             : 
     264             : static void TestSignature(const char* operation, Local<Value> receiver,
     265             :                           v8::Isolate* isolate) {
     266         420 :   TestSignatureLooped(operation, receiver, isolate);
     267         420 :   TestSignatureOptimized(operation, receiver, isolate);
     268             : }
     269             : 
     270       26645 : THREADED_TEST(ReceiverSignature) {
     271           6 :   i::FLAG_allow_natives_syntax = true;
     272           6 :   LocalContext env;
     273           6 :   v8::Isolate* isolate = env->GetIsolate();
     274          12 :   v8::HandleScope scope(isolate);
     275             :   // Setup templates.
     276           6 :   v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
     277           6 :   v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
     278             :   v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
     279           6 :       isolate, IncrementingSignatureCallback, Local<Value>(), sig);
     280             :   v8::Local<v8::FunctionTemplate> callback =
     281           6 :       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
     282           6 :   v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
     283           6 :   sub_fun->Inherit(fun);
     284             :   v8::Local<v8::FunctionTemplate> direct_sub_fun =
     285           6 :       v8::FunctionTemplate::New(isolate);
     286           6 :   direct_sub_fun->Inherit(fun);
     287             :   v8::Local<v8::FunctionTemplate> unrel_fun =
     288           6 :       v8::FunctionTemplate::New(isolate);
     289             :   // Install properties.
     290           6 :   v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
     291          12 :   fun_proto->Set(v8_str("prop_sig"), callback_sig);
     292          12 :   fun_proto->Set(v8_str("prop"), callback);
     293          12 :   fun_proto->SetAccessorProperty(
     294           6 :       v8_str("accessor_sig"), callback_sig, callback_sig);
     295          12 :   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
     296             :   // Instantiate templates.
     297             :   Local<Value> fun_instance =
     298          18 :       fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
     299             :   Local<Value> sub_fun_instance =
     300          18 :       sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
     301             :   // Instance template with properties.
     302             :   v8::Local<v8::ObjectTemplate> direct_instance_templ =
     303           6 :       direct_sub_fun->InstanceTemplate();
     304          12 :   direct_instance_templ->Set(v8_str("prop_sig"), callback_sig);
     305          12 :   direct_instance_templ->Set(v8_str("prop"), callback);
     306          12 :   direct_instance_templ->SetAccessorProperty(v8_str("accessor_sig"),
     307           6 :                                              callback_sig, callback_sig);
     308          12 :   direct_instance_templ->SetAccessorProperty(v8_str("accessor"), callback,
     309           6 :                                              callback);
     310             :   Local<Value> direct_instance =
     311           6 :       direct_instance_templ->NewInstance(env.local()).ToLocalChecked();
     312             :   // Setup global variables.
     313          30 :   CHECK(env->Global()
     314             :             ->Set(env.local(), v8_str("Fun"),
     315             :                   fun->GetFunction(env.local()).ToLocalChecked())
     316             :             .FromJust());
     317          30 :   CHECK(env->Global()
     318             :             ->Set(env.local(), v8_str("UnrelFun"),
     319             :                   unrel_fun->GetFunction(env.local()).ToLocalChecked())
     320             :             .FromJust());
     321          24 :   CHECK(env->Global()
     322             :             ->Set(env.local(), v8_str("fun_instance"), fun_instance)
     323             :             .FromJust());
     324          24 :   CHECK(env->Global()
     325             :             ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
     326             :             .FromJust());
     327          24 :   CHECK(env->Global()
     328             :             ->Set(env.local(), v8_str("direct_instance"), direct_instance)
     329             :             .FromJust());
     330             :   CompileRun(
     331             :       "var accessor_sig_key = 'accessor_sig';"
     332             :       "var accessor_key = 'accessor';"
     333             :       "var prop_sig_key = 'prop_sig';"
     334             :       "var prop_key = 'prop';"
     335             :       ""
     336             :       "function copy_props(obj) {"
     337             :       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
     338             :       "  var source = Fun.prototype;"
     339             :       "  for (var i in keys) {"
     340             :       "    var key = keys[i];"
     341             :       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
     342             :       "    Object.defineProperty(obj, key, desc);"
     343             :       "  }"
     344             :       "}"
     345             :       ""
     346             :       "var plain = {};"
     347             :       "copy_props(plain);"
     348             :       "var unrelated = new UnrelFun();"
     349             :       "copy_props(unrelated);"
     350             :       "var inherited = { __proto__: fun_instance };"
     351             :       "var inherited_direct = { __proto__: direct_instance };");
     352             :   // Test with and without ICs
     353             :   const char* test_objects[] = {
     354             :       "fun_instance", "sub_fun_instance", "direct_instance", "plain",
     355           6 :       "unrelated",    "inherited",        "inherited_direct"};
     356             :   unsigned bad_signature_start_offset = 3;
     357          90 :   for (unsigned i = 0; i < arraysize(test_objects); i++) {
     358             :     i::ScopedVector<char> source(200);
     359          42 :     i::SNPrintF(
     360          42 :         source, "var test_object = %s; test_object", test_objects[i]);
     361             :     Local<Value> test_object = CompileRun(source.start());
     362             :     TestSignature("test_object.prop();", test_object, isolate);
     363             :     TestSignature("test_object.accessor;", test_object, isolate);
     364             :     TestSignature("test_object[accessor_key];", test_object, isolate);
     365             :     TestSignature("test_object.accessor = 1;", test_object, isolate);
     366             :     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
     367          42 :     if (i >= bad_signature_start_offset) test_object = Local<Value>();
     368             :     TestSignature("test_object.prop_sig();", test_object, isolate);
     369             :     TestSignature("test_object.accessor_sig;", test_object, isolate);
     370             :     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
     371             :     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
     372             :     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
     373             :   }
     374           6 : }
     375             : 
     376             : 
     377       26645 : THREADED_TEST(HulIgennem) {
     378           6 :   LocalContext env;
     379           6 :   v8::Isolate* isolate = env->GetIsolate();
     380          12 :   v8::HandleScope scope(isolate);
     381             :   v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
     382           6 :   Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
     383           6 :   char* value = i::NewArray<char>(undef_str->Utf8Length(isolate) + 1);
     384           6 :   undef_str->WriteUtf8(isolate, value);
     385           6 :   CHECK_EQ(0, strcmp(value, "undefined"));
     386             :   i::DeleteArray(value);
     387           6 : }
     388             : 
     389             : 
     390       26645 : THREADED_TEST(Access) {
     391           6 :   LocalContext env;
     392           6 :   v8::Isolate* isolate = env->GetIsolate();
     393          12 :   v8::HandleScope scope(isolate);
     394           6 :   Local<v8::Object> obj = v8::Object::New(isolate);
     395             :   Local<Value> foo_before =
     396          18 :       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
     397           6 :   CHECK(foo_before->IsUndefined());
     398           6 :   Local<String> bar_str = v8_str("bar");
     399          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
     400             :   Local<Value> foo_after =
     401          18 :       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
     402           6 :   CHECK(!foo_after->IsUndefined());
     403           6 :   CHECK(foo_after->IsString());
     404          12 :   CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
     405             : 
     406          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).ToChecked());
     407             :   bool result;
     408          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).To(&result));
     409           6 :   CHECK(result);
     410           6 : }
     411             : 
     412             : 
     413       26645 : THREADED_TEST(AccessElement) {
     414           6 :   LocalContext env;
     415          12 :   v8::HandleScope scope(env->GetIsolate());
     416           6 :   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
     417           6 :   Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
     418           6 :   CHECK(before->IsUndefined());
     419           6 :   Local<String> bar_str = v8_str("bar");
     420          12 :   CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
     421           6 :   Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
     422           6 :   CHECK(!after->IsUndefined());
     423           6 :   CHECK(after->IsString());
     424          12 :   CHECK(bar_str->Equals(env.local(), after).FromJust());
     425             : 
     426             :   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
     427          24 :   CHECK(v8_str("a")
     428             :             ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
     429             :             .FromJust());
     430          24 :   CHECK(v8_str("b")
     431             :             ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
     432             :             .FromJust());
     433           6 : }
     434             : 
     435             : 
     436       26645 : THREADED_TEST(Script) {
     437           6 :   LocalContext env;
     438          12 :   v8::HandleScope scope(env->GetIsolate());
     439             :   const char* source = "1 + 2 + 3";
     440           6 :   Local<Script> script = v8_compile(source);
     441           6 :   CHECK_EQ(6, v8_run_int32value(script));
     442           6 : }
     443             : 
     444             : 
     445             : class TestResource: public String::ExternalStringResource {
     446             :  public:
     447             :   explicit TestResource(uint16_t* data, int* counter = nullptr,
     448             :                         bool owning_data = true)
     449       17941 :       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
     450     3082581 :     while (data[length_]) ++length_;
     451             :   }
     452             : 
     453       53817 :   ~TestResource() override {
     454       17941 :     if (owning_data_) i::DeleteArray(data_);
     455       17941 :     if (counter_ != nullptr) ++*counter_;
     456       35876 :   }
     457             : 
     458       54425 :   const uint16_t* data() const override { return data_; }
     459             : 
     460       71698 :   size_t length() const override { return length_; }
     461             : 
     462             :  private:
     463             :   uint16_t* data_;
     464             :   size_t length_;
     465             :   int* counter_;
     466             :   bool owning_data_;
     467             : };
     468             : 
     469             : 
     470             : class TestOneByteResource : public String::ExternalOneByteStringResource {
     471             :  public:
     472             :   explicit TestOneByteResource(const char* data, int* counter = nullptr,
     473             :                                size_t offset = 0)
     474             :       : orig_data_(data),
     475          10 :         data_(data + offset),
     476          69 :         length_(strlen(data) - offset),
     477         148 :         counter_(counter) {}
     478             : 
     479         197 :   ~TestOneByteResource() override {
     480          69 :     i::DeleteArray(orig_data_);
     481          69 :     if (counter_ != nullptr) ++*counter_;
     482         128 :   }
     483             : 
     484         194 :   const char* data() const override { return data_; }
     485             : 
     486         183 :   size_t length() const override { return length_; }
     487             : 
     488             :  private:
     489             :   const char* orig_data_;
     490             :   const char* data_;
     491             :   size_t length_;
     492             :   int* counter_;
     493             : };
     494             : 
     495             : 
     496       26645 : THREADED_TEST(ScriptUsingStringResource) {
     497           6 :   int dispose_count = 0;
     498             :   const char* c_source = "1 + 2 * 3";
     499           6 :   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
     500             :   {
     501           6 :     LocalContext env;
     502          12 :     v8::HandleScope scope(env->GetIsolate());
     503           6 :     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
     504             :     Local<String> source =
     505           6 :         String::NewExternalTwoByte(env->GetIsolate(), resource)
     506             :             .ToLocalChecked();
     507           6 :     Local<Script> script = v8_compile(source);
     508           6 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     509           6 :     CHECK(value->IsNumber());
     510          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     511           6 :     CHECK(source->IsExternal());
     512           6 :     CHECK_EQ(resource,
     513             :              static_cast<TestResource*>(source->GetExternalStringResource()));
     514           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     515           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     516             :              source->GetExternalStringResourceBase(&encoding));
     517           6 :     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
     518           6 :     CcTest::CollectAllGarbage();
     519           6 :     CHECK_EQ(0, dispose_count);
     520             :   }
     521           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     522           6 :   CcTest::CollectAllAvailableGarbage();
     523           6 :   CHECK_EQ(1, dispose_count);
     524           6 : }
     525             : 
     526             : 
     527       26645 : THREADED_TEST(ScriptUsingOneByteStringResource) {
     528           6 :   int dispose_count = 0;
     529             :   const char* c_source = "1 + 2 * 3";
     530             :   {
     531           6 :     LocalContext env;
     532          12 :     v8::HandleScope scope(env->GetIsolate());
     533             :     TestOneByteResource* resource =
     534           6 :         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
     535             :     Local<String> source =
     536           6 :         String::NewExternalOneByte(env->GetIsolate(), resource)
     537             :             .ToLocalChecked();
     538           6 :     CHECK(source->IsExternalOneByte());
     539           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     540             :              source->GetExternalOneByteStringResource());
     541           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     542           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     543             :              source->GetExternalStringResourceBase(&encoding));
     544           6 :     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     545           6 :     Local<Script> script = v8_compile(source);
     546           6 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     547           6 :     CHECK(value->IsNumber());
     548          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     549           6 :     CcTest::CollectAllGarbage();
     550           6 :     CHECK_EQ(0, dispose_count);
     551             :   }
     552           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     553           6 :   CcTest::CollectAllAvailableGarbage();
     554           6 :   CHECK_EQ(1, dispose_count);
     555           6 : }
     556             : 
     557             : 
     558       26645 : THREADED_TEST(ScriptMakingExternalString) {
     559           6 :   int dispose_count = 0;
     560           6 :   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
     561             :   {
     562           6 :     LocalContext env;
     563          12 :     v8::HandleScope scope(env->GetIsolate());
     564             :     Local<String> source =
     565           6 :         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     566           6 :                                v8::NewStringType::kNormal)
     567             :             .ToLocalChecked();
     568             :     // Trigger GCs so that the newly allocated string moves to old gen.
     569           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     570           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     571           6 :     CHECK(!source->IsExternal());
     572           6 :     CHECK(!source->IsExternalOneByte());
     573           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     574           6 :     CHECK(!source->GetExternalStringResourceBase(&encoding));
     575           6 :     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     576           6 :     bool success = source->MakeExternal(new TestResource(two_byte_source,
     577           6 :                                                          &dispose_count));
     578           6 :     CHECK(success);
     579           6 :     Local<Script> script = v8_compile(source);
     580           6 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     581           6 :     CHECK(value->IsNumber());
     582          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     583           6 :     CcTest::CollectAllGarbage();
     584           6 :     CHECK_EQ(0, dispose_count);
     585             :   }
     586           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     587           6 :   CcTest::CollectAllGarbage();
     588           6 :   CHECK_EQ(1, dispose_count);
     589           6 : }
     590             : 
     591             : 
     592       26645 : THREADED_TEST(ScriptMakingExternalOneByteString) {
     593           6 :   int dispose_count = 0;
     594             :   const char* c_source = "1 + 2 * 3";
     595             :   {
     596           6 :     LocalContext env;
     597          12 :     v8::HandleScope scope(env->GetIsolate());
     598           6 :     Local<String> source = v8_str(c_source);
     599             :     // Trigger GCs so that the newly allocated string moves to old gen.
     600           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     601           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     602           6 :     bool success = source->MakeExternal(
     603           6 :         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
     604           6 :     CHECK(success);
     605           6 :     Local<Script> script = v8_compile(source);
     606           6 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     607           6 :     CHECK(value->IsNumber());
     608          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     609           6 :     CcTest::CollectAllGarbage();
     610           6 :     CHECK_EQ(0, dispose_count);
     611             :   }
     612           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     613           6 :   CcTest::CollectAllGarbage();
     614           6 :   CHECK_EQ(1, dispose_count);
     615           6 : }
     616             : 
     617             : 
     618       26644 : TEST(MakingExternalStringConditions) {
     619           5 :   LocalContext env;
     620          10 :   v8::HandleScope scope(env->GetIsolate());
     621             : 
     622             :   // Free some space in the new space so that we can check freshness.
     623           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     624           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     625             : 
     626           5 :   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
     627             :   Local<String> tiny_local_string =
     628           5 :       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
     629           5 :                              v8::NewStringType::kNormal)
     630             :           .ToLocalChecked();
     631             :   i::DeleteArray(two_byte_string);
     632             : 
     633           5 :   two_byte_string = AsciiToTwoByteString("s1234");
     634             :   Local<String> local_string =
     635           5 :       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
     636           5 :                              v8::NewStringType::kNormal)
     637             :           .ToLocalChecked();
     638             :   i::DeleteArray(two_byte_string);
     639             : 
     640             :   // We should refuse to externalize new space strings.
     641           5 :   CHECK(!local_string->CanMakeExternal());
     642             :   // Trigger GCs so that the newly allocated string moves to old gen.
     643           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     644           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     645             :   // Old space strings should be accepted.
     646           5 :   CHECK(local_string->CanMakeExternal());
     647             : 
     648             :   // Tiny strings are not in-place externalizable when pointer compression is
     649             :   // enabled.
     650           5 :   CHECK_EQ(i::kTaggedSize == i::kSystemPointerSize,
     651             :            tiny_local_string->CanMakeExternal());
     652           5 : }
     653             : 
     654             : 
     655       26644 : TEST(MakingExternalOneByteStringConditions) {
     656           5 :   LocalContext env;
     657          10 :   v8::HandleScope scope(env->GetIsolate());
     658             : 
     659             :   // Free some space in the new space so that we can check freshness.
     660           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     661           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     662             : 
     663           5 :   Local<String> tiny_local_string = v8_str("s");
     664           5 :   Local<String> local_string = v8_str("s1234");
     665             :   // We should refuse to externalize new space strings.
     666           5 :   CHECK(!local_string->CanMakeExternal());
     667             :   // Trigger GCs so that the newly allocated string moves to old gen.
     668           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     669           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     670             :   // Old space strings should be accepted.
     671           5 :   CHECK(local_string->CanMakeExternal());
     672             : 
     673             :   // Tiny strings are not in-place externalizable when pointer compression is
     674             :   // enabled.
     675           5 :   CHECK_EQ(i::kTaggedSize == i::kSystemPointerSize,
     676             :            tiny_local_string->CanMakeExternal());
     677           5 : }
     678             : 
     679             : 
     680       26644 : TEST(MakingExternalUnalignedOneByteString) {
     681           5 :   LocalContext env;
     682          10 :   v8::HandleScope scope(env->GetIsolate());
     683             : 
     684             :   CompileRun("function cons(a, b) { return a + b; }"
     685             :              "function slice(a) { return a.substring(1); }");
     686             :   // Create a cons string that will land in old pointer space.
     687             :   Local<String> cons = Local<String>::Cast(CompileRun(
     688             :       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
     689             :   // Create a sliced string that will land in old pointer space.
     690             :   Local<String> slice = Local<String>::Cast(CompileRun(
     691             :       "slice('abcdefghijklmnopqrstuvwxyz');"));
     692             : 
     693             :   // Trigger GCs so that the newly allocated string moves to old gen.
     694           5 :   i::heap::SimulateFullSpace(CcTest::heap()->old_space());
     695           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     696           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     697             : 
     698             :   // Turn into external string with unaligned resource data.
     699             :   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
     700           5 :   bool success = cons->MakeExternal(
     701           5 :       new TestOneByteResource(i::StrDup(c_cons), nullptr, 1));
     702           5 :   CHECK(success);
     703             :   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
     704           5 :   success = slice->MakeExternal(
     705           5 :       new TestOneByteResource(i::StrDup(c_slice), nullptr, 1));
     706           5 :   CHECK(success);
     707             : 
     708             :   // Trigger GCs and force evacuation.
     709           5 :   CcTest::CollectAllGarbage();
     710           5 :   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask,
     711           5 :                                     i::GarbageCollectionReason::kTesting);
     712           5 : }
     713             : 
     714       26645 : THREADED_TEST(UsingExternalString) {
     715             :   i::Factory* factory = CcTest::i_isolate()->factory();
     716             :   {
     717          12 :     v8::HandleScope scope(CcTest::isolate());
     718           6 :     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
     719             :     Local<String> string =
     720           6 :         String::NewExternalTwoByte(CcTest::isolate(),
     721          12 :                                    new TestResource(two_byte_string))
     722             :             .ToLocalChecked();
     723           6 :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     724             :     // Trigger GCs so that the newly allocated string moves to old gen.
     725           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     726           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     727             :     i::Handle<i::String> isymbol =
     728           6 :         factory->InternalizeString(istring);
     729          12 :     CHECK(isymbol->IsInternalizedString());
     730             :   }
     731           6 :   CcTest::CollectAllGarbage();
     732           6 :   CcTest::CollectAllGarbage();
     733           6 : }
     734             : 
     735             : 
     736       26645 : THREADED_TEST(UsingExternalOneByteString) {
     737             :   i::Factory* factory = CcTest::i_isolate()->factory();
     738             :   {
     739          12 :     v8::HandleScope scope(CcTest::isolate());
     740             :     const char* one_byte_string = "test string";
     741             :     Local<String> string =
     742           6 :         String::NewExternalOneByte(
     743             :             CcTest::isolate(),
     744          12 :             new TestOneByteResource(i::StrDup(one_byte_string)))
     745             :             .ToLocalChecked();
     746           6 :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     747             :     // Trigger GCs so that the newly allocated string moves to old gen.
     748           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     749           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     750             :     i::Handle<i::String> isymbol =
     751           6 :         factory->InternalizeString(istring);
     752          12 :     CHECK(isymbol->IsInternalizedString());
     753             :   }
     754           6 :   CcTest::CollectAllGarbage();
     755           6 :   CcTest::CollectAllGarbage();
     756           6 : }
     757             : 
     758             : 
     759          12 : class RandomLengthResource : public v8::String::ExternalStringResource {
     760             :  public:
     761           6 :   explicit RandomLengthResource(int length) : length_(length) {}
     762           6 :   const uint16_t* data() const override { return string_; }
     763           6 :   size_t length() const override { return length_; }
     764             : 
     765             :  private:
     766             :   uint16_t string_[10];
     767             :   int length_;
     768             : };
     769             : 
     770             : 
     771          22 : class RandomLengthOneByteResource
     772             :     : public v8::String::ExternalOneByteStringResource {
     773             :  public:
     774          11 :   explicit RandomLengthOneByteResource(int length) : length_(length) {}
     775          16 :   const char* data() const override { return string_; }
     776          26 :   size_t length() const override { return length_; }
     777             : 
     778             :  private:
     779             :   char string_[10];
     780             :   int length_;
     781             : };
     782             : 
     783             : 
     784       26645 : THREADED_TEST(NewExternalForVeryLongString) {
     785           6 :   auto isolate = CcTest::isolate();
     786             :   {
     787          12 :     v8::HandleScope scope(isolate);
     788          12 :     v8::TryCatch try_catch(isolate);
     789             :     RandomLengthOneByteResource r(1 << 30);
     790             :     v8::MaybeLocal<v8::String> maybe_str =
     791           6 :         v8::String::NewExternalOneByte(isolate, &r);
     792           6 :     CHECK(maybe_str.IsEmpty());
     793           6 :     CHECK(!try_catch.HasCaught());
     794             :   }
     795             : 
     796             :   {
     797          12 :     v8::HandleScope scope(isolate);
     798          12 :     v8::TryCatch try_catch(isolate);
     799             :     RandomLengthResource r(1 << 30);
     800             :     v8::MaybeLocal<v8::String> maybe_str =
     801           6 :         v8::String::NewExternalTwoByte(isolate, &r);
     802           6 :     CHECK(maybe_str.IsEmpty());
     803           6 :     CHECK(!try_catch.HasCaught());
     804             :   }
     805           6 : }
     806             : 
     807       26644 : TEST(ScavengeExternalString) {
     808             :   ManualGCScope manual_gc_scope;
     809           5 :   i::FLAG_stress_compaction = false;
     810           5 :   i::FLAG_gc_global = false;
     811           5 :   int dispose_count = 0;
     812             :   bool in_young_generation = false;
     813             :   {
     814          10 :     v8::HandleScope scope(CcTest::isolate());
     815           5 :     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
     816             :     Local<String> string =
     817           5 :         String::NewExternalTwoByte(
     818             :             CcTest::isolate(),
     819          10 :             new TestResource(two_byte_string, &dispose_count))
     820             :             .ToLocalChecked();
     821             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     822           5 :     CcTest::CollectGarbage(i::NEW_SPACE);
     823             :     in_young_generation = i::Heap::InYoungGeneration(*istring);
     824          10 :     CHECK_IMPLIES(!in_young_generation,
     825             :                   CcTest::heap()->old_space()->Contains(*istring));
     826           5 :     CHECK_EQ(0, dispose_count);
     827             :   }
     828           5 :   CcTest::CollectGarbage(in_young_generation ? i::NEW_SPACE : i::OLD_SPACE);
     829           5 :   CHECK_EQ(1, dispose_count);
     830           5 : }
     831             : 
     832       26644 : TEST(ScavengeExternalOneByteString) {
     833             :   ManualGCScope manual_gc_scope;
     834           5 :   i::FLAG_stress_compaction = false;
     835           5 :   i::FLAG_gc_global = false;
     836           5 :   int dispose_count = 0;
     837             :   bool in_young_generation = false;
     838             :   {
     839          10 :     v8::HandleScope scope(CcTest::isolate());
     840             :     const char* one_byte_string = "test string";
     841             :     Local<String> string =
     842           5 :         String::NewExternalOneByte(
     843             :             CcTest::isolate(),
     844          10 :             new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
     845             :             .ToLocalChecked();
     846             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     847           5 :     CcTest::CollectGarbage(i::NEW_SPACE);
     848             :     in_young_generation = i::Heap::InYoungGeneration(*istring);
     849          10 :     CHECK_IMPLIES(!in_young_generation,
     850             :                   CcTest::heap()->old_space()->Contains(*istring));
     851           5 :     CHECK_EQ(0, dispose_count);
     852             :   }
     853           5 :   CcTest::CollectGarbage(in_young_generation ? i::NEW_SPACE : i::OLD_SPACE);
     854           5 :   CHECK_EQ(1, dispose_count);
     855           5 : }
     856             : 
     857             : 
     858          10 : class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
     859             :  public:
     860             :   // Only used by non-threaded tests, so it can use static fields.
     861             :   static int dispose_calls;
     862             :   static int dispose_count;
     863             : 
     864             :   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
     865          10 :       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
     866             : 
     867          10 :   void Dispose() override {
     868          10 :     ++dispose_calls;
     869          10 :     if (dispose_) delete this;
     870          10 :   }
     871             :  private:
     872             :   bool dispose_;
     873             : };
     874             : 
     875             : 
     876             : int TestOneByteResourceWithDisposeControl::dispose_count = 0;
     877             : int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     878             : 
     879             : 
     880       26644 : TEST(ExternalStringWithDisposeHandling) {
     881             :   const char* c_source = "1 + 2 * 3";
     882             : 
     883             :   // Use a stack allocated external string resource allocated object.
     884           5 :   TestOneByteResourceWithDisposeControl::dispose_count = 0;
     885           5 :   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     886           5 :   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
     887             :   {
     888           5 :     LocalContext env;
     889          10 :     v8::HandleScope scope(env->GetIsolate());
     890             :     Local<String> source =
     891           5 :         String::NewExternalOneByte(env->GetIsolate(), &res_stack)
     892           5 :             .ToLocalChecked();
     893           5 :     Local<Script> script = v8_compile(source);
     894           5 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     895           5 :     CHECK(value->IsNumber());
     896          10 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     897           5 :     CcTest::CollectAllAvailableGarbage();
     898           5 :     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     899             :   }
     900           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
     901           5 :   CcTest::CollectAllAvailableGarbage();
     902           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
     903           5 :   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     904             : 
     905             :   // Use a heap allocated external string resource allocated object.
     906           5 :   TestOneByteResourceWithDisposeControl::dispose_count = 0;
     907           5 :   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     908             :   TestOneByteResource* res_heap =
     909           5 :       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
     910             :   {
     911           5 :     LocalContext env;
     912          10 :     v8::HandleScope scope(env->GetIsolate());
     913             :     Local<String> source =
     914           5 :         String::NewExternalOneByte(env->GetIsolate(), res_heap)
     915           5 :             .ToLocalChecked();
     916           5 :     Local<Script> script = v8_compile(source);
     917           5 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     918           5 :     CHECK(value->IsNumber());
     919          10 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     920           5 :     CcTest::CollectAllAvailableGarbage();
     921           5 :     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     922             :   }
     923           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
     924           5 :   CcTest::CollectAllAvailableGarbage();
     925           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
     926           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
     927           5 : }
     928             : 
     929             : 
     930       26645 : THREADED_TEST(StringConcat) {
     931             :   {
     932           6 :     LocalContext env;
     933           6 :     v8::Isolate* isolate = env->GetIsolate();
     934          12 :     v8::HandleScope scope(isolate);
     935             :     const char* one_byte_string_1 = "function a_times_t";
     936             :     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
     937             :     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
     938             :     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
     939             :     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
     940             :     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
     941             :     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
     942           6 :     Local<String> left = v8_str(one_byte_string_1);
     943             : 
     944           6 :     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
     945             :     Local<String> right =
     946           6 :         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     947           6 :                                v8::NewStringType::kNormal)
     948           6 :             .ToLocalChecked();
     949             :     i::DeleteArray(two_byte_source);
     950             : 
     951           6 :     Local<String> source = String::Concat(isolate, left, right);
     952           6 :     right = String::NewExternalOneByte(
     953             :                 env->GetIsolate(),
     954          12 :                 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
     955           6 :                 .ToLocalChecked();
     956           6 :     source = String::Concat(isolate, source, right);
     957           6 :     right = String::NewExternalTwoByte(
     958             :                 env->GetIsolate(),
     959          12 :                 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
     960           6 :                 .ToLocalChecked();
     961           6 :     source = String::Concat(isolate, source, right);
     962           6 :     right = v8_str(one_byte_string_2);
     963           6 :     source = String::Concat(isolate, source, right);
     964             : 
     965           6 :     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
     966           6 :     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     967           6 :                                    v8::NewStringType::kNormal)
     968           6 :                 .ToLocalChecked();
     969             :     i::DeleteArray(two_byte_source);
     970             : 
     971           6 :     source = String::Concat(isolate, source, right);
     972           6 :     right = String::NewExternalTwoByte(
     973             :                 env->GetIsolate(),
     974          12 :                 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
     975           6 :                 .ToLocalChecked();
     976           6 :     source = String::Concat(isolate, source, right);
     977           6 :     Local<Script> script = v8_compile(source);
     978           6 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     979           6 :     CHECK(value->IsNumber());
     980          12 :     CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
     981             :   }
     982           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     983           6 :   CcTest::CollectAllGarbage();
     984           6 :   CcTest::CollectAllGarbage();
     985           6 : }
     986             : 
     987             : 
     988       26645 : THREADED_TEST(GlobalProperties) {
     989           6 :   LocalContext env;
     990          12 :   v8::HandleScope scope(env->GetIsolate());
     991           6 :   v8::Local<v8::Object> global = env->Global();
     992          18 :   CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
     993          18 :   Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
     994          12 :   CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
     995           6 : }
     996             : 
     997             : 
     998         660 : static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
     999             :                                  i::Address callback) {
    1000         660 :   ApiTestFuzzer::Fuzz();
    1001         660 :   CheckReturnValue(info, callback);
    1002         660 :   info.GetReturnValue().Set(v8_str("bad value"));
    1003         660 :   info.GetReturnValue().Set(v8_num(102));
    1004         660 : }
    1005             : 
    1006             : 
    1007         330 : static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
    1008         330 :   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
    1009             : }
    1010             : 
    1011             : 
    1012         330 : static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
    1013         330 :   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
    1014             : }
    1015             : 
    1016          22 : static void construct_callback(
    1017             :     const v8::FunctionCallbackInfo<Value>& info) {
    1018          22 :   ApiTestFuzzer::Fuzz();
    1019          22 :   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
    1020          88 :   CHECK(
    1021             :       info.This()
    1022             :           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
    1023             :           .FromJust());
    1024          88 :   CHECK(
    1025             :       info.This()
    1026             :           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
    1027             :           .FromJust());
    1028          22 :   info.GetReturnValue().Set(v8_str("bad value"));
    1029             :   info.GetReturnValue().Set(info.This());
    1030          22 : }
    1031             : 
    1032             : 
    1033         330 : static void Return239Callback(
    1034             :     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
    1035         330 :   ApiTestFuzzer::Fuzz();
    1036         330 :   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
    1037         330 :   info.GetReturnValue().Set(v8_str("bad value"));
    1038         330 :   info.GetReturnValue().Set(v8_num(239));
    1039         330 : }
    1040             : 
    1041             : 
    1042             : template<typename Handler>
    1043          11 : static void TestFunctionTemplateInitializer(Handler handler,
    1044             :                                             Handler handler_2) {
    1045             :   // Test constructor calls.
    1046             :   {
    1047          11 :     LocalContext env;
    1048          11 :     v8::Isolate* isolate = env->GetIsolate();
    1049          22 :     v8::HandleScope scope(isolate);
    1050             : 
    1051             :     Local<v8::FunctionTemplate> fun_templ =
    1052          11 :         v8::FunctionTemplate::New(isolate, handler);
    1053          11 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1054          44 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1055          11 :     Local<Script> script = v8_compile("obj()");
    1056         671 :     for (int i = 0; i < 30; i++) {
    1057         330 :       CHECK_EQ(102, v8_run_int32value(script));
    1058             :     }
    1059             :   }
    1060             :   // Use SetCallHandler to initialize a function template, should work like
    1061             :   // the previous one.
    1062             :   {
    1063          11 :     LocalContext env;
    1064          11 :     v8::Isolate* isolate = env->GetIsolate();
    1065          22 :     v8::HandleScope scope(isolate);
    1066             : 
    1067          11 :     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
    1068          11 :     fun_templ->SetCallHandler(handler_2);
    1069          11 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1070          44 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1071          11 :     Local<Script> script = v8_compile("obj()");
    1072         671 :     for (int i = 0; i < 30; i++) {
    1073         330 :       CHECK_EQ(102, v8_run_int32value(script));
    1074             :     }
    1075             :   }
    1076          11 : }
    1077             : 
    1078             : 
    1079             : template<typename Constructor, typename Accessor>
    1080          11 : static void TestFunctionTemplateAccessor(Constructor constructor,
    1081             :                                          Accessor accessor) {
    1082          11 :   LocalContext env;
    1083          22 :   v8::HandleScope scope(env->GetIsolate());
    1084             : 
    1085             :   Local<v8::FunctionTemplate> fun_templ =
    1086          11 :       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
    1087          11 :   fun_templ->SetClassName(v8_str("funky"));
    1088          22 :   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
    1089          11 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1090          44 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1091             :   Local<Value> result =
    1092          22 :       v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
    1093          33 :   CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
    1094             :   CompileRun("var obj_instance = new obj();");
    1095             :   Local<Script> script;
    1096          11 :   script = v8_compile("obj_instance.x");
    1097         671 :   for (int i = 0; i < 30; i++) {
    1098         330 :     CHECK_EQ(1, v8_run_int32value(script));
    1099             :   }
    1100          11 :   script = v8_compile("obj_instance.m");
    1101         671 :   for (int i = 0; i < 30; i++) {
    1102         330 :     CHECK_EQ(239, v8_run_int32value(script));
    1103             :   }
    1104          11 : }
    1105             : 
    1106             : 
    1107       53294 : THREADED_PROFILED_TEST(FunctionTemplate) {
    1108          11 :   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
    1109          11 :   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
    1110          11 : }
    1111             : 
    1112          18 : static void FunctionCallbackForProxyTest(
    1113             :     const v8::FunctionCallbackInfo<Value>& info) {
    1114             :   info.GetReturnValue().Set(info.This());
    1115          18 : }
    1116             : 
    1117       26645 : THREADED_TEST(FunctionTemplateWithProxy) {
    1118           6 :   LocalContext env;
    1119           6 :   v8::Isolate* isolate = env->GetIsolate();
    1120          12 :   v8::HandleScope scope(isolate);
    1121             : 
    1122             :   v8::Local<v8::FunctionTemplate> function_template =
    1123           6 :       v8::FunctionTemplate::New(isolate, FunctionCallbackForProxyTest);
    1124             :   v8::Local<v8::Function> function =
    1125           6 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1126          24 :   CHECK((*env)->Global()->Set(env.local(), v8_str("f"), function).FromJust());
    1127             :   v8::Local<v8::Value> proxy =
    1128             :       CompileRun("var proxy = new Proxy({}, {}); proxy");
    1129           6 :   CHECK(proxy->IsProxy());
    1130             : 
    1131             :   v8::Local<v8::Value> result = CompileRun("f(proxy)");
    1132          18 :   CHECK(result->Equals(env.local(), (*env)->Global()).FromJust());
    1133             : 
    1134             :   result = CompileRun("f.call(proxy)");
    1135          12 :   CHECK(result->Equals(env.local(), proxy).FromJust());
    1136             : 
    1137             :   result = CompileRun("Reflect.apply(f, proxy, [1])");
    1138          12 :   CHECK(result->Equals(env.local(), proxy).FromJust());
    1139           6 : }
    1140             : 
    1141         660 : static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    1142         660 :   ApiTestFuzzer::Fuzz();
    1143         660 :   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
    1144         660 :   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
    1145         660 : }
    1146             : 
    1147             : 
    1148             : template<typename Callback>
    1149          11 : static void TestSimpleCallback(Callback callback) {
    1150          11 :   LocalContext env;
    1151          11 :   v8::Isolate* isolate = env->GetIsolate();
    1152          22 :   v8::HandleScope scope(isolate);
    1153             : 
    1154             :   v8::Local<v8::ObjectTemplate> object_template =
    1155          11 :       v8::ObjectTemplate::New(isolate);
    1156          22 :   object_template->Set(isolate, "callback",
    1157             :                        v8::FunctionTemplate::New(isolate, callback));
    1158             :   v8::Local<v8::Object> object =
    1159          11 :       object_template->NewInstance(env.local()).ToLocalChecked();
    1160          44 :   CHECK((*env)
    1161             :             ->Global()
    1162             :             ->Set(env.local(), v8_str("callback_object"), object)
    1163             :             .FromJust());
    1164             :   v8::Local<v8::Script> script;
    1165          11 :   script = v8_compile("callback_object.callback(17)");
    1166         671 :   for (int i = 0; i < 30; i++) {
    1167         330 :     CHECK_EQ(51424, v8_run_int32value(script));
    1168             :   }
    1169          11 :   script = v8_compile("callback_object.callback(17, 24)");
    1170         671 :   for (int i = 0; i < 30; i++) {
    1171         330 :     CHECK_EQ(51425, v8_run_int32value(script));
    1172             :   }
    1173          11 : }
    1174             : 
    1175             : 
    1176       53294 : THREADED_PROFILED_TEST(SimpleCallback) {
    1177          11 :   TestSimpleCallback(SimpleCallback);
    1178          11 : }
    1179             : 
    1180             : 
    1181             : template<typename T>
    1182             : void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
    1183             : 
    1184             : // constant return values
    1185             : static int32_t fast_return_value_int32 = 471;
    1186             : static uint32_t fast_return_value_uint32 = 571;
    1187             : static const double kFastReturnValueDouble = 2.7;
    1188             : // variable return values
    1189             : static bool fast_return_value_bool = false;
    1190             : enum ReturnValueOddball {
    1191             :   kNullReturnValue,
    1192             :   kUndefinedReturnValue,
    1193             :   kEmptyStringReturnValue
    1194             : };
    1195             : static ReturnValueOddball fast_return_value_void;
    1196             : static bool fast_return_value_object_is_empty = false;
    1197             : 
    1198             : // Helper function to avoid compiler error: insufficient contextual information
    1199             : // to determine type when applying FUNCTION_ADDR to a template function.
    1200             : static i::Address address_of(v8::FunctionCallback callback) {
    1201         396 :   return FUNCTION_ADDR(callback);
    1202             : }
    1203             : 
    1204             : template<>
    1205         165 : void FastReturnValueCallback<int32_t>(
    1206             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1207         165 :   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
    1208         165 :   info.GetReturnValue().Set(fast_return_value_int32);
    1209         165 : }
    1210             : 
    1211             : template<>
    1212         165 : void FastReturnValueCallback<uint32_t>(
    1213             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1214         165 :   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
    1215         165 :   info.GetReturnValue().Set(fast_return_value_uint32);
    1216         165 : }
    1217             : 
    1218             : template<>
    1219          11 : void FastReturnValueCallback<double>(
    1220             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1221          11 :   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
    1222             :   info.GetReturnValue().Set(kFastReturnValueDouble);
    1223          11 : }
    1224             : 
    1225             : template<>
    1226          22 : void FastReturnValueCallback<bool>(
    1227             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1228          22 :   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
    1229          22 :   info.GetReturnValue().Set(fast_return_value_bool);
    1230          22 : }
    1231             : 
    1232             : template<>
    1233          33 : void FastReturnValueCallback<void>(
    1234             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1235          33 :   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
    1236          33 :   switch (fast_return_value_void) {
    1237             :     case kNullReturnValue:
    1238             :       info.GetReturnValue().SetNull();
    1239          11 :       break;
    1240             :     case kUndefinedReturnValue:
    1241             :       info.GetReturnValue().SetUndefined();
    1242          11 :       break;
    1243             :     case kEmptyStringReturnValue:
    1244             :       info.GetReturnValue().SetEmptyString();
    1245          11 :       break;
    1246             :   }
    1247          33 : }
    1248             : 
    1249             : template<>
    1250          22 : void FastReturnValueCallback<Object>(
    1251             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1252             :   v8::Local<v8::Object> object;
    1253          22 :   if (!fast_return_value_object_is_empty) {
    1254          11 :     object = Object::New(info.GetIsolate());
    1255             :   }
    1256             :   info.GetReturnValue().Set(object);
    1257          22 : }
    1258             : 
    1259             : template <typename T>
    1260         418 : Local<Value> TestFastReturnValues() {
    1261         418 :   LocalContext env;
    1262         418 :   v8::Isolate* isolate = env->GetIsolate();
    1263         418 :   v8::EscapableHandleScope scope(isolate);
    1264             :   v8::Local<v8::ObjectTemplate> object_template =
    1265         418 :       v8::ObjectTemplate::New(isolate);
    1266             :   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
    1267         836 :   object_template->Set(isolate, "callback",
    1268             :                        v8::FunctionTemplate::New(isolate, callback));
    1269             :   v8::Local<v8::Object> object =
    1270         418 :       object_template->NewInstance(env.local()).ToLocalChecked();
    1271        1672 :   CHECK((*env)
    1272             :             ->Global()
    1273             :             ->Set(env.local(), v8_str("callback_object"), object)
    1274             :             .FromJust());
    1275         418 :   return scope.Escape(CompileRun("callback_object.callback()"));
    1276             : }
    1277             : 
    1278             : 
    1279       53294 : THREADED_PROFILED_TEST(FastReturnValues) {
    1280          11 :   LocalContext env;
    1281          11 :   v8::Isolate* isolate = env->GetIsolate();
    1282          22 :   v8::HandleScope scope(isolate);
    1283             :   v8::Local<v8::Value> value;
    1284             :   // check int32_t and uint32_t
    1285             :   int32_t int_values[] = {
    1286             :       0, 234, -723,
    1287             :       i::Smi::kMinValue, i::Smi::kMaxValue
    1288          11 :   };
    1289         121 :   for (size_t i = 0; i < arraysize(int_values); i++) {
    1290         385 :     for (int modifier = -1; modifier <= 1; modifier++) {
    1291         165 :       int int_value = v8::base::AddWithWraparound(int_values[i], modifier);
    1292             :       // check int32_t
    1293         165 :       fast_return_value_int32 = int_value;
    1294         165 :       value = TestFastReturnValues<int32_t>();
    1295         165 :       CHECK(value->IsInt32());
    1296         330 :       CHECK_EQ(fast_return_value_int32,
    1297             :                value->Int32Value(env.local()).FromJust());
    1298             :       // check uint32_t
    1299         165 :       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
    1300         165 :       value = TestFastReturnValues<uint32_t>();
    1301         165 :       CHECK(value->IsUint32());
    1302         330 :       CHECK_EQ(fast_return_value_uint32,
    1303             :                value->Uint32Value(env.local()).FromJust());
    1304             :     }
    1305             :   }
    1306             :   // check double
    1307          11 :   value = TestFastReturnValues<double>();
    1308          11 :   CHECK(value->IsNumber());
    1309          22 :   CHECK_EQ(kFastReturnValueDouble,
    1310             :            value->ToNumber(env.local()).ToLocalChecked()->Value());
    1311             :   // check bool values
    1312          55 :   for (int i = 0; i < 2; i++) {
    1313          22 :     fast_return_value_bool = i == 0;
    1314          22 :     value = TestFastReturnValues<bool>();
    1315          22 :     CHECK(value->IsBoolean());
    1316          22 :     CHECK_EQ(fast_return_value_bool, value->BooleanValue(isolate));
    1317             :   }
    1318             :   // check oddballs
    1319             :   ReturnValueOddball oddballs[] = {
    1320             :       kNullReturnValue,
    1321             :       kUndefinedReturnValue,
    1322             :       kEmptyStringReturnValue
    1323          11 :   };
    1324          77 :   for (size_t i = 0; i < arraysize(oddballs); i++) {
    1325          33 :     fast_return_value_void = oddballs[i];
    1326          33 :     value = TestFastReturnValues<void>();
    1327          33 :     switch (fast_return_value_void) {
    1328             :       case kNullReturnValue:
    1329          11 :         CHECK(value->IsNull());
    1330             :         break;
    1331             :       case kUndefinedReturnValue:
    1332          11 :         CHECK(value->IsUndefined());
    1333             :         break;
    1334             :       case kEmptyStringReturnValue:
    1335          11 :         CHECK(value->IsString());
    1336          11 :         CHECK_EQ(0, v8::String::Cast(*value)->Length());
    1337             :         break;
    1338             :     }
    1339             :   }
    1340             :   // check handles
    1341          11 :   fast_return_value_object_is_empty = false;
    1342          11 :   value = TestFastReturnValues<Object>();
    1343          11 :   CHECK(value->IsObject());
    1344          11 :   fast_return_value_object_is_empty = true;
    1345          11 :   value = TestFastReturnValues<Object>();
    1346          11 :   CHECK(value->IsUndefined());
    1347          11 : }
    1348             : 
    1349             : 
    1350       26645 : THREADED_TEST(FunctionTemplateSetLength) {
    1351           6 :   LocalContext env;
    1352           6 :   v8::Isolate* isolate = env->GetIsolate();
    1353          12 :   v8::HandleScope scope(isolate);
    1354             :   {
    1355             :     Local<v8::FunctionTemplate> fun_templ =
    1356             :         v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
    1357           6 :                                   Local<v8::Signature>(), 23);
    1358           6 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1359          24 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1360           6 :     Local<Script> script = v8_compile("obj.length");
    1361           6 :     CHECK_EQ(23, v8_run_int32value(script));
    1362             :   }
    1363             :   {
    1364             :     Local<v8::FunctionTemplate> fun_templ =
    1365           6 :         v8::FunctionTemplate::New(isolate, handle_callback);
    1366           6 :     fun_templ->SetLength(22);
    1367           6 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1368          24 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1369           6 :     Local<Script> script = v8_compile("obj.length");
    1370           6 :     CHECK_EQ(22, v8_run_int32value(script));
    1371             :   }
    1372             :   {
    1373             :     // Without setting length it defaults to 0.
    1374             :     Local<v8::FunctionTemplate> fun_templ =
    1375           6 :         v8::FunctionTemplate::New(isolate, handle_callback);
    1376           6 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1377          24 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1378           6 :     Local<Script> script = v8_compile("obj.length");
    1379           6 :     CHECK_EQ(0, v8_run_int32value(script));
    1380             :   }
    1381           6 : }
    1382             : 
    1383             : 
    1384             : static void* expected_ptr;
    1385        8424 : static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1386        8424 :   void* ptr = v8::External::Cast(*args.Data())->Value();
    1387        8424 :   CHECK_EQ(expected_ptr, ptr);
    1388             :   args.GetReturnValue().Set(true);
    1389        8424 : }
    1390             : 
    1391             : 
    1392         648 : static void TestExternalPointerWrapping() {
    1393         648 :   LocalContext env;
    1394         648 :   v8::Isolate* isolate = env->GetIsolate();
    1395        1296 :   v8::HandleScope scope(isolate);
    1396             : 
    1397         648 :   v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
    1398             : 
    1399         648 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    1400        3240 :   CHECK(obj->Set(env.local(), v8_str("func"),
    1401             :                  v8::FunctionTemplate::New(isolate, callback, data)
    1402             :                      ->GetFunction(env.local())
    1403             :                      .ToLocalChecked())
    1404             :             .FromJust());
    1405        2592 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
    1406             : 
    1407         648 :   CHECK(CompileRun("function foo() {\n"
    1408             :                    "  for (var i = 0; i < 13; i++) obj.func();\n"
    1409             :                    "}\n"
    1410             :                    "foo(), true")
    1411             :             ->BooleanValue(isolate));
    1412         648 : }
    1413             : 
    1414             : 
    1415       26645 : THREADED_TEST(ExternalWrap) {
    1416             :   // Check heap allocated object.
    1417           6 :   int* ptr = new int;
    1418           6 :   expected_ptr = ptr;
    1419           6 :   TestExternalPointerWrapping();
    1420           6 :   delete ptr;
    1421             : 
    1422             :   // Check stack allocated object.
    1423             :   int foo;
    1424           6 :   expected_ptr = &foo;
    1425           6 :   TestExternalPointerWrapping();
    1426             : 
    1427             :   // Check not aligned addresses.
    1428             :   const int n = 100;
    1429           6 :   char* s = new char[n];
    1430        1206 :   for (int i = 0; i < n; i++) {
    1431         600 :     expected_ptr = s + i;
    1432         600 :     TestExternalPointerWrapping();
    1433             :   }
    1434             : 
    1435           6 :   delete[] s;
    1436             : 
    1437             :   // Check several invalid addresses.
    1438           6 :   expected_ptr = reinterpret_cast<void*>(1);
    1439           6 :   TestExternalPointerWrapping();
    1440             : 
    1441           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEF);
    1442           6 :   TestExternalPointerWrapping();
    1443             : 
    1444           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEF + 1);
    1445           6 :   TestExternalPointerWrapping();
    1446             : 
    1447             : #if defined(V8_HOST_ARCH_X64)
    1448             :   // Check a value with a leading 1 bit in x64 Smi encoding.
    1449           6 :   expected_ptr = reinterpret_cast<void*>(0x400000000);
    1450           6 :   TestExternalPointerWrapping();
    1451             : 
    1452           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEFDEADBEEF);
    1453           6 :   TestExternalPointerWrapping();
    1454             : 
    1455           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEFDEADBEEF + 1);
    1456           6 :   TestExternalPointerWrapping();
    1457             : #endif
    1458           6 : }
    1459             : 
    1460             : 
    1461       26645 : THREADED_TEST(FindInstanceInPrototypeChain) {
    1462           6 :   LocalContext env;
    1463           6 :   v8::Isolate* isolate = env->GetIsolate();
    1464          12 :   v8::HandleScope scope(isolate);
    1465             : 
    1466           6 :   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
    1467           6 :   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
    1468           6 :   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
    1469           6 :   derived->Inherit(base);
    1470             : 
    1471             :   Local<v8::Function> base_function =
    1472           6 :       base->GetFunction(env.local()).ToLocalChecked();
    1473             :   Local<v8::Function> derived_function =
    1474           6 :       derived->GetFunction(env.local()).ToLocalChecked();
    1475             :   Local<v8::Function> other_function =
    1476           6 :       other->GetFunction(env.local()).ToLocalChecked();
    1477             : 
    1478             :   Local<v8::Object> base_instance =
    1479             :       base_function->NewInstance(env.local()).ToLocalChecked();
    1480             :   Local<v8::Object> derived_instance =
    1481             :       derived_function->NewInstance(env.local()).ToLocalChecked();
    1482             :   Local<v8::Object> derived_instance2 =
    1483             :       derived_function->NewInstance(env.local()).ToLocalChecked();
    1484             :   Local<v8::Object> other_instance =
    1485             :       other_function->NewInstance(env.local()).ToLocalChecked();
    1486          18 :   CHECK(
    1487             :       derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
    1488             :           .FromJust());
    1489          18 :   CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
    1490             :             .FromJust());
    1491             : 
    1492             :   // base_instance is only an instance of base.
    1493          18 :   CHECK(base_instance->Equals(env.local(),
    1494             :                               base_instance->FindInstanceInPrototypeChain(base))
    1495             :             .FromJust());
    1496          12 :   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
    1497          12 :   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    1498             : 
    1499             :   // derived_instance is an instance of base and derived.
    1500          18 :   CHECK(derived_instance->Equals(env.local(),
    1501             :                                  derived_instance->FindInstanceInPrototypeChain(
    1502             :                                      base))
    1503             :             .FromJust());
    1504          18 :   CHECK(derived_instance->Equals(env.local(),
    1505             :                                  derived_instance->FindInstanceInPrototypeChain(
    1506             :                                      derived))
    1507             :             .FromJust());
    1508          12 :   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    1509             : 
    1510             :   // other_instance is an instance of other and its immediate
    1511             :   // prototype derived_instance2 is an instance of base and derived.
    1512             :   // Note, derived_instance is an instance of base and derived too,
    1513             :   // but it comes after derived_instance2 in the prototype chain of
    1514             :   // other_instance.
    1515          18 :   CHECK(derived_instance2->Equals(
    1516             :                              env.local(),
    1517             :                              other_instance->FindInstanceInPrototypeChain(base))
    1518             :             .FromJust());
    1519          18 :   CHECK(derived_instance2->Equals(env.local(),
    1520             :                                   other_instance->FindInstanceInPrototypeChain(
    1521             :                                       derived))
    1522             :             .FromJust());
    1523          18 :   CHECK(other_instance->Equals(
    1524             :                           env.local(),
    1525             :                           other_instance->FindInstanceInPrototypeChain(other))
    1526             :             .FromJust());
    1527           6 : }
    1528             : 
    1529             : 
    1530       26645 : THREADED_TEST(TinyInteger) {
    1531           6 :   LocalContext env;
    1532           6 :   v8::Isolate* isolate = env->GetIsolate();
    1533          12 :   v8::HandleScope scope(isolate);
    1534             : 
    1535             :   int32_t value = 239;
    1536           6 :   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1537           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1538           6 : }
    1539             : 
    1540             : 
    1541       26645 : THREADED_TEST(BigSmiInteger) {
    1542           6 :   LocalContext env;
    1543          12 :   v8::HandleScope scope(env->GetIsolate());
    1544           6 :   v8::Isolate* isolate = CcTest::isolate();
    1545             : 
    1546             :   int32_t value = i::Smi::kMaxValue;
    1547             :   // We cannot add one to a Smi::kMaxValue without wrapping.
    1548             :   if (i::SmiValuesAre31Bits()) {
    1549             :     CHECK(i::Smi::IsValid(value));
    1550             :     CHECK(!i::Smi::IsValid(value + 1));
    1551             : 
    1552             :     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1553             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1554             :   }
    1555           6 : }
    1556             : 
    1557             : 
    1558       26645 : THREADED_TEST(BigInteger) {
    1559           6 :   LocalContext env;
    1560          12 :   v8::HandleScope scope(env->GetIsolate());
    1561           6 :   v8::Isolate* isolate = CcTest::isolate();
    1562             : 
    1563             :   // We cannot add one to a Smi::kMaxValue without wrapping.
    1564             :   if (i::SmiValuesAre31Bits()) {
    1565             :     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
    1566             :     // The code will not be run in that case, due to the "if" guard.
    1567             :     int32_t value =
    1568             :         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
    1569             :     CHECK_GT(value, i::Smi::kMaxValue);
    1570             :     CHECK(!i::Smi::IsValid(value));
    1571             : 
    1572             :     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1573             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1574             :   }
    1575           6 : }
    1576             : 
    1577             : 
    1578       26645 : THREADED_TEST(TinyUnsignedInteger) {
    1579           6 :   LocalContext env;
    1580          12 :   v8::HandleScope scope(env->GetIsolate());
    1581           6 :   v8::Isolate* isolate = CcTest::isolate();
    1582             : 
    1583             :   uint32_t value = 239;
    1584             : 
    1585           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1586           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1587           6 : }
    1588             : 
    1589             : 
    1590       26645 : THREADED_TEST(BigUnsignedSmiInteger) {
    1591           6 :   LocalContext env;
    1592          12 :   v8::HandleScope scope(env->GetIsolate());
    1593           6 :   v8::Isolate* isolate = CcTest::isolate();
    1594             : 
    1595             :   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
    1596             :   CHECK(i::Smi::IsValid(value));
    1597             :   CHECK(!i::Smi::IsValid(value + 1));
    1598             : 
    1599           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1600           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1601           6 : }
    1602             : 
    1603             : 
    1604       26645 : THREADED_TEST(BigUnsignedInteger) {
    1605           6 :   LocalContext env;
    1606          12 :   v8::HandleScope scope(env->GetIsolate());
    1607           6 :   v8::Isolate* isolate = CcTest::isolate();
    1608             : 
    1609             :   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
    1610             :   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
    1611             :   CHECK(!i::Smi::IsValid(value));
    1612             : 
    1613           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1614           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1615           6 : }
    1616             : 
    1617             : 
    1618       26645 : THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
    1619           6 :   LocalContext env;
    1620          12 :   v8::HandleScope scope(env->GetIsolate());
    1621           6 :   v8::Isolate* isolate = CcTest::isolate();
    1622             : 
    1623             :   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
    1624             :   uint32_t value = INT32_MAX_AS_UINT + 1;
    1625             :   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
    1626             : 
    1627           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1628           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1629           6 : }
    1630             : 
    1631             : 
    1632       26645 : THREADED_TEST(IsNativeError) {
    1633           6 :   LocalContext env;
    1634          12 :   v8::HandleScope scope(env->GetIsolate());
    1635             :   v8::Local<Value> syntax_error = CompileRun(
    1636             :       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
    1637           6 :   CHECK(syntax_error->IsNativeError());
    1638             :   v8::Local<Value> not_error = CompileRun("{a:42}");
    1639           6 :   CHECK(!not_error->IsNativeError());
    1640             :   v8::Local<Value> not_object = CompileRun("42");
    1641           6 :   CHECK(!not_object->IsNativeError());
    1642           6 : }
    1643             : 
    1644             : 
    1645       26645 : THREADED_TEST(IsGeneratorFunctionOrObject) {
    1646           6 :   LocalContext env;
    1647          12 :   v8::HandleScope scope(env->GetIsolate());
    1648             : 
    1649             :   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
    1650             :   v8::Local<Value> gen = CompileRun("gen");
    1651             :   v8::Local<Value> genObj = CompileRun("gen()");
    1652             :   v8::Local<Value> object = CompileRun("{a:42}");
    1653             :   v8::Local<Value> func = CompileRun("func");
    1654             : 
    1655           6 :   CHECK(gen->IsGeneratorFunction());
    1656           6 :   CHECK(gen->IsFunction());
    1657           6 :   CHECK(!gen->IsGeneratorObject());
    1658             : 
    1659           6 :   CHECK(!genObj->IsGeneratorFunction());
    1660           6 :   CHECK(!genObj->IsFunction());
    1661           6 :   CHECK(genObj->IsGeneratorObject());
    1662             : 
    1663           6 :   CHECK(!object->IsGeneratorFunction());
    1664           6 :   CHECK(!object->IsFunction());
    1665           6 :   CHECK(!object->IsGeneratorObject());
    1666             : 
    1667           6 :   CHECK(!func->IsGeneratorFunction());
    1668           6 :   CHECK(func->IsFunction());
    1669           6 :   CHECK(!func->IsGeneratorObject());
    1670           6 : }
    1671             : 
    1672       26645 : THREADED_TEST(IsAsyncFunction) {
    1673           6 :   LocalContext env;
    1674           6 :   v8::Isolate* isolate = env->GetIsolate();
    1675          12 :   v8::HandleScope scope(isolate);
    1676             : 
    1677             :   CompileRun("async function foo() {}");
    1678             :   v8::Local<Value> foo = CompileRun("foo");
    1679             : 
    1680           6 :   CHECK(foo->IsAsyncFunction());
    1681           6 :   CHECK(foo->IsFunction());
    1682           6 :   CHECK(!foo->IsGeneratorFunction());
    1683           6 :   CHECK(!foo->IsGeneratorObject());
    1684             : 
    1685             :   CompileRun("function bar() {}");
    1686             :   v8::Local<Value> bar = CompileRun("bar");
    1687             : 
    1688           6 :   CHECK(!bar->IsAsyncFunction());
    1689           6 :   CHECK(bar->IsFunction());
    1690           6 : }
    1691             : 
    1692       26645 : THREADED_TEST(ArgumentsObject) {
    1693           6 :   LocalContext env;
    1694          12 :   v8::HandleScope scope(env->GetIsolate());
    1695             :   v8::Local<Value> arguments_object =
    1696             :       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
    1697           6 :   CHECK(arguments_object->IsArgumentsObject());
    1698             :   v8::Local<Value> array = CompileRun("[1,2,3]");
    1699           6 :   CHECK(!array->IsArgumentsObject());
    1700             :   v8::Local<Value> object = CompileRun("{a:42}");
    1701           6 :   CHECK(!object->IsArgumentsObject());
    1702           6 : }
    1703             : 
    1704             : 
    1705       26645 : THREADED_TEST(IsMapOrSet) {
    1706           6 :   LocalContext env;
    1707          12 :   v8::HandleScope scope(env->GetIsolate());
    1708             :   v8::Local<Value> map = CompileRun("new Map()");
    1709             :   v8::Local<Value> set = CompileRun("new Set()");
    1710             :   v8::Local<Value> weak_map = CompileRun("new WeakMap()");
    1711             :   v8::Local<Value> weak_set = CompileRun("new WeakSet()");
    1712           6 :   CHECK(map->IsMap());
    1713           6 :   CHECK(set->IsSet());
    1714           6 :   CHECK(weak_map->IsWeakMap());
    1715           6 :   CHECK(weak_set->IsWeakSet());
    1716             : 
    1717           6 :   CHECK(!map->IsSet());
    1718           6 :   CHECK(!map->IsWeakMap());
    1719           6 :   CHECK(!map->IsWeakSet());
    1720             : 
    1721           6 :   CHECK(!set->IsMap());
    1722           6 :   CHECK(!set->IsWeakMap());
    1723           6 :   CHECK(!set->IsWeakSet());
    1724             : 
    1725           6 :   CHECK(!weak_map->IsMap());
    1726           6 :   CHECK(!weak_map->IsSet());
    1727           6 :   CHECK(!weak_map->IsWeakSet());
    1728             : 
    1729           6 :   CHECK(!weak_set->IsMap());
    1730           6 :   CHECK(!weak_set->IsSet());
    1731           6 :   CHECK(!weak_set->IsWeakMap());
    1732             : 
    1733             :   v8::Local<Value> object = CompileRun("{a:42}");
    1734           6 :   CHECK(!object->IsMap());
    1735           6 :   CHECK(!object->IsSet());
    1736           6 :   CHECK(!object->IsWeakMap());
    1737           6 :   CHECK(!object->IsWeakSet());
    1738           6 : }
    1739             : 
    1740             : 
    1741       26645 : THREADED_TEST(StringObject) {
    1742           6 :   LocalContext env;
    1743          12 :   v8::HandleScope scope(env->GetIsolate());
    1744             :   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
    1745           6 :   CHECK(boxed_string->IsStringObject());
    1746             :   v8::Local<Value> unboxed_string = CompileRun("\"test\"");
    1747           6 :   CHECK(!unboxed_string->IsStringObject());
    1748             :   v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
    1749           6 :   CHECK(!boxed_not_string->IsStringObject());
    1750             :   v8::Local<Value> not_object = CompileRun("0");
    1751           6 :   CHECK(!not_object->IsStringObject());
    1752             :   v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
    1753           6 :   CHECK(!as_boxed.IsEmpty());
    1754           6 :   Local<v8::String> the_string = as_boxed->ValueOf();
    1755           6 :   CHECK(!the_string.IsEmpty());
    1756           6 :   ExpectObject("\"test\"", the_string);
    1757             :   v8::Local<v8::Value> new_boxed_string =
    1758           6 :       v8::StringObject::New(CcTest::isolate(), the_string);
    1759           6 :   CHECK(new_boxed_string->IsStringObject());
    1760             :   as_boxed = new_boxed_string.As<v8::StringObject>();
    1761           6 :   the_string = as_boxed->ValueOf();
    1762           6 :   CHECK(!the_string.IsEmpty());
    1763           6 :   ExpectObject("\"test\"", the_string);
    1764           6 : }
    1765             : 
    1766             : 
    1767       26644 : TEST(StringObjectDelete) {
    1768           5 :   LocalContext context;
    1769          10 :   v8::HandleScope scope(context->GetIsolate());
    1770             :   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
    1771           5 :   CHECK(boxed_string->IsStringObject());
    1772             :   v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
    1773          10 :   CHECK(!str_obj->Delete(context.local(), 2).FromJust());
    1774          15 :   CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
    1775           5 : }
    1776             : 
    1777             : 
    1778       26645 : THREADED_TEST(NumberObject) {
    1779           6 :   LocalContext env;
    1780          12 :   v8::HandleScope scope(env->GetIsolate());
    1781             :   v8::Local<Value> boxed_number = CompileRun("new Number(42)");
    1782           6 :   CHECK(boxed_number->IsNumberObject());
    1783             :   v8::Local<Value> unboxed_number = CompileRun("42");
    1784           6 :   CHECK(!unboxed_number->IsNumberObject());
    1785             :   v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
    1786           6 :   CHECK(!boxed_not_number->IsNumberObject());
    1787             :   v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
    1788           6 :   CHECK(!as_boxed.IsEmpty());
    1789           6 :   double the_number = as_boxed->ValueOf();
    1790           6 :   CHECK_EQ(42.0, the_number);
    1791             :   v8::Local<v8::Value> new_boxed_number =
    1792           6 :       v8::NumberObject::New(env->GetIsolate(), 43);
    1793           6 :   CHECK(new_boxed_number->IsNumberObject());
    1794             :   as_boxed = new_boxed_number.As<v8::NumberObject>();
    1795           6 :   the_number = as_boxed->ValueOf();
    1796           6 :   CHECK_EQ(43.0, the_number);
    1797           6 : }
    1798             : 
    1799       26645 : THREADED_TEST(BigIntObject) {
    1800           6 :   LocalContext env;
    1801           6 :   v8::Isolate* isolate = env->GetIsolate();
    1802          12 :   v8::HandleScope scope(isolate);
    1803           6 :   v8::Local<v8::Context> context(env.local());
    1804             :   v8::Local<Value> boxed_bigint = CompileRun("new Object(42n)");
    1805           6 :   CHECK(!boxed_bigint->IsBigInt());
    1806           6 :   CHECK(boxed_bigint->IsBigIntObject());
    1807             :   v8::Local<Value> unboxed_bigint = CompileRun("42n");
    1808           6 :   CHECK(unboxed_bigint->IsBigInt());
    1809           6 :   CHECK(!unboxed_bigint->IsBigIntObject());
    1810             :   v8::Local<v8::BigIntObject> as_boxed = boxed_bigint.As<v8::BigIntObject>();
    1811           6 :   CHECK(!as_boxed.IsEmpty());
    1812           6 :   v8::Local<v8::BigInt> unpacked = as_boxed->ValueOf();
    1813           6 :   CHECK(!unpacked.IsEmpty());
    1814           6 :   v8::Local<v8::Value> new_boxed_bigint = v8::BigIntObject::New(isolate, 43);
    1815           6 :   CHECK(new_boxed_bigint->IsBigIntObject());
    1816           6 :   v8::Local<v8::Value> new_unboxed_bigint = v8::BigInt::New(isolate, 44);
    1817           6 :   CHECK(new_unboxed_bigint->IsBigInt());
    1818             : 
    1819             :   // Test functionality inherited from v8::Value.
    1820           6 :   CHECK(unboxed_bigint->BooleanValue(isolate));
    1821             :   v8::Local<v8::String> string =
    1822           6 :       unboxed_bigint->ToString(context).ToLocalChecked();
    1823           6 :   CHECK_EQ(0, strcmp("42", *v8::String::Utf8Value(isolate, string)));
    1824             : 
    1825             :   // IntegerValue throws.
    1826          12 :   CHECK(unboxed_bigint->IntegerValue(context).IsNothing());
    1827           6 : }
    1828             : 
    1829       26645 : THREADED_TEST(BooleanObject) {
    1830           6 :   LocalContext env;
    1831          12 :   v8::HandleScope scope(env->GetIsolate());
    1832             :   v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
    1833           6 :   CHECK(boxed_boolean->IsBooleanObject());
    1834             :   v8::Local<Value> unboxed_boolean = CompileRun("true");
    1835           6 :   CHECK(!unboxed_boolean->IsBooleanObject());
    1836             :   v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
    1837           6 :   CHECK(!boxed_not_boolean->IsBooleanObject());
    1838             :   v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
    1839           6 :   CHECK(!as_boxed.IsEmpty());
    1840           6 :   bool the_boolean = as_boxed->ValueOf();
    1841           6 :   CHECK(the_boolean);
    1842             :   v8::Local<v8::Value> boxed_true =
    1843           6 :       v8::BooleanObject::New(env->GetIsolate(), true);
    1844             :   v8::Local<v8::Value> boxed_false =
    1845           6 :       v8::BooleanObject::New(env->GetIsolate(), false);
    1846           6 :   CHECK(boxed_true->IsBooleanObject());
    1847           6 :   CHECK(boxed_false->IsBooleanObject());
    1848             :   as_boxed = boxed_true.As<v8::BooleanObject>();
    1849           6 :   CHECK(as_boxed->ValueOf());
    1850             :   as_boxed = boxed_false.As<v8::BooleanObject>();
    1851           6 :   CHECK(!as_boxed->ValueOf());
    1852           6 : }
    1853             : 
    1854             : 
    1855       26645 : THREADED_TEST(PrimitiveAndWrappedBooleans) {
    1856           6 :   LocalContext env;
    1857           6 :   v8::Isolate* isolate = env->GetIsolate();
    1858          12 :   v8::HandleScope scope(isolate);
    1859             : 
    1860             :   Local<Value> primitive_false = Boolean::New(isolate, false);
    1861           6 :   CHECK(primitive_false->IsBoolean());
    1862           6 :   CHECK(!primitive_false->IsBooleanObject());
    1863           6 :   CHECK(!primitive_false->BooleanValue(isolate));
    1864           6 :   CHECK(!primitive_false->IsTrue());
    1865           6 :   CHECK(primitive_false->IsFalse());
    1866             : 
    1867           6 :   Local<Value> false_value = BooleanObject::New(isolate, false);
    1868           6 :   CHECK(!false_value->IsBoolean());
    1869           6 :   CHECK(false_value->IsBooleanObject());
    1870           6 :   CHECK(false_value->BooleanValue(isolate));
    1871           6 :   CHECK(!false_value->IsTrue());
    1872           6 :   CHECK(!false_value->IsFalse());
    1873             : 
    1874             :   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
    1875           6 :   CHECK(!false_boolean_object->IsBoolean());
    1876           6 :   CHECK(false_boolean_object->IsBooleanObject());
    1877           6 :   CHECK(false_boolean_object->BooleanValue(isolate));
    1878           6 :   CHECK(!false_boolean_object->ValueOf());
    1879           6 :   CHECK(!false_boolean_object->IsTrue());
    1880           6 :   CHECK(!false_boolean_object->IsFalse());
    1881             : 
    1882             :   Local<Value> primitive_true = Boolean::New(isolate, true);
    1883           6 :   CHECK(primitive_true->IsBoolean());
    1884           6 :   CHECK(!primitive_true->IsBooleanObject());
    1885           6 :   CHECK(primitive_true->BooleanValue(isolate));
    1886           6 :   CHECK(primitive_true->IsTrue());
    1887           6 :   CHECK(!primitive_true->IsFalse());
    1888             : 
    1889           6 :   Local<Value> true_value = BooleanObject::New(isolate, true);
    1890           6 :   CHECK(!true_value->IsBoolean());
    1891           6 :   CHECK(true_value->IsBooleanObject());
    1892           6 :   CHECK(true_value->BooleanValue(isolate));
    1893           6 :   CHECK(!true_value->IsTrue());
    1894           6 :   CHECK(!true_value->IsFalse());
    1895             : 
    1896             :   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
    1897           6 :   CHECK(!true_boolean_object->IsBoolean());
    1898           6 :   CHECK(true_boolean_object->IsBooleanObject());
    1899           6 :   CHECK(true_boolean_object->BooleanValue(isolate));
    1900           6 :   CHECK(true_boolean_object->ValueOf());
    1901           6 :   CHECK(!true_boolean_object->IsTrue());
    1902           6 :   CHECK(!true_boolean_object->IsFalse());
    1903           6 : }
    1904             : 
    1905             : 
    1906       26645 : THREADED_TEST(Number) {
    1907           6 :   LocalContext env;
    1908          12 :   v8::HandleScope scope(env->GetIsolate());
    1909             :   double PI = 3.1415926;
    1910           6 :   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
    1911          12 :   CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
    1912           6 : }
    1913             : 
    1914             : 
    1915       26645 : THREADED_TEST(ToNumber) {
    1916           6 :   LocalContext env;
    1917           6 :   v8::Isolate* isolate = CcTest::isolate();
    1918          12 :   v8::HandleScope scope(isolate);
    1919           6 :   Local<String> str = v8_str("3.1415926");
    1920          12 :   CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
    1921             :   v8::Local<v8::Boolean> t = v8::True(isolate);
    1922          12 :   CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
    1923             :   v8::Local<v8::Boolean> f = v8::False(isolate);
    1924          12 :   CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
    1925           6 : }
    1926             : 
    1927             : 
    1928       26645 : THREADED_TEST(Date) {
    1929           6 :   LocalContext env;
    1930          12 :   v8::HandleScope scope(env->GetIsolate());
    1931             :   double PI = 3.1415926;
    1932           6 :   Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
    1933          12 :   CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
    1934          24 :   CHECK(date.As<v8::Date>()
    1935             :             ->Set(env.local(), v8_str("property"),
    1936             :                   v8::Integer::New(env->GetIsolate(), 42))
    1937             :             .FromJust());
    1938          24 :   CHECK_EQ(42, date.As<v8::Date>()
    1939             :                    ->Get(env.local(), v8_str("property"))
    1940             :                    .ToLocalChecked()
    1941             :                    ->Int32Value(env.local())
    1942             :                    .FromJust());
    1943           6 : }
    1944             : 
    1945             : 
    1946       26645 : THREADED_TEST(Boolean) {
    1947           6 :   LocalContext env;
    1948           6 :   v8::Isolate* isolate = env->GetIsolate();
    1949          12 :   v8::HandleScope scope(isolate);
    1950             :   v8::Local<v8::Boolean> t = v8::True(isolate);
    1951           6 :   CHECK(t->Value());
    1952             :   v8::Local<v8::Boolean> f = v8::False(isolate);
    1953           6 :   CHECK(!f->Value());
    1954             :   v8::Local<v8::Primitive> u = v8::Undefined(isolate);
    1955           6 :   CHECK(!u->BooleanValue(isolate));
    1956             :   v8::Local<v8::Primitive> n = v8::Null(isolate);
    1957           6 :   CHECK(!n->BooleanValue(isolate));
    1958           6 :   v8::Local<String> str1 = v8_str("");
    1959           6 :   CHECK(!str1->BooleanValue(isolate));
    1960           6 :   v8::Local<String> str2 = v8_str("x");
    1961           6 :   CHECK(str2->BooleanValue(isolate));
    1962          12 :   CHECK(!v8::Number::New(isolate, 0)->BooleanValue(isolate));
    1963          12 :   CHECK(v8::Number::New(isolate, -1)->BooleanValue(isolate));
    1964          12 :   CHECK(v8::Number::New(isolate, 1)->BooleanValue(isolate));
    1965          12 :   CHECK(v8::Number::New(isolate, 42)->BooleanValue(isolate));
    1966          12 :   CHECK(!v8_compile("NaN")
    1967             :              ->Run(env.local())
    1968             :              .ToLocalChecked()
    1969             :              ->BooleanValue(isolate));
    1970           6 : }
    1971             : 
    1972             : 
    1973           6 : static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1974           6 :   ApiTestFuzzer::Fuzz();
    1975           6 :   args.GetReturnValue().Set(v8_num(13.4));
    1976           6 : }
    1977             : 
    1978             : 
    1979           6 : static void GetM(Local<String> name,
    1980             :                  const v8::PropertyCallbackInfo<v8::Value>& info) {
    1981           6 :   ApiTestFuzzer::Fuzz();
    1982           6 :   info.GetReturnValue().Set(v8_num(876));
    1983           6 : }
    1984             : 
    1985             : 
    1986       26645 : THREADED_TEST(GlobalPrototype) {
    1987           6 :   v8::Isolate* isolate = CcTest::isolate();
    1988          12 :   v8::HandleScope scope(isolate);
    1989             :   v8::Local<v8::FunctionTemplate> func_templ =
    1990           6 :       v8::FunctionTemplate::New(isolate);
    1991          12 :   func_templ->PrototypeTemplate()->Set(
    1992             :       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
    1993           6 :   v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
    1994           6 :   templ->Set(isolate, "x", v8_num(200));
    1995           6 :   templ->SetAccessor(v8_str("m"), GetM);
    1996           6 :   LocalContext env(nullptr, templ);
    1997             :   v8::Local<Script> script(v8_compile("dummy()"));
    1998           6 :   v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
    1999          12 :   CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
    2000           6 :   CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
    2001           6 :   CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
    2002           6 : }
    2003             : 
    2004             : 
    2005       26645 : THREADED_TEST(ObjectTemplate) {
    2006           6 :   LocalContext env;
    2007           6 :   v8::Isolate* isolate = CcTest::isolate();
    2008          12 :   v8::HandleScope scope(isolate);
    2009             :   Local<v8::FunctionTemplate> acc =
    2010           6 :       v8::FunctionTemplate::New(isolate, Returns42);
    2011          30 :   CHECK(env->Global()
    2012             :             ->Set(env.local(), v8_str("acc"),
    2013             :                   acc->GetFunction(env.local()).ToLocalChecked())
    2014             :             .FromJust());
    2015             : 
    2016           6 :   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
    2017           6 :   v8::Local<v8::String> class_name = v8_str("the_class_name");
    2018           6 :   fun->SetClassName(class_name);
    2019           6 :   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
    2020           6 :   templ1->Set(isolate, "x", v8_num(10));
    2021           6 :   templ1->Set(isolate, "y", v8_num(13));
    2022          12 :   templ1->Set(v8_str("foo"), acc);
    2023             :   Local<v8::Object> instance1 =
    2024           6 :       templ1->NewInstance(env.local()).ToLocalChecked();
    2025          12 :   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
    2026          24 :   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
    2027           6 :   CHECK(CompileRun("(p.x == 10)")->BooleanValue(isolate));
    2028           6 :   CHECK(CompileRun("(p.y == 13)")->BooleanValue(isolate));
    2029           6 :   CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(isolate));
    2030           6 :   CHECK(CompileRun("(p.foo == acc)")->BooleanValue(isolate));
    2031             :   // Ensure that foo become a data field.
    2032             :   CompileRun("p.foo = function() {}");
    2033           6 :   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
    2034          12 :   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
    2035           6 :   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
    2036           6 :   templ2->Set(isolate, "a", v8_num(12));
    2037             :   templ2->Set(isolate, "b", templ1);
    2038          12 :   templ2->Set(v8_str("bar"), acc);
    2039          12 :   templ2->SetAccessorProperty(v8_str("acc"), acc);
    2040             :   Local<v8::Object> instance2 =
    2041           6 :       templ2->NewInstance(env.local()).ToLocalChecked();
    2042          24 :   CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
    2043           6 :   CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(isolate));
    2044           6 :   CHECK(CompileRun("(q.a == 12)")->BooleanValue(isolate));
    2045           6 :   CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(isolate));
    2046           6 :   CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(isolate));
    2047           6 :   CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(isolate));
    2048           6 :   CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(isolate));
    2049           6 :   CHECK(CompileRun("(q.b !== p)")->BooleanValue(isolate));
    2050           6 :   CHECK(CompileRun("(q.acc == 42)")->BooleanValue(isolate));
    2051           6 :   CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(isolate));
    2052           6 :   CHECK(CompileRun("(q.bar == acc)")->BooleanValue(isolate));
    2053             : 
    2054           6 :   instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
    2055          24 :   CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
    2056           6 :   CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(isolate));
    2057           6 :   CHECK(CompileRun("(q2.a == 12)")->BooleanValue(isolate));
    2058           6 :   CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(isolate));
    2059           6 :   CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(isolate));
    2060           6 :   CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(isolate));
    2061           6 :   CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(isolate));
    2062           6 :   CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(isolate));
    2063           6 :   CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(isolate));
    2064           6 :   CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(isolate));
    2065             : 
    2066           6 :   CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(isolate));
    2067           6 :   CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")->BooleanValue(isolate));
    2068           6 :   CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
    2069             :                    "(desc1.get === acc)")
    2070             :             ->BooleanValue(isolate));
    2071           6 :   CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
    2072             :                    "(desc2.get === acc)")
    2073             :             ->BooleanValue(isolate));
    2074           6 : }
    2075             : 
    2076       26645 : THREADED_TEST(IntegerValue) {
    2077           6 :   LocalContext env;
    2078           6 :   v8::Isolate* isolate = CcTest::isolate();
    2079          12 :   v8::HandleScope scope(isolate);
    2080             : 
    2081          12 :   CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
    2082           6 : }
    2083             : 
    2084         126 : static void GetNirk(Local<String> name,
    2085             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2086         126 :   ApiTestFuzzer::Fuzz();
    2087         126 :   info.GetReturnValue().Set(v8_num(900));
    2088         126 : }
    2089             : 
    2090         126 : static void GetRino(Local<String> name,
    2091             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2092         126 :   ApiTestFuzzer::Fuzz();
    2093         126 :   info.GetReturnValue().Set(v8_num(560));
    2094         126 : }
    2095             : 
    2096             : enum ObjectInstantiationMode {
    2097             :   // Create object using ObjectTemplate::NewInstance.
    2098             :   ObjectTemplate_NewInstance,
    2099             :   // Create object using FunctionTemplate::NewInstance on constructor.
    2100             :   Constructor_GetFunction_NewInstance,
    2101             :   // Create object using new operator on constructor.
    2102             :   Constructor_GetFunction_New
    2103             : };
    2104             : 
    2105             : // Test object instance creation using a function template with an instance
    2106             : // template inherited from another function template with accessors and data
    2107             : // properties in prototype template.
    2108          18 : static void TestObjectTemplateInheritedWithPrototype(
    2109             :     ObjectInstantiationMode mode) {
    2110          18 :   LocalContext env;
    2111          18 :   v8::Isolate* isolate = CcTest::isolate();
    2112          36 :   v8::HandleScope scope(isolate);
    2113             : 
    2114          18 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2115          18 :   fun_A->SetClassName(v8_str("A"));
    2116          18 :   v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
    2117          18 :   prototype_templ->Set(isolate, "a", v8_num(113));
    2118          18 :   prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2119          18 :   prototype_templ->Set(isolate, "b", v8_num(153));
    2120             : 
    2121          18 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2122          18 :   v8::Local<v8::String> class_name = v8_str("B");
    2123          18 :   fun_B->SetClassName(class_name);
    2124          18 :   fun_B->Inherit(fun_A);
    2125          18 :   prototype_templ = fun_B->PrototypeTemplate();
    2126          18 :   prototype_templ->Set(isolate, "c", v8_num(713));
    2127          18 :   prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
    2128          18 :   prototype_templ->Set(isolate, "d", v8_num(753));
    2129             : 
    2130          18 :   Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
    2131          18 :   templ->Set(isolate, "x", v8_num(10));
    2132          18 :   templ->Set(isolate, "y", v8_num(13));
    2133             : 
    2134             :   // Perform several iterations to trigger creation from cached boilerplate.
    2135         126 :   for (int i = 0; i < 3; i++) {
    2136             :     Local<v8::Object> instance;
    2137          54 :     switch (mode) {
    2138             :       case ObjectTemplate_NewInstance:
    2139          18 :         instance = templ->NewInstance(env.local()).ToLocalChecked();
    2140             :         break;
    2141             : 
    2142             :       case Constructor_GetFunction_NewInstance: {
    2143             :         Local<v8::Function> function_B =
    2144          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2145             :         instance = function_B->NewInstance(env.local()).ToLocalChecked();
    2146             :         break;
    2147             :       }
    2148             :       case Constructor_GetFunction_New: {
    2149             :         Local<v8::Function> function_B =
    2150          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2151          18 :         if (i == 0) {
    2152          18 :           CHECK(env->Global()
    2153             :                     ->Set(env.local(), class_name, function_B)
    2154             :                     .FromJust());
    2155             :         }
    2156             :         instance =
    2157          18 :             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
    2158             :         break;
    2159             :       }
    2160             :       default:
    2161           0 :         UNREACHABLE();
    2162             :     }
    2163             : 
    2164         108 :     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
    2165         216 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2166             : 
    2167         108 :     CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
    2168         108 :     CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
    2169             : 
    2170         108 :     CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
    2171         108 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2172         108 :     CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
    2173         108 :     CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
    2174         108 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2175         108 :     CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
    2176             :   }
    2177          18 : }
    2178             : 
    2179       26645 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
    2180           6 :   TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
    2181           6 : }
    2182             : 
    2183       26645 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
    2184           6 :   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
    2185           6 : }
    2186             : 
    2187       26645 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
    2188           6 :   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
    2189           6 : }
    2190             : 
    2191             : // Test object instance creation using a function template without an instance
    2192             : // template inherited from another function template.
    2193          12 : static void TestObjectTemplateInheritedWithoutInstanceTemplate(
    2194             :     ObjectInstantiationMode mode) {
    2195          12 :   LocalContext env;
    2196          12 :   v8::Isolate* isolate = CcTest::isolate();
    2197          24 :   v8::HandleScope scope(isolate);
    2198             : 
    2199          12 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2200          12 :   fun_A->SetClassName(v8_str("A"));
    2201             : 
    2202          12 :   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
    2203          12 :   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2204          12 :   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
    2205             : 
    2206          12 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2207          12 :   v8::Local<v8::String> class_name = v8_str("B");
    2208          12 :   fun_B->SetClassName(class_name);
    2209          12 :   fun_B->Inherit(fun_A);
    2210             : 
    2211             :   // Perform several iterations to trigger creation from cached boilerplate.
    2212          84 :   for (int i = 0; i < 3; i++) {
    2213             :     Local<v8::Object> instance;
    2214          36 :     switch (mode) {
    2215             :       case Constructor_GetFunction_NewInstance: {
    2216             :         Local<v8::Function> function_B =
    2217          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2218             :         instance = function_B->NewInstance(env.local()).ToLocalChecked();
    2219             :         break;
    2220             :       }
    2221             :       case Constructor_GetFunction_New: {
    2222             :         Local<v8::Function> function_B =
    2223          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2224          18 :         if (i == 0) {
    2225          18 :           CHECK(env->Global()
    2226             :                     ->Set(env.local(), class_name, function_B)
    2227             :                     .FromJust());
    2228             :         }
    2229             :         instance =
    2230          18 :             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
    2231             :         break;
    2232             :       }
    2233             :       default:
    2234           0 :         UNREACHABLE();
    2235             :     }
    2236             : 
    2237          72 :     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
    2238         144 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2239             : 
    2240          72 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2241          72 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2242             :   }
    2243          12 : }
    2244             : 
    2245       26645 : THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
    2246             :   TestObjectTemplateInheritedWithoutInstanceTemplate(
    2247           6 :       Constructor_GetFunction_NewInstance);
    2248           6 : }
    2249             : 
    2250       26645 : THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
    2251             :   TestObjectTemplateInheritedWithoutInstanceTemplate(
    2252           6 :       Constructor_GetFunction_New);
    2253           6 : }
    2254             : 
    2255       26645 : THREADED_TEST(TestObjectTemplateClassInheritance) {
    2256           6 :   LocalContext env;
    2257           6 :   v8::Isolate* isolate = CcTest::isolate();
    2258          12 :   v8::HandleScope scope(isolate);
    2259             : 
    2260           6 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2261           6 :   fun_A->SetClassName(v8_str("A"));
    2262             : 
    2263           6 :   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
    2264           6 :   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2265           6 :   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
    2266             : 
    2267           6 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2268           6 :   v8::Local<v8::String> class_name = v8_str("B");
    2269           6 :   fun_B->SetClassName(class_name);
    2270           6 :   fun_B->Inherit(fun_A);
    2271             : 
    2272           6 :   v8::Local<v8::String> subclass_name = v8_str("C");
    2273             :   v8::Local<v8::Object> b_proto;
    2274             :   v8::Local<v8::Object> c_proto;
    2275             :   // Perform several iterations to make sure the cache doesn't break
    2276             :   // subclassing.
    2277          42 :   for (int i = 0; i < 3; i++) {
    2278             :     Local<v8::Function> function_B =
    2279          18 :         fun_B->GetFunction(env.local()).ToLocalChecked();
    2280          18 :     if (i == 0) {
    2281          18 :       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
    2282             :       CompileRun("class C extends B {}");
    2283             :       b_proto =
    2284           6 :           CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked();
    2285             :       c_proto =
    2286           6 :           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
    2287          18 :       CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust());
    2288             :     }
    2289             :     Local<v8::Object> instance =
    2290          18 :         CompileRun("new C()")->ToObject(env.local()).ToLocalChecked();
    2291          54 :     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
    2292             : 
    2293          36 :     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
    2294          72 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2295             : 
    2296          36 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2297          36 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2298             :   }
    2299           6 : }
    2300             : 
    2301         276 : static void NamedPropertyGetterWhichReturns42(
    2302             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2303         276 :   info.GetReturnValue().Set(v8_num(42));
    2304         276 : }
    2305             : 
    2306       26645 : THREADED_TEST(TestObjectTemplateReflectConstruct) {
    2307           6 :   LocalContext env;
    2308           6 :   v8::Isolate* isolate = CcTest::isolate();
    2309          12 :   v8::HandleScope scope(isolate);
    2310             : 
    2311           6 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2312          12 :   fun_B->InstanceTemplate()->SetHandler(
    2313           6 :       v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42));
    2314           6 :   v8::Local<v8::String> class_name = v8_str("B");
    2315           6 :   fun_B->SetClassName(class_name);
    2316             : 
    2317           6 :   v8::Local<v8::String> subclass_name = v8_str("C");
    2318             :   v8::Local<v8::Object> b_proto;
    2319             :   v8::Local<v8::Object> c_proto;
    2320             :   // Perform several iterations to make sure the cache doesn't break
    2321             :   // subclassing.
    2322          42 :   for (int i = 0; i < 3; i++) {
    2323             :     Local<v8::Function> function_B =
    2324          18 :         fun_B->GetFunction(env.local()).ToLocalChecked();
    2325          18 :     if (i == 0) {
    2326          18 :       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
    2327             :       CompileRun("function C() {}");
    2328             :       c_proto =
    2329           6 :           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
    2330             :     }
    2331             :     Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)")
    2332          18 :                                      ->ToObject(env.local())
    2333             :                                      .ToLocalChecked();
    2334          54 :     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
    2335             : 
    2336          36 :     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
    2337          72 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2338             : 
    2339          36 :     CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2340          36 :     CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2341             :   }
    2342           6 : }
    2343             : 
    2344          12 : static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
    2345          12 :   ApiTestFuzzer::Fuzz();
    2346          12 :   args.GetReturnValue().Set(v8_num(17.2));
    2347          12 : }
    2348             : 
    2349             : 
    2350          30 : static void GetKnurd(Local<String> property,
    2351             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
    2352          30 :   ApiTestFuzzer::Fuzz();
    2353          30 :   info.GetReturnValue().Set(v8_num(15.2));
    2354          30 : }
    2355             : 
    2356             : 
    2357       26645 : THREADED_TEST(DescriptorInheritance) {
    2358           6 :   v8::Isolate* isolate = CcTest::isolate();
    2359          12 :   v8::HandleScope scope(isolate);
    2360           6 :   v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
    2361          12 :   super->PrototypeTemplate()->Set(isolate, "flabby",
    2362             :                                   v8::FunctionTemplate::New(isolate,
    2363             :                                                             GetFlabby));
    2364          12 :   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
    2365             : 
    2366          12 :   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
    2367             : 
    2368           6 :   v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
    2369           6 :   base1->Inherit(super);
    2370          12 :   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
    2371             : 
    2372           6 :   v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
    2373           6 :   base2->Inherit(super);
    2374          12 :   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
    2375             : 
    2376           6 :   LocalContext env;
    2377             : 
    2378          30 :   CHECK(env->Global()
    2379             :             ->Set(env.local(), v8_str("s"),
    2380             :                   super->GetFunction(env.local()).ToLocalChecked())
    2381             :             .FromJust());
    2382          30 :   CHECK(env->Global()
    2383             :             ->Set(env.local(), v8_str("base1"),
    2384             :                   base1->GetFunction(env.local()).ToLocalChecked())
    2385             :             .FromJust());
    2386          30 :   CHECK(env->Global()
    2387             :             ->Set(env.local(), v8_str("base2"),
    2388             :                   base2->GetFunction(env.local()).ToLocalChecked())
    2389             :             .FromJust());
    2390             : 
    2391             :   // Checks right __proto__ chain.
    2392           6 :   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
    2393             :             ->BooleanValue(isolate));
    2394           6 :   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
    2395             :             ->BooleanValue(isolate));
    2396             : 
    2397          12 :   CHECK(v8_compile("s.prototype.PI == 3.14")
    2398             :             ->Run(env.local())
    2399             :             .ToLocalChecked()
    2400             :             ->BooleanValue(isolate));
    2401             : 
    2402             :   // Instance accessor should not be visible on function object or its prototype
    2403           6 :   CHECK(CompileRun("s.knurd == undefined")->BooleanValue(isolate));
    2404           6 :   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue(isolate));
    2405           6 :   CHECK(
    2406             :       CompileRun("base1.prototype.knurd == undefined")->BooleanValue(isolate));
    2407             : 
    2408          30 :   CHECK(env->Global()
    2409             :             ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
    2410             :                                                   .ToLocalChecked()
    2411             :                                                   ->NewInstance(env.local())
    2412             :                                                   .ToLocalChecked())
    2413             :             .FromJust());
    2414          12 :   CHECK_EQ(17.2,
    2415             :            CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
    2416           6 :   CHECK(CompileRun("'flabby' in obj")->BooleanValue(isolate));
    2417          12 :   CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
    2418           6 :   CHECK(CompileRun("'knurd' in obj")->BooleanValue(isolate));
    2419          12 :   CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
    2420             : 
    2421          30 :   CHECK(env->Global()
    2422             :             ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
    2423             :                                                    .ToLocalChecked()
    2424             :                                                    ->NewInstance(env.local())
    2425             :                                                    .ToLocalChecked())
    2426             :             .FromJust());
    2427          12 :   CHECK_EQ(17.2,
    2428             :            CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
    2429           6 :   CHECK(CompileRun("'flabby' in obj2")->BooleanValue(isolate));
    2430          12 :   CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
    2431           6 :   CHECK(CompileRun("'knurd' in obj2")->BooleanValue(isolate));
    2432          12 :   CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
    2433             : 
    2434             :   // base1 and base2 cannot cross reference to each's prototype
    2435           6 :   CHECK(CompileRun("obj.v2")->IsUndefined());
    2436           6 :   CHECK(CompileRun("obj2.v1")->IsUndefined());
    2437           6 : }
    2438             : 
    2439       26645 : THREADED_TEST(DescriptorInheritance2) {
    2440           6 :   LocalContext env;
    2441           6 :   v8::Isolate* isolate = CcTest::isolate();
    2442          12 :   v8::HandleScope scope(isolate);
    2443           6 :   v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2444           6 :   fun_A->SetClassName(v8_str("A"));
    2445          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
    2446          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
    2447          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
    2448             : 
    2449           6 :   v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2450           6 :   fun_B->SetClassName(v8_str("B"));
    2451           6 :   fun_B->Inherit(fun_A);
    2452             : 
    2453           6 :   v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
    2454           6 :   fun_C->SetClassName(v8_str("C"));
    2455           6 :   fun_C->Inherit(fun_B);
    2456          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
    2457          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
    2458          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
    2459             : 
    2460           6 :   v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
    2461           6 :   fun_D->SetClassName(v8_str("D"));
    2462           6 :   fun_D->Inherit(fun_C);
    2463             : 
    2464           6 :   v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
    2465           6 :   fun_E->SetClassName(v8_str("E"));
    2466           6 :   fun_E->Inherit(fun_D);
    2467          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
    2468          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
    2469          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
    2470             : 
    2471           6 :   v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
    2472           6 :   fun_F->SetClassName(v8_str("F"));
    2473           6 :   fun_F->Inherit(fun_E);
    2474           6 :   v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
    2475             :   const int kDataPropertiesNumber = 100;
    2476        1206 :   for (int i = 0; i < kDataPropertiesNumber; i++) {
    2477         600 :     v8::Local<v8::Value> val = v8_num(i);
    2478         600 :     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
    2479         600 :     v8::Local<v8::String> name = String::Concat(isolate, v8_str("p"), val_str);
    2480             : 
    2481         600 :     templ->Set(name, val);
    2482         600 :     templ->Set(val_str, val);
    2483             :   }
    2484             : 
    2485          30 :   CHECK(env->Global()
    2486             :             ->Set(env.local(), v8_str("F"),
    2487             :                   fun_F->GetFunction(env.local()).ToLocalChecked())
    2488             :             .FromJust());
    2489             : 
    2490             :   v8::Local<v8::Script> script = v8_compile("o = new F()");
    2491             : 
    2492        1206 :   for (int i = 0; i < 100; i++) {
    2493        1200 :     v8::HandleScope scope(isolate);
    2494         600 :     script->Run(env.local()).ToLocalChecked();
    2495             :   }
    2496           6 :   v8::Local<v8::Object> object = script->Run(env.local())
    2497             :                                      .ToLocalChecked()
    2498           6 :                                      ->ToObject(env.local())
    2499             :                                      .ToLocalChecked();
    2500             : 
    2501          12 :   CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
    2502          12 :   CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
    2503          12 :   CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
    2504             : 
    2505          12 :   CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
    2506          12 :   CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
    2507          12 :   CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
    2508             : 
    2509          12 :   CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
    2510          12 :   CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
    2511          12 :   CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
    2512             : 
    2513        1206 :   for (int i = 0; i < kDataPropertiesNumber; i++) {
    2514         600 :     v8::Local<v8::Value> val = v8_num(i);
    2515        1200 :     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
    2516         600 :     v8::Local<v8::String> name = String::Concat(isolate, v8_str("p"), val_str);
    2517             : 
    2518        1800 :     CHECK_EQ(i, object->Get(env.local(), name)
    2519             :                     .ToLocalChecked()
    2520             :                     ->IntegerValue(env.local())
    2521             :                     .FromJust());
    2522        1800 :     CHECK_EQ(i, object->Get(env.local(), val)
    2523             :                     .ToLocalChecked()
    2524             :                     ->IntegerValue(env.local())
    2525             :                     .FromJust());
    2526             :   }
    2527           6 : }
    2528             : 
    2529             : 
    2530             : // Helper functions for Interceptor/Accessor interaction tests
    2531             : 
    2532          36 : void SimpleAccessorGetter(Local<String> name,
    2533             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    2534             :   Local<Object> self = Local<Object>::Cast(info.This());
    2535             :   info.GetReturnValue().Set(
    2536          36 :       self->Get(info.GetIsolate()->GetCurrentContext(),
    2537         144 :                 String::Concat(info.GetIsolate(), v8_str("accessor_"), name))
    2538             :           .ToLocalChecked());
    2539          36 : }
    2540             : 
    2541           6 : void SimpleAccessorSetter(Local<String> name, Local<Value> value,
    2542             :                           const v8::PropertyCallbackInfo<void>& info) {
    2543             :   Local<Object> self = Local<Object>::Cast(info.This());
    2544          24 :   CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
    2545             :                   String::Concat(info.GetIsolate(), v8_str("accessor_"), name),
    2546             :                   value)
    2547             :             .FromJust());
    2548           6 : }
    2549             : 
    2550          36 : void SymbolAccessorGetter(Local<Name> name,
    2551             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    2552          36 :   CHECK(name->IsSymbol());
    2553             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2554          72 :   if (sym->Name()->IsUndefined())
    2555             :     return;
    2556          36 :   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
    2557             : }
    2558             : 
    2559           6 : void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
    2560             :                           const v8::PropertyCallbackInfo<void>& info) {
    2561           6 :   CHECK(name->IsSymbol());
    2562             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2563          12 :   if (sym->Name()->IsUndefined())
    2564             :     return;
    2565           6 :   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
    2566             : }
    2567             : 
    2568           5 : void SymbolAccessorGetterReturnsDefault(
    2569             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2570           5 :   CHECK(name->IsSymbol());
    2571             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2572          10 :   if (sym->Name()->IsUndefined()) return;
    2573             :   info.GetReturnValue().Set(info.Data());
    2574             : }
    2575             : 
    2576           5 : static void ThrowingSymbolAccessorGetter(
    2577             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2578          10 :   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
    2579           5 : }
    2580             : 
    2581             : 
    2582       26645 : THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
    2583           6 :   v8::Isolate* isolate = CcTest::isolate();
    2584          12 :   v8::HandleScope scope(isolate);
    2585           6 :   LocalContext env;
    2586             :   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
    2587             :   i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
    2588           6 :   CHECK_EQ(1, a->map()->instance_descriptors()->number_of_descriptors());
    2589             :   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
    2590           6 :   CHECK_EQ(0, a->map()->instance_descriptors()->number_of_descriptors());
    2591             :   // But we should still have an AccessorInfo.
    2592          12 :   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
    2593             :   i::LookupIterator it(CcTest::i_isolate(), a, name,
    2594           6 :                        i::LookupIterator::OWN_SKIP_INTERCEPTOR);
    2595           6 :   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
    2596          12 :   CHECK(it.GetAccessors()->IsAccessorInfo());
    2597           6 : }
    2598             : 
    2599             : 
    2600       26645 : THREADED_TEST(UndefinedIsNotEnumerable) {
    2601           6 :   LocalContext env;
    2602          12 :   v8::HandleScope scope(env->GetIsolate());
    2603             :   v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
    2604           6 :   CHECK(result->IsFalse());
    2605           6 : }
    2606             : 
    2607             : 
    2608             : v8::Local<Script> call_recursively_script;
    2609             : static const int kTargetRecursionDepth = 100;  // near maximum
    2610             : 
    2611         606 : static void CallScriptRecursivelyCall(
    2612             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2613         606 :   ApiTestFuzzer::Fuzz();
    2614         606 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    2615             :   int depth = args.This()
    2616        1818 :                   ->Get(context, v8_str("depth"))
    2617             :                   .ToLocalChecked()
    2618        1212 :                   ->Int32Value(context)
    2619             :                   .FromJust();
    2620         612 :   if (depth == kTargetRecursionDepth) return;
    2621        3000 :   CHECK(args.This()
    2622             :             ->Set(context, v8_str("depth"),
    2623             :                   v8::Integer::New(args.GetIsolate(), depth + 1))
    2624             :             .FromJust());
    2625             :   args.GetReturnValue().Set(
    2626         600 :       call_recursively_script->Run(context).ToLocalChecked());
    2627             : }
    2628             : 
    2629             : 
    2630         606 : static void CallFunctionRecursivelyCall(
    2631             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2632         606 :   ApiTestFuzzer::Fuzz();
    2633         606 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    2634             :   int depth = args.This()
    2635        1818 :                   ->Get(context, v8_str("depth"))
    2636             :                   .ToLocalChecked()
    2637        1212 :                   ->Int32Value(context)
    2638             :                   .FromJust();
    2639         606 :   if (depth == kTargetRecursionDepth) {
    2640             :     printf("[depth = %d]\n", depth);
    2641           6 :     return;
    2642             :   }
    2643        3000 :   CHECK(args.This()
    2644             :             ->Set(context, v8_str("depth"),
    2645             :                   v8::Integer::New(args.GetIsolate(), depth + 1))
    2646             :             .FromJust());
    2647             :   v8::Local<Value> function =
    2648             :       args.This()
    2649        1800 :           ->Get(context, v8_str("callFunctionRecursively"))
    2650             :           .ToLocalChecked();
    2651             :   args.GetReturnValue().Set(function.As<Function>()
    2652        1200 :                                 ->Call(context, args.This(), 0, nullptr)
    2653             :                                 .ToLocalChecked());
    2654             : }
    2655             : 
    2656             : 
    2657       26645 : THREADED_TEST(DeepCrossLanguageRecursion) {
    2658           6 :   v8::Isolate* isolate = CcTest::isolate();
    2659          12 :   v8::HandleScope scope(isolate);
    2660           6 :   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
    2661          18 :   global->Set(v8_str("callScriptRecursively"),
    2662           6 :               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
    2663          18 :   global->Set(v8_str("callFunctionRecursively"),
    2664           6 :               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
    2665           6 :   LocalContext env(nullptr, global);
    2666             : 
    2667          30 :   CHECK(env->Global()
    2668             :             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
    2669             :             .FromJust());
    2670           6 :   call_recursively_script = v8_compile("callScriptRecursively()");
    2671           6 :   call_recursively_script->Run(env.local()).ToLocalChecked();
    2672           6 :   call_recursively_script = v8::Local<Script>();
    2673             : 
    2674          30 :   CHECK(env->Global()
    2675             :             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
    2676             :             .FromJust());
    2677             :   CompileRun("callFunctionRecursively()");
    2678           6 : }
    2679             : 
    2680             : 
    2681          24 : static void ThrowingPropertyHandlerGet(
    2682             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2683             :   // Since this interceptor is used on "with" objects, the runtime will look up
    2684             :   // @@unscopables.  Punt.
    2685          24 :   if (key->IsSymbol()) return;
    2686          12 :   ApiTestFuzzer::Fuzz();
    2687          24 :   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
    2688             : }
    2689             : 
    2690             : 
    2691           0 : static void ThrowingPropertyHandlerSet(
    2692             :     Local<Name> key, Local<Value>,
    2693             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2694           0 :   info.GetIsolate()->ThrowException(key);
    2695             :   info.GetReturnValue().SetUndefined();  // not the same as empty handle
    2696           0 : }
    2697             : 
    2698             : 
    2699       26645 : THREADED_TEST(CallbackExceptionRegression) {
    2700           6 :   v8::Isolate* isolate = CcTest::isolate();
    2701          12 :   v8::HandleScope scope(isolate);
    2702           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    2703           6 :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2704           6 :       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
    2705           6 :   LocalContext env;
    2706          30 :   CHECK(env->Global()
    2707             :             ->Set(env.local(), v8_str("obj"),
    2708             :                   obj->NewInstance(env.local()).ToLocalChecked())
    2709             :             .FromJust());
    2710             :   v8::Local<Value> otto =
    2711           6 :       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
    2712          18 :   CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
    2713             :   v8::Local<Value> netto =
    2714           6 :       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
    2715          18 :   CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
    2716           6 : }
    2717             : 
    2718             : 
    2719       26645 : THREADED_TEST(FunctionPrototype) {
    2720           6 :   v8::Isolate* isolate = CcTest::isolate();
    2721          12 :   v8::HandleScope scope(isolate);
    2722           6 :   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
    2723          24 :   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
    2724           6 :   LocalContext env;
    2725          30 :   CHECK(env->Global()
    2726             :             ->Set(env.local(), v8_str("Foo"),
    2727             :                   Foo->GetFunction(env.local()).ToLocalChecked())
    2728             :             .FromJust());
    2729           6 :   Local<Script> script = v8_compile("Foo.prototype.plak");
    2730           6 :   CHECK_EQ(v8_run_int32value(script), 321);
    2731           6 : }
    2732             : 
    2733       26645 : THREADED_TEST(InternalFields) {
    2734           6 :   LocalContext env;
    2735           6 :   v8::Isolate* isolate = env->GetIsolate();
    2736          12 :   v8::HandleScope scope(isolate);
    2737             : 
    2738           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2739           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2740           6 :   instance_templ->SetInternalFieldCount(1);
    2741           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2742             :                               .ToLocalChecked()
    2743             :                               ->NewInstance(env.local())
    2744             :                               .ToLocalChecked();
    2745           6 :   CHECK_EQ(1, obj->InternalFieldCount());
    2746           6 :   CHECK(obj->GetInternalField(0)->IsUndefined());
    2747           6 :   obj->SetInternalField(0, v8_num(17));
    2748          12 :   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
    2749           6 : }
    2750             : 
    2751       26644 : TEST(InternalFieldsSubclassing) {
    2752           5 :   LocalContext env;
    2753           5 :   v8::Isolate* isolate = env->GetIsolate();
    2754             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    2755          10 :   v8::HandleScope scope(isolate);
    2756          60 :   for (int nof_embedder_fields = 0;
    2757          65 :        nof_embedder_fields < i::JSObject::kMaxEmbedderFields;
    2758             :        nof_embedder_fields++) {
    2759          60 :     Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2760          60 :     Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2761          60 :     instance_templ->SetInternalFieldCount(nof_embedder_fields);
    2762             :     Local<Function> constructor =
    2763          60 :         templ->GetFunction(env.local()).ToLocalChecked();
    2764             :     // Check that instances have the correct NOF properties.
    2765             :     Local<v8::Object> obj =
    2766             :         constructor->NewInstance(env.local()).ToLocalChecked();
    2767             : 
    2768             :     i::Handle<i::JSObject> i_obj =
    2769             :         i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj));
    2770          60 :     CHECK_EQ(nof_embedder_fields, obj->InternalFieldCount());
    2771          60 :     CHECK_EQ(0, i_obj->map()->GetInObjectProperties());
    2772             :     // Check writing and reading internal fields.
    2773         720 :     for (int j = 0; j < nof_embedder_fields; j++) {
    2774         330 :       CHECK(obj->GetInternalField(j)->IsUndefined());
    2775         330 :       int value = 17 + j;
    2776         330 :       obj->SetInternalField(j, v8_num(value));
    2777             :     }
    2778         720 :     for (int j = 0; j < nof_embedder_fields; j++) {
    2779         330 :       int value = 17 + j;
    2780         660 :       CHECK_EQ(value,
    2781             :                obj->GetInternalField(j)->Int32Value(env.local()).FromJust());
    2782             :     }
    2783         240 :     CHECK(env->Global()
    2784             :               ->Set(env.local(), v8_str("BaseClass"), constructor)
    2785             :               .FromJust());
    2786             :     // Create various levels of subclasses to stress instance size calculation.
    2787             :     const int kMaxNofProperties =
    2788             :         i::JSObject::kMaxInObjectProperties -
    2789          60 :         nof_embedder_fields * i::kEmbedderDataSlotSizeInTaggedSlots;
    2790             :     // Select only a few values to speed up the test.
    2791             :     int sizes[] = {0,
    2792             :                    1,
    2793             :                    2,
    2794             :                    3,
    2795             :                    4,
    2796             :                    5,
    2797             :                    6,
    2798          60 :                    kMaxNofProperties / 4,
    2799          60 :                    kMaxNofProperties / 2,
    2800          60 :                    kMaxNofProperties - 2,
    2801          60 :                    kMaxNofProperties - 1,
    2802          60 :                    kMaxNofProperties + 1,
    2803          60 :                    kMaxNofProperties + 2,
    2804          60 :                    kMaxNofProperties * 2,
    2805         480 :                    kMaxNofProperties * 2};
    2806        1860 :     for (size_t i = 0; i < arraysize(sizes); i++) {
    2807         900 :       int nof_properties = sizes[i];
    2808             :       bool in_object_only = nof_properties <= kMaxNofProperties;
    2809        1800 :       std::ostringstream src;
    2810             :       // Assembler source string for a subclass with {nof_properties}
    2811             :       // in-object properties.
    2812             :       src << "(function() {\n"
    2813             :           << "  class SubClass extends BaseClass {\n"
    2814             :           << "    constructor() {\n"
    2815         900 :           << "      super();\n";
    2816             :       // Set {nof_properties} instance properties in the constructor.
    2817      262170 :       for (int j = 0; j < nof_properties; j++) {
    2818      261270 :         src << "      this.property" << j << " = " << j << ";\n";
    2819             :       }
    2820             :       src << "    }\n"
    2821             :           << "  };\n"
    2822             :           << "  let instance;\n"
    2823             :           << "  for (let i = 0; i < 3; i++) {\n"
    2824             :           << "    instance = new SubClass();\n"
    2825             :           << "  }"
    2826             :           << "  return instance;\n"
    2827         900 :           << "})();";
    2828         900 :       Local<v8::Object> value = CompileRun(src.str().c_str()).As<v8::Object>();
    2829             : 
    2830             :       i::Handle<i::JSObject> i_value =
    2831             :           i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*value));
    2832             : #ifdef VERIFY_HEAP
    2833             :       i_value->HeapObjectVerify(i_isolate);
    2834             :       i_value->map()->HeapObjectVerify(i_isolate);
    2835             :       i_value->map()->FindRootMap(i_isolate)->HeapObjectVerify(i_isolate);
    2836             : #endif
    2837         900 :       CHECK_EQ(nof_embedder_fields, value->InternalFieldCount());
    2838         900 :       if (in_object_only) {
    2839         660 :         CHECK_LE(nof_properties, i_value->map()->GetInObjectProperties());
    2840             :       } else {
    2841         240 :         CHECK_LE(i_value->map()->GetInObjectProperties(), kMaxNofProperties);
    2842             :       }
    2843             : 
    2844             :       // Make Sure we get the precise property count.
    2845        1800 :       i_value->map()->FindRootMap(i_isolate)->CompleteInobjectSlackTracking(
    2846         900 :           i_isolate);
    2847             :       // TODO(cbruni): fix accounting to make this condition true.
    2848             :       // CHECK_EQ(0, i_value->map()->UnusedPropertyFields());
    2849         900 :       if (in_object_only) {
    2850         660 :         CHECK_EQ(nof_properties, i_value->map()->GetInObjectProperties());
    2851             :       } else {
    2852         240 :         CHECK_LE(i_value->map()->GetInObjectProperties(), kMaxNofProperties);
    2853             :       }
    2854             :     }
    2855             :   }
    2856           5 : }
    2857             : 
    2858       26645 : THREADED_TEST(InternalFieldsOfRegularObjects) {
    2859           6 :   LocalContext env;
    2860           6 :   v8::Isolate* isolate = env->GetIsolate();
    2861          12 :   v8::HandleScope scope(isolate);
    2862             : 
    2863           6 :   const char* sources[] = {"new Object()", "{ a: 'a property' }", "arguments"};
    2864          42 :   for (size_t i = 0; i < arraysize(sources); ++i) {
    2865             :     i::ScopedVector<char> source(128);
    2866          18 :     i::SNPrintF(source, "(function() { return %s })()", sources[i]);
    2867             :     v8::Local<v8::Object> obj = CompileRun(source.start()).As<v8::Object>();
    2868          18 :     CHECK_EQ(0, obj->InternalFieldCount());
    2869             :   }
    2870           6 : }
    2871             : 
    2872       26645 : THREADED_TEST(GlobalObjectInternalFields) {
    2873           6 :   v8::Isolate* isolate = CcTest::isolate();
    2874          12 :   v8::HandleScope scope(isolate);
    2875           6 :   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
    2876           6 :   global_template->SetInternalFieldCount(1);
    2877           6 :   LocalContext env(nullptr, global_template);
    2878           6 :   v8::Local<v8::Object> global_proxy = env->Global();
    2879           6 :   v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
    2880           6 :   CHECK_EQ(1, global->InternalFieldCount());
    2881           6 :   CHECK(global->GetInternalField(0)->IsUndefined());
    2882           6 :   global->SetInternalField(0, v8_num(17));
    2883          12 :   CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
    2884           6 : }
    2885             : 
    2886             : 
    2887       26645 : THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
    2888           6 :   LocalContext env;
    2889          12 :   v8::HandleScope scope(CcTest::isolate());
    2890             : 
    2891           6 :   v8::Local<v8::Object> global = env->Global();
    2892          18 :   CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
    2893          12 :   CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
    2894           6 : }
    2895             : 
    2896          24 : static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
    2897             :                                                void* value) {
    2898          24 :   CHECK(HAS_SMI_TAG(reinterpret_cast<i::Address>(value)));
    2899          24 :   obj->SetAlignedPointerInInternalField(0, value);
    2900          24 :   CcTest::CollectAllGarbage();
    2901          24 :   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
    2902          24 : }
    2903             : 
    2904       26645 : THREADED_TEST(InternalFieldsAlignedPointers) {
    2905           6 :   LocalContext env;
    2906           6 :   v8::Isolate* isolate = env->GetIsolate();
    2907          12 :   v8::HandleScope scope(isolate);
    2908             : 
    2909           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2910           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2911           6 :   instance_templ->SetInternalFieldCount(1);
    2912           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2913             :                               .ToLocalChecked()
    2914             :                               ->NewInstance(env.local())
    2915             :                               .ToLocalChecked();
    2916           6 :   CHECK_EQ(1, obj->InternalFieldCount());
    2917             : 
    2918           6 :   CheckAlignedPointerInInternalField(obj, nullptr);
    2919             : 
    2920           6 :   int* heap_allocated = new int[100];
    2921           6 :   CheckAlignedPointerInInternalField(obj, heap_allocated);
    2922           6 :   delete[] heap_allocated;
    2923             : 
    2924             :   int stack_allocated[100];
    2925           6 :   CheckAlignedPointerInInternalField(obj, stack_allocated);
    2926             : 
    2927             :   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
    2928           6 :   CheckAlignedPointerInInternalField(obj, huge);
    2929             : 
    2930             :   v8::Global<v8::Object> persistent(isolate, obj);
    2931           6 :   CHECK_EQ(1, Object::InternalFieldCount(persistent));
    2932           6 :   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
    2933           6 : }
    2934             : 
    2935       26645 : THREADED_TEST(SetAlignedPointerInInternalFields) {
    2936           6 :   LocalContext env;
    2937           6 :   v8::Isolate* isolate = env->GetIsolate();
    2938          12 :   v8::HandleScope scope(isolate);
    2939             : 
    2940           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2941           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2942           6 :   instance_templ->SetInternalFieldCount(2);
    2943           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2944             :                               .ToLocalChecked()
    2945             :                               ->NewInstance(env.local())
    2946             :                               .ToLocalChecked();
    2947           6 :   CHECK_EQ(2, obj->InternalFieldCount());
    2948             : 
    2949           6 :   int* heap_allocated_1 = new int[100];
    2950           6 :   int* heap_allocated_2 = new int[100];
    2951           6 :   int indices[] = {0, 1};
    2952           6 :   void* values[] = {heap_allocated_1, heap_allocated_2};
    2953             : 
    2954           6 :   obj->SetAlignedPointerInInternalFields(2, indices, values);
    2955           6 :   CcTest::CollectAllGarbage();
    2956           6 :   CHECK_EQ(heap_allocated_1, obj->GetAlignedPointerFromInternalField(0));
    2957           6 :   CHECK_EQ(heap_allocated_2, obj->GetAlignedPointerFromInternalField(1));
    2958             : 
    2959           6 :   indices[0] = 1;
    2960           6 :   indices[1] = 0;
    2961           6 :   obj->SetAlignedPointerInInternalFields(2, indices, values);
    2962           6 :   CcTest::CollectAllGarbage();
    2963           6 :   CHECK_EQ(heap_allocated_2, obj->GetAlignedPointerFromInternalField(0));
    2964           6 :   CHECK_EQ(heap_allocated_1, obj->GetAlignedPointerFromInternalField(1));
    2965             : 
    2966           6 :   delete[] heap_allocated_1;
    2967           6 :   delete[] heap_allocated_2;
    2968           6 : }
    2969             : 
    2970          24 : static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
    2971             :                                               void* value) {
    2972          24 :   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
    2973          24 :   (*env)->SetAlignedPointerInEmbedderData(index, value);
    2974          24 :   CcTest::CollectAllGarbage();
    2975          24 :   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
    2976          24 : }
    2977             : 
    2978             : 
    2979             : static void* AlignedTestPointer(int i) {
    2980        1200 :   return reinterpret_cast<void*>(i * 1234);
    2981             : }
    2982             : 
    2983             : 
    2984       26645 : THREADED_TEST(EmbedderDataAlignedPointers) {
    2985           6 :   LocalContext env;
    2986          12 :   v8::HandleScope scope(env->GetIsolate());
    2987             : 
    2988           6 :   CheckAlignedPointerInEmbedderData(&env, 0, nullptr);
    2989           6 :   CHECK_EQ(1, (*env)->GetNumberOfEmbedderDataFields());
    2990             : 
    2991           6 :   int* heap_allocated = new int[100];
    2992           6 :   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
    2993           6 :   CHECK_EQ(2, (*env)->GetNumberOfEmbedderDataFields());
    2994           6 :   delete[] heap_allocated;
    2995             : 
    2996             :   int stack_allocated[100];
    2997           6 :   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
    2998           6 :   CHECK_EQ(3, (*env)->GetNumberOfEmbedderDataFields());
    2999             : 
    3000             :   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
    3001           6 :   CheckAlignedPointerInEmbedderData(&env, 3, huge);
    3002           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3003             : 
    3004             :   // Test growing of the embedder data's backing store.
    3005        1206 :   for (int i = 0; i < 100; i++) {
    3006         600 :     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
    3007             :   }
    3008           6 :   CcTest::CollectAllGarbage();
    3009        1206 :   for (int i = 0; i < 100; i++) {
    3010         600 :     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
    3011             :   }
    3012           6 : }
    3013             : 
    3014          30 : static void CheckEmbedderData(LocalContext* env, int index,
    3015             :                               v8::Local<Value> data) {
    3016          30 :   (*env)->SetEmbedderData(index, data);
    3017          30 :   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
    3018          30 : }
    3019             : 
    3020             : 
    3021       26645 : THREADED_TEST(EmbedderData) {
    3022           6 :   LocalContext env;
    3023           6 :   v8::Isolate* isolate = env->GetIsolate();
    3024          12 :   v8::HandleScope scope(isolate);
    3025             : 
    3026           6 :   CHECK_EQ(0, (*env)->GetNumberOfEmbedderDataFields());
    3027          12 :   CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
    3028           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3029          12 :   CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
    3030           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3031          12 :   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
    3032           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3033           6 :   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
    3034           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3035           6 :   CheckEmbedderData(&env, 211, v8::Boolean::New(isolate, true));
    3036           6 :   CHECK_EQ(212, (*env)->GetNumberOfEmbedderDataFields());
    3037           6 : }
    3038             : 
    3039             : 
    3040       26645 : THREADED_TEST(IdentityHash) {
    3041           6 :   LocalContext env;
    3042           6 :   v8::Isolate* isolate = env->GetIsolate();
    3043          12 :   v8::HandleScope scope(isolate);
    3044             : 
    3045             :   // Ensure that the test starts with an fresh heap to test whether the hash
    3046             :   // code is based on the address.
    3047           6 :   CcTest::CollectAllGarbage();
    3048           6 :   Local<v8::Object> obj = v8::Object::New(isolate);
    3049           6 :   int hash = obj->GetIdentityHash();
    3050           6 :   int hash1 = obj->GetIdentityHash();
    3051           6 :   CHECK_EQ(hash, hash1);
    3052          12 :   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
    3053             :   // Since the identity hash is essentially a random number two consecutive
    3054             :   // objects should not be assigned the same hash code. If the test below fails
    3055             :   // the random number generator should be evaluated.
    3056           6 :   CHECK_NE(hash, hash2);
    3057           6 :   CcTest::CollectAllGarbage();
    3058          12 :   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
    3059             :   // Make sure that the identity hash is not based on the initial address of
    3060             :   // the object alone. If the test below fails the random number generator
    3061             :   // should be evaluated.
    3062           6 :   CHECK_NE(hash, hash3);
    3063           6 :   int hash4 = obj->GetIdentityHash();
    3064           6 :   CHECK_EQ(hash, hash4);
    3065             : 
    3066             :   // Check identity hashes behaviour in the presence of JS accessors.
    3067             :   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
    3068             :   {
    3069             :     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
    3070           6 :     Local<v8::Object> o1 = v8::Object::New(isolate);
    3071           6 :     Local<v8::Object> o2 = v8::Object::New(isolate);
    3072          12 :     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
    3073             :   }
    3074             :   {
    3075             :     CompileRun(
    3076             :         "function cnst() { return 42; };\n"
    3077             :         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
    3078           6 :     Local<v8::Object> o1 = v8::Object::New(isolate);
    3079           6 :     Local<v8::Object> o2 = v8::Object::New(isolate);
    3080          12 :     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
    3081             :   }
    3082           6 : }
    3083             : 
    3084             : 
    3085          12 : void GlobalProxyIdentityHash(bool set_in_js) {
    3086          12 :   LocalContext env;
    3087          12 :   v8::Isolate* isolate = env->GetIsolate();
    3088             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    3089          24 :   v8::HandleScope scope(isolate);
    3090          12 :   Local<Object> global_proxy = env->Global();
    3091             :   i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
    3092          48 :   CHECK(env->Global()
    3093             :             ->Set(env.local(), v8_str("global"), global_proxy)
    3094             :             .FromJust());
    3095             :   int32_t hash1;
    3096          12 :   if (set_in_js) {
    3097             :     CompileRun("var m = new Set(); m.add(global);");
    3098           6 :     i::Object original_hash = i_global_proxy->GetHash();
    3099           6 :     CHECK(original_hash->IsSmi());
    3100             :     hash1 = i::Smi::ToInt(original_hash);
    3101             :   } else {
    3102          12 :     hash1 = i_global_proxy->GetOrCreateHash(i_isolate)->value();
    3103             :   }
    3104             :   // Hash should be retained after being detached.
    3105          12 :   env->DetachGlobal();
    3106          12 :   int hash2 = global_proxy->GetIdentityHash();
    3107          12 :   CHECK_EQ(hash1, hash2);
    3108             :   {
    3109             :     // Re-attach global proxy to a new context, hash should stay the same.
    3110          12 :     LocalContext env2(nullptr, Local<ObjectTemplate>(), global_proxy);
    3111          12 :     int hash3 = global_proxy->GetIdentityHash();
    3112          12 :     CHECK_EQ(hash1, hash3);
    3113             :   }
    3114          12 : }
    3115             : 
    3116             : 
    3117       26645 : THREADED_TEST(GlobalProxyIdentityHash) {
    3118           6 :   GlobalProxyIdentityHash(true);
    3119           6 :   GlobalProxyIdentityHash(false);
    3120           6 : }
    3121             : 
    3122             : 
    3123       26644 : TEST(SymbolIdentityHash) {
    3124           5 :   LocalContext env;
    3125           5 :   v8::Isolate* isolate = env->GetIsolate();
    3126          10 :   v8::HandleScope scope(isolate);
    3127             : 
    3128             :   {
    3129           5 :     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
    3130           5 :     int hash = symbol->GetIdentityHash();
    3131           5 :     int hash1 = symbol->GetIdentityHash();
    3132           5 :     CHECK_EQ(hash, hash1);
    3133           5 :     CcTest::CollectAllGarbage();
    3134           5 :     int hash3 = symbol->GetIdentityHash();
    3135           5 :     CHECK_EQ(hash, hash3);
    3136             :   }
    3137             : 
    3138             :   {
    3139             :     v8::Local<v8::Symbol> js_symbol =
    3140             :         CompileRun("Symbol('foo')").As<v8::Symbol>();
    3141           5 :     int hash = js_symbol->GetIdentityHash();
    3142           5 :     int hash1 = js_symbol->GetIdentityHash();
    3143           5 :     CHECK_EQ(hash, hash1);
    3144           5 :     CcTest::CollectAllGarbage();
    3145           5 :     int hash3 = js_symbol->GetIdentityHash();
    3146           5 :     CHECK_EQ(hash, hash3);
    3147             :   }
    3148           5 : }
    3149             : 
    3150             : 
    3151       26644 : TEST(StringIdentityHash) {
    3152           5 :   LocalContext env;
    3153           5 :   v8::Isolate* isolate = env->GetIsolate();
    3154          10 :   v8::HandleScope scope(isolate);
    3155             : 
    3156           5 :   Local<v8::String> str = v8_str("str1");
    3157           5 :   int hash = str->GetIdentityHash();
    3158           5 :   int hash1 = str->GetIdentityHash();
    3159           5 :   CHECK_EQ(hash, hash1);
    3160           5 :   CcTest::CollectAllGarbage();
    3161           5 :   int hash3 = str->GetIdentityHash();
    3162           5 :   CHECK_EQ(hash, hash3);
    3163             : 
    3164           5 :   Local<v8::String> str2 = v8_str("str1");
    3165           5 :   int hash4 = str2->GetIdentityHash();
    3166           5 :   CHECK_EQ(hash, hash4);
    3167           5 : }
    3168             : 
    3169             : 
    3170       26645 : THREADED_TEST(SymbolProperties) {
    3171           6 :   LocalContext env;
    3172           6 :   v8::Isolate* isolate = env->GetIsolate();
    3173          12 :   v8::HandleScope scope(isolate);
    3174             : 
    3175           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3176           6 :   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
    3177           6 :   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
    3178           6 :   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
    3179           6 :   v8::Local<v8::Symbol> sym4 = v8::Symbol::New(isolate, v8_str("native"));
    3180             : 
    3181           6 :   CcTest::CollectAllGarbage();
    3182             : 
    3183             :   // Check basic symbol functionality.
    3184           6 :   CHECK(sym1->IsSymbol());
    3185           6 :   CHECK(sym2->IsSymbol());
    3186           6 :   CHECK(!obj->IsSymbol());
    3187             : 
    3188          12 :   CHECK(sym1->Equals(env.local(), sym1).FromJust());
    3189          12 :   CHECK(sym2->Equals(env.local(), sym2).FromJust());
    3190          12 :   CHECK(!sym1->Equals(env.local(), sym2).FromJust());
    3191          12 :   CHECK(!sym2->Equals(env.local(), sym1).FromJust());
    3192           6 :   CHECK(sym1->StrictEquals(sym1));
    3193           6 :   CHECK(sym2->StrictEquals(sym2));
    3194           6 :   CHECK(!sym1->StrictEquals(sym2));
    3195           6 :   CHECK(!sym2->StrictEquals(sym1));
    3196             : 
    3197          24 :   CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
    3198             : 
    3199             :   v8::Local<v8::Value> sym_val = sym2;
    3200           6 :   CHECK(sym_val->IsSymbol());
    3201          12 :   CHECK(sym_val->Equals(env.local(), sym2).FromJust());
    3202           6 :   CHECK(sym_val->StrictEquals(sym2));
    3203          12 :   CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
    3204             : 
    3205           6 :   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
    3206           6 :   CHECK(sym_obj->IsSymbolObject());
    3207           6 :   CHECK(!sym2->IsSymbolObject());
    3208           6 :   CHECK(!obj->IsSymbolObject());
    3209          12 :   CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
    3210           6 :   CHECK(!sym_obj->StrictEquals(sym2));
    3211          12 :   CHECK(v8::SymbolObject::Cast(*sym_obj)
    3212             :             ->Equals(env.local(), sym_obj)
    3213             :             .FromJust());
    3214          18 :   CHECK(v8::SymbolObject::Cast(*sym_obj)
    3215             :             ->ValueOf()
    3216             :             ->Equals(env.local(), sym2)
    3217             :             .FromJust());
    3218             : 
    3219             :   // Make sure delete of a non-existent symbol property works.
    3220          12 :   CHECK(obj->Delete(env.local(), sym1).FromJust());
    3221          12 :   CHECK(!obj->Has(env.local(), sym1).FromJust());
    3222             : 
    3223          18 :   CHECK(
    3224             :       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
    3225          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3226          18 :   CHECK_EQ(1503, obj->Get(env.local(), sym1)
    3227             :                      .ToLocalChecked()
    3228             :                      ->Int32Value(env.local())
    3229             :                      .FromJust());
    3230          18 :   CHECK(
    3231             :       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
    3232          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3233          18 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3234             :                      .ToLocalChecked()
    3235             :                      ->Int32Value(env.local())
    3236             :                      .FromJust());
    3237          12 :   CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
    3238             : 
    3239          12 :   CHECK_EQ(0u,
    3240             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3241             :   unsigned num_props =
    3242          12 :       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3243          24 :   CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
    3244             :             .FromJust());
    3245          12 :   CHECK_EQ(1u,
    3246             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3247          12 :   CHECK_EQ(num_props + 1,
    3248             :            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3249             : 
    3250           6 :   CcTest::CollectAllGarbage();
    3251             : 
    3252          12 :   CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
    3253             :                          SymbolAccessorSetter)
    3254             :             .FromJust());
    3255          12 :   CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
    3256          18 :   CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
    3257          24 :   CHECK(obj->Get(env.local(), sym3)
    3258             :             .ToLocalChecked()
    3259             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3260             :             .FromJust());
    3261          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3262             :             .ToLocalChecked()
    3263             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3264             :             .FromJust());
    3265             : 
    3266          12 :   CHECK(obj->SetNativeDataProperty(env.local(), sym4, SymbolAccessorGetter)
    3267             :             .FromJust());
    3268          12 :   CHECK(obj->Get(env.local(), sym4).ToLocalChecked()->IsUndefined());
    3269          24 :   CHECK(obj->Set(env.local(), v8_str("accessor_native"),
    3270             :                  v8::Integer::New(isolate, 123))
    3271             :             .FromJust());
    3272          18 :   CHECK_EQ(123, obj->Get(env.local(), sym4)
    3273             :                     .ToLocalChecked()
    3274             :                     ->Int32Value(env.local())
    3275             :                     .FromJust());
    3276          18 :   CHECK(obj->Set(env.local(), sym4, v8::Integer::New(isolate, 314)).FromJust());
    3277          24 :   CHECK(obj->Get(env.local(), sym4)
    3278             :             .ToLocalChecked()
    3279             :             ->Equals(env.local(), v8::Integer::New(isolate, 314))
    3280             :             .FromJust());
    3281          18 :   CHECK(obj->Delete(env.local(), v8_str("accessor_native")).FromJust());
    3282             : 
    3283             :   // Add another property and delete it afterwards to force the object in
    3284             :   // slow case.
    3285          18 :   CHECK(
    3286             :       obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
    3287          18 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3288             :                      .ToLocalChecked()
    3289             :                      ->Int32Value(env.local())
    3290             :                      .FromJust());
    3291          18 :   CHECK_EQ(2008, obj->Get(env.local(), sym2)
    3292             :                      .ToLocalChecked()
    3293             :                      ->Int32Value(env.local())
    3294             :                      .FromJust());
    3295          18 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3296             :                      .ToLocalChecked()
    3297             :                      ->Int32Value(env.local())
    3298             :                      .FromJust());
    3299          12 :   CHECK_EQ(2u,
    3300             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3301             : 
    3302          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3303          12 :   CHECK(obj->Has(env.local(), sym2).FromJust());
    3304          12 :   CHECK(obj->Has(env.local(), sym3).FromJust());
    3305          18 :   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
    3306          12 :   CHECK(obj->Delete(env.local(), sym2).FromJust());
    3307          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3308          12 :   CHECK(!obj->Has(env.local(), sym2).FromJust());
    3309          12 :   CHECK(obj->Has(env.local(), sym3).FromJust());
    3310          18 :   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
    3311          18 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3312             :                      .ToLocalChecked()
    3313             :                      ->Int32Value(env.local())
    3314             :                      .FromJust());
    3315          24 :   CHECK(obj->Get(env.local(), sym3)
    3316             :             .ToLocalChecked()
    3317             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3318             :             .FromJust());
    3319          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3320             :             .ToLocalChecked()
    3321             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3322             :             .FromJust());
    3323          12 :   CHECK_EQ(2u,
    3324             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3325             : 
    3326             :   // Symbol properties are inherited.
    3327           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3328          12 :   CHECK(child->SetPrototype(env.local(), obj).FromJust());
    3329          12 :   CHECK(child->Has(env.local(), sym1).FromJust());
    3330          18 :   CHECK_EQ(2002, child->Get(env.local(), sym1)
    3331             :                      .ToLocalChecked()
    3332             :                      ->Int32Value(env.local())
    3333             :                      .FromJust());
    3334          24 :   CHECK(obj->Get(env.local(), sym3)
    3335             :             .ToLocalChecked()
    3336             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3337             :             .FromJust());
    3338          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3339             :             .ToLocalChecked()
    3340             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3341             :             .FromJust());
    3342          12 :   CHECK_EQ(0u,
    3343             :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3344           6 : }
    3345             : 
    3346             : 
    3347       26645 : THREADED_TEST(SymbolTemplateProperties) {
    3348           6 :   LocalContext env;
    3349           6 :   v8::Isolate* isolate = env->GetIsolate();
    3350          12 :   v8::HandleScope scope(isolate);
    3351           6 :   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
    3352           6 :   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
    3353           6 :   CHECK(!name.IsEmpty());
    3354          18 :   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
    3355             :   v8::Local<v8::Object> new_instance =
    3356          18 :       foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
    3357           6 :   CHECK(!new_instance.IsEmpty());
    3358          12 :   CHECK(new_instance->Has(env.local(), name).FromJust());
    3359           6 : }
    3360             : 
    3361             : 
    3362       26645 : THREADED_TEST(PrivatePropertiesOnProxies) {
    3363           6 :   LocalContext env;
    3364           6 :   v8::Isolate* isolate = env->GetIsolate();
    3365          12 :   v8::HandleScope scope(isolate);
    3366             : 
    3367           6 :   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
    3368           6 :   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
    3369             : 
    3370             :   v8::Local<v8::Proxy> proxy =
    3371           6 :       v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
    3372             : 
    3373           6 :   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
    3374             :   v8::Local<v8::Private> priv2 =
    3375           6 :       v8::Private::New(isolate, v8_str("my-private"));
    3376             : 
    3377           6 :   CcTest::CollectAllGarbage();
    3378             : 
    3379          24 :   CHECK(priv2->Name()
    3380             :             ->Equals(env.local(),
    3381             :                      v8::String::NewFromUtf8(isolate, "my-private",
    3382             :                                              v8::NewStringType::kNormal)
    3383             :                          .ToLocalChecked())
    3384             :             .FromJust());
    3385             : 
    3386             :   // Make sure delete of a non-existent private symbol property works.
    3387          12 :   proxy->DeletePrivate(env.local(), priv1).FromJust();
    3388          12 :   CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
    3389             : 
    3390          18 :   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
    3391             :             .FromJust());
    3392          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3393          18 :   CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
    3394             :                      .ToLocalChecked()
    3395             :                      ->Int32Value(env.local())
    3396             :                      .FromJust());
    3397          18 :   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
    3398             :             .FromJust());
    3399          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3400          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3401             :                      .ToLocalChecked()
    3402             :                      ->Int32Value(env.local())
    3403             :                      .FromJust());
    3404             : 
    3405          12 :   CHECK_EQ(0u,
    3406             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3407             :   unsigned num_props =
    3408          12 :       proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3409          24 :   CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
    3410             :                                     isolate, "bla", v8::NewStringType::kNormal)
    3411             :                                     .ToLocalChecked(),
    3412             :                    v8::Integer::New(isolate, 20))
    3413             :             .FromJust());
    3414          12 :   CHECK_EQ(1u,
    3415             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3416          12 :   CHECK_EQ(num_props + 1,
    3417             :            proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3418             : 
    3419           6 :   CcTest::CollectAllGarbage();
    3420             : 
    3421             :   // Add another property and delete it afterwards to force the object in
    3422             :   // slow case.
    3423          18 :   CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
    3424             :             .FromJust());
    3425          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3426             :                      .ToLocalChecked()
    3427             :                      ->Int32Value(env.local())
    3428             :                      .FromJust());
    3429          18 :   CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
    3430             :                      .ToLocalChecked()
    3431             :                      ->Int32Value(env.local())
    3432             :                      .FromJust());
    3433          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3434             :                      .ToLocalChecked()
    3435             :                      ->Int32Value(env.local())
    3436             :                      .FromJust());
    3437          12 :   CHECK_EQ(1u,
    3438             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3439             : 
    3440          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3441          12 :   CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
    3442          12 :   CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
    3443          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3444          12 :   CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
    3445          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3446             :                      .ToLocalChecked()
    3447             :                      ->Int32Value(env.local())
    3448             :                      .FromJust());
    3449          12 :   CHECK_EQ(1u,
    3450             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3451             : 
    3452             :   // Private properties are not inherited (for the time being).
    3453           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3454          12 :   CHECK(child->SetPrototype(env.local(), proxy).FromJust());
    3455          12 :   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
    3456          12 :   CHECK_EQ(0u,
    3457             :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3458           6 : }
    3459             : 
    3460             : 
    3461       26645 : THREADED_TEST(PrivateProperties) {
    3462           6 :   LocalContext env;
    3463           6 :   v8::Isolate* isolate = env->GetIsolate();
    3464          12 :   v8::HandleScope scope(isolate);
    3465             : 
    3466           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3467           6 :   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
    3468             :   v8::Local<v8::Private> priv2 =
    3469           6 :       v8::Private::New(isolate, v8_str("my-private"));
    3470             : 
    3471           6 :   CcTest::CollectAllGarbage();
    3472             : 
    3473          24 :   CHECK(priv2->Name()
    3474             :             ->Equals(env.local(),
    3475             :                      v8::String::NewFromUtf8(isolate, "my-private",
    3476             :                                              v8::NewStringType::kNormal)
    3477             :                          .ToLocalChecked())
    3478             :             .FromJust());
    3479             : 
    3480             :   // Make sure delete of a non-existent private symbol property works.
    3481          12 :   obj->DeletePrivate(env.local(), priv1).FromJust();
    3482          12 :   CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
    3483             : 
    3484          18 :   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
    3485             :             .FromJust());
    3486          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3487          18 :   CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
    3488             :                      .ToLocalChecked()
    3489             :                      ->Int32Value(env.local())
    3490             :                      .FromJust());
    3491          18 :   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
    3492             :             .FromJust());
    3493          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3494          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3495             :                      .ToLocalChecked()
    3496             :                      ->Int32Value(env.local())
    3497             :                      .FromJust());
    3498             : 
    3499          12 :   CHECK_EQ(0u,
    3500             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3501             :   unsigned num_props =
    3502          12 :       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3503          24 :   CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
    3504             :                                   isolate, "bla", v8::NewStringType::kNormal)
    3505             :                                   .ToLocalChecked(),
    3506             :                  v8::Integer::New(isolate, 20))
    3507             :             .FromJust());
    3508          12 :   CHECK_EQ(1u,
    3509             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3510          12 :   CHECK_EQ(num_props + 1,
    3511             :            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3512             : 
    3513           6 :   CcTest::CollectAllGarbage();
    3514             : 
    3515             :   // Add another property and delete it afterwards to force the object in
    3516             :   // slow case.
    3517          18 :   CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
    3518             :             .FromJust());
    3519          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3520             :                      .ToLocalChecked()
    3521             :                      ->Int32Value(env.local())
    3522             :                      .FromJust());
    3523          18 :   CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
    3524             :                      .ToLocalChecked()
    3525             :                      ->Int32Value(env.local())
    3526             :                      .FromJust());
    3527          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3528             :                      .ToLocalChecked()
    3529             :                      ->Int32Value(env.local())
    3530             :                      .FromJust());
    3531          12 :   CHECK_EQ(1u,
    3532             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3533             : 
    3534          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3535          12 :   CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
    3536          12 :   CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
    3537          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3538          12 :   CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
    3539          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3540             :                      .ToLocalChecked()
    3541             :                      ->Int32Value(env.local())
    3542             :                      .FromJust());
    3543          12 :   CHECK_EQ(1u,
    3544             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3545             : 
    3546             :   // Private properties are not inherited (for the time being).
    3547           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3548          12 :   CHECK(child->SetPrototype(env.local(), obj).FromJust());
    3549          12 :   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
    3550          12 :   CHECK_EQ(0u,
    3551             :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3552           6 : }
    3553             : 
    3554             : 
    3555       26645 : THREADED_TEST(GlobalSymbols) {
    3556           6 :   LocalContext env;
    3557           6 :   v8::Isolate* isolate = env->GetIsolate();
    3558          12 :   v8::HandleScope scope(isolate);
    3559             : 
    3560           6 :   v8::Local<String> name = v8_str("my-symbol");
    3561           6 :   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
    3562           6 :   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
    3563           6 :   CHECK(glob2->SameValue(glob));
    3564             : 
    3565           6 :   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
    3566           6 :   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
    3567           6 :   CHECK(glob_api2->SameValue(glob_api));
    3568           6 :   CHECK(!glob_api->SameValue(glob));
    3569             : 
    3570           6 :   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
    3571           6 :   CHECK(!sym->SameValue(glob));
    3572             : 
    3573             :   CompileRun("var sym2 = Symbol.for('my-symbol')");
    3574             :   v8::Local<Value> sym2 =
    3575          24 :       env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
    3576           6 :   CHECK(sym2->SameValue(glob));
    3577           6 :   CHECK(!sym2->SameValue(glob_api));
    3578           6 : }
    3579             : 
    3580       26645 : THREADED_TEST(GlobalSymbolsNoContext) {
    3581           6 :   v8::Isolate* isolate = CcTest::isolate();
    3582          12 :   v8::HandleScope scope(isolate);
    3583             : 
    3584           6 :   v8::Local<String> name = v8_str("my-symbol");
    3585           6 :   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
    3586           6 :   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
    3587           6 :   CHECK(glob2->SameValue(glob));
    3588             : 
    3589           6 :   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
    3590           6 :   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
    3591           6 :   CHECK(glob_api2->SameValue(glob_api));
    3592           6 :   CHECK(!glob_api->SameValue(glob));
    3593           6 : }
    3594             : 
    3595          60 : static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
    3596             :                                  const char* name) {
    3597          60 :   LocalContext env;
    3598          60 :   v8::Isolate* isolate = env->GetIsolate();
    3599         120 :   v8::HandleScope scope(isolate);
    3600             : 
    3601          60 :   v8::Local<v8::Symbol> symbol = getter(isolate);
    3602         120 :   std::string script = std::string("var sym = ") + name;
    3603             :   CompileRun(script.c_str());
    3604             :   v8::Local<Value> value =
    3605         240 :       env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
    3606             : 
    3607          60 :   CHECK(!value.IsEmpty());
    3608          60 :   CHECK(!symbol.IsEmpty());
    3609          60 :   CHECK(value->SameValue(symbol));
    3610          60 : }
    3611             : 
    3612             : 
    3613       26645 : THREADED_TEST(WellKnownSymbols) {
    3614           6 :   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
    3615           6 :   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
    3616           6 :   CheckWellKnownSymbol(v8::Symbol::GetHasInstance, "Symbol.hasInstance");
    3617             :   CheckWellKnownSymbol(v8::Symbol::GetIsConcatSpreadable,
    3618           6 :                        "Symbol.isConcatSpreadable");
    3619           6 :   CheckWellKnownSymbol(v8::Symbol::GetMatch, "Symbol.match");
    3620           6 :   CheckWellKnownSymbol(v8::Symbol::GetReplace, "Symbol.replace");
    3621           6 :   CheckWellKnownSymbol(v8::Symbol::GetSearch, "Symbol.search");
    3622           6 :   CheckWellKnownSymbol(v8::Symbol::GetSplit, "Symbol.split");
    3623           6 :   CheckWellKnownSymbol(v8::Symbol::GetToPrimitive, "Symbol.toPrimitive");
    3624           6 :   CheckWellKnownSymbol(v8::Symbol::GetToStringTag, "Symbol.toStringTag");
    3625           6 : }
    3626             : 
    3627             : 
    3628       26645 : THREADED_TEST(GlobalPrivates) {
    3629           6 :   i::FLAG_allow_natives_syntax = true;
    3630           6 :   LocalContext env;
    3631           6 :   v8::Isolate* isolate = env->GetIsolate();
    3632          12 :   v8::HandleScope scope(isolate);
    3633             : 
    3634           6 :   v8::Local<String> name = v8_str("my-private");
    3635           6 :   v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
    3636           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3637          18 :   CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
    3638             :             .FromJust());
    3639             : 
    3640           6 :   v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
    3641          12 :   CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
    3642             : 
    3643           6 :   v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
    3644          12 :   CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
    3645             : 
    3646             :   CompileRun("var intern = %CreatePrivateSymbol('my-private')");
    3647             :   v8::Local<Value> intern =
    3648          24 :       env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
    3649          12 :   CHECK(!obj->Has(env.local(), intern).FromJust());
    3650           6 : }
    3651             : 
    3652             : 
    3653             : class ScopedArrayBufferContents {
    3654             :  public:
    3655             :   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
    3656          36 :       : contents_(contents) {}
    3657          36 :   ~ScopedArrayBufferContents() { free(contents_.AllocationBase()); }
    3658             :   void* Data() const { return contents_.Data(); }
    3659             :   size_t ByteLength() const { return contents_.ByteLength(); }
    3660             : 
    3661             :   void* AllocationBase() const { return contents_.AllocationBase(); }
    3662             :   size_t AllocationLength() const { return contents_.AllocationLength(); }
    3663             :   v8::ArrayBuffer::Allocator::AllocationMode AllocationMode() const {
    3664             :     return contents_.AllocationMode();
    3665             :   }
    3666             : 
    3667             :  private:
    3668             :   const v8::ArrayBuffer::Contents contents_;
    3669             : };
    3670             : 
    3671             : template <typename T>
    3672         282 : static void CheckInternalFieldsAreZero(v8::Local<T> value) {
    3673         282 :   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
    3674        1410 :   for (int i = 0; i < value->InternalFieldCount(); i++) {
    3675        1692 :     CHECK_EQ(0, value->GetInternalField(i)
    3676             :                     ->Int32Value(CcTest::isolate()->GetCurrentContext())
    3677             :                     .FromJust());
    3678             :   }
    3679         282 : }
    3680             : 
    3681             : 
    3682       26645 : THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
    3683           6 :   LocalContext env;
    3684           6 :   v8::Isolate* isolate = env->GetIsolate();
    3685          12 :   v8::HandleScope handle_scope(isolate);
    3686             : 
    3687           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
    3688           6 :   CheckInternalFieldsAreZero(ab);
    3689           6 :   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
    3690           6 :   CHECK(!ab->IsExternal());
    3691           6 :   CcTest::CollectAllGarbage();
    3692             : 
    3693          12 :   ScopedArrayBufferContents ab_contents(ab->Externalize());
    3694           6 :   CHECK(ab->IsExternal());
    3695             : 
    3696           6 :   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
    3697             :   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
    3698           6 :   CHECK_NOT_NULL(data);
    3699          24 :   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
    3700             : 
    3701             :   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
    3702          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3703             : 
    3704             :   result = CompileRun(
    3705             :       "var u8 = new Uint8Array(ab);"
    3706             :       "u8[0] = 0xFF;"
    3707             :       "u8[1] = 0xAA;"
    3708             :       "u8.length");
    3709          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3710          12 :   CHECK_EQ(0xFF, data[0]);
    3711          12 :   CHECK_EQ(0xAA, data[1]);
    3712           6 :   data[0] = 0xCC;
    3713           6 :   data[1] = 0x11;
    3714             :   result = CompileRun("u8[0] + u8[1]");
    3715          12 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3716           6 : }
    3717             : 
    3718             : 
    3719       26645 : THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
    3720           6 :   LocalContext env;
    3721           6 :   v8::Isolate* isolate = env->GetIsolate();
    3722          12 :   v8::HandleScope handle_scope(isolate);
    3723             : 
    3724             : 
    3725             :   v8::Local<v8::Value> result = CompileRun(
    3726             :       "var ab1 = new ArrayBuffer(2);"
    3727             :       "var u8_a = new Uint8Array(ab1);"
    3728             :       "u8_a[0] = 0xAA;"
    3729             :       "u8_a[1] = 0xFF; u8_a.buffer");
    3730             :   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
    3731           6 :   CheckInternalFieldsAreZero(ab1);
    3732           6 :   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
    3733           6 :   CHECK(!ab1->IsExternal());
    3734          12 :   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
    3735           6 :   CHECK(ab1->IsExternal());
    3736             : 
    3737             :   result = CompileRun("ab1.byteLength");
    3738          12 :   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
    3739             :   result = CompileRun("u8_a[0]");
    3740          12 :   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
    3741             :   result = CompileRun("u8_a[1]");
    3742          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3743             :   result = CompileRun(
    3744             :       "var u8_b = new Uint8Array(ab1);"
    3745             :       "u8_b[0] = 0xBB;"
    3746             :       "u8_a[0]");
    3747          12 :   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
    3748             :   result = CompileRun("u8_b[1]");
    3749          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3750             : 
    3751           6 :   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
    3752             :   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
    3753          12 :   CHECK_EQ(0xBB, ab1_data[0]);
    3754          12 :   CHECK_EQ(0xFF, ab1_data[1]);
    3755           6 :   ab1_data[0] = 0xCC;
    3756           6 :   ab1_data[1] = 0x11;
    3757             :   result = CompileRun("u8_a[0] + u8_a[1]");
    3758          12 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3759           6 : }
    3760             : 
    3761             : 
    3762       26645 : THREADED_TEST(ArrayBuffer_External) {
    3763           6 :   LocalContext env;
    3764           6 :   v8::Isolate* isolate = env->GetIsolate();
    3765          12 :   v8::HandleScope handle_scope(isolate);
    3766             : 
    3767             :   i::ScopedVector<uint8_t> my_data(100);
    3768             :   memset(my_data.start(), 0, 100);
    3769             :   Local<v8::ArrayBuffer> ab3 =
    3770           6 :       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
    3771           6 :   CheckInternalFieldsAreZero(ab3);
    3772           6 :   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
    3773           6 :   CHECK(ab3->IsExternal());
    3774             : 
    3775          24 :   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
    3776             : 
    3777             :   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
    3778          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3779             : 
    3780             :   result = CompileRun(
    3781             :       "var u8_b = new Uint8Array(ab3);"
    3782             :       "u8_b[0] = 0xBB;"
    3783             :       "u8_b[1] = 0xCC;"
    3784             :       "u8_b.length");
    3785          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3786          12 :   CHECK_EQ(0xBB, my_data[0]);
    3787          12 :   CHECK_EQ(0xCC, my_data[1]);
    3788           6 :   my_data[0] = 0xCC;
    3789           6 :   my_data[1] = 0x11;
    3790             :   result = CompileRun("u8_b[0] + u8_b[1]");
    3791          12 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3792           6 : }
    3793             : 
    3794       26645 : THREADED_TEST(ArrayBuffer_DisableDetach) {
    3795           6 :   LocalContext env;
    3796           6 :   v8::Isolate* isolate = env->GetIsolate();
    3797          12 :   v8::HandleScope handle_scope(isolate);
    3798             : 
    3799             :   i::ScopedVector<uint8_t> my_data(100);
    3800             :   memset(my_data.start(), 0, 100);
    3801             :   Local<v8::ArrayBuffer> ab =
    3802           6 :       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
    3803           6 :   CHECK(ab->IsDetachable());
    3804             : 
    3805             :   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
    3806             :   buf->set_is_detachable(false);
    3807             : 
    3808           6 :   CHECK(!ab->IsDetachable());
    3809           6 : }
    3810             : 
    3811          12 : static void CheckDataViewIsDetached(v8::Local<v8::DataView> dv) {
    3812          12 :   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
    3813          12 :   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
    3814          12 : }
    3815             : 
    3816         108 : static void CheckIsDetached(v8::Local<v8::TypedArray> ta) {
    3817         108 :   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
    3818         108 :   CHECK_EQ(0, static_cast<int>(ta->Length()));
    3819         108 :   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
    3820         108 : }
    3821             : 
    3822          54 : static void CheckIsTypedArrayVarDetached(const char* name) {
    3823             :   i::ScopedVector<char> source(1024);
    3824             :   i::SNPrintF(source,
    3825             :               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
    3826          54 :               name, name, name);
    3827          54 :   CHECK(CompileRun(source.start())->IsTrue());
    3828             :   v8::Local<v8::TypedArray> ta =
    3829          54 :       v8::Local<v8::TypedArray>::Cast(CompileRun(name));
    3830          54 :   CheckIsDetached(ta);
    3831          54 : }
    3832             : 
    3833             : template <typename TypedArray, int kElementSize>
    3834          54 : static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
    3835             :                                         int byteOffset, int length) {
    3836          54 :   v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
    3837          54 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
    3838          54 :   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
    3839          54 :   CHECK_EQ(length, static_cast<int>(ta->Length()));
    3840          54 :   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
    3841          54 :   return ta;
    3842             : }
    3843             : 
    3844       26645 : THREADED_TEST(ArrayBuffer_DetachingApi) {
    3845           6 :   LocalContext env;
    3846           6 :   v8::Isolate* isolate = env->GetIsolate();
    3847          12 :   v8::HandleScope handle_scope(isolate);
    3848             : 
    3849           6 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
    3850             : 
    3851             :   v8::Local<v8::Uint8Array> u8a =
    3852           6 :       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
    3853             :   v8::Local<v8::Uint8ClampedArray> u8c =
    3854           6 :       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
    3855             :   v8::Local<v8::Int8Array> i8a =
    3856           6 :       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
    3857             : 
    3858             :   v8::Local<v8::Uint16Array> u16a =
    3859           6 :       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
    3860             :   v8::Local<v8::Int16Array> i16a =
    3861           6 :       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
    3862             : 
    3863             :   v8::Local<v8::Uint32Array> u32a =
    3864           6 :       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
    3865             :   v8::Local<v8::Int32Array> i32a =
    3866           6 :       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
    3867             : 
    3868             :   v8::Local<v8::Float32Array> f32a =
    3869           6 :       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
    3870             :   v8::Local<v8::Float64Array> f64a =
    3871           6 :       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
    3872             : 
    3873           6 :   v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
    3874           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
    3875           6 :   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
    3876           6 :   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
    3877             : 
    3878          12 :   ScopedArrayBufferContents contents(buffer->Externalize());
    3879           6 :   buffer->Detach();
    3880           6 :   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
    3881           6 :   CheckIsDetached(u8a);
    3882           6 :   CheckIsDetached(u8c);
    3883           6 :   CheckIsDetached(i8a);
    3884           6 :   CheckIsDetached(u16a);
    3885           6 :   CheckIsDetached(i16a);
    3886           6 :   CheckIsDetached(u32a);
    3887           6 :   CheckIsDetached(i32a);
    3888           6 :   CheckIsDetached(f32a);
    3889           6 :   CheckIsDetached(f64a);
    3890           6 :   CheckDataViewIsDetached(dv);
    3891           6 : }
    3892             : 
    3893       26645 : THREADED_TEST(ArrayBuffer_DetachingScript) {
    3894           6 :   LocalContext env;
    3895           6 :   v8::Isolate* isolate = env->GetIsolate();
    3896          12 :   v8::HandleScope handle_scope(isolate);
    3897             : 
    3898             :   CompileRun(
    3899             :       "var ab = new ArrayBuffer(1024);"
    3900             :       "var u8a = new Uint8Array(ab, 1, 1023);"
    3901             :       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
    3902             :       "var i8a = new Int8Array(ab, 1, 1023);"
    3903             :       "var u16a = new Uint16Array(ab, 2, 511);"
    3904             :       "var i16a = new Int16Array(ab, 2, 511);"
    3905             :       "var u32a = new Uint32Array(ab, 4, 255);"
    3906             :       "var i32a = new Int32Array(ab, 4, 255);"
    3907             :       "var f32a = new Float32Array(ab, 4, 255);"
    3908             :       "var f64a = new Float64Array(ab, 8, 127);"
    3909             :       "var dv = new DataView(ab, 1, 1023);");
    3910             : 
    3911             :   v8::Local<v8::ArrayBuffer> ab =
    3912             :       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
    3913             : 
    3914           6 :   v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
    3915             : 
    3916          12 :   ScopedArrayBufferContents contents(ab->Externalize());
    3917           6 :   ab->Detach();
    3918           6 :   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
    3919           6 :   CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
    3920             : 
    3921           6 :   CheckIsTypedArrayVarDetached("u8a");
    3922           6 :   CheckIsTypedArrayVarDetached("u8c");
    3923           6 :   CheckIsTypedArrayVarDetached("i8a");
    3924           6 :   CheckIsTypedArrayVarDetached("u16a");
    3925           6 :   CheckIsTypedArrayVarDetached("i16a");
    3926           6 :   CheckIsTypedArrayVarDetached("u32a");
    3927           6 :   CheckIsTypedArrayVarDetached("i32a");
    3928           6 :   CheckIsTypedArrayVarDetached("f32a");
    3929           6 :   CheckIsTypedArrayVarDetached("f64a");
    3930             : 
    3931           6 :   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
    3932           6 :   CheckDataViewIsDetached(dv);
    3933           6 : }
    3934             : 
    3935       26645 : THREADED_TEST(ArrayBuffer_AllocationInformation) {
    3936           6 :   LocalContext env;
    3937           6 :   v8::Isolate* isolate = env->GetIsolate();
    3938          12 :   v8::HandleScope handle_scope(isolate);
    3939             : 
    3940             :   const size_t ab_size = 1024;
    3941           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, ab_size);
    3942          12 :   ScopedArrayBufferContents contents(ab->Externalize());
    3943             : 
    3944             :   // Array buffers should have normal allocation mode.
    3945           6 :   CHECK_EQ(contents.AllocationMode(),
    3946             :            v8::ArrayBuffer::Allocator::AllocationMode::kNormal);
    3947             :   // The allocation must contain the buffer (normally they will be equal, but
    3948             :   // this is not required by the contract).
    3949           6 :   CHECK_NOT_NULL(contents.AllocationBase());
    3950             :   const uintptr_t alloc =
    3951           6 :       reinterpret_cast<uintptr_t>(contents.AllocationBase());
    3952           6 :   const uintptr_t data = reinterpret_cast<uintptr_t>(contents.Data());
    3953           6 :   CHECK_LE(alloc, data);
    3954           6 :   CHECK_LE(data + contents.ByteLength(), alloc + contents.AllocationLength());
    3955           6 : }
    3956             : 
    3957       26645 : THREADED_TEST(ArrayBuffer_ExternalizeEmpty) {
    3958           6 :   LocalContext env;
    3959           6 :   v8::Isolate* isolate = env->GetIsolate();
    3960          12 :   v8::HandleScope handle_scope(isolate);
    3961             : 
    3962           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 0);
    3963           6 :   CheckInternalFieldsAreZero(ab);
    3964           6 :   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
    3965           6 :   CHECK(!ab->IsExternal());
    3966             : 
    3967             :   // Externalize the buffer (taking ownership of the backing store memory).
    3968          12 :   ScopedArrayBufferContents ab_contents(ab->Externalize());
    3969             : 
    3970           6 :   Local<v8::Uint8Array> u8a = v8::Uint8Array::New(ab, 0, 0);
    3971             :   // Calling Buffer() will materialize the ArrayBuffer (transitioning it from
    3972             :   // on-heap to off-heap if need be). This should not affect whether it is
    3973             :   // marked as is_external or not.
    3974           6 :   USE(u8a->Buffer());
    3975             : 
    3976           6 :   CHECK(ab->IsExternal());
    3977           6 : }
    3978             : 
    3979             : class ScopedSharedArrayBufferContents {
    3980             :  public:
    3981             :   explicit ScopedSharedArrayBufferContents(
    3982             :       const v8::SharedArrayBuffer::Contents& contents)
    3983          18 :       : contents_(contents) {}
    3984          18 :   ~ScopedSharedArrayBufferContents() { free(contents_.AllocationBase()); }
    3985             :   void* Data() const { return contents_.Data(); }
    3986             :   size_t ByteLength() const { return contents_.ByteLength(); }
    3987             : 
    3988             :   void* AllocationBase() const { return contents_.AllocationBase(); }
    3989             :   size_t AllocationLength() const { return contents_.AllocationLength(); }
    3990             :   v8::ArrayBuffer::Allocator::AllocationMode AllocationMode() const {
    3991             :     return contents_.AllocationMode();
    3992             :   }
    3993             : 
    3994             :  private:
    3995             :   const v8::SharedArrayBuffer::Contents contents_;
    3996             : };
    3997             : 
    3998             : 
    3999       26645 : THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
    4000           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    4001           6 :   LocalContext env;
    4002           6 :   v8::Isolate* isolate = env->GetIsolate();
    4003          12 :   v8::HandleScope handle_scope(isolate);
    4004             : 
    4005           6 :   Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
    4006           6 :   CheckInternalFieldsAreZero(ab);
    4007           6 :   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
    4008           6 :   CHECK(!ab->IsExternal());
    4009           6 :   CcTest::CollectAllGarbage();
    4010             : 
    4011          12 :   ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
    4012           6 :   CHECK(ab->IsExternal());
    4013             : 
    4014           6 :   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
    4015             :   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
    4016           6 :   CHECK_NOT_NULL(data);
    4017          24 :   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
    4018             : 
    4019             :   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
    4020          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    4021             : 
    4022             :   result = CompileRun(
    4023             :       "var u8 = new Uint8Array(ab);"
    4024             :       "u8[0] = 0xFF;"
    4025             :       "u8[1] = 0xAA;"
    4026             :       "u8.length");
    4027          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    4028          12 :   CHECK_EQ(0xFF, data[0]);
    4029          12 :   CHECK_EQ(0xAA, data[1]);
    4030           6 :   data[0] = 0xCC;
    4031           6 :   data[1] = 0x11;
    4032             :   result = CompileRun("u8[0] + u8[1]");
    4033          12 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4034           6 : }
    4035             : 
    4036             : 
    4037       26645 : THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
    4038           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    4039           6 :   LocalContext env;
    4040           6 :   v8::Isolate* isolate = env->GetIsolate();
    4041          12 :   v8::HandleScope handle_scope(isolate);
    4042             : 
    4043             : 
    4044             :   v8::Local<v8::Value> result = CompileRun(
    4045             :       "var ab1 = new SharedArrayBuffer(2);"
    4046             :       "var u8_a = new Uint8Array(ab1);"
    4047             :       "u8_a[0] = 0xAA;"
    4048             :       "u8_a[1] = 0xFF; u8_a.buffer");
    4049             :   Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
    4050           6 :   CheckInternalFieldsAreZero(ab1);
    4051           6 :   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
    4052           6 :   CHECK(!ab1->IsExternal());
    4053          12 :   ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
    4054           6 :   CHECK(ab1->IsExternal());
    4055             : 
    4056             :   result = CompileRun("ab1.byteLength");
    4057          12 :   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
    4058             :   result = CompileRun("u8_a[0]");
    4059          12 :   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
    4060             :   result = CompileRun("u8_a[1]");
    4061          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    4062             :   result = CompileRun(
    4063             :       "var u8_b = new Uint8Array(ab1);"
    4064             :       "u8_b[0] = 0xBB;"
    4065             :       "u8_a[0]");
    4066          12 :   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
    4067             :   result = CompileRun("u8_b[1]");
    4068          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    4069             : 
    4070           6 :   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
    4071             :   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
    4072          12 :   CHECK_EQ(0xBB, ab1_data[0]);
    4073          12 :   CHECK_EQ(0xFF, ab1_data[1]);
    4074           6 :   ab1_data[0] = 0xCC;
    4075           6 :   ab1_data[1] = 0x11;
    4076             :   result = CompileRun("u8_a[0] + u8_a[1]");
    4077          12 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4078           6 : }
    4079             : 
    4080             : 
    4081       26645 : THREADED_TEST(SharedArrayBuffer_External) {
    4082           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    4083           6 :   LocalContext env;
    4084           6 :   v8::Isolate* isolate = env->GetIsolate();
    4085          12 :   v8::HandleScope handle_scope(isolate);
    4086             : 
    4087             :   i::ScopedVector<uint8_t> my_data(100);
    4088             :   memset(my_data.start(), 0, 100);
    4089             :   Local<v8::SharedArrayBuffer> ab3 =
    4090           6 :       v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
    4091           6 :   CheckInternalFieldsAreZero(ab3);
    4092           6 :   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
    4093           6 :   CHECK(ab3->IsExternal());
    4094             : 
    4095          24 :   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
    4096             : 
    4097             :   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
    4098          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    4099             : 
    4100             :   result = CompileRun(
    4101             :       "var u8_b = new Uint8Array(ab3);"
    4102             :       "u8_b[0] = 0xBB;"
    4103             :       "u8_b[1] = 0xCC;"
    4104             :       "u8_b.length");
    4105          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    4106          12 :   CHECK_EQ(0xBB, my_data[0]);
    4107          12 :   CHECK_EQ(0xCC, my_data[1]);
    4108           6 :   my_data[0] = 0xCC;
    4109           6 :   my_data[1] = 0x11;
    4110             :   result = CompileRun("u8_b[0] + u8_b[1]");
    4111          12 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4112           6 : }
    4113             : 
    4114             : 
    4115       26645 : THREADED_TEST(HiddenProperties) {
    4116           6 :   LocalContext env;
    4117           6 :   v8::Isolate* isolate = env->GetIsolate();
    4118          12 :   v8::HandleScope scope(isolate);
    4119             : 
    4120           6 :   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    4121             :   v8::Local<v8::Private> key =
    4122           6 :       v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
    4123           6 :   v8::Local<v8::String> empty = v8_str("");
    4124           6 :   v8::Local<v8::String> prop_name = v8_str("prop_name");
    4125             : 
    4126           6 :   CcTest::CollectAllGarbage();
    4127             : 
    4128             :   // Make sure delete of a non-existent hidden value works
    4129          12 :   obj->DeletePrivate(env.local(), key).FromJust();
    4130             : 
    4131          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
    4132             :             .FromJust());
    4133          18 :   CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
    4134             :                      .ToLocalChecked()
    4135             :                      ->Int32Value(env.local())
    4136             :                      .FromJust());
    4137          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
    4138             :             .FromJust());
    4139          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4140             :                      .ToLocalChecked()
    4141             :                      ->Int32Value(env.local())
    4142             :                      .FromJust());
    4143             : 
    4144           6 :   CcTest::CollectAllGarbage();
    4145             : 
    4146             :   // Make sure we do not find the hidden property.
    4147          12 :   CHECK(!obj->Has(env.local(), empty).FromJust());
    4148          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4149             :                      .ToLocalChecked()
    4150             :                      ->Int32Value(env.local())
    4151             :                      .FromJust());
    4152          12 :   CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
    4153          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4154             :                      .ToLocalChecked()
    4155             :                      ->Int32Value(env.local())
    4156             :                      .FromJust());
    4157          18 :   CHECK(
    4158             :       obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
    4159          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4160             :                      .ToLocalChecked()
    4161             :                      ->Int32Value(env.local())
    4162             :                      .FromJust());
    4163          18 :   CHECK_EQ(2003, obj->Get(env.local(), empty)
    4164             :                      .ToLocalChecked()
    4165             :                      ->Int32Value(env.local())
    4166             :                      .FromJust());
    4167             : 
    4168           6 :   CcTest::CollectAllGarbage();
    4169             : 
    4170             :   // Add another property and delete it afterwards to force the object in
    4171             :   // slow case.
    4172          18 :   CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
    4173             :             .FromJust());
    4174          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4175             :                      .ToLocalChecked()
    4176             :                      ->Int32Value(env.local())
    4177             :                      .FromJust());
    4178          18 :   CHECK_EQ(2008, obj->Get(env.local(), prop_name)
    4179             :                      .ToLocalChecked()
    4180             :                      ->Int32Value(env.local())
    4181             :                      .FromJust());
    4182          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4183             :                      .ToLocalChecked()
    4184             :                      ->Int32Value(env.local())
    4185             :                      .FromJust());
    4186          12 :   CHECK(obj->Delete(env.local(), prop_name).FromJust());
    4187          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4188             :                      .ToLocalChecked()
    4189             :                      ->Int32Value(env.local())
    4190             :                      .FromJust());
    4191             : 
    4192           6 :   CcTest::CollectAllGarbage();
    4193             : 
    4194          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
    4195             :             .FromJust());
    4196          12 :   CHECK(obj->DeletePrivate(env.local(), key).FromJust());
    4197          12 :   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
    4198           6 : }
    4199             : 
    4200             : 
    4201       26645 : THREADED_TEST(Regress97784) {
    4202             :   // Regression test for crbug.com/97784
    4203             :   // Messing with the Object.prototype should not have effect on
    4204             :   // hidden properties.
    4205           6 :   LocalContext env;
    4206          12 :   v8::HandleScope scope(env->GetIsolate());
    4207             : 
    4208           6 :   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    4209             :   v8::Local<v8::Private> key =
    4210          12 :       v8::Private::New(env->GetIsolate(), v8_str("hidden"));
    4211             : 
    4212             :   CompileRun(
    4213             :       "set_called = false;"
    4214             :       "Object.defineProperty("
    4215             :       "    Object.prototype,"
    4216             :       "    'hidden',"
    4217             :       "    {get: function() { return 45; },"
    4218             :       "     set: function() { set_called = true; }})");
    4219             : 
    4220          12 :   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
    4221             :   // Make sure that the getter and setter from Object.prototype is not invoked.
    4222             :   // If it did we would have full access to the hidden properties in
    4223             :   // the accessor.
    4224          18 :   CHECK(
    4225             :       obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
    4226             :           .FromJust());
    4227             :   ExpectFalse("set_called");
    4228          18 :   CHECK_EQ(42, obj->GetPrivate(env.local(), key)
    4229             :                    .ToLocalChecked()
    4230             :                    ->Int32Value(env.local())
    4231             :                    .FromJust());
    4232           6 : }
    4233             : 
    4234             : 
    4235       26645 : THREADED_TEST(External) {
    4236          12 :   v8::HandleScope scope(CcTest::isolate());
    4237           6 :   int x = 3;
    4238           6 :   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
    4239           6 :   LocalContext env;
    4240          24 :   CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
    4241             :   Local<Value> reext_obj = CompileRun("this.ext");
    4242             :   v8::Local<v8::External> reext = reext_obj.As<v8::External>();
    4243           6 :   int* ptr = static_cast<int*>(reext->Value());
    4244           6 :   CHECK_EQ(3, x);
    4245           6 :   *ptr = 10;
    4246           6 :   CHECK_EQ(x, 10);
    4247             : 
    4248             :   {
    4249             :     i::Handle<i::Object> obj = v8::Utils::OpenHandle(*ext);
    4250          12 :     CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
    4251           6 :     CHECK(ext->IsExternal());
    4252           6 :     CHECK(!CompileRun("new Set().add(this.ext)").IsEmpty());
    4253          12 :     CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
    4254           6 :     CHECK(ext->IsExternal());
    4255             :   }
    4256             : 
    4257             :   // Make sure unaligned pointers are wrapped properly.
    4258           6 :   char* data = i::StrDup("0123456789");
    4259           6 :   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
    4260           6 :   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
    4261           6 :   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
    4262           6 :   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
    4263             : 
    4264           6 :   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
    4265           6 :   CHECK_EQ('0', *char_ptr);
    4266           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
    4267           6 :   CHECK_EQ('1', *char_ptr);
    4268           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
    4269           6 :   CHECK_EQ('2', *char_ptr);
    4270           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
    4271           6 :   CHECK_EQ('3', *char_ptr);
    4272             :   i::DeleteArray(data);
    4273           6 : }
    4274             : 
    4275             : 
    4276       26645 : THREADED_TEST(GlobalHandle) {
    4277           6 :   v8::Isolate* isolate = CcTest::isolate();
    4278             :   v8::Persistent<String> global;
    4279             :   {
    4280          12 :     v8::HandleScope scope(isolate);
    4281          12 :     global.Reset(isolate, v8_str("str"));
    4282             :   }
    4283             :   {
    4284          12 :     v8::HandleScope scope(isolate);
    4285           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4286             :   }
    4287             :   global.Reset();
    4288             :   {
    4289          12 :     v8::HandleScope scope(isolate);
    4290          12 :     global.Reset(isolate, v8_str("str"));
    4291             :   }
    4292             :   {
    4293          12 :     v8::HandleScope scope(isolate);
    4294           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4295             :   }
    4296             :   global.Reset();
    4297           6 : }
    4298             : 
    4299             : 
    4300       26645 : THREADED_TEST(ResettingGlobalHandle) {
    4301           6 :   v8::Isolate* isolate = CcTest::isolate();
    4302             :   v8::Persistent<String> global;
    4303             :   {
    4304          12 :     v8::HandleScope scope(isolate);
    4305          12 :     global.Reset(isolate, v8_str("str"));
    4306             :   }
    4307             :   v8::internal::GlobalHandles* global_handles =
    4308             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4309             :   size_t initial_handle_count = global_handles->handles_count();
    4310             :   {
    4311          12 :     v8::HandleScope scope(isolate);
    4312           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4313             :   }
    4314             :   {
    4315          12 :     v8::HandleScope scope(isolate);
    4316          12 :     global.Reset(isolate, v8_str("longer"));
    4317             :   }
    4318           6 :   CHECK_EQ(global_handles->handles_count(), initial_handle_count);
    4319             :   {
    4320          12 :     v8::HandleScope scope(isolate);
    4321           6 :     CHECK_EQ(6, v8::Local<String>::New(isolate, global)->Length());
    4322             :   }
    4323             :   global.Reset();
    4324           6 :   CHECK_EQ(global_handles->handles_count(), initial_handle_count - 1);
    4325           6 : }
    4326             : 
    4327             : 
    4328       26645 : THREADED_TEST(ResettingGlobalHandleToEmpty) {
    4329           6 :   v8::Isolate* isolate = CcTest::isolate();
    4330             :   v8::Persistent<String> global;
    4331             :   {
    4332          12 :     v8::HandleScope scope(isolate);
    4333          12 :     global.Reset(isolate, v8_str("str"));
    4334             :   }
    4335             :   v8::internal::GlobalHandles* global_handles =
    4336             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4337             :   size_t initial_handle_count = global_handles->handles_count();
    4338             :   {
    4339          12 :     v8::HandleScope scope(isolate);
    4340           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4341             :   }
    4342             :   {
    4343          12 :     v8::HandleScope scope(isolate);
    4344             :     Local<String> empty;
    4345             :     global.Reset(isolate, empty);
    4346             :   }
    4347           6 :   CHECK(global.IsEmpty());
    4348           6 :   CHECK_EQ(global_handles->handles_count(), initial_handle_count - 1);
    4349           6 : }
    4350             : 
    4351             : 
    4352             : template <class T>
    4353             : static v8::Global<T> PassUnique(v8::Global<T> unique) {
    4354             :   return unique.Pass();
    4355             : }
    4356             : 
    4357             : 
    4358             : template <class T>
    4359           6 : static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
    4360             :                                   const v8::Persistent<T>& global) {
    4361             :   v8::Global<String> unique(isolate, global);
    4362           6 :   return unique.Pass();
    4363             : }
    4364             : 
    4365             : 
    4366       26645 : THREADED_TEST(Global) {
    4367           6 :   v8::Isolate* isolate = CcTest::isolate();
    4368             :   v8::Persistent<String> global;
    4369             :   {
    4370          12 :     v8::HandleScope scope(isolate);
    4371          12 :     global.Reset(isolate, v8_str("str"));
    4372             :   }
    4373             :   v8::internal::GlobalHandles* global_handles =
    4374             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4375             :   size_t initial_handle_count = global_handles->handles_count();
    4376             :   {
    4377             :     v8::Global<String> unique(isolate, global);
    4378           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4379             :     // Test assignment via Pass
    4380             :     {
    4381             :       v8::Global<String> copy = unique.Pass();
    4382           6 :       CHECK(unique.IsEmpty());
    4383           6 :       CHECK(copy == global);
    4384           6 :       CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4385           6 :       unique = copy.Pass();
    4386             :     }
    4387             :     // Test ctor via Pass
    4388             :     {
    4389             :       v8::Global<String> copy(unique.Pass());
    4390           6 :       CHECK(unique.IsEmpty());
    4391           6 :       CHECK(copy == global);
    4392           6 :       CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4393           6 :       unique = copy.Pass();
    4394             :     }
    4395             :     // Test pass through function call
    4396             :     {
    4397           6 :       v8::Global<String> copy = PassUnique(unique.Pass());
    4398           6 :       CHECK(unique.IsEmpty());
    4399           6 :       CHECK(copy == global);
    4400           6 :       CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4401           6 :       unique = copy.Pass();
    4402             :     }
    4403           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4404             :   }
    4405             :   // Test pass from function call
    4406             :   {
    4407           6 :     v8::Global<String> unique = ReturnUnique(isolate, global);
    4408           6 :     CHECK(unique == global);
    4409           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4410             :   }
    4411           6 :   CHECK_EQ(initial_handle_count, global_handles->handles_count());
    4412             :   global.Reset();
    4413           6 : }
    4414             : 
    4415             : 
    4416             : namespace {
    4417             : 
    4418             : class TwoPassCallbackData;
    4419             : void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
    4420             : void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
    4421             : 
    4422             : 
    4423             : class TwoPassCallbackData {
    4424             :  public:
    4425         215 :   TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
    4426             :       : first_pass_called_(false),
    4427             :         second_pass_called_(false),
    4428             :         trigger_gc_(false),
    4429         430 :         instance_counter_(instance_counter) {
    4430         430 :     HandleScope scope(isolate);
    4431             :     i::ScopedVector<char> buffer(40);
    4432         215 :     i::SNPrintF(buffer, "%p", static_cast<void*>(this));
    4433             :     auto string =
    4434         215 :         v8::String::NewFromUtf8(isolate, buffer.start(),
    4435             :                                 v8::NewStringType::kNormal).ToLocalChecked();
    4436             :     cell_.Reset(isolate, string);
    4437         215 :     (*instance_counter_)++;
    4438         215 :   }
    4439             : 
    4440         430 :   ~TwoPassCallbackData() {
    4441         215 :     CHECK(first_pass_called_);
    4442         215 :     CHECK(second_pass_called_);
    4443         215 :     CHECK(cell_.IsEmpty());
    4444         215 :     (*instance_counter_)--;
    4445         215 :   }
    4446             : 
    4447         215 :   void FirstPass() {
    4448         215 :     CHECK(!first_pass_called_);
    4449         215 :     CHECK(!second_pass_called_);
    4450         215 :     CHECK(!cell_.IsEmpty());
    4451             :     cell_.Reset();
    4452         215 :     first_pass_called_ = true;
    4453         215 :   }
    4454             : 
    4455         215 :   void SecondPass() {
    4456         215 :     CHECK(first_pass_called_);
    4457         215 :     CHECK(!second_pass_called_);
    4458         215 :     CHECK(cell_.IsEmpty());
    4459         215 :     second_pass_called_ = true;
    4460         215 :     delete this;
    4461         215 :   }
    4462             : 
    4463             :   void SetWeak() {
    4464             :     cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
    4465             :   }
    4466             : 
    4467          15 :   void MarkTriggerGc() { trigger_gc_ = true; }
    4468             :   bool trigger_gc() { return trigger_gc_; }
    4469             : 
    4470             :   int* instance_counter() { return instance_counter_; }
    4471             : 
    4472             :  private:
    4473             :   bool first_pass_called_;
    4474             :   bool second_pass_called_;
    4475             :   bool trigger_gc_;
    4476             :   v8::Global<v8::String> cell_;
    4477             :   int* instance_counter_;
    4478             : };
    4479             : 
    4480             : 
    4481         215 : void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
    4482         215 :   ApiTestFuzzer::Fuzz();
    4483             :   bool trigger_gc = data.GetParameter()->trigger_gc();
    4484             :   int* instance_counter = data.GetParameter()->instance_counter();
    4485         215 :   data.GetParameter()->SecondPass();
    4486         215 :   if (!trigger_gc) return;
    4487          15 :   auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
    4488             :   data_2->SetWeak();
    4489          15 :   CcTest::CollectAllGarbage();
    4490             : }
    4491             : 
    4492             : 
    4493         215 : void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
    4494         215 :   data.GetParameter()->FirstPass();
    4495             :   data.SetSecondPassCallback(SecondPassCallback);
    4496         215 : }
    4497             : 
    4498             : }  // namespace
    4499             : 
    4500             : 
    4501       26644 : TEST(TwoPassPhantomCallbacks) {
    4502           5 :   auto isolate = CcTest::isolate();
    4503             :   const size_t kLength = 20;
    4504           5 :   int instance_counter = 0;
    4505         205 :   for (size_t i = 0; i < kLength; ++i) {
    4506         100 :     auto data = new TwoPassCallbackData(isolate, &instance_counter);
    4507             :     data->SetWeak();
    4508             :   }
    4509           5 :   CHECK_EQ(static_cast<int>(kLength), instance_counter);
    4510           5 :   CcTest::CollectAllGarbage();
    4511           5 :   EmptyMessageQueues(isolate);
    4512           5 :   CHECK_EQ(0, instance_counter);
    4513           5 : }
    4514             : 
    4515             : 
    4516       26644 : TEST(TwoPassPhantomCallbacksNestedGc) {
    4517           5 :   auto isolate = CcTest::isolate();
    4518             :   const size_t kLength = 20;
    4519             :   TwoPassCallbackData* array[kLength];
    4520           5 :   int instance_counter = 0;
    4521         205 :   for (size_t i = 0; i < kLength; ++i) {
    4522         100 :     array[i] = new TwoPassCallbackData(isolate, &instance_counter);
    4523             :     array[i]->SetWeak();
    4524             :   }
    4525           5 :   array[5]->MarkTriggerGc();
    4526           5 :   array[10]->MarkTriggerGc();
    4527           5 :   array[15]->MarkTriggerGc();
    4528           5 :   CHECK_EQ(static_cast<int>(kLength), instance_counter);
    4529           5 :   CcTest::CollectAllGarbage();
    4530           5 :   EmptyMessageQueues(isolate);
    4531           5 :   CHECK_EQ(0, instance_counter);
    4532           5 : }
    4533             : 
    4534             : 
    4535             : namespace {
    4536             : 
    4537          30 : void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
    4538             : 
    4539             : 
    4540          20 : Local<v8::Object> NewObjectForIntKey(
    4541             :     v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
    4542             :     int key) {
    4543             :   auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
    4544          20 :   auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
    4545          20 :   obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
    4546          20 :   return obj;
    4547             : }
    4548             : 
    4549             : 
    4550             : template <typename K, typename V>
    4551             : class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
    4552             :  public:
    4553             :   typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
    4554             :   static const v8::PersistentContainerCallbackType kCallbackType =
    4555             :       v8::kWeakWithInternalFields;
    4556             :   struct WeakCallbackDataType {
    4557             :     MapType* map;
    4558             :     K key;
    4559             :   };
    4560             :   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
    4561             :                                                      Local<V> value) {
    4562          25 :     WeakCallbackDataType* data = new WeakCallbackDataType;
    4563          25 :     data->map = map;
    4564          25 :     data->key = key;
    4565             :     return data;
    4566             :   }
    4567             :   static MapType* MapFromWeakCallbackInfo(
    4568             :       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
    4569           5 :     return data.GetParameter()->map;
    4570             :   }
    4571             :   static K KeyFromWeakCallbackInfo(
    4572             :       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
    4573          10 :     return data.GetParameter()->key;
    4574             :   }
    4575          25 :   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
    4576           5 :   static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
    4577           5 :     CHECK_EQ(IntKeyToVoidPointer(key),
    4578             :              v8::Object::GetAlignedPointerFromInternalField(value, 0));
    4579           5 :   }
    4580             :   static void OnWeakCallback(
    4581             :       const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
    4582           5 :   static void DisposeWeak(
    4583             :       const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
    4584             :     K key = KeyFromWeakCallbackInfo(info);
    4585           5 :     CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
    4586             :     DisposeCallbackData(info.GetParameter());
    4587           5 :   }
    4588             : };
    4589             : 
    4590             : 
    4591             : template <typename Map>
    4592          10 : void TestGlobalValueMap() {
    4593          10 :   LocalContext env;
    4594          10 :   v8::Isolate* isolate = env->GetIsolate();
    4595             :   v8::Global<ObjectTemplate> templ;
    4596             :   {
    4597          20 :     HandleScope scope(isolate);
    4598          10 :     auto t = ObjectTemplate::New(isolate);
    4599          10 :     t->SetInternalFieldCount(1);
    4600             :     templ.Reset(isolate, t);
    4601             :   }
    4602             :   Map map(isolate);
    4603             :   v8::internal::GlobalHandles* global_handles =
    4604             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4605             :   size_t initial_handle_count = global_handles->handles_count();
    4606             :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4607             :   {
    4608          20 :     HandleScope scope(isolate);
    4609          10 :     Local<v8::Object> obj = map.Get(7);
    4610          10 :     CHECK(obj.IsEmpty());
    4611          10 :     Local<v8::Object> expected = v8::Object::New(isolate);
    4612          20 :     map.Set(7, expected);
    4613          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4614          10 :     obj = map.Get(7);
    4615          20 :     CHECK(expected->Equals(env.local(), obj).FromJust());
    4616             :     {
    4617             :       typename Map::PersistentValueReference ref = map.GetReference(7);
    4618          20 :       CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
    4619             :     }
    4620          10 :     v8::Global<v8::Object> removed = map.Remove(7);
    4621          10 :     CHECK_EQ(0, static_cast<int>(map.Size()));
    4622          10 :     CHECK(expected == removed);
    4623          20 :     removed = map.Remove(7);
    4624          10 :     CHECK(removed.IsEmpty());
    4625          20 :     map.Set(8, expected);
    4626          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4627          20 :     map.Set(8, expected);
    4628          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4629             :     {
    4630             :       typename Map::PersistentValueReference ref;
    4631          10 :       Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
    4632          30 :       removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
    4633          10 :       CHECK_EQ(1, static_cast<int>(map.Size()));
    4634          10 :       CHECK(expected == removed);
    4635          20 :       CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
    4636             :     }
    4637             :   }
    4638          10 :   CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4639             :   if (map.IsWeak()) {
    4640           5 :     CcTest::PreciseCollectAllGarbage();
    4641             :   } else {
    4642           5 :     map.Clear();
    4643             :   }
    4644          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4645          10 :   CHECK_EQ(initial_handle_count, global_handles->handles_count());
    4646             :   {
    4647          20 :     HandleScope scope(isolate);
    4648          10 :     Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
    4649          20 :     map.Set(9, value);
    4650          10 :     map.Clear();
    4651             :   }
    4652          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4653          10 :   CHECK_EQ(initial_handle_count, global_handles->handles_count());
    4654          10 : }
    4655             : 
    4656             : }  // namespace
    4657             : 
    4658             : 
    4659       26644 : TEST(GlobalValueMap) {
    4660             :   // Default case, w/o weak callbacks:
    4661           5 :   TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
    4662             : 
    4663             :   // Custom traits with weak callbacks:
    4664             :   typedef v8::GlobalValueMap<int, v8::Object,
    4665             :                              PhantomStdMapTraits<int, v8::Object>> WeakMap;
    4666           5 :   TestGlobalValueMap<WeakMap>();
    4667           5 : }
    4668             : 
    4669             : 
    4670       26644 : TEST(PersistentValueVector) {
    4671           5 :   LocalContext env;
    4672           5 :   v8::Isolate* isolate = env->GetIsolate();
    4673             :   v8::internal::GlobalHandles* global_handles =
    4674             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4675             :   size_t handle_count = global_handles->handles_count();
    4676          10 :   HandleScope scope(isolate);
    4677             : 
    4678           5 :   v8::PersistentValueVector<v8::Object> vector(isolate);
    4679             : 
    4680           5 :   Local<v8::Object> obj1 = v8::Object::New(isolate);
    4681           5 :   Local<v8::Object> obj2 = v8::Object::New(isolate);
    4682           5 :   v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
    4683             : 
    4684           5 :   CHECK(vector.IsEmpty());
    4685           5 :   CHECK_EQ(0, static_cast<int>(vector.Size()));
    4686             : 
    4687             :   vector.ReserveCapacity(3);
    4688           5 :   CHECK(vector.IsEmpty());
    4689             : 
    4690           5 :   vector.Append(obj1);
    4691           5 :   vector.Append(obj2);
    4692           5 :   vector.Append(obj1);
    4693           5 :   vector.Append(obj3.Pass());
    4694           5 :   vector.Append(obj1);
    4695             : 
    4696           5 :   CHECK(!vector.IsEmpty());
    4697           5 :   CHECK_EQ(5, static_cast<int>(vector.Size()));
    4698           5 :   CHECK(obj3.IsEmpty());
    4699          15 :   CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
    4700          15 :   CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
    4701          15 :   CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
    4702          15 :   CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
    4703             : 
    4704           5 :   CHECK_EQ(5 + handle_count, global_handles->handles_count());
    4705             : 
    4706           5 :   vector.Clear();
    4707           5 :   CHECK(vector.IsEmpty());
    4708           5 :   CHECK_EQ(0, static_cast<int>(vector.Size()));
    4709           5 :   CHECK_EQ(handle_count, global_handles->handles_count());
    4710           5 : }
    4711             : 
    4712             : 
    4713       26645 : THREADED_TEST(GlobalHandleUpcast) {
    4714           6 :   v8::Isolate* isolate = CcTest::isolate();
    4715          12 :   v8::HandleScope scope(isolate);
    4716           6 :   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
    4717             :   v8::Persistent<String> global_string(isolate, local);
    4718             :   v8::Persistent<Value>& global_value =
    4719             :       v8::Persistent<Value>::Cast(global_string);
    4720           6 :   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
    4721           6 :   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
    4722             :   global_string.Reset();
    4723           6 : }
    4724             : 
    4725             : 
    4726       26645 : THREADED_TEST(HandleEquality) {
    4727           6 :   v8::Isolate* isolate = CcTest::isolate();
    4728             :   v8::Persistent<String> global1;
    4729             :   v8::Persistent<String> global2;
    4730             :   {
    4731          12 :     v8::HandleScope scope(isolate);
    4732          12 :     global1.Reset(isolate, v8_str("str"));
    4733          12 :     global2.Reset(isolate, v8_str("str2"));
    4734             :   }
    4735           6 :   CHECK(global1 == global1);
    4736           6 :   CHECK(!(global1 != global1));
    4737             :   {
    4738          12 :     v8::HandleScope scope(isolate);
    4739             :     Local<String> local1 = Local<String>::New(isolate, global1);
    4740             :     Local<String> local2 = Local<String>::New(isolate, global2);
    4741             : 
    4742           6 :     CHECK(global1 == local1);
    4743           6 :     CHECK(!(global1 != local1));
    4744           6 :     CHECK(local1 == global1);
    4745           6 :     CHECK(!(local1 != global1));
    4746             : 
    4747           6 :     CHECK(!(global1 == local2));
    4748           6 :     CHECK(global1 != local2);
    4749           6 :     CHECK(!(local2 == global1));
    4750           6 :     CHECK(local2 != global1);
    4751             : 
    4752           6 :     CHECK(!(local1 == local2));
    4753           6 :     CHECK(local1 != local2);
    4754             : 
    4755             :     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
    4756           6 :     CHECK(local1 == anotherLocal1);
    4757           6 :     CHECK(!(local1 != anotherLocal1));
    4758             :   }
    4759             :   global1.Reset();
    4760             :   global2.Reset();
    4761           6 : }
    4762             : 
    4763             : 
    4764       26645 : THREADED_TEST(LocalHandle) {
    4765          12 :   v8::HandleScope scope(CcTest::isolate());
    4766             :   v8::Local<String> local =
    4767           6 :       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
    4768           6 :   CHECK_EQ(3, local->Length());
    4769           6 : }
    4770             : 
    4771             : 
    4772             : class WeakCallCounter {
    4773             :  public:
    4774           5 :   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
    4775             :   int id() { return id_; }
    4776          10 :   void increment() { number_of_weak_calls_++; }
    4777             :   int NumberOfWeakCalls() { return number_of_weak_calls_; }
    4778             : 
    4779             :  private:
    4780             :   int id_;
    4781             :   int number_of_weak_calls_;
    4782             : };
    4783             : 
    4784             : 
    4785             : template <typename T>
    4786          10 : struct WeakCallCounterAndPersistent {
    4787             :   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
    4788          10 :       : counter(counter) {}
    4789             :   WeakCallCounter* counter;
    4790             :   v8::Persistent<T> handle;
    4791             : };
    4792             : 
    4793             : 
    4794             : template <typename T>
    4795          10 : static void WeakPointerCallback(
    4796             :     const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
    4797          10 :   CHECK_EQ(1234, data.GetParameter()->counter->id());
    4798             :   data.GetParameter()->counter->increment();
    4799             :   data.GetParameter()->handle.Reset();
    4800          10 : }
    4801             : 
    4802       26645 : THREADED_TEST(ScriptException) {
    4803           6 :   LocalContext env;
    4804          12 :   v8::HandleScope scope(env->GetIsolate());
    4805             :   Local<Script> script = v8_compile("throw 'panama!';");
    4806          12 :   v8::TryCatch try_catch(env->GetIsolate());
    4807           6 :   v8::MaybeLocal<Value> result = script->Run(env.local());
    4808           6 :   CHECK(result.IsEmpty());
    4809           6 :   CHECK(try_catch.HasCaught());
    4810          18 :   String::Utf8Value exception_value(env->GetIsolate(), try_catch.Exception());
    4811           6 :   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
    4812           6 : }
    4813             : 
    4814             : 
    4815       26644 : TEST(TryCatchCustomException) {
    4816           5 :   LocalContext env;
    4817           5 :   v8::Isolate* isolate = env->GetIsolate();
    4818          10 :   v8::HandleScope scope(isolate);
    4819          10 :   v8::TryCatch try_catch(isolate);
    4820             :   CompileRun(
    4821             :       "function CustomError() { this.a = 'b'; }"
    4822             :       "(function f() { throw new CustomError(); })();");
    4823           5 :   CHECK(try_catch.HasCaught());
    4824          35 :   CHECK(try_catch.Exception()
    4825             :             ->ToObject(env.local())
    4826             :             .ToLocalChecked()
    4827             :             ->Get(env.local(), v8_str("a"))
    4828             :             .ToLocalChecked()
    4829             :             ->Equals(env.local(), v8_str("b"))
    4830             :             .FromJust());
    4831           5 : }
    4832             : 
    4833             : 
    4834             : bool message_received;
    4835             : 
    4836             : 
    4837           6 : static void check_message_0(v8::Local<v8::Message> message,
    4838             :                             v8::Local<Value> data) {
    4839          18 :   CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
    4840             :                      .FromJust());
    4841          18 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4842             :                      .ResourceName()
    4843             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4844             :                      .FromJust());
    4845           6 :   CHECK(!message->IsSharedCrossOrigin());
    4846           6 :   message_received = true;
    4847           6 : }
    4848             : 
    4849             : 
    4850       26645 : THREADED_TEST(MessageHandler0) {
    4851           6 :   message_received = false;
    4852          12 :   v8::HandleScope scope(CcTest::isolate());
    4853           6 :   CHECK(!message_received);
    4854           6 :   LocalContext context;
    4855           6 :   CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
    4856             :   v8::Local<v8::Script> script =
    4857           6 :       CompileWithOrigin("throw 'error'", "6.75", false);
    4858          12 :   CHECK(script->Run(context.local()).IsEmpty());
    4859           6 :   CHECK(message_received);
    4860             :   // clear out the message listener
    4861           6 :   CcTest::isolate()->RemoveMessageListeners(check_message_0);
    4862           6 : }
    4863             : 
    4864             : 
    4865           5 : static void check_message_1(v8::Local<v8::Message> message,
    4866             :                             v8::Local<Value> data) {
    4867           5 :   CHECK(data->IsNumber());
    4868          10 :   CHECK_EQ(1337,
    4869             :            data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
    4870           5 :   CHECK(!message->IsSharedCrossOrigin());
    4871           5 :   message_received = true;
    4872           5 : }
    4873             : 
    4874             : 
    4875       26644 : TEST(MessageHandler1) {
    4876           5 :   message_received = false;
    4877          10 :   v8::HandleScope scope(CcTest::isolate());
    4878           5 :   CHECK(!message_received);
    4879           5 :   CcTest::isolate()->AddMessageListener(check_message_1);
    4880           5 :   LocalContext context;
    4881             :   CompileRun("throw 1337;");
    4882           5 :   CHECK(message_received);
    4883             :   // clear out the message listener
    4884           5 :   CcTest::isolate()->RemoveMessageListeners(check_message_1);
    4885           5 : }
    4886             : 
    4887             : 
    4888           5 : static void check_message_2(v8::Local<v8::Message> message,
    4889             :                             v8::Local<Value> data) {
    4890           5 :   LocalContext context;
    4891           5 :   CHECK(data->IsObject());
    4892             :   v8::Local<v8::Value> hidden_property =
    4893             :       v8::Object::Cast(*data)
    4894           5 :           ->GetPrivate(
    4895             :               context.local(),
    4896           5 :               v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
    4897           5 :           .ToLocalChecked();
    4898          15 :   CHECK(v8_str("hidden value")
    4899             :             ->Equals(context.local(), hidden_property)
    4900             :             .FromJust());
    4901           5 :   CHECK(!message->IsSharedCrossOrigin());
    4902           5 :   message_received = true;
    4903           5 : }
    4904             : 
    4905             : 
    4906       26644 : TEST(MessageHandler2) {
    4907           5 :   message_received = false;
    4908          10 :   v8::HandleScope scope(CcTest::isolate());
    4909           5 :   CHECK(!message_received);
    4910           5 :   CcTest::isolate()->AddMessageListener(check_message_2);
    4911           5 :   LocalContext context;
    4912           5 :   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
    4913             :   v8::Object::Cast(*error)
    4914          10 :       ->SetPrivate(context.local(),
    4915             :                    v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
    4916          15 :                    v8_str("hidden value"))
    4917             :       .FromJust();
    4918          20 :   CHECK(context->Global()
    4919             :             ->Set(context.local(), v8_str("error"), error)
    4920             :             .FromJust());
    4921             :   CompileRun("throw error;");
    4922           5 :   CHECK(message_received);
    4923             :   // clear out the message listener
    4924           5 :   CcTest::isolate()->RemoveMessageListeners(check_message_2);
    4925           5 : }
    4926             : 
    4927             : 
    4928           5 : static void check_message_3(v8::Local<v8::Message> message,
    4929             :                             v8::Local<Value> data) {
    4930           5 :   CHECK(message->IsSharedCrossOrigin());
    4931          10 :   CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
    4932          10 :   CHECK(message->GetScriptOrigin().Options().IsOpaque());
    4933          15 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4934             :                      .ResourceName()
    4935             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4936             :                      .FromJust());
    4937          15 :   CHECK_EQ(7.40, message->GetScriptOrigin()
    4938             :                      .SourceMapUrl()
    4939             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4940             :                      .FromJust());
    4941           5 :   message_received = true;
    4942           5 : }
    4943             : 
    4944             : 
    4945       26644 : TEST(MessageHandler3) {
    4946           5 :   message_received = false;
    4947           5 :   v8::Isolate* isolate = CcTest::isolate();
    4948          10 :   v8::HandleScope scope(isolate);
    4949           5 :   CHECK(!message_received);
    4950           5 :   isolate->AddMessageListener(check_message_3);
    4951           5 :   LocalContext context;
    4952             :   v8::ScriptOrigin origin =
    4953             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4954             :                        v8::Integer::New(isolate, 2), v8::True(isolate),
    4955           5 :                        Local<v8::Integer>(), v8_str("7.40"), v8::True(isolate));
    4956             :   v8::Local<v8::Script> script =
    4957          10 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
    4958             :           .ToLocalChecked();
    4959          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4960           5 :   CHECK(message_received);
    4961             :   // clear out the message listener
    4962           5 :   isolate->RemoveMessageListeners(check_message_3);
    4963           5 : }
    4964             : 
    4965             : 
    4966           5 : static void check_message_4(v8::Local<v8::Message> message,
    4967             :                             v8::Local<Value> data) {
    4968           5 :   CHECK(!message->IsSharedCrossOrigin());
    4969          15 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4970             :                      .ResourceName()
    4971             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4972             :                      .FromJust());
    4973           5 :   message_received = true;
    4974           5 : }
    4975             : 
    4976             : 
    4977       26644 : TEST(MessageHandler4) {
    4978           5 :   message_received = false;
    4979           5 :   v8::Isolate* isolate = CcTest::isolate();
    4980          10 :   v8::HandleScope scope(isolate);
    4981           5 :   CHECK(!message_received);
    4982           5 :   isolate->AddMessageListener(check_message_4);
    4983           5 :   LocalContext context;
    4984             :   v8::ScriptOrigin origin =
    4985             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4986           5 :                        v8::Integer::New(isolate, 2), v8::False(isolate));
    4987             :   v8::Local<v8::Script> script =
    4988          10 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
    4989             :           .ToLocalChecked();
    4990          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4991           5 :   CHECK(message_received);
    4992             :   // clear out the message listener
    4993           5 :   isolate->RemoveMessageListeners(check_message_4);
    4994           5 : }
    4995             : 
    4996             : 
    4997           5 : static void check_message_5a(v8::Local<v8::Message> message,
    4998             :                              v8::Local<Value> data) {
    4999           5 :   CHECK(message->IsSharedCrossOrigin());
    5000          15 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    5001             :                      .ResourceName()
    5002             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    5003             :                      .FromJust());
    5004           5 :   message_received = true;
    5005           5 : }
    5006             : 
    5007             : 
    5008           5 : static void check_message_5b(v8::Local<v8::Message> message,
    5009             :                              v8::Local<Value> data) {
    5010           5 :   CHECK(!message->IsSharedCrossOrigin());
    5011          15 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    5012             :                      .ResourceName()
    5013             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    5014             :                      .FromJust());
    5015           5 :   message_received = true;
    5016           5 : }
    5017             : 
    5018             : 
    5019       26644 : TEST(MessageHandler5) {
    5020           5 :   message_received = false;
    5021           5 :   v8::Isolate* isolate = CcTest::isolate();
    5022          10 :   v8::HandleScope scope(isolate);
    5023           5 :   CHECK(!message_received);
    5024           5 :   isolate->AddMessageListener(check_message_5a);
    5025           5 :   LocalContext context;
    5026             :   v8::ScriptOrigin origin1 =
    5027             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    5028           5 :                        v8::Integer::New(isolate, 2), v8::True(isolate));
    5029             :   v8::Local<v8::Script> script =
    5030          10 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
    5031             :           .ToLocalChecked();
    5032          10 :   CHECK(script->Run(context.local()).IsEmpty());
    5033           5 :   CHECK(message_received);
    5034             :   // clear out the message listener
    5035           5 :   isolate->RemoveMessageListeners(check_message_5a);
    5036             : 
    5037           5 :   message_received = false;
    5038           5 :   isolate->AddMessageListener(check_message_5b);
    5039             :   v8::ScriptOrigin origin2 =
    5040             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    5041           5 :                        v8::Integer::New(isolate, 2), v8::False(isolate));
    5042          10 :   script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
    5043             :                .ToLocalChecked();
    5044          10 :   CHECK(script->Run(context.local()).IsEmpty());
    5045           5 :   CHECK(message_received);
    5046             :   // clear out the message listener
    5047           5 :   isolate->RemoveMessageListeners(check_message_5b);
    5048           5 : }
    5049             : 
    5050             : 
    5051       26645 : THREADED_TEST(GetSetProperty) {
    5052           6 :   LocalContext context;
    5053           6 :   v8::Isolate* isolate = context->GetIsolate();
    5054          12 :   v8::HandleScope scope(isolate);
    5055          24 :   CHECK(context->Global()
    5056             :             ->Set(context.local(), v8_str("foo"), v8_num(14))
    5057             :             .FromJust());
    5058          24 :   CHECK(context->Global()
    5059             :             ->Set(context.local(), v8_str("12"), v8_num(92))
    5060             :             .FromJust());
    5061          24 :   CHECK(context->Global()
    5062             :             ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
    5063             :             .FromJust());
    5064          24 :   CHECK(context->Global()
    5065             :             ->Set(context.local(), v8_num(13), v8_num(56))
    5066             :             .FromJust());
    5067             :   Local<Value> foo = CompileRun("this.foo");
    5068          12 :   CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
    5069             :   Local<Value> twelve = CompileRun("this[12]");
    5070          12 :   CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
    5071             :   Local<Value> sixteen = CompileRun("this[16]");
    5072          12 :   CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
    5073             :   Local<Value> thirteen = CompileRun("this[13]");
    5074          12 :   CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
    5075          30 :   CHECK_EQ(92, context->Global()
    5076             :                    ->Get(context.local(), v8::Integer::New(isolate, 12))
    5077             :                    .ToLocalChecked()
    5078             :                    ->Int32Value(context.local())
    5079             :                    .FromJust());
    5080          30 :   CHECK_EQ(92, context->Global()
    5081             :                    ->Get(context.local(), v8_str("12"))
    5082             :                    .ToLocalChecked()
    5083             :                    ->Int32Value(context.local())
    5084             :                    .FromJust());
    5085          30 :   CHECK_EQ(92, context->Global()
    5086             :                    ->Get(context.local(), v8_num(12))
    5087             :                    .ToLocalChecked()
    5088             :                    ->Int32Value(context.local())
    5089             :                    .FromJust());
    5090          30 :   CHECK_EQ(32, context->Global()
    5091             :                    ->Get(context.local(), v8::Integer::New(isolate, 16))
    5092             :                    .ToLocalChecked()
    5093             :                    ->Int32Value(context.local())
    5094             :                    .FromJust());
    5095          30 :   CHECK_EQ(32, context->Global()
    5096             :                    ->Get(context.local(), v8_str("16"))
    5097             :                    .ToLocalChecked()
    5098             :                    ->Int32Value(context.local())
    5099             :                    .FromJust());
    5100          30 :   CHECK_EQ(32, context->Global()
    5101             :                    ->Get(context.local(), v8_num(16))
    5102             :                    .ToLocalChecked()
    5103             :                    ->Int32Value(context.local())
    5104             :                    .FromJust());
    5105          30 :   CHECK_EQ(56, context->Global()
    5106             :                    ->Get(context.local(), v8::Integer::New(isolate, 13))
    5107             :                    .ToLocalChecked()
    5108             :                    ->Int32Value(context.local())
    5109             :                    .FromJust());
    5110          30 :   CHECK_EQ(56, context->Global()
    5111             :                    ->Get(context.local(), v8_str("13"))
    5112             :                    .ToLocalChecked()
    5113             :                    ->Int32Value(context.local())
    5114             :                    .FromJust());
    5115          30 :   CHECK_EQ(56, context->Global()
    5116             :                    ->Get(context.local(), v8_num(13))
    5117             :                    .ToLocalChecked()
    5118             :                    ->Int32Value(context.local())
    5119             :                    .FromJust());
    5120           6 : }
    5121             : 
    5122             : 
    5123       26645 : THREADED_TEST(PropertyAttributes) {
    5124           6 :   LocalContext context;
    5125          12 :   v8::HandleScope scope(context->GetIsolate());
    5126             :   // none
    5127           6 :   Local<String> prop = v8_str("none");
    5128          24 :   CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
    5129          18 :   CHECK_EQ(v8::None, context->Global()
    5130             :                          ->GetPropertyAttributes(context.local(), prop)
    5131             :                          .FromJust());
    5132             :   // read-only
    5133           6 :   prop = v8_str("read_only");
    5134          12 :   context->Global()
    5135          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
    5136             :       .FromJust();
    5137          24 :   CHECK_EQ(7, context->Global()
    5138             :                   ->Get(context.local(), prop)
    5139             :                   .ToLocalChecked()
    5140             :                   ->Int32Value(context.local())
    5141             :                   .FromJust());
    5142          18 :   CHECK_EQ(v8::ReadOnly, context->Global()
    5143             :                              ->GetPropertyAttributes(context.local(), prop)
    5144             :                              .FromJust());
    5145             :   CompileRun("read_only = 9");
    5146          24 :   CHECK_EQ(7, context->Global()
    5147             :                   ->Get(context.local(), prop)
    5148             :                   .ToLocalChecked()
    5149             :                   ->Int32Value(context.local())
    5150             :                   .FromJust());
    5151          24 :   CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
    5152          24 :   CHECK_EQ(7, context->Global()
    5153             :                   ->Get(context.local(), prop)
    5154             :                   .ToLocalChecked()
    5155             :                   ->Int32Value(context.local())
    5156             :                   .FromJust());
    5157             :   // dont-delete
    5158           6 :   prop = v8_str("dont_delete");
    5159          12 :   context->Global()
    5160          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
    5161             :       .FromJust();
    5162          24 :   CHECK_EQ(13, context->Global()
    5163             :                    ->Get(context.local(), prop)
    5164             :                    .ToLocalChecked()
    5165             :                    ->Int32Value(context.local())
    5166             :                    .FromJust());
    5167             :   CompileRun("delete dont_delete");
    5168          24 :   CHECK_EQ(13, context->Global()
    5169             :                    ->Get(context.local(), prop)
    5170             :                    .ToLocalChecked()
    5171             :                    ->Int32Value(context.local())
    5172             :                    .FromJust());
    5173          18 :   CHECK_EQ(v8::DontDelete, context->Global()
    5174             :                                ->GetPropertyAttributes(context.local(), prop)
    5175             :                                .FromJust());
    5176             :   // dont-enum
    5177           6 :   prop = v8_str("dont_enum");
    5178          12 :   context->Global()
    5179          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
    5180             :       .FromJust();
    5181          18 :   CHECK_EQ(v8::DontEnum, context->Global()
    5182             :                              ->GetPropertyAttributes(context.local(), prop)
    5183             :                              .FromJust());
    5184             :   // absent
    5185           6 :   prop = v8_str("absent");
    5186          18 :   CHECK_EQ(v8::None, context->Global()
    5187             :                          ->GetPropertyAttributes(context.local(), prop)
    5188             :                          .FromJust());
    5189           6 :   Local<Value> fake_prop = v8_num(1);
    5190          18 :   CHECK_EQ(v8::None, context->Global()
    5191             :                          ->GetPropertyAttributes(context.local(), fake_prop)
    5192             :                          .FromJust());
    5193             :   // exception
    5194          12 :   TryCatch try_catch(context->GetIsolate());
    5195             :   Local<Value> exception =
    5196           6 :       CompileRun("({ toString: function() { throw 'exception';} })");
    5197          18 :   CHECK(context->Global()
    5198             :             ->GetPropertyAttributes(context.local(), exception)
    5199             :             .IsNothing());
    5200           6 :   CHECK(try_catch.HasCaught());
    5201             :   String::Utf8Value exception_value(context->GetIsolate(),
    5202          18 :                                     try_catch.Exception());
    5203           6 :   CHECK_EQ(0, strcmp("exception", *exception_value));
    5204           6 :   try_catch.Reset();
    5205           6 : }
    5206             : 
    5207             : 
    5208       26645 : THREADED_TEST(Array) {
    5209           6 :   LocalContext context;
    5210          12 :   v8::HandleScope scope(context->GetIsolate());
    5211           6 :   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
    5212           6 :   CHECK_EQ(0u, array->Length());
    5213          12 :   CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
    5214          12 :   CHECK(!array->Has(context.local(), 0).FromJust());
    5215          12 :   CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
    5216          12 :   CHECK(!array->Has(context.local(), 100).FromJust());
    5217          18 :   CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
    5218           6 :   CHECK_EQ(3u, array->Length());
    5219          12 :   CHECK(!array->Has(context.local(), 0).FromJust());
    5220          12 :   CHECK(!array->Has(context.local(), 1).FromJust());
    5221          12 :   CHECK(array->Has(context.local(), 2).FromJust());
    5222          18 :   CHECK_EQ(7, array->Get(context.local(), 2)
    5223             :                   .ToLocalChecked()
    5224             :                   ->Int32Value(context.local())
    5225             :                   .FromJust());
    5226             :   Local<Value> obj = CompileRun("[1, 2, 3]");
    5227             :   Local<v8::Array> arr = obj.As<v8::Array>();
    5228           6 :   CHECK_EQ(3u, arr->Length());
    5229          18 :   CHECK_EQ(1, arr->Get(context.local(), 0)
    5230             :                   .ToLocalChecked()
    5231             :                   ->Int32Value(context.local())
    5232             :                   .FromJust());
    5233          18 :   CHECK_EQ(2, arr->Get(context.local(), 1)
    5234             :                   .ToLocalChecked()
    5235             :                   ->Int32Value(context.local())
    5236             :                   .FromJust());
    5237          18 :   CHECK_EQ(3, arr->Get(context.local(), 2)
    5238             :                   .ToLocalChecked()
    5239             :                   ->Int32Value(context.local())
    5240             :                   .FromJust());
    5241           6 :   array = v8::Array::New(context->GetIsolate(), 27);
    5242           6 :   CHECK_EQ(27u, array->Length());
    5243           6 :   array = v8::Array::New(context->GetIsolate(), -27);
    5244           6 :   CHECK_EQ(0u, array->Length());
    5245             : 
    5246          12 :   std::vector<Local<Value>> vector = {v8_num(1), v8_num(2), v8_num(3)};
    5247           6 :   array = v8::Array::New(context->GetIsolate(), vector.data(), vector.size());
    5248          12 :   CHECK_EQ(vector.size(), array->Length());
    5249          18 :   CHECK_EQ(1, arr->Get(context.local(), 0)
    5250             :                   .ToLocalChecked()
    5251             :                   ->Int32Value(context.local())
    5252             :                   .FromJust());
    5253          18 :   CHECK_EQ(2, arr->Get(context.local(), 1)
    5254             :                   .ToLocalChecked()
    5255             :                   ->Int32Value(context.local())
    5256             :                   .FromJust());
    5257          18 :   CHECK_EQ(3, arr->Get(context.local(), 2)
    5258             :                   .ToLocalChecked()
    5259             :                   ->Int32Value(context.local())
    5260             :                   .FromJust());
    5261           6 : }
    5262             : 
    5263             : 
    5264          30 : void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5265          30 :   v8::EscapableHandleScope scope(args.GetIsolate());
    5266          30 :   ApiTestFuzzer::Fuzz();
    5267          30 :   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
    5268         150 :   for (int i = 0; i < args.Length(); i++) {
    5269         180 :     CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
    5270             :               .FromJust());
    5271             :   }
    5272             :   args.GetReturnValue().Set(scope.Escape(result));
    5273          30 : }
    5274             : 
    5275             : 
    5276       26645 : THREADED_TEST(Vector) {
    5277           6 :   v8::Isolate* isolate = CcTest::isolate();
    5278          12 :   v8::HandleScope scope(isolate);
    5279           6 :   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
    5280          18 :   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
    5281           6 :   LocalContext context(nullptr, global);
    5282             : 
    5283             :   const char* fun = "f()";
    5284             :   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
    5285           6 :   CHECK_EQ(0u, a0->Length());
    5286             : 
    5287             :   const char* fun2 = "f(11)";
    5288             :   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
    5289           6 :   CHECK_EQ(1u, a1->Length());
    5290          18 :   CHECK_EQ(11, a1->Get(context.local(), 0)
    5291             :                    .ToLocalChecked()
    5292             :                    ->Int32Value(context.local())
    5293             :                    .FromJust());
    5294             : 
    5295             :   const char* fun3 = "f(12, 13)";
    5296             :   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
    5297           6 :   CHECK_EQ(2u, a2->Length());
    5298          18 :   CHECK_EQ(12, a2->Get(context.local(), 0)
    5299             :                    .ToLocalChecked()
    5300             :                    ->Int32Value(context.local())
    5301             :                    .FromJust());
    5302          18 :   CHECK_EQ(13, a2->Get(context.local(), 1)
    5303             :                    .ToLocalChecked()
    5304             :                    ->Int32Value(context.local())
    5305             :                    .FromJust());
    5306             : 
    5307             :   const char* fun4 = "f(14, 15, 16)";
    5308             :   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
    5309           6 :   CHECK_EQ(3u, a3->Length());
    5310          18 :   CHECK_EQ(14, a3->Get(context.local(), 0)
    5311             :                    .ToLocalChecked()
    5312             :                    ->Int32Value(context.local())
    5313             :                    .FromJust());
    5314          18 :   CHECK_EQ(15, a3->Get(context.local(), 1)
    5315             :                    .ToLocalChecked()
    5316             :                    ->Int32Value(context.local())
    5317             :                    .FromJust());
    5318          18 :   CHECK_EQ(16, a3->Get(context.local(), 2)
    5319             :                    .ToLocalChecked()
    5320             :                    ->Int32Value(context.local())
    5321             :                    .FromJust());
    5322             : 
    5323             :   const char* fun5 = "f(17, 18, 19, 20)";
    5324             :   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
    5325           6 :   CHECK_EQ(4u, a4->Length());
    5326          18 :   CHECK_EQ(17, a4->Get(context.local(), 0)
    5327             :                    .ToLocalChecked()
    5328             :                    ->Int32Value(context.local())
    5329             :                    .FromJust());
    5330          18 :   CHECK_EQ(18, a4->Get(context.local(), 1)
    5331             :                    .ToLocalChecked()
    5332             :                    ->Int32Value(context.local())
    5333             :                    .FromJust());
    5334          18 :   CHECK_EQ(19, a4->Get(context.local(), 2)
    5335             :                    .ToLocalChecked()
    5336             :                    ->Int32Value(context.local())
    5337             :                    .FromJust());
    5338          18 :   CHECK_EQ(20, a4->Get(context.local(), 3)
    5339             :                    .ToLocalChecked()
    5340             :                    ->Int32Value(context.local())
    5341             :                    .FromJust());
    5342           6 : }
    5343             : 
    5344             : 
    5345       26645 : THREADED_TEST(FunctionCall) {
    5346           6 :   LocalContext context;
    5347           6 :   v8::Isolate* isolate = context->GetIsolate();
    5348          12 :   v8::HandleScope scope(isolate);
    5349             :   CompileRun(
    5350             :       "function Foo() {"
    5351             :       "  var result = [];"
    5352             :       "  for (var i = 0; i < arguments.length; i++) {"
    5353             :       "    result.push(arguments[i]);"
    5354             :       "  }"
    5355             :       "  return result;"
    5356             :       "}"
    5357             :       "function ReturnThisSloppy() {"
    5358             :       "  return this;"
    5359             :       "}"
    5360             :       "function ReturnThisStrict() {"
    5361             :       "  'use strict';"
    5362             :       "  return this;"
    5363             :       "}");
    5364             :   Local<Function> Foo = Local<Function>::Cast(
    5365          24 :       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
    5366             :   Local<Function> ReturnThisSloppy = Local<Function>::Cast(
    5367          12 :       context->Global()
    5368          18 :           ->Get(context.local(), v8_str("ReturnThisSloppy"))
    5369             :           .ToLocalChecked());
    5370             :   Local<Function> ReturnThisStrict = Local<Function>::Cast(
    5371          12 :       context->Global()
    5372          18 :           ->Get(context.local(), v8_str("ReturnThisStrict"))
    5373             :           .ToLocalChecked());
    5374             : 
    5375             :   v8::Local<Value>* args0 = nullptr;
    5376             :   Local<v8::Array> a0 = Local<v8::Array>::Cast(
    5377          12 :       Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
    5378           6 :   CHECK_EQ(0u, a0->Length());
    5379             : 
    5380           6 :   v8::Local<Value> args1[] = {v8_num(1.1)};
    5381             :   Local<v8::Array> a1 = Local<v8::Array>::Cast(
    5382          12 :       Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
    5383           6 :   CHECK_EQ(1u, a1->Length());
    5384          24 :   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
    5385             :                     .ToLocalChecked()
    5386             :                     ->NumberValue(context.local())
    5387             :                     .FromJust());
    5388             : 
    5389           6 :   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
    5390             :   Local<v8::Array> a2 = Local<v8::Array>::Cast(
    5391          12 :       Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
    5392           6 :   CHECK_EQ(2u, a2->Length());
    5393          24 :   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
    5394             :                     .ToLocalChecked()
    5395             :                     ->NumberValue(context.local())
    5396             :                     .FromJust());
    5397          24 :   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
    5398             :                     .ToLocalChecked()
    5399             :                     ->NumberValue(context.local())
    5400             :                     .FromJust());
    5401             : 
    5402           6 :   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
    5403             :   Local<v8::Array> a3 = Local<v8::Array>::Cast(
    5404          12 :       Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
    5405           6 :   CHECK_EQ(3u, a3->Length());
    5406          24 :   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
    5407             :                     .ToLocalChecked()
    5408             :                     ->NumberValue(context.local())
    5409             :                     .FromJust());
    5410          24 :   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
    5411             :                     .ToLocalChecked()
    5412             :                     ->NumberValue(context.local())
    5413             :                     .FromJust());
    5414          24 :   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
    5415             :                     .ToLocalChecked()
    5416             :                     ->NumberValue(context.local())
    5417             :                     .FromJust());
    5418             : 
    5419             :   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
    5420           6 :                               v8_num(10.11)};
    5421             :   Local<v8::Array> a4 = Local<v8::Array>::Cast(
    5422          12 :       Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
    5423           6 :   CHECK_EQ(4u, a4->Length());
    5424          24 :   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
    5425             :                     .ToLocalChecked()
    5426             :                     ->NumberValue(context.local())
    5427             :                     .FromJust());
    5428          24 :   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
    5429             :                     .ToLocalChecked()
    5430             :                     ->NumberValue(context.local())
    5431             :                     .FromJust());
    5432          24 :   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
    5433             :                     .ToLocalChecked()
    5434             :                     ->NumberValue(context.local())
    5435             :                     .FromJust());
    5436          24 :   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
    5437             :                       .ToLocalChecked()
    5438             :                       ->NumberValue(context.local())
    5439             :                       .FromJust());
    5440             : 
    5441             :   Local<v8::Value> r1 =
    5442             :       ReturnThisSloppy
    5443          12 :           ->Call(context.local(), v8::Undefined(isolate), 0, nullptr)
    5444             :           .ToLocalChecked();
    5445          12 :   CHECK(r1->StrictEquals(context->Global()));
    5446             :   Local<v8::Value> r2 =
    5447          12 :       ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, nullptr)
    5448             :           .ToLocalChecked();
    5449          12 :   CHECK(r2->StrictEquals(context->Global()));
    5450             :   Local<v8::Value> r3 =
    5451          12 :       ReturnThisSloppy->Call(context.local(), v8_num(42), 0, nullptr)
    5452             :           .ToLocalChecked();
    5453           6 :   CHECK(r3->IsNumberObject());
    5454           6 :   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
    5455             :   Local<v8::Value> r4 =
    5456          18 :       ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, nullptr)
    5457             :           .ToLocalChecked();
    5458           6 :   CHECK(r4->IsStringObject());
    5459          18 :   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
    5460             :   Local<v8::Value> r5 =
    5461          12 :       ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, nullptr)
    5462             :           .ToLocalChecked();
    5463           6 :   CHECK(r5->IsBooleanObject());
    5464           6 :   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
    5465             : 
    5466             :   Local<v8::Value> r6 =
    5467             :       ReturnThisStrict
    5468          12 :           ->Call(context.local(), v8::Undefined(isolate), 0, nullptr)
    5469             :           .ToLocalChecked();
    5470           6 :   CHECK(r6->IsUndefined());
    5471             :   Local<v8::Value> r7 =
    5472          12 :       ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, nullptr)
    5473             :           .ToLocalChecked();
    5474           6 :   CHECK(r7->IsNull());
    5475             :   Local<v8::Value> r8 =
    5476          12 :       ReturnThisStrict->Call(context.local(), v8_num(42), 0, nullptr)
    5477             :           .ToLocalChecked();
    5478           6 :   CHECK(r8->StrictEquals(v8_num(42)));
    5479             :   Local<v8::Value> r9 =
    5480          18 :       ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, nullptr)
    5481             :           .ToLocalChecked();
    5482          12 :   CHECK(r9->StrictEquals(v8_str("hello")));
    5483             :   Local<v8::Value> r10 =
    5484          12 :       ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, nullptr)
    5485             :           .ToLocalChecked();
    5486           6 :   CHECK(r10->StrictEquals(v8::True(isolate)));
    5487           6 : }
    5488             : 
    5489             : 
    5490       26645 : THREADED_TEST(ConstructCall) {
    5491           6 :   LocalContext context;
    5492           6 :   v8::Isolate* isolate = context->GetIsolate();
    5493          12 :   v8::HandleScope scope(isolate);
    5494             :   CompileRun(
    5495             :       "function Foo() {"
    5496             :       "  var result = [];"
    5497             :       "  for (var i = 0; i < arguments.length; i++) {"
    5498             :       "    result.push(arguments[i]);"
    5499             :       "  }"
    5500             :       "  return result;"
    5501             :       "}");
    5502             :   Local<Function> Foo = Local<Function>::Cast(
    5503          24 :       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
    5504             : 
    5505             :   v8::Local<Value>* args0 = nullptr;
    5506             :   Local<v8::Array> a0 = Local<v8::Array>::Cast(
    5507           6 :       Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
    5508           6 :   CHECK_EQ(0u, a0->Length());
    5509             : 
    5510           6 :   v8::Local<Value> args1[] = {v8_num(1.1)};
    5511             :   Local<v8::Array> a1 = Local<v8::Array>::Cast(
    5512           6 :       Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
    5513           6 :   CHECK_EQ(1u, a1->Length());
    5514          24 :   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
    5515             :                     .ToLocalChecked()
    5516             :                     ->NumberValue(context.local())
    5517             :                     .FromJust());
    5518             : 
    5519           6 :   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
    5520             :   Local<v8::Array> a2 = Local<v8::Array>::Cast(
    5521           6 :       Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
    5522           6 :   CHECK_EQ(2u, a2->Length());
    5523          24 :   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
    5524             :                     .ToLocalChecked()
    5525             :                     ->NumberValue(context.local())
    5526             :                     .FromJust());
    5527          24 :   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
    5528             :                     .ToLocalChecked()
    5529             :                     ->NumberValue(context.local())
    5530             :                     .FromJust());
    5531             : 
    5532           6 :   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
    5533             :   Local<v8::Array> a3 = Local<v8::Array>::Cast(
    5534           6 :       Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
    5535           6 :   CHECK_EQ(3u, a3->Length());
    5536          24 :   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
    5537             :                     .ToLocalChecked()
    5538             :                     ->NumberValue(context.local())
    5539             :                     .FromJust());
    5540          24 :   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
    5541             :                     .ToLocalChecked()
    5542             :                     ->NumberValue(context.local())
    5543             :                     .FromJust());
    5544          24 :   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
    5545             :                     .ToLocalChecked()
    5546             :                     ->NumberValue(context.local())
    5547             :                     .FromJust());
    5548             : 
    5549             :   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
    5550           6 :                               v8_num(10.11)};
    5551             :   Local<v8::Array> a4 = Local<v8::Array>::Cast(
    5552           6 :       Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
    5553           6 :   CHECK_EQ(4u, a4->Length());
    5554          24 :   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
    5555             :                     .ToLocalChecked()
    5556             :                     ->NumberValue(context.local())
    5557             :                     .FromJust());
    5558          24 :   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
    5559             :                     .ToLocalChecked()
    5560             :                     ->NumberValue(context.local())
    5561             :                     .FromJust());
    5562          24 :   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
    5563             :                     .ToLocalChecked()
    5564             :                     ->NumberValue(context.local())
    5565             :                     .FromJust());
    5566          24 :   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
    5567             :                       .ToLocalChecked()
    5568             :                       ->NumberValue(context.local())
    5569             :                       .FromJust());
    5570           6 : }
    5571             : 
    5572             : 
    5573       26645 : THREADED_TEST(ConversionNumber) {
    5574           6 :   LocalContext env;
    5575           6 :   v8::Isolate* isolate = env->GetIsolate();
    5576          12 :   v8::HandleScope scope(isolate);
    5577             :   // Very large number.
    5578             :   CompileRun("var obj = Math.pow(2,32) * 1237;");
    5579             :   Local<Value> obj =
    5580          24 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5581          12 :   CHECK_EQ(5312874545152.0,
    5582             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5583          12 :   CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5584          12 :   CHECK_EQ(0, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5585             :   // Large number.
    5586             :   CompileRun("var obj = -1234567890123;");
    5587          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5588          12 :   CHECK_EQ(-1234567890123.0,
    5589             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5590          12 :   CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5591          18 :   CHECK_EQ(2382691125, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5592             :   // Small positive integer.
    5593             :   CompileRun("var obj = 42;");
    5594          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5595          12 :   CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5596          12 :   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5597          12 :   CHECK_EQ(42, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5598             :   // Negative integer.
    5599             :   CompileRun("var obj = -37;");
    5600          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5601          12 :   CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5602          12 :   CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5603          18 :   CHECK_EQ(4294967259, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5604             :   // Positive non-int32 integer.
    5605             :   CompileRun("var obj = 0x81234567;");
    5606          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5607          12 :   CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5608          12 :   CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5609          18 :   CHECK_EQ(2166572391, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5610             :   // Fraction.
    5611             :   CompileRun("var obj = 42.3;");
    5612          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5613          12 :   CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5614          12 :   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5615          12 :   CHECK_EQ(42, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5616             :   // Large negative fraction.
    5617             :   CompileRun("var obj = -5726623061.75;");
    5618          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5619          12 :   CHECK_EQ(-5726623061.75,
    5620             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5621          12 :   CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5622          18 :   CHECK_EQ(2863311531, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5623           6 : }
    5624             : 
    5625             : 
    5626       26645 : THREADED_TEST(isNumberType) {
    5627           6 :   LocalContext env;
    5628          12 :   v8::HandleScope scope(env->GetIsolate());
    5629             :   // Very large number.
    5630             :   CompileRun("var obj = Math.pow(2,32) * 1237;");
    5631             :   Local<Value> obj =
    5632          24 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5633           6 :   CHECK(!obj->IsInt32());
    5634           6 :   CHECK(!obj->IsUint32());
    5635             :   // Large negative number.
    5636             :   CompileRun("var obj = -1234567890123;");
    5637          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5638           6 :   CHECK(!obj->IsInt32());
    5639           6 :   CHECK(!obj->IsUint32());
    5640             :   // Small positive integer.
    5641             :   CompileRun("var obj = 42;");
    5642          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5643           6 :   CHECK(obj->IsInt32());
    5644           6 :   CHECK(obj->IsUint32());
    5645             :   // Negative integer.
    5646             :   CompileRun("var obj = -37;");
    5647          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5648           6 :   CHECK(obj->IsInt32());
    5649           6 :   CHECK(!obj->IsUint32());
    5650             :   // Positive non-int32 integer.
    5651             :   CompileRun("var obj = 0x81234567;");
    5652          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5653           6 :   CHECK(!obj->IsInt32());
    5654           6 :   CHECK(obj->IsUint32());
    5655             :   // Fraction.
    5656             :   CompileRun("var obj = 42.3;");
    5657          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5658           6 :   CHECK(!obj->IsInt32());
    5659           6 :   CHECK(!obj->IsUint32());
    5660             :   // Large negative fraction.
    5661             :   CompileRun("var obj = -5726623061.75;");
    5662          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5663           6 :   CHECK(!obj->IsInt32());
    5664           6 :   CHECK(!obj->IsUint32());
    5665             :   // Positive zero
    5666             :   CompileRun("var obj = 0.0;");
    5667          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5668           6 :   CHECK(obj->IsInt32());
    5669           6 :   CHECK(obj->IsUint32());
    5670             :   // Negative zero
    5671             :   CompileRun("var obj = -0.0;");
    5672          24 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5673           6 :   CHECK(!obj->IsInt32());
    5674           6 :   CHECK(!obj->IsUint32());
    5675           6 : }
    5676             : 
    5677       26645 : THREADED_TEST(IntegerType) {
    5678           6 :   LocalContext env;
    5679          12 :   v8::HandleScope scope(env->GetIsolate());
    5680             :   Local<Value> result;
    5681             : 
    5682             :   // Small positive integer
    5683             :   result = CompileRun("42;");
    5684           6 :   CHECK(result->IsNumber());
    5685           6 :   CHECK_EQ(42, result.As<v8::Integer>()->Value());
    5686             :   // Small negative integer
    5687             :   result = CompileRun("-42;");
    5688           6 :   CHECK(result->IsNumber());
    5689           6 :   CHECK_EQ(-42, result.As<v8::Integer>()->Value());
    5690             :   // Positive non-int32 integer
    5691             :   result = CompileRun("1099511627776;");
    5692           6 :   CHECK(result->IsNumber());
    5693           6 :   CHECK_EQ(1099511627776, result.As<v8::Integer>()->Value());
    5694             :   // Negative non-int32 integer
    5695             :   result = CompileRun("-1099511627776;");
    5696           6 :   CHECK(result->IsNumber());
    5697           6 :   CHECK_EQ(-1099511627776, result.As<v8::Integer>()->Value());
    5698             :   // Positive non-integer
    5699             :   result = CompileRun("3.14;");
    5700           6 :   CHECK(result->IsNumber());
    5701           6 :   CHECK_EQ(3, result.As<v8::Integer>()->Value());
    5702             :   // Negative non-integer
    5703             :   result = CompileRun("-3.14;");
    5704           6 :   CHECK(result->IsNumber());
    5705           6 :   CHECK_EQ(-3, result.As<v8::Integer>()->Value());
    5706           6 : }
    5707             : 
    5708          54 : static void CheckUncle(v8::Isolate* isolate, v8::TryCatch* try_catch) {
    5709          54 :   CHECK(try_catch->HasCaught());
    5710         108 :   String::Utf8Value str_value(isolate, try_catch->Exception());
    5711          54 :   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
    5712          54 :   try_catch->Reset();
    5713          54 : }
    5714             : 
    5715       26645 : THREADED_TEST(ConversionException) {
    5716           6 :   LocalContext env;
    5717           6 :   v8::Isolate* isolate = env->GetIsolate();
    5718          12 :   v8::HandleScope scope(isolate);
    5719             :   CompileRun(
    5720             :       "function TestClass() { };"
    5721             :       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
    5722             :       "var obj = new TestClass();");
    5723             :   Local<Value> obj =
    5724          24 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5725             : 
    5726          12 :   v8::TryCatch try_catch(isolate);
    5727             : 
    5728          12 :   CHECK(obj->ToString(env.local()).IsEmpty());
    5729           6 :   CheckUncle(isolate, &try_catch);
    5730             : 
    5731          12 :   CHECK(obj->ToNumber(env.local()).IsEmpty());
    5732           6 :   CheckUncle(isolate, &try_catch);
    5733             : 
    5734          12 :   CHECK(obj->ToInteger(env.local()).IsEmpty());
    5735           6 :   CheckUncle(isolate, &try_catch);
    5736             : 
    5737          12 :   CHECK(obj->ToUint32(env.local()).IsEmpty());
    5738           6 :   CheckUncle(isolate, &try_catch);
    5739             : 
    5740          12 :   CHECK(obj->ToInt32(env.local()).IsEmpty());
    5741           6 :   CheckUncle(isolate, &try_catch);
    5742             : 
    5743          12 :   CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
    5744           6 :   CHECK(try_catch.HasCaught());
    5745           6 :   try_catch.Reset();
    5746             : 
    5747          12 :   CHECK(obj->Int32Value(env.local()).IsNothing());
    5748           6 :   CheckUncle(isolate, &try_catch);
    5749             : 
    5750          12 :   CHECK(obj->Uint32Value(env.local()).IsNothing());
    5751           6 :   CheckUncle(isolate, &try_catch);
    5752             : 
    5753          12 :   CHECK(obj->NumberValue(env.local()).IsNothing());
    5754           6 :   CheckUncle(isolate, &try_catch);
    5755             : 
    5756          12 :   CHECK(obj->IntegerValue(env.local()).IsNothing());
    5757           6 :   CheckUncle(isolate, &try_catch);
    5758           6 : }
    5759             : 
    5760             : 
    5761          28 : void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5762          28 :   ApiTestFuzzer::Fuzz();
    5763          56 :   args.GetIsolate()->ThrowException(v8_str("konto"));
    5764          28 : }
    5765             : 
    5766             : 
    5767           5 : void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5768           5 :   if (args.Length() < 1) {
    5769             :     args.GetReturnValue().Set(false);
    5770           0 :     return;
    5771             :   }
    5772          10 :   v8::HandleScope scope(args.GetIsolate());
    5773          10 :   v8::TryCatch try_catch(args.GetIsolate());
    5774             :   Local<Value> result =
    5775             :       CompileRun(args[0]
    5776          10 :                      ->ToString(args.GetIsolate()->GetCurrentContext())
    5777           5 :                      .ToLocalChecked());
    5778          10 :   CHECK(!try_catch.HasCaught() || result.IsEmpty());
    5779           5 :   args.GetReturnValue().Set(try_catch.HasCaught());
    5780             : }
    5781             : 
    5782             : 
    5783       26645 : THREADED_TEST(APICatch) {
    5784           6 :   v8::Isolate* isolate = CcTest::isolate();
    5785          12 :   v8::HandleScope scope(isolate);
    5786           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5787          18 :   templ->Set(v8_str("ThrowFromC"),
    5788           6 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5789           6 :   LocalContext context(nullptr, templ);
    5790             :   CompileRun(
    5791             :       "var thrown = false;"
    5792             :       "try {"
    5793             :       "  ThrowFromC();"
    5794             :       "} catch (e) {"
    5795             :       "  thrown = true;"
    5796             :       "}");
    5797          12 :   Local<Value> thrown = context->Global()
    5798          18 :                             ->Get(context.local(), v8_str("thrown"))
    5799             :                             .ToLocalChecked();
    5800           6 :   CHECK(thrown->BooleanValue(isolate));
    5801           6 : }
    5802             : 
    5803             : 
    5804       26645 : THREADED_TEST(APIThrowTryCatch) {
    5805           6 :   v8::Isolate* isolate = CcTest::isolate();
    5806          12 :   v8::HandleScope scope(isolate);
    5807           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5808          18 :   templ->Set(v8_str("ThrowFromC"),
    5809           6 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5810           6 :   LocalContext context(nullptr, templ);
    5811          12 :   v8::TryCatch try_catch(isolate);
    5812             :   CompileRun("ThrowFromC();");
    5813           6 :   CHECK(try_catch.HasCaught());
    5814           6 : }
    5815             : 
    5816             : 
    5817             : // Test that a try-finally block doesn't shadow a try-catch block
    5818             : // when setting up an external handler.
    5819             : //
    5820             : // BUG(271): Some of the exception propagation does not work on the
    5821             : // ARM simulator because the simulator separates the C++ stack and the
    5822             : // JS stack.  This test therefore fails on the simulator.  The test is
    5823             : // not threaded to allow the threading tests to run on the simulator.
    5824       26644 : TEST(TryCatchInTryFinally) {
    5825           5 :   v8::Isolate* isolate = CcTest::isolate();
    5826          10 :   v8::HandleScope scope(isolate);
    5827           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5828          15 :   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
    5829           5 :   LocalContext context(nullptr, templ);
    5830             :   Local<Value> result = CompileRun(
    5831             :       "try {"
    5832             :       "  try {"
    5833             :       "    CCatcher('throw 7;');"
    5834             :       "  } finally {"
    5835             :       "  }"
    5836             :       "} catch (e) {"
    5837             :       "}");
    5838           5 :   CHECK(result->IsTrue());
    5839           5 : }
    5840             : 
    5841             : 
    5842           5 : static void check_custom_error_tostring(v8::Local<v8::Message> message,
    5843             :                                         v8::Local<v8::Value> data) {
    5844             :   const char* uncaught_error = "Uncaught MyError toString";
    5845          25 :   CHECK(message->Get()
    5846             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5847             :                      v8_str(uncaught_error))
    5848             :             .FromJust());
    5849           5 : }
    5850             : 
    5851             : 
    5852       26644 : TEST(CustomErrorToString) {
    5853           5 :   LocalContext context;
    5854          10 :   v8::HandleScope scope(context->GetIsolate());
    5855           5 :   context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
    5856             :   CompileRun(
    5857             :       "function MyError(name, message) {                   "
    5858             :       "  this.name = name;                                 "
    5859             :       "  this.message = message;                           "
    5860             :       "}                                                   "
    5861             :       "MyError.prototype = Object.create(Error.prototype); "
    5862             :       "MyError.prototype.toString = function() {           "
    5863             :       "  return 'MyError toString';                        "
    5864             :       "};                                                  "
    5865             :       "throw new MyError('my name', 'my message');         ");
    5866           5 :   context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
    5867           5 : }
    5868             : 
    5869             : 
    5870          15 : static void check_custom_error_message(v8::Local<v8::Message> message,
    5871             :                                        v8::Local<v8::Value> data) {
    5872             :   const char* uncaught_error = "Uncaught MyError: my message";
    5873          45 :   printf("%s\n", *v8::String::Utf8Value(CcTest::isolate(), message->Get()));
    5874          60 :   CHECK(message->Get()
    5875             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5876             :                      v8_str(uncaught_error))
    5877             :             .FromJust());
    5878          15 : }
    5879             : 
    5880             : 
    5881       26644 : TEST(CustomErrorMessage) {
    5882           5 :   LocalContext context;
    5883          10 :   v8::HandleScope scope(context->GetIsolate());
    5884           5 :   context->GetIsolate()->AddMessageListener(check_custom_error_message);
    5885             : 
    5886             :   // Handlebars.
    5887             :   CompileRun(
    5888             :       "function MyError(msg) {                             "
    5889             :       "  this.name = 'MyError';                            "
    5890             :       "  this.message = msg;                               "
    5891             :       "}                                                   "
    5892             :       "MyError.prototype = new Error();                    "
    5893             :       "throw new MyError('my message');                    ");
    5894             : 
    5895             :   // Closure.
    5896             :   CompileRun(
    5897             :       "function MyError(msg) {                             "
    5898             :       "  this.name = 'MyError';                            "
    5899             :       "  this.message = msg;                               "
    5900             :       "}                                                   "
    5901             :       "inherits = function(childCtor, parentCtor) {        "
    5902             :       "    function tempCtor() {};                         "
    5903             :       "    tempCtor.prototype = parentCtor.prototype;      "
    5904             :       "    childCtor.superClass_ = parentCtor.prototype;   "
    5905             :       "    childCtor.prototype = new tempCtor();           "
    5906             :       "    childCtor.prototype.constructor = childCtor;    "
    5907             :       "};                                                  "
    5908             :       "inherits(MyError, Error);                           "
    5909             :       "throw new MyError('my message');                    ");
    5910             : 
    5911             :   // Object.create.
    5912             :   CompileRun(
    5913             :       "function MyError(msg) {                             "
    5914             :       "  this.name = 'MyError';                            "
    5915             :       "  this.message = msg;                               "
    5916             :       "}                                                   "
    5917             :       "MyError.prototype = Object.create(Error.prototype); "
    5918             :       "throw new MyError('my message');                    ");
    5919             : 
    5920           5 :   context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
    5921           5 : }
    5922             : 
    5923             : 
    5924          10 : static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
    5925             :                                             v8::Local<v8::Value> data) {
    5926          10 :   CHECK(data->IsExternal());
    5927          10 :   int* callcount = static_cast<int*>(data.As<v8::External>()->Value());
    5928          10 :   ++*callcount;
    5929             : 
    5930             :   const char* uncaught_error = "Uncaught exception";
    5931          50 :   CHECK(message->Get()
    5932             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5933             :                      v8_str(uncaught_error))
    5934             :             .FromJust());
    5935             :   // Test that compiling code inside a message handler works.
    5936          40 :   CHECK(CompileRunChecked(CcTest::isolate(), "(function(a) { return a; })(42)")
    5937             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5938             :                      v8::Integer::NewFromUnsigned(CcTest::isolate(), 42))
    5939             :             .FromJust());
    5940          10 : }
    5941             : 
    5942             : 
    5943       26644 : TEST(CustomErrorRethrowsOnToString) {
    5944           5 :   int callcount = 0;
    5945           5 :   LocalContext context;
    5946           5 :   v8::Isolate* isolate = context->GetIsolate();
    5947          10 :   v8::HandleScope scope(isolate);
    5948          15 :   context->GetIsolate()->AddMessageListener(
    5949           5 :       check_custom_rethrowing_message, v8::External::New(isolate, &callcount));
    5950             : 
    5951             :   CompileRun(
    5952             :       "var e = { toString: function() { throw e; } };"
    5953             :       "try { throw e; } finally {}");
    5954             : 
    5955           5 :   CHECK_EQ(callcount, 1);
    5956           5 :   context->GetIsolate()->RemoveMessageListeners(
    5957           5 :       check_custom_rethrowing_message);
    5958           5 : }
    5959             : 
    5960       26644 : TEST(CustomErrorRethrowsOnToStringInsideVerboseTryCatch) {
    5961           5 :   int callcount = 0;
    5962           5 :   LocalContext context;
    5963           5 :   v8::Isolate* isolate = context->GetIsolate();
    5964          10 :   v8::HandleScope scope(isolate);
    5965          10 :   v8::TryCatch try_catch(isolate);
    5966           5 :   try_catch.SetVerbose(true);
    5967          15 :   context->GetIsolate()->AddMessageListener(
    5968           5 :       check_custom_rethrowing_message, v8::External::New(isolate, &callcount));
    5969             : 
    5970             :   CompileRun(
    5971             :       "var e = { toString: function() { throw e; } };"
    5972             :       "try { throw e; } finally {}");
    5973             : 
    5974           5 :   CHECK_EQ(callcount, 1);
    5975           5 :   context->GetIsolate()->RemoveMessageListeners(
    5976           5 :       check_custom_rethrowing_message);
    5977           5 : }
    5978             : 
    5979             : 
    5980          15 : static void receive_message(v8::Local<v8::Message> message,
    5981             :                             v8::Local<v8::Value> data) {
    5982          15 :   message->Get();
    5983          15 :   message_received = true;
    5984          15 : }
    5985             : 
    5986             : 
    5987       26644 : TEST(APIThrowMessage) {
    5988           5 :   message_received = false;
    5989           5 :   v8::Isolate* isolate = CcTest::isolate();
    5990          10 :   v8::HandleScope scope(isolate);
    5991           5 :   isolate->AddMessageListener(receive_message);
    5992           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5993          15 :   templ->Set(v8_str("ThrowFromC"),
    5994           5 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5995           5 :   LocalContext context(nullptr, templ);
    5996             :   CompileRun("ThrowFromC();");
    5997           5 :   CHECK(message_received);
    5998           5 :   isolate->RemoveMessageListeners(receive_message);
    5999           5 : }
    6000             : 
    6001             : 
    6002       26644 : TEST(APIThrowMessageAndVerboseTryCatch) {
    6003           5 :   message_received = false;
    6004           5 :   v8::Isolate* isolate = CcTest::isolate();
    6005          10 :   v8::HandleScope scope(isolate);
    6006           5 :   isolate->AddMessageListener(receive_message);
    6007           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6008          15 :   templ->Set(v8_str("ThrowFromC"),
    6009           5 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    6010           5 :   LocalContext context(nullptr, templ);
    6011          10 :   v8::TryCatch try_catch(isolate);
    6012           5 :   try_catch.SetVerbose(true);
    6013             :   Local<Value> result = CompileRun("ThrowFromC();");
    6014           5 :   CHECK(try_catch.HasCaught());
    6015           5 :   CHECK(result.IsEmpty());
    6016           5 :   CHECK(message_received);
    6017           5 :   isolate->RemoveMessageListeners(receive_message);
    6018           5 : }
    6019             : 
    6020             : 
    6021       26644 : TEST(APIStackOverflowAndVerboseTryCatch) {
    6022           5 :   message_received = false;
    6023           5 :   LocalContext context;
    6024          10 :   v8::HandleScope scope(context->GetIsolate());
    6025           5 :   context->GetIsolate()->AddMessageListener(receive_message);
    6026          10 :   v8::TryCatch try_catch(context->GetIsolate());
    6027           5 :   try_catch.SetVerbose(true);
    6028             :   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
    6029           5 :   CHECK(try_catch.HasCaught());
    6030           5 :   CHECK(result.IsEmpty());
    6031           5 :   CHECK(message_received);
    6032           5 :   context->GetIsolate()->RemoveMessageListeners(receive_message);
    6033           5 : }
    6034             : 
    6035             : 
    6036       26645 : THREADED_TEST(ExternalScriptException) {
    6037           6 :   v8::Isolate* isolate = CcTest::isolate();
    6038          12 :   v8::HandleScope scope(isolate);
    6039           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6040          18 :   templ->Set(v8_str("ThrowFromC"),
    6041           6 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    6042           6 :   LocalContext context(nullptr, templ);
    6043             : 
    6044          12 :   v8::TryCatch try_catch(isolate);
    6045             :   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
    6046           6 :   CHECK(result.IsEmpty());
    6047           6 :   CHECK(try_catch.HasCaught());
    6048          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6049           6 :   CHECK_EQ(0, strcmp("konto", *exception_value));
    6050           6 : }
    6051             : 
    6052             : 
    6053          85 : void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6054          85 :   ApiTestFuzzer::Fuzz();
    6055          85 :   CHECK_EQ(4, args.Length());
    6056          85 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    6057         170 :   int count = args[0]->Int32Value(context).FromJust();
    6058         170 :   int cInterval = args[2]->Int32Value(context).FromJust();
    6059          85 :   if (count == 0) {
    6060          10 :     args.GetIsolate()->ThrowException(v8_str("FromC"));
    6061           5 :     return;
    6062             :   } else {
    6063          80 :     Local<v8::Object> global = context->Global();
    6064             :     Local<Value> fun =
    6065         240 :         global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
    6066         320 :     v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
    6067          80 :     if (count % cInterval == 0) {
    6068          60 :       v8::TryCatch try_catch(args.GetIsolate());
    6069             :       Local<Value> result = fun.As<Function>()
    6070          60 :                                 ->Call(context, global, 4, argv)
    6071             :                                 .FromMaybe(Local<Value>());
    6072          60 :       int expected = args[3]->Int32Value(context).FromJust();
    6073          30 :       if (try_catch.HasCaught()) {
    6074          15 :         CHECK_EQ(expected, count);
    6075          15 :         CHECK(result.IsEmpty());
    6076          15 :         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
    6077             :       } else {
    6078          15 :         CHECK_NE(expected, count);
    6079             :       }
    6080             :       args.GetReturnValue().Set(result);
    6081             :       return;
    6082             :     } else {
    6083             :       args.GetReturnValue().Set(fun.As<Function>()
    6084         100 :                                     ->Call(context, global, 4, argv)
    6085             :                                     .FromMaybe(v8::Local<v8::Value>()));
    6086          50 :       return;
    6087             :     }
    6088             :   }
    6089             : }
    6090             : 
    6091             : 
    6092          25 : void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6093          25 :   ApiTestFuzzer::Fuzz();
    6094          25 :   CHECK_EQ(3, args.Length());
    6095             :   v8::Isolate* isolate = args.GetIsolate();
    6096          25 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
    6097          25 :   bool equality = args[0]->BooleanValue(isolate);
    6098          50 :   int count = args[1]->Int32Value(context).FromJust();
    6099          50 :   int expected = args[2]->Int32Value(context).FromJust();
    6100          25 :   if (equality) {
    6101          15 :     CHECK_EQ(count, expected);
    6102             :   } else {
    6103          10 :     CHECK_NE(count, expected);
    6104             :   }
    6105          25 : }
    6106             : 
    6107             : 
    6108       26645 : THREADED_TEST(EvalInTryFinally) {
    6109           6 :   LocalContext context;
    6110          12 :   v8::HandleScope scope(context->GetIsolate());
    6111          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6112             :   CompileRun(
    6113             :       "(function() {"
    6114             :       "  try {"
    6115             :       "    eval('asldkf (*&^&*^');"
    6116             :       "  } finally {"
    6117             :       "    return;"
    6118             :       "  }"
    6119             :       "})()");
    6120           6 :   CHECK(!try_catch.HasCaught());
    6121           6 : }
    6122             : 
    6123             : 
    6124             : // This test works by making a stack of alternating JavaScript and C
    6125             : // activations.  These activations set up exception handlers with regular
    6126             : // intervals, one interval for C activations and another for JavaScript
    6127             : // activations.  When enough activations have been created an exception is
    6128             : // thrown and we check that the right activation catches the exception and that
    6129             : // no other activations do.  The right activation is always the topmost one with
    6130             : // a handler, regardless of whether it is in JavaScript or C.
    6131             : //
    6132             : // The notation used to describe a test case looks like this:
    6133             : //
    6134             : //    *JS[4] *C[3] @JS[2] C[1] JS[0]
    6135             : //
    6136             : // Each entry is an activation, either JS or C.  The index is the count at that
    6137             : // level.  Stars identify activations with exception handlers, the @ identifies
    6138             : // the exception handler that should catch the exception.
    6139             : //
    6140             : // BUG(271): Some of the exception propagation does not work on the
    6141             : // ARM simulator because the simulator separates the C++ stack and the
    6142             : // JS stack.  This test therefore fails on the simulator.  The test is
    6143             : // not threaded to allow the threading tests to run on the simulator.
    6144       26644 : TEST(ExceptionOrder) {
    6145           5 :   v8::Isolate* isolate = CcTest::isolate();
    6146          10 :   v8::HandleScope scope(isolate);
    6147           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6148          15 :   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
    6149          15 :   templ->Set(v8_str("CThrowCountDown"),
    6150           5 :              v8::FunctionTemplate::New(isolate, CThrowCountDown));
    6151           5 :   LocalContext context(nullptr, templ);
    6152             :   CompileRun(
    6153             :       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
    6154             :       "  if (count == 0) throw 'FromJS';"
    6155             :       "  if (count % jsInterval == 0) {"
    6156             :       "    try {"
    6157             :       "      var value = CThrowCountDown(count - 1,"
    6158             :       "                                  jsInterval,"
    6159             :       "                                  cInterval,"
    6160             :       "                                  expected);"
    6161             :       "      check(false, count, expected);"
    6162             :       "      return value;"
    6163             :       "    } catch (e) {"
    6164             :       "      check(true, count, expected);"
    6165             :       "    }"
    6166             :       "  } else {"
    6167             :       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
    6168             :       "  }"
    6169             :       "}");
    6170             :   Local<Function> fun = Local<Function>::Cast(
    6171          10 :       context->Global()
    6172          15 :           ->Get(context.local(), v8_str("JSThrowCountDown"))
    6173             :           .ToLocalChecked());
    6174             : 
    6175             :   const int argc = 4;
    6176             :   //                             count      jsInterval cInterval  expected
    6177             : 
    6178             :   // *JS[4] *C[3] @JS[2] C[1] JS[0]
    6179           5 :   v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
    6180          10 :   fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
    6181             : 
    6182             :   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
    6183           5 :   v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
    6184          10 :   fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
    6185             : 
    6186             :   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
    6187           5 :   v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
    6188          10 :   fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
    6189             : 
    6190             :   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
    6191           5 :   v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
    6192          10 :   fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
    6193             : 
    6194             :   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
    6195           5 :   v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
    6196          10 :   fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
    6197             : 
    6198             :   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
    6199           5 :   v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
    6200          10 :   fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
    6201           5 : }
    6202             : 
    6203             : 
    6204          42 : void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6205          42 :   ApiTestFuzzer::Fuzz();
    6206          42 :   CHECK_EQ(1, args.Length());
    6207          42 :   args.GetIsolate()->ThrowException(args[0]);
    6208          42 : }
    6209             : 
    6210             : 
    6211       26645 : THREADED_TEST(ThrowValues) {
    6212           6 :   v8::Isolate* isolate = CcTest::isolate();
    6213          12 :   v8::HandleScope scope(isolate);
    6214           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6215          18 :   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
    6216           6 :   LocalContext context(nullptr, templ);
    6217             :   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
    6218             :       CompileRun("function Run(obj) {"
    6219             :                  "  try {"
    6220             :                  "    Throw(obj);"
    6221             :                  "  } catch (e) {"
    6222             :                  "    return e;"
    6223             :                  "  }"
    6224             :                  "  return 'no exception';"
    6225             :                  "}"
    6226             :                  "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
    6227           6 :   CHECK_EQ(5u, result->Length());
    6228          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
    6229             :             .ToLocalChecked()
    6230             :             ->IsString());
    6231          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
    6232             :             .ToLocalChecked()
    6233             :             ->IsNumber());
    6234          24 :   CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
    6235             :                   .ToLocalChecked()
    6236             :                   ->Int32Value(context.local())
    6237             :                   .FromJust());
    6238          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
    6239             :             .ToLocalChecked()
    6240             :             ->IsNumber());
    6241          24 :   CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
    6242             :                   .ToLocalChecked()
    6243             :                   ->Int32Value(context.local())
    6244             :                   .FromJust());
    6245          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
    6246             :             .ToLocalChecked()
    6247             :             ->IsNull());
    6248          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
    6249             :             .ToLocalChecked()
    6250             :             ->IsUndefined());
    6251           6 : }
    6252             : 
    6253             : 
    6254       26645 : THREADED_TEST(CatchZero) {
    6255           6 :   LocalContext context;
    6256          12 :   v8::HandleScope scope(context->GetIsolate());
    6257          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6258           6 :   CHECK(!try_catch.HasCaught());
    6259             :   CompileRun("throw 10");
    6260           6 :   CHECK(try_catch.HasCaught());
    6261          18 :   CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
    6262           6 :   try_catch.Reset();
    6263           6 :   CHECK(!try_catch.HasCaught());
    6264             :   CompileRun("throw 0");
    6265           6 :   CHECK(try_catch.HasCaught());
    6266          18 :   CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
    6267           6 : }
    6268             : 
    6269             : 
    6270       26645 : THREADED_TEST(CatchExceptionFromWith) {
    6271           6 :   LocalContext context;
    6272          12 :   v8::HandleScope scope(context->GetIsolate());
    6273          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6274           6 :   CHECK(!try_catch.HasCaught());
    6275             :   CompileRun("var o = {}; with (o) { throw 42; }");
    6276           6 :   CHECK(try_catch.HasCaught());
    6277           6 : }
    6278             : 
    6279             : 
    6280       26645 : THREADED_TEST(TryCatchAndFinallyHidingException) {
    6281           6 :   LocalContext context;
    6282          12 :   v8::HandleScope scope(context->GetIsolate());
    6283          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6284           6 :   CHECK(!try_catch.HasCaught());
    6285             :   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
    6286             :   CompileRun("f({toString: function() { throw 42; }});");
    6287           6 :   CHECK(!try_catch.HasCaught());
    6288           6 : }
    6289             : 
    6290             : 
    6291           6 : void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6292           6 :   v8::TryCatch try_catch(args.GetIsolate());
    6293           6 : }
    6294             : 
    6295             : 
    6296       26645 : THREADED_TEST(TryCatchAndFinally) {
    6297           6 :   LocalContext context;
    6298           6 :   v8::Isolate* isolate = context->GetIsolate();
    6299          12 :   v8::HandleScope scope(isolate);
    6300          36 :   CHECK(context->Global()
    6301             :             ->Set(context.local(), v8_str("native_with_try_catch"),
    6302             :                   v8::FunctionTemplate::New(isolate, WithTryCatch)
    6303             :                       ->GetFunction(context.local())
    6304             :                       .ToLocalChecked())
    6305             :             .FromJust());
    6306          12 :   v8::TryCatch try_catch(isolate);
    6307           6 :   CHECK(!try_catch.HasCaught());
    6308             :   CompileRun(
    6309             :       "try {\n"
    6310             :       "  throw new Error('a');\n"
    6311             :       "} finally {\n"
    6312             :       "  native_with_try_catch();\n"
    6313             :       "}\n");
    6314           6 :   CHECK(try_catch.HasCaught());
    6315           6 : }
    6316             : 
    6317             : 
    6318          30 : static void TryCatchNested1Helper(int depth) {
    6319          30 :   if (depth > 0) {
    6320          50 :     v8::TryCatch try_catch(CcTest::isolate());
    6321          25 :     try_catch.SetVerbose(true);
    6322          25 :     TryCatchNested1Helper(depth - 1);
    6323          25 :     CHECK(try_catch.HasCaught());
    6324          25 :     try_catch.ReThrow();
    6325             :   } else {
    6326          10 :     CcTest::isolate()->ThrowException(v8_str("E1"));
    6327             :   }
    6328          30 : }
    6329             : 
    6330             : 
    6331          30 : static void TryCatchNested2Helper(int depth) {
    6332          30 :   if (depth > 0) {
    6333          50 :     v8::TryCatch try_catch(CcTest::isolate());
    6334          25 :     try_catch.SetVerbose(true);
    6335          25 :     TryCatchNested2Helper(depth - 1);
    6336          25 :     CHECK(try_catch.HasCaught());
    6337          25 :     try_catch.ReThrow();
    6338             :   } else {
    6339             :     CompileRun("throw 'E2';");
    6340             :   }
    6341          30 : }
    6342             : 
    6343             : 
    6344       26644 : TEST(TryCatchNested) {
    6345           5 :   v8::V8::Initialize();
    6346           5 :   LocalContext context;
    6347          10 :   v8::HandleScope scope(context->GetIsolate());
    6348             : 
    6349             :   {
    6350             :     // Test nested try-catch with a native throw in the end.
    6351          10 :     v8::TryCatch try_catch(context->GetIsolate());
    6352           5 :     TryCatchNested1Helper(5);
    6353           5 :     CHECK(try_catch.HasCaught());
    6354          10 :     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(),
    6355             :                                               try_catch.Exception()),
    6356             :                        "E1"));
    6357             :   }
    6358             : 
    6359             :   {
    6360             :     // Test nested try-catch with a JavaScript throw in the end.
    6361          10 :     v8::TryCatch try_catch(context->GetIsolate());
    6362           5 :     TryCatchNested2Helper(5);
    6363           5 :     CHECK(try_catch.HasCaught());
    6364          10 :     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(),
    6365             :                                               try_catch.Exception()),
    6366             :                        "E2"));
    6367             :   }
    6368           5 : }
    6369             : 
    6370             : 
    6371          10 : void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
    6372          10 :   CHECK(try_catch->HasCaught());
    6373          10 :   Local<Message> message = try_catch->Message();
    6374          20 :   Local<Value> resource = message->GetScriptOrigin().ResourceName();
    6375          10 :   CHECK_EQ(
    6376             :       0, strcmp(*v8::String::Utf8Value(CcTest::isolate(), resource), "inner"));
    6377          20 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(CcTest::isolate(), message->Get()),
    6378             :                      "Uncaught Error: a"));
    6379          20 :   CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
    6380             :                   .FromJust());
    6381          20 :   CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
    6382             :                   .FromJust());
    6383          10 : }
    6384             : 
    6385             : 
    6386           5 : void TryCatchMixedNestingHelper(
    6387             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    6388           5 :   ApiTestFuzzer::Fuzz();
    6389          10 :   v8::TryCatch try_catch(args.GetIsolate());
    6390           5 :   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
    6391           5 :   CHECK(try_catch.HasCaught());
    6392           5 :   TryCatchMixedNestingCheck(&try_catch);
    6393           5 :   try_catch.ReThrow();
    6394           5 : }
    6395             : 
    6396             : 
    6397             : // This test ensures that an outer TryCatch in the following situation:
    6398             : //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
    6399             : // does not clobber the Message object generated for the inner TryCatch.
    6400             : // This exercises the ability of TryCatch.ReThrow() to restore the
    6401             : // inner pending Message before throwing the exception again.
    6402       26644 : TEST(TryCatchMixedNesting) {
    6403           5 :   v8::Isolate* isolate = CcTest::isolate();
    6404          10 :   v8::HandleScope scope(isolate);
    6405           5 :   v8::V8::Initialize();
    6406          10 :   v8::TryCatch try_catch(isolate);
    6407           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6408          15 :   templ->Set(v8_str("TryCatchMixedNestingHelper"),
    6409           5 :              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
    6410           5 :   LocalContext context(nullptr, templ);
    6411           5 :   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
    6412           5 :   TryCatchMixedNestingCheck(&try_catch);
    6413           5 : }
    6414             : 
    6415             : 
    6416           5 : void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6417           5 :   ApiTestFuzzer::Fuzz();
    6418          10 :   v8::TryCatch try_catch(args.GetIsolate());
    6419          10 :   args.GetIsolate()->ThrowException(v8_str("boom"));
    6420           5 :   CHECK(try_catch.HasCaught());
    6421           5 : }
    6422             : 
    6423             : 
    6424       26644 : TEST(TryCatchNative) {
    6425           5 :   v8::Isolate* isolate = CcTest::isolate();
    6426          10 :   v8::HandleScope scope(isolate);
    6427           5 :   v8::V8::Initialize();
    6428          10 :   v8::TryCatch try_catch(isolate);
    6429           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6430          15 :   templ->Set(v8_str("TryCatchNativeHelper"),
    6431           5 :              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
    6432           5 :   LocalContext context(nullptr, templ);
    6433             :   CompileRun("TryCatchNativeHelper();");
    6434           5 :   CHECK(!try_catch.HasCaught());
    6435           5 : }
    6436             : 
    6437             : 
    6438           5 : void TryCatchNativeResetHelper(
    6439             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    6440           5 :   ApiTestFuzzer::Fuzz();
    6441          10 :   v8::TryCatch try_catch(args.GetIsolate());
    6442          10 :   args.GetIsolate()->ThrowException(v8_str("boom"));
    6443           5 :   CHECK(try_catch.HasCaught());
    6444           5 :   try_catch.Reset();
    6445           5 :   CHECK(!try_catch.HasCaught());
    6446           5 : }
    6447             : 
    6448             : 
    6449       26644 : TEST(TryCatchNativeReset) {
    6450           5 :   v8::Isolate* isolate = CcTest::isolate();
    6451          10 :   v8::HandleScope scope(isolate);
    6452           5 :   v8::V8::Initialize();
    6453          10 :   v8::TryCatch try_catch(isolate);
    6454           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6455          15 :   templ->Set(v8_str("TryCatchNativeResetHelper"),
    6456           5 :              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
    6457           5 :   LocalContext context(nullptr, templ);
    6458             :   CompileRun("TryCatchNativeResetHelper();");
    6459           5 :   CHECK(!try_catch.HasCaught());
    6460           5 : }
    6461             : 
    6462             : 
    6463       26645 : THREADED_TEST(Equality) {
    6464           6 :   LocalContext context;
    6465           6 :   v8::Isolate* isolate = context->GetIsolate();
    6466          12 :   v8::HandleScope scope(context->GetIsolate());
    6467             :   // Check that equality works at all before relying on CHECK_EQ
    6468          24 :   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
    6469          24 :   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
    6470             : 
    6471          24 :   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
    6472          24 :   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
    6473          24 :   CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
    6474          24 :   CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
    6475          24 :   CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
    6476             : 
    6477             :   // Assume String is not internalized.
    6478          18 :   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
    6479          18 :   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
    6480          12 :   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
    6481          12 :   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
    6482          12 :   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
    6483          12 :   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
    6484           6 :   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
    6485           6 :   CHECK(!not_a_number->StrictEquals(not_a_number));
    6486           6 :   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
    6487           6 :   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
    6488             : 
    6489           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    6490             :   v8::Persistent<v8::Object> alias(isolate, obj);
    6491           6 :   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
    6492             :   alias.Reset();
    6493             : 
    6494          18 :   CHECK(v8_str("a")->SameValue(v8_str("a")));
    6495          18 :   CHECK(!v8_str("a")->SameValue(v8_str("b")));
    6496          12 :   CHECK(!v8_str("5")->SameValue(v8_num(5)));
    6497          12 :   CHECK(v8_num(1)->SameValue(v8_num(1)));
    6498          12 :   CHECK(!v8_num(1)->SameValue(v8_num(2)));
    6499          12 :   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
    6500           6 :   CHECK(not_a_number->SameValue(not_a_number));
    6501           6 :   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
    6502           6 :   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
    6503           6 : }
    6504             : 
    6505       26645 : THREADED_TEST(TypeOf) {
    6506           6 :   LocalContext context;
    6507           6 :   v8::Isolate* isolate = context->GetIsolate();
    6508          12 :   v8::HandleScope scope(context->GetIsolate());
    6509             : 
    6510           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
    6511           6 :   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
    6512             : 
    6513          24 :   CHECK(v8::Undefined(isolate)
    6514             :             ->TypeOf(isolate)
    6515             :             ->Equals(context.local(), v8_str("undefined"))
    6516             :             .FromJust());
    6517          24 :   CHECK(v8::Null(isolate)
    6518             :             ->TypeOf(isolate)
    6519             :             ->Equals(context.local(), v8_str("object"))
    6520             :             .FromJust());
    6521          30 :   CHECK(v8_str("str")
    6522             :             ->TypeOf(isolate)
    6523             :             ->Equals(context.local(), v8_str("string"))
    6524             :             .FromJust());
    6525          30 :   CHECK(v8_num(0.0)
    6526             :             ->TypeOf(isolate)
    6527             :             ->Equals(context.local(), v8_str("number"))
    6528             :             .FromJust());
    6529          30 :   CHECK(v8_num(1)
    6530             :             ->TypeOf(isolate)
    6531             :             ->Equals(context.local(), v8_str("number"))
    6532             :             .FromJust());
    6533          30 :   CHECK(v8::Object::New(isolate)
    6534             :             ->TypeOf(isolate)
    6535             :             ->Equals(context.local(), v8_str("object"))
    6536             :             .FromJust());
    6537          24 :   CHECK(v8::Boolean::New(isolate, true)
    6538             :             ->TypeOf(isolate)
    6539             :             ->Equals(context.local(), v8_str("boolean"))
    6540             :             .FromJust());
    6541          24 :   CHECK(fun->TypeOf(isolate)
    6542             :             ->Equals(context.local(), v8_str("function"))
    6543             :             .FromJust());
    6544           6 : }
    6545             : 
    6546       26645 : THREADED_TEST(InstanceOf) {
    6547           6 :   LocalContext env;
    6548          12 :   v8::HandleScope scope(env->GetIsolate());
    6549             :   CompileRun(
    6550             :       "var A = {};"
    6551             :       "var B = {};"
    6552             :       "var C = {};"
    6553             :       "B.__proto__ = A;"
    6554             :       "C.__proto__ = B;"
    6555             :       "function F() {}"
    6556             :       "F.prototype = A;"
    6557             :       "var G = { [Symbol.hasInstance] : null};"
    6558             :       "var H = { [Symbol.hasInstance] : () => { throw new Error(); } };"
    6559             :       "var J = { [Symbol.hasInstance] : () => true };"
    6560             :       "class K {}"
    6561             :       "var D = new K;"
    6562             :       "class L extends K {}"
    6563             :       "var E = new L");
    6564             : 
    6565           6 :   v8::Local<v8::Object> f = v8::Local<v8::Object>::Cast(CompileRun("F"));
    6566           6 :   v8::Local<v8::Object> g = v8::Local<v8::Object>::Cast(CompileRun("G"));
    6567           6 :   v8::Local<v8::Object> h = v8::Local<v8::Object>::Cast(CompileRun("H"));
    6568           6 :   v8::Local<v8::Object> j = v8::Local<v8::Object>::Cast(CompileRun("J"));
    6569           6 :   v8::Local<v8::Object> k = v8::Local<v8::Object>::Cast(CompileRun("K"));
    6570           6 :   v8::Local<v8::Object> l = v8::Local<v8::Object>::Cast(CompileRun("L"));
    6571             :   v8::Local<v8::Value> a = v8::Local<v8::Value>::Cast(CompileRun("A"));
    6572             :   v8::Local<v8::Value> b = v8::Local<v8::Value>::Cast(CompileRun("B"));
    6573             :   v8::Local<v8::Value> c = v8::Local<v8::Value>::Cast(CompileRun("C"));
    6574             :   v8::Local<v8::Value> d = v8::Local<v8::Value>::Cast(CompileRun("D"));
    6575             :   v8::Local<v8::Value> e = v8::Local<v8::Value>::Cast(CompileRun("E"));
    6576             : 
    6577          12 :   v8::TryCatch try_catch(env->GetIsolate());
    6578          12 :   CHECK(!a->InstanceOf(env.local(), f).ToChecked());
    6579          12 :   CHECK(b->InstanceOf(env.local(), f).ToChecked());
    6580          12 :   CHECK(c->InstanceOf(env.local(), f).ToChecked());
    6581          12 :   CHECK(!d->InstanceOf(env.local(), f).ToChecked());
    6582          12 :   CHECK(!e->InstanceOf(env.local(), f).ToChecked());
    6583           6 :   CHECK(!try_catch.HasCaught());
    6584             : 
    6585          12 :   CHECK(a->InstanceOf(env.local(), g).IsNothing());
    6586           6 :   CHECK(try_catch.HasCaught());
    6587           6 :   try_catch.Reset();
    6588             : 
    6589          12 :   CHECK(b->InstanceOf(env.local(), h).IsNothing());
    6590           6 :   CHECK(try_catch.HasCaught());
    6591           6 :   try_catch.Reset();
    6592             : 
    6593          18 :   CHECK(v8_num(1)->InstanceOf(env.local(), j).ToChecked());
    6594           6 :   CHECK(!try_catch.HasCaught());
    6595             : 
    6596          12 :   CHECK(d->InstanceOf(env.local(), k).ToChecked());
    6597          12 :   CHECK(e->InstanceOf(env.local(), k).ToChecked());
    6598          12 :   CHECK(!d->InstanceOf(env.local(), l).ToChecked());
    6599          12 :   CHECK(e->InstanceOf(env.local(), l).ToChecked());
    6600           6 :   CHECK(!try_catch.HasCaught());
    6601           6 : }
    6602             : 
    6603       26645 : THREADED_TEST(MultiRun) {
    6604           6 :   LocalContext context;
    6605          12 :   v8::HandleScope scope(context->GetIsolate());
    6606             :   Local<Script> script = v8_compile("x");
    6607         126 :   for (int i = 0; i < 10; i++) {
    6608          60 :     script->Run(context.local()).IsEmpty();
    6609             :   }
    6610           6 : }
    6611             : 
    6612             : 
    6613         204 : static void GetXValue(Local<Name> name,
    6614             :                       const v8::PropertyCallbackInfo<v8::Value>& info) {
    6615         204 :   ApiTestFuzzer::Fuzz();
    6616         816 :   CHECK(info.Data()
    6617             :             ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
    6618             :             .FromJust());
    6619         816 :   CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
    6620             :             .FromJust());
    6621             :   info.GetReturnValue().Set(name);
    6622         204 : }
    6623             : 
    6624             : 
    6625       26645 : THREADED_TEST(SimplePropertyRead) {
    6626           6 :   LocalContext context;
    6627           6 :   v8::Isolate* isolate = context->GetIsolate();
    6628          12 :   v8::HandleScope scope(isolate);
    6629           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6630          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6631          30 :   CHECK(context->Global()
    6632             :             ->Set(context.local(), v8_str("obj"),
    6633             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6634             :             .FromJust());
    6635             :   Local<Script> script = v8_compile("obj.x");
    6636         126 :   for (int i = 0; i < 10; i++) {
    6637          60 :     Local<Value> result = script->Run(context.local()).ToLocalChecked();
    6638         180 :     CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
    6639             :   }
    6640           6 : }
    6641             : 
    6642             : 
    6643       26645 : THREADED_TEST(DefinePropertyOnAPIAccessor) {
    6644           6 :   LocalContext context;
    6645           6 :   v8::Isolate* isolate = context->GetIsolate();
    6646          12 :   v8::HandleScope scope(isolate);
    6647           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6648          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6649          30 :   CHECK(context->Global()
    6650             :             ->Set(context.local(), v8_str("obj"),
    6651             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6652             :             .FromJust());
    6653             : 
    6654             :   // Uses getOwnPropertyDescriptor to check the configurable status
    6655             :   Local<Script> script_desc = v8_compile(
    6656             :       "var prop = Object.getOwnPropertyDescriptor( "
    6657             :       "obj, 'x');"
    6658             :       "prop.configurable;");
    6659           6 :   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
    6660           6 :   CHECK(result->BooleanValue(isolate));
    6661             : 
    6662             :   // Redefine get - but still configurable
    6663             :   Local<Script> script_define = v8_compile(
    6664             :       "var desc = { get: function(){return 42; },"
    6665             :       "            configurable: true };"
    6666             :       "Object.defineProperty(obj, 'x', desc);"
    6667             :       "obj.x");
    6668           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6669          18 :   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
    6670             : 
    6671             :   // Check that the accessor is still configurable
    6672           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6673           6 :   CHECK(result->BooleanValue(isolate));
    6674             : 
    6675             :   // Redefine to a non-configurable
    6676             :   script_define = v8_compile(
    6677             :       "var desc = { get: function(){return 43; },"
    6678             :       "             configurable: false };"
    6679             :       "Object.defineProperty(obj, 'x', desc);"
    6680             :       "obj.x");
    6681           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6682          18 :   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
    6683           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6684           6 :   CHECK(!result->BooleanValue(isolate));
    6685             : 
    6686             :   // Make sure that it is not possible to redefine again
    6687          12 :   v8::TryCatch try_catch(isolate);
    6688          12 :   CHECK(script_define->Run(context.local()).IsEmpty());
    6689           6 :   CHECK(try_catch.HasCaught());
    6690          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6691           6 :   CHECK_EQ(0,
    6692             :            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6693           6 : }
    6694             : 
    6695             : 
    6696       26645 : THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
    6697           6 :   v8::Isolate* isolate = CcTest::isolate();
    6698          12 :   v8::HandleScope scope(isolate);
    6699           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6700          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6701           6 :   LocalContext context;
    6702          30 :   CHECK(context->Global()
    6703             :             ->Set(context.local(), v8_str("obj"),
    6704             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6705             :             .FromJust());
    6706             : 
    6707             :   Local<Script> script_desc = v8_compile(
    6708             :       "var prop ="
    6709             :       "Object.getOwnPropertyDescriptor( "
    6710             :       "obj, 'x');"
    6711             :       "prop.configurable;");
    6712           6 :   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
    6713           6 :   CHECK(result->BooleanValue(isolate));
    6714             : 
    6715             :   Local<Script> script_define = v8_compile(
    6716             :       "var desc = {get: function(){return 42; },"
    6717             :       "            configurable: true };"
    6718             :       "Object.defineProperty(obj, 'x', desc);"
    6719             :       "obj.x");
    6720           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6721          18 :   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
    6722             : 
    6723           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6724           6 :   CHECK(result->BooleanValue(isolate));
    6725             : 
    6726             :   script_define = v8_compile(
    6727             :       "var desc = {get: function(){return 43; },"
    6728             :       "            configurable: false };"
    6729             :       "Object.defineProperty(obj, 'x', desc);"
    6730             :       "obj.x");
    6731           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6732          18 :   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
    6733             : 
    6734           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6735           6 :   CHECK(!result->BooleanValue(isolate));
    6736             : 
    6737          12 :   v8::TryCatch try_catch(isolate);
    6738          12 :   CHECK(script_define->Run(context.local()).IsEmpty());
    6739           6 :   CHECK(try_catch.HasCaught());
    6740          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6741           6 :   CHECK_EQ(0,
    6742             :            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6743           6 : }
    6744             : 
    6745             : 
    6746          72 : static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
    6747             :                                                char const* name) {
    6748             :   return v8::Local<v8::Object>::Cast(
    6749             :       (*context)
    6750         144 :           ->Global()
    6751         288 :           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
    6752          72 :           .ToLocalChecked());
    6753             : }
    6754             : 
    6755             : 
    6756       26645 : THREADED_TEST(DefineAPIAccessorOnObject) {
    6757           6 :   v8::Isolate* isolate = CcTest::isolate();
    6758          12 :   v8::HandleScope scope(isolate);
    6759           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6760           6 :   LocalContext context;
    6761             : 
    6762          30 :   CHECK(context->Global()
    6763             :             ->Set(context.local(), v8_str("obj1"),
    6764             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6765             :             .FromJust());
    6766             :   CompileRun("var obj2 = {};");
    6767             : 
    6768           6 :   CHECK(CompileRun("obj1.x")->IsUndefined());
    6769           6 :   CHECK(CompileRun("obj2.x")->IsUndefined());
    6770             : 
    6771          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6772             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6773             :                           v8_str("donut"))
    6774             :             .FromJust());
    6775             : 
    6776           6 :   ExpectString("obj1.x", "x");
    6777           6 :   CHECK(CompileRun("obj2.x")->IsUndefined());
    6778             : 
    6779          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6780             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6781             :                           v8_str("donut"))
    6782             :             .FromJust());
    6783             : 
    6784           6 :   ExpectString("obj1.x", "x");
    6785           6 :   ExpectString("obj2.x", "x");
    6786             : 
    6787             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6788             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6789             : 
    6790             :   CompileRun(
    6791             :       "Object.defineProperty(obj1, 'x',"
    6792             :       "{ get: function() { return 'y'; }, configurable: true })");
    6793             : 
    6794           6 :   ExpectString("obj1.x", "y");
    6795           6 :   ExpectString("obj2.x", "x");
    6796             : 
    6797             :   CompileRun(
    6798             :       "Object.defineProperty(obj2, 'x',"
    6799             :       "{ get: function() { return 'y'; }, configurable: true })");
    6800             : 
    6801           6 :   ExpectString("obj1.x", "y");
    6802           6 :   ExpectString("obj2.x", "y");
    6803             : 
    6804             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6805             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6806             : 
    6807          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6808             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6809             :                           v8_str("donut"))
    6810             :             .FromJust());
    6811          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6812             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6813             :                           v8_str("donut"))
    6814             :             .FromJust());
    6815             : 
    6816           6 :   ExpectString("obj1.x", "x");
    6817           6 :   ExpectString("obj2.x", "x");
    6818             : 
    6819             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6820             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6821             : 
    6822             :   // Define getters/setters, but now make them not configurable.
    6823             :   CompileRun(
    6824             :       "Object.defineProperty(obj1, 'x',"
    6825             :       "{ get: function() { return 'z'; }, configurable: false })");
    6826             :   CompileRun(
    6827             :       "Object.defineProperty(obj2, 'x',"
    6828             :       "{ get: function() { return 'z'; }, configurable: false })");
    6829             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6830             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6831             : 
    6832           6 :   ExpectString("obj1.x", "z");
    6833           6 :   ExpectString("obj2.x", "z");
    6834             : 
    6835          30 :   CHECK(!GetGlobalProperty(&context, "obj1")
    6836             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6837             :                            v8_str("donut"))
    6838             :              .FromJust());
    6839          30 :   CHECK(!GetGlobalProperty(&context, "obj2")
    6840             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6841             :                            v8_str("donut"))
    6842             :              .FromJust());
    6843             : 
    6844           6 :   ExpectString("obj1.x", "z");
    6845           6 :   ExpectString("obj2.x", "z");
    6846           6 : }
    6847             : 
    6848             : 
    6849       26645 : THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
    6850           6 :   v8::Isolate* isolate = CcTest::isolate();
    6851          12 :   v8::HandleScope scope(isolate);
    6852           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6853           6 :   LocalContext context;
    6854             : 
    6855          30 :   CHECK(context->Global()
    6856             :             ->Set(context.local(), v8_str("obj1"),
    6857             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6858             :             .FromJust());
    6859             :   CompileRun("var obj2 = {};");
    6860             : 
    6861          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6862             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6863             :                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
    6864             :             .FromJust());
    6865          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6866             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6867             :                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
    6868             :             .FromJust());
    6869             : 
    6870           6 :   ExpectString("obj1.x", "x");
    6871           6 :   ExpectString("obj2.x", "x");
    6872             : 
    6873             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6874             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6875             : 
    6876          30 :   CHECK(!GetGlobalProperty(&context, "obj1")
    6877             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6878             :                            v8_str("donut"))
    6879             :              .FromJust());
    6880          30 :   CHECK(!GetGlobalProperty(&context, "obj2")
    6881             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6882             :                            v8_str("donut"))
    6883             :              .FromJust());
    6884             : 
    6885             :   {
    6886          12 :     v8::TryCatch try_catch(isolate);
    6887             :     CompileRun(
    6888             :         "Object.defineProperty(obj1, 'x',"
    6889             :         "{get: function() { return 'func'; }})");
    6890           6 :     CHECK(try_catch.HasCaught());
    6891          12 :     String::Utf8Value exception_value(isolate, try_catch.Exception());
    6892           6 :     CHECK_EQ(
    6893             :         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6894             :   }
    6895             :   {
    6896          12 :     v8::TryCatch try_catch(isolate);
    6897             :     CompileRun(
    6898             :         "Object.defineProperty(obj2, 'x',"
    6899             :         "{get: function() { return 'func'; }})");
    6900           6 :     CHECK(try_catch.HasCaught());
    6901          12 :     String::Utf8Value exception_value(isolate, try_catch.Exception());
    6902           6 :     CHECK_EQ(
    6903             :         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6904             :   }
    6905           6 : }
    6906             : 
    6907             : 
    6908          24 : static void Get239Value(Local<Name> name,
    6909             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    6910          24 :   ApiTestFuzzer::Fuzz();
    6911          96 :   CHECK(info.Data()
    6912             :             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
    6913             :             .FromJust());
    6914          96 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
    6915             :             .FromJust());
    6916             :   info.GetReturnValue().Set(name);
    6917          24 : }
    6918             : 
    6919             : 
    6920       26645 : THREADED_TEST(ElementAPIAccessor) {
    6921           6 :   v8::Isolate* isolate = CcTest::isolate();
    6922          12 :   v8::HandleScope scope(isolate);
    6923           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6924           6 :   LocalContext context;
    6925             : 
    6926          30 :   CHECK(context->Global()
    6927             :             ->Set(context.local(), v8_str("obj1"),
    6928             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6929             :             .FromJust());
    6930             :   CompileRun("var obj2 = {};");
    6931             : 
    6932          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6933             :             ->SetAccessor(context.local(), v8_str("239"), Get239Value, nullptr,
    6934             :                           v8_str("donut"))
    6935             :             .FromJust());
    6936          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6937             :             ->SetAccessor(context.local(), v8_str("239"), Get239Value, nullptr,
    6938             :                           v8_str("donut"))
    6939             :             .FromJust());
    6940             : 
    6941           6 :   ExpectString("obj1[239]", "239");
    6942           6 :   ExpectString("obj2[239]", "239");
    6943           6 :   ExpectString("obj1['239']", "239");
    6944           6 :   ExpectString("obj2['239']", "239");
    6945           6 : }
    6946             : 
    6947             : 
    6948       26639 : v8::Persistent<Value> xValue;
    6949             : 
    6950             : 
    6951         120 : static void SetXValue(Local<Name> name, Local<Value> value,
    6952             :                       const v8::PropertyCallbackInfo<void>& info) {
    6953         120 :   Local<Context> context = info.GetIsolate()->GetCurrentContext();
    6954         240 :   CHECK(value->Equals(context, v8_num(4)).FromJust());
    6955         360 :   CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
    6956         360 :   CHECK(name->Equals(context, v8_str("x")).FromJust());
    6957         120 :   CHECK(xValue.IsEmpty());
    6958             :   xValue.Reset(info.GetIsolate(), value);
    6959         120 : }
    6960             : 
    6961             : 
    6962       26645 : THREADED_TEST(SimplePropertyWrite) {
    6963           6 :   v8::Isolate* isolate = CcTest::isolate();
    6964          12 :   v8::HandleScope scope(isolate);
    6965           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6966          18 :   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
    6967           6 :   LocalContext context;
    6968          30 :   CHECK(context->Global()
    6969             :             ->Set(context.local(), v8_str("obj"),
    6970             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6971             :             .FromJust());
    6972             :   Local<Script> script = v8_compile("obj.x = 4");
    6973         126 :   for (int i = 0; i < 10; i++) {
    6974          60 :     CHECK(xValue.IsEmpty());
    6975          60 :     script->Run(context.local()).ToLocalChecked();
    6976         240 :     CHECK(v8_num(4)
    6977             :               ->Equals(context.local(),
    6978             :                        Local<Value>::New(CcTest::isolate(), xValue))
    6979             :               .FromJust());
    6980             :     xValue.Reset();
    6981             :   }
    6982           6 : }
    6983             : 
    6984             : 
    6985       26645 : THREADED_TEST(SetterOnly) {
    6986           6 :   v8::Isolate* isolate = CcTest::isolate();
    6987          12 :   v8::HandleScope scope(isolate);
    6988           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6989          18 :   templ->SetAccessor(v8_str("x"), nullptr, SetXValue, v8_str("donut"));
    6990           6 :   LocalContext context;
    6991          30 :   CHECK(context->Global()
    6992             :             ->Set(context.local(), v8_str("obj"),
    6993             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6994             :             .FromJust());
    6995             :   Local<Script> script = v8_compile("obj.x = 4; obj.x");
    6996         126 :   for (int i = 0; i < 10; i++) {
    6997          60 :     CHECK(xValue.IsEmpty());
    6998          60 :     script->Run(context.local()).ToLocalChecked();
    6999         240 :     CHECK(v8_num(4)
    7000             :               ->Equals(context.local(),
    7001             :                        Local<Value>::New(CcTest::isolate(), xValue))
    7002             :               .FromJust());
    7003             :     xValue.Reset();
    7004             :   }
    7005           6 : }
    7006             : 
    7007             : 
    7008       26645 : THREADED_TEST(NoAccessors) {
    7009           6 :   v8::Isolate* isolate = CcTest::isolate();
    7010          12 :   v8::HandleScope scope(isolate);
    7011           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    7012          18 :   templ->SetAccessor(v8_str("x"),
    7013             :                      static_cast<v8::AccessorGetterCallback>(nullptr), nullptr,
    7014           6 :                      v8_str("donut"));
    7015           6 :   LocalContext context;
    7016          30 :   CHECK(context->Global()
    7017             :             ->Set(context.local(), v8_str("obj"),
    7018             :                   templ->NewInstance(context.local()).ToLocalChecked())
    7019             :             .FromJust());
    7020             :   Local<Script> script = v8_compile("obj.x = 4; obj.x");
    7021         126 :   for (int i = 0; i < 10; i++) {
    7022          60 :     script->Run(context.local()).ToLocalChecked();
    7023             :   }
    7024           6 : }
    7025             : 
    7026             : 
    7027       26645 : THREADED_TEST(MultiContexts) {
    7028           6 :   v8::Isolate* isolate = CcTest::isolate();
    7029          12 :   v8::HandleScope scope(isolate);
    7030           6 :   v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    7031          18 :   templ->Set(v8_str("dummy"),
    7032           6 :              v8::FunctionTemplate::New(isolate, DummyCallHandler));
    7033             : 
    7034           6 :   Local<String> password = v8_str("Password");
    7035             : 
    7036             :   // Create an environment
    7037           6 :   LocalContext context0(nullptr, templ);
    7038           6 :   context0->SetSecurityToken(password);
    7039           6 :   v8::Local<v8::Object> global0 = context0->Global();
    7040          18 :   CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
    7041             :             .FromJust());
    7042          24 :   CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
    7043             :                      .ToLocalChecked()
    7044             :                      ->Int32Value(context0.local())
    7045             :                      .FromJust());
    7046             : 
    7047             :   // Create an independent environment
    7048           6 :   LocalContext context1(nullptr, templ);
    7049           6 :   context1->SetSecurityToken(password);
    7050           6 :   v8::Local<v8::Object> global1 = context1->Global();
    7051          18 :   CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
    7052             :             .FromJust());
    7053          12 :   CHECK(!global0->Equals(context1.local(), global1).FromJust());
    7054          24 :   CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
    7055             :                      .ToLocalChecked()
    7056             :                      ->Int32Value(context0.local())
    7057             :                      .FromJust());
    7058          24 :   CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
    7059             :                      .ToLocalChecked()
    7060             :                      ->Int32Value(context1.local())
    7061             :                      .FromJust());
    7062             : 
    7063             :   // Now create a new context with the old global
    7064           6 :   LocalContext context2(nullptr, templ, global1);
    7065           6 :   context2->SetSecurityToken(password);
    7066           6 :   v8::Local<v8::Object> global2 = context2->Global();
    7067          12 :   CHECK(global1->Equals(context2.local(), global2).FromJust());
    7068          24 :   CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
    7069             :                   .ToLocalChecked()
    7070             :                   ->Int32Value(context1.local())
    7071             :                   .FromJust());
    7072          24 :   CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
    7073             :                   .ToLocalChecked()
    7074             :                   ->Int32Value(context2.local())
    7075             :                   .FromJust());
    7076           6 : }
    7077             : 
    7078             : 
    7079       26645 : THREADED_TEST(FunctionPrototypeAcrossContexts) {
    7080             :   // Make sure that functions created by cloning boilerplates cannot
    7081             :   // communicate through their __proto__ field.
    7082             : 
    7083          12 :   v8::HandleScope scope(CcTest::isolate());
    7084             : 
    7085           6 :   LocalContext env0;
    7086           6 :   v8::Local<v8::Object> global0 = env0->Global();
    7087          18 :   v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
    7088             :                                       .ToLocalChecked()
    7089             :                                       .As<v8::Object>();
    7090             :   v8::Local<v8::Object> tostring0 =
    7091          18 :       object0->Get(env0.local(), v8_str("toString"))
    7092             :           .ToLocalChecked()
    7093             :           .As<v8::Object>();
    7094             :   v8::Local<v8::Object> proto0 =
    7095          18 :       tostring0->Get(env0.local(), v8_str("__proto__"))
    7096             :           .ToLocalChecked()
    7097             :           .As<v8::Object>();
    7098          18 :   CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
    7099             : 
    7100           6 :   LocalContext env1;
    7101           6 :   v8::Local<v8::Object> global1 = env1->Global();
    7102          18 :   v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
    7103             :                                       .ToLocalChecked()
    7104             :                                       .As<v8::Object>();
    7105             :   v8::Local<v8::Object> tostring1 =
    7106          18 :       object1->Get(env1.local(), v8_str("toString"))
    7107             :           .ToLocalChecked()
    7108             :           .As<v8::Object>();
    7109             :   v8::Local<v8::Object> proto1 =
    7110          18 :       tostring1->Get(env1.local(), v8_str("__proto__"))
    7111             :           .ToLocalChecked()
    7112             :           .As<v8::Object>();
    7113          18 :   CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
    7114           6 : }
    7115             : 
    7116             : 
    7117       26645 : THREADED_TEST(Regress892105) {
    7118             :   // Make sure that object and array literals created by cloning
    7119             :   // boilerplates cannot communicate through their __proto__
    7120             :   // field. This is rather difficult to check, but we try to add stuff
    7121             :   // to Object.prototype and Array.prototype and create a new
    7122             :   // environment. This should succeed.
    7123             : 
    7124          12 :   v8::HandleScope scope(CcTest::isolate());
    7125             : 
    7126             :   Local<String> source = v8_str(
    7127             :       "Object.prototype.obj = 1234;"
    7128             :       "Array.prototype.arr = 4567;"
    7129           6 :       "8901");
    7130             : 
    7131           6 :   LocalContext env0;
    7132           6 :   Local<Script> script0 = v8_compile(source);
    7133          18 :   CHECK_EQ(8901.0, script0->Run(env0.local())
    7134             :                        .ToLocalChecked()
    7135             :                        ->NumberValue(env0.local())
    7136             :                        .FromJust());
    7137             : 
    7138           6 :   LocalContext env1;
    7139           6 :   Local<Script> script1 = v8_compile(source);
    7140          18 :   CHECK_EQ(8901.0, script1->Run(env1.local())
    7141             :                        .ToLocalChecked()
    7142             :                        ->NumberValue(env1.local())
    7143             :                        .FromJust());
    7144           6 : }
    7145             : 
    7146          30 : static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7147             :   args.GetReturnValue().Set(args.This());
    7148          30 : }
    7149             : 
    7150       26645 : THREADED_TEST(UndetectableObject) {
    7151           6 :   LocalContext env;
    7152          12 :   v8::HandleScope scope(env->GetIsolate());
    7153             : 
    7154             :   Local<v8::FunctionTemplate> desc =
    7155           6 :       v8::FunctionTemplate::New(env->GetIsolate());
    7156          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7157          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7158             : 
    7159           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7160             :                               .ToLocalChecked()
    7161             :                               ->NewInstance(env.local())
    7162             :                               .ToLocalChecked();
    7163          24 :   CHECK(
    7164             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7165             : 
    7166           6 :   ExpectString("undetectable.toString()", "[object Object]");
    7167           6 :   ExpectString("typeof undetectable", "undefined");
    7168           6 :   ExpectString("typeof(undetectable)", "undefined");
    7169           6 :   ExpectBoolean("typeof undetectable == 'undefined'", true);
    7170           6 :   ExpectBoolean("typeof undetectable == 'object'", false);
    7171           6 :   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
    7172           6 :   ExpectBoolean("!undetectable", true);
    7173             : 
    7174           6 :   ExpectObject("true&&undetectable", obj);
    7175           6 :   ExpectBoolean("false&&undetectable", false);
    7176           6 :   ExpectBoolean("true||undetectable", true);
    7177           6 :   ExpectObject("false||undetectable", obj);
    7178             : 
    7179           6 :   ExpectObject("undetectable&&true", obj);
    7180           6 :   ExpectObject("undetectable&&false", obj);
    7181           6 :   ExpectBoolean("undetectable||true", true);
    7182           6 :   ExpectBoolean("undetectable||false", false);
    7183             : 
    7184           6 :   ExpectBoolean("undetectable==null", true);
    7185           6 :   ExpectBoolean("null==undetectable", true);
    7186           6 :   ExpectBoolean("undetectable==undefined", true);
    7187           6 :   ExpectBoolean("undefined==undetectable", true);
    7188           6 :   ExpectBoolean("undetectable==undetectable", true);
    7189             : 
    7190             : 
    7191           6 :   ExpectBoolean("undetectable===null", false);
    7192           6 :   ExpectBoolean("null===undetectable", false);
    7193           6 :   ExpectBoolean("undetectable===undefined", false);
    7194           6 :   ExpectBoolean("undefined===undetectable", false);
    7195           6 :   ExpectBoolean("undetectable===undetectable", true);
    7196           6 : }
    7197             : 
    7198             : 
    7199       26645 : THREADED_TEST(VoidLiteral) {
    7200           6 :   LocalContext env;
    7201           6 :   v8::Isolate* isolate = env->GetIsolate();
    7202          12 :   v8::HandleScope scope(isolate);
    7203             : 
    7204           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7205          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7206          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7207             : 
    7208           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7209             :                               .ToLocalChecked()
    7210             :                               ->NewInstance(env.local())
    7211             :                               .ToLocalChecked();
    7212          24 :   CHECK(
    7213             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7214             : 
    7215           6 :   ExpectBoolean("undefined == void 0", true);
    7216           6 :   ExpectBoolean("undetectable == void 0", true);
    7217           6 :   ExpectBoolean("null == void 0", true);
    7218           6 :   ExpectBoolean("undefined === void 0", true);
    7219           6 :   ExpectBoolean("undetectable === void 0", false);
    7220           6 :   ExpectBoolean("null === void 0", false);
    7221             : 
    7222           6 :   ExpectBoolean("void 0 == undefined", true);
    7223           6 :   ExpectBoolean("void 0 == undetectable", true);
    7224           6 :   ExpectBoolean("void 0 == null", true);
    7225           6 :   ExpectBoolean("void 0 === undefined", true);
    7226           6 :   ExpectBoolean("void 0 === undetectable", false);
    7227           6 :   ExpectBoolean("void 0 === null", false);
    7228             : 
    7229             :   ExpectString(
    7230             :       "(function() {"
    7231             :       "  try {"
    7232             :       "    return x === void 0;"
    7233             :       "  } catch(e) {"
    7234             :       "    return e.toString();"
    7235             :       "  }"
    7236             :       "})()",
    7237           6 :       "ReferenceError: x is not defined");
    7238             :   ExpectString(
    7239             :       "(function() {"
    7240             :       "  try {"
    7241             :       "    return void 0 === x;"
    7242             :       "  } catch(e) {"
    7243             :       "    return e.toString();"
    7244             :       "  }"
    7245             :       "})()",
    7246           6 :       "ReferenceError: x is not defined");
    7247           6 : }
    7248             : 
    7249             : 
    7250       26645 : THREADED_TEST(ExtensibleOnUndetectable) {
    7251           6 :   LocalContext env;
    7252           6 :   v8::Isolate* isolate = env->GetIsolate();
    7253          12 :   v8::HandleScope scope(isolate);
    7254             : 
    7255           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7256          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7257          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7258             : 
    7259           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7260             :                               .ToLocalChecked()
    7261             :                               ->NewInstance(env.local())
    7262             :                               .ToLocalChecked();
    7263          24 :   CHECK(
    7264             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7265             : 
    7266             :   Local<String> source = v8_str(
    7267             :       "undetectable.x = 42;"
    7268           6 :       "undetectable.x");
    7269             : 
    7270           6 :   Local<Script> script = v8_compile(source);
    7271             : 
    7272          24 :   CHECK(v8::Integer::New(isolate, 42)
    7273             :             ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
    7274             :             .FromJust());
    7275             : 
    7276           6 :   ExpectBoolean("Object.isExtensible(undetectable)", true);
    7277             : 
    7278           6 :   source = v8_str("Object.preventExtensions(undetectable);");
    7279           6 :   script = v8_compile(source);
    7280           6 :   script->Run(env.local()).ToLocalChecked();
    7281           6 :   ExpectBoolean("Object.isExtensible(undetectable)", false);
    7282             : 
    7283           6 :   source = v8_str("undetectable.y = 2000;");
    7284           6 :   script = v8_compile(source);
    7285           6 :   script->Run(env.local()).ToLocalChecked();
    7286           6 :   ExpectBoolean("undetectable.y == undefined", true);
    7287           6 : }
    7288             : 
    7289       26645 : THREADED_TEST(ConstructCallWithUndetectable) {
    7290           6 :   LocalContext env;
    7291           6 :   v8::Isolate* isolate = env->GetIsolate();
    7292          12 :   v8::HandleScope scope(isolate);
    7293             : 
    7294           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7295          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7296          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7297             : 
    7298           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7299             :                               .ToLocalChecked()
    7300             :                               ->NewInstance(env.local())
    7301             :                               .ToLocalChecked();
    7302          24 :   CHECK(
    7303             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7304             : 
    7305             :   // Undetectable object cannot be called as constructor.
    7306          12 :   v8::TryCatch try_catch(env->GetIsolate());
    7307           6 :   CHECK(CompileRun("new undetectable()").IsEmpty());
    7308           6 :   CHECK(try_catch.HasCaught());
    7309          18 :   String::Utf8Value exception_value(env->GetIsolate(), try_catch.Exception());
    7310           6 :   CHECK_EQ(0, strcmp("TypeError: undetectable is not a constructor",
    7311             :                      *exception_value));
    7312           6 : }
    7313             : 
    7314             : static int increment_callback_counter = 0;
    7315             : 
    7316          12 : static void IncrementCounterConstructCallback(
    7317             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    7318          12 :   increment_callback_counter++;
    7319          48 :   CHECK(Local<Object>::Cast(args.NewTarget())
    7320             :             ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("counter"),
    7321             :                   v8_num(increment_callback_counter))
    7322             :             .FromJust());
    7323             :   args.GetReturnValue().Set(args.NewTarget());
    7324          12 : }
    7325             : 
    7326       26645 : THREADED_TEST(SetCallAsFunctionHandlerConstructor) {
    7327           6 :   LocalContext env;
    7328           6 :   v8::Isolate* isolate = env->GetIsolate();
    7329          12 :   v8::HandleScope scope(isolate);
    7330             : 
    7331           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7332          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(
    7333           6 :       IncrementCounterConstructCallback);  // callable
    7334             : 
    7335           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7336             :                               .ToLocalChecked()
    7337             :                               ->NewInstance(env.local())
    7338             :                               .ToLocalChecked();
    7339          24 :   CHECK(env->Global()->Set(env.local(), v8_str("Counter"), obj).FromJust());
    7340             : 
    7341           6 :   ExpectInt32("(new Counter()).counter", 1);
    7342           6 :   CHECK_EQ(1, increment_callback_counter);
    7343           6 :   ExpectInt32("(new Counter()).counter", 2);
    7344           6 :   CHECK_EQ(2, increment_callback_counter);
    7345           6 : }
    7346             : // The point of this test is type checking. We run it only so compilers
    7347             : // don't complain about an unused function.
    7348       26644 : TEST(PersistentHandles) {
    7349           5 :   LocalContext env;
    7350           5 :   v8::Isolate* isolate = CcTest::isolate();
    7351          10 :   v8::HandleScope scope(isolate);
    7352           5 :   Local<String> str = v8_str("foo");
    7353             :   v8::Persistent<String> p_str(isolate, str);
    7354             :   p_str.Reset();
    7355             :   Local<Script> scr = v8_compile("");
    7356             :   v8::Persistent<Script> p_scr(isolate, scr);
    7357             :   p_scr.Reset();
    7358           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    7359             :   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
    7360             :   p_templ.Reset();
    7361           5 : }
    7362             : 
    7363             : 
    7364           6 : static void HandleLogDelegator(
    7365             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    7366           6 :   ApiTestFuzzer::Fuzz();
    7367           6 : }
    7368             : 
    7369             : 
    7370       26645 : THREADED_TEST(GlobalObjectTemplate) {
    7371           6 :   v8::Isolate* isolate = CcTest::isolate();
    7372          12 :   v8::HandleScope handle_scope(isolate);
    7373           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
    7374          18 :   global_template->Set(v8_str("JSNI_Log"),
    7375           6 :                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
    7376           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
    7377             :   Context::Scope context_scope(context);
    7378             :   CompileRun("JSNI_Log('LOG')");
    7379           6 : }
    7380             : 
    7381             : 
    7382             : static const char* kSimpleExtensionSource =
    7383             :     "function Foo() {"
    7384             :     "  return 4;"
    7385             :     "}";
    7386             : 
    7387             : 
    7388       26644 : TEST(SimpleExtensions) {
    7389          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7390             :   v8::RegisterExtension(
    7391          10 :       v8::base::make_unique<Extension>("simpletest", kSimpleExtensionSource));
    7392           5 :   const char* extension_names[] = {"simpletest"};
    7393             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7394           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7395             :   Context::Scope lock(context);
    7396             :   v8::Local<Value> result = CompileRun("Foo()");
    7397          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7398             :             .FromJust());
    7399           5 : }
    7400             : 
    7401             : 
    7402             : static const char* kStackTraceFromExtensionSource =
    7403             :     "function foo() {"
    7404             :     "  throw new Error();"
    7405             :     "}"
    7406             :     "function bar() {"
    7407             :     "  foo();"
    7408             :     "}";
    7409             : 
    7410             : 
    7411       26644 : TEST(StackTraceInExtension) {
    7412          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7413          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7414           5 :       "stacktracetest", kStackTraceFromExtensionSource));
    7415           5 :   const char* extension_names[] = {"stacktracetest"};
    7416             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7417           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7418             :   Context::Scope lock(context);
    7419             :   CompileRun(
    7420             :       "function user() { bar(); }"
    7421             :       "var error;"
    7422             :       "try{ user(); } catch (e) { error = e; }");
    7423           5 :   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
    7424           5 :   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
    7425           5 :   CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
    7426           5 : }
    7427             : 
    7428             : 
    7429       26644 : TEST(NullExtensions) {
    7430          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7431          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>("nulltest", nullptr));
    7432           5 :   const char* extension_names[] = {"nulltest"};
    7433             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7434           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7435             :   Context::Scope lock(context);
    7436             :   v8::Local<Value> result = CompileRun("1+3");
    7437          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7438             :             .FromJust());
    7439           5 : }
    7440             : 
    7441             : static const char* kEmbeddedExtensionSource =
    7442             :     "function Ret54321(){return 54321;}~~@@$"
    7443             :     "$%% THIS IS A SERIES OF NON-nullptr-TERMINATED STRINGS.";
    7444             : static const int kEmbeddedExtensionSourceValidLen = 34;
    7445             : 
    7446             : 
    7447       26644 : TEST(ExtensionMissingSourceLength) {
    7448          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7449          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7450           5 :       "srclentest_fail", kEmbeddedExtensionSource));
    7451           5 :   const char* extension_names[] = {"srclentest_fail"};
    7452             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7453           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7454           5 :   CHECK_NULL(*context);
    7455           5 : }
    7456             : 
    7457             : 
    7458       26644 : TEST(ExtensionWithSourceLength) {
    7459          20 :   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
    7460          20 :        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
    7461          30 :     v8::HandleScope handle_scope(CcTest::isolate());
    7462             :     i::ScopedVector<char> extension_name(32);
    7463          15 :     i::SNPrintF(extension_name, "ext #%d", source_len);
    7464          30 :     v8::RegisterExtension(v8::base::make_unique<Extension>(
    7465             :         extension_name.start(), kEmbeddedExtensionSource, 0, nullptr,
    7466          15 :         source_len));
    7467          15 :     const char* extension_names[1] = {extension_name.start()};
    7468             :     v8::ExtensionConfiguration extensions(1, extension_names);
    7469          15 :     v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7470          15 :     if (source_len == kEmbeddedExtensionSourceValidLen) {
    7471             :       Context::Scope lock(context);
    7472           5 :       v8::Local<Value> result = CompileRun("Ret54321()");
    7473          15 :       CHECK(v8::Integer::New(CcTest::isolate(), 54321)
    7474             :                 ->Equals(context, result)
    7475             :                 .FromJust());
    7476             :     } else {
    7477             :       // Anything but exactly the right length should fail to compile.
    7478          10 :       CHECK_NULL(*context);
    7479             :     }
    7480             :   }
    7481           5 : }
    7482             : 
    7483             : 
    7484             : static const char* kEvalExtensionSource1 =
    7485             :     "function UseEval1() {"
    7486             :     "  var x = 42;"
    7487             :     "  return eval('x');"
    7488             :     "}";
    7489             : 
    7490             : 
    7491             : static const char* kEvalExtensionSource2 =
    7492             :     "(function() {"
    7493             :     "  var x = 42;"
    7494             :     "  function e() {"
    7495             :     "    return eval('x');"
    7496             :     "  }"
    7497             :     "  this.UseEval2 = e;"
    7498             :     "})()";
    7499             : 
    7500             : 
    7501       26644 : TEST(UseEvalFromExtension) {
    7502          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7503             :   v8::RegisterExtension(
    7504          10 :       v8::base::make_unique<Extension>("evaltest1", kEvalExtensionSource1));
    7505             :   v8::RegisterExtension(
    7506          10 :       v8::base::make_unique<Extension>("evaltest2", kEvalExtensionSource2));
    7507           5 :   const char* extension_names[] = {"evaltest1", "evaltest2"};
    7508             :   v8::ExtensionConfiguration extensions(2, extension_names);
    7509           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7510             :   Context::Scope lock(context);
    7511             :   v8::Local<Value> result = CompileRun("UseEval1()");
    7512          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7513             :             .FromJust());
    7514             :   result = CompileRun("UseEval2()");
    7515          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7516             :             .FromJust());
    7517           5 : }
    7518             : 
    7519             : 
    7520             : static const char* kWithExtensionSource1 =
    7521             :     "function UseWith1() {"
    7522             :     "  var x = 42;"
    7523             :     "  with({x:87}) { return x; }"
    7524             :     "}";
    7525             : 
    7526             : 
    7527             : static const char* kWithExtensionSource2 =
    7528             :     "(function() {"
    7529             :     "  var x = 42;"
    7530             :     "  function e() {"
    7531             :     "    with ({x:87}) { return x; }"
    7532             :     "  }"
    7533             :     "  this.UseWith2 = e;"
    7534             :     "})()";
    7535             : 
    7536             : 
    7537       26644 : TEST(UseWithFromExtension) {
    7538          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7539             :   v8::RegisterExtension(
    7540          10 :       v8::base::make_unique<Extension>("withtest1", kWithExtensionSource1));
    7541             :   v8::RegisterExtension(
    7542          10 :       v8::base::make_unique<Extension>("withtest2", kWithExtensionSource2));
    7543           5 :   const char* extension_names[] = {"withtest1", "withtest2"};
    7544             :   v8::ExtensionConfiguration extensions(2, extension_names);
    7545           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7546             :   Context::Scope lock(context);
    7547             :   v8::Local<Value> result = CompileRun("UseWith1()");
    7548          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
    7549             :             .FromJust());
    7550             :   result = CompileRun("UseWith2()");
    7551          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
    7552             :             .FromJust());
    7553           5 : }
    7554             : 
    7555             : 
    7556       26644 : TEST(AutoExtensions) {
    7557          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7558             :   auto extension =
    7559           5 :       v8::base::make_unique<Extension>("autotest", kSimpleExtensionSource);
    7560             :   extension->set_auto_enable(true);
    7561          10 :   v8::RegisterExtension(std::move(extension));
    7562           5 :   v8::Local<Context> context = Context::New(CcTest::isolate());
    7563             :   Context::Scope lock(context);
    7564             :   v8::Local<Value> result = CompileRun("Foo()");
    7565          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7566             :             .FromJust());
    7567           5 : }
    7568             : 
    7569             : 
    7570             : static const char* kSyntaxErrorInExtensionSource = "[";
    7571             : 
    7572             : 
    7573             : // Test that a syntax error in an extension does not cause a fatal
    7574             : // error but results in an empty context.
    7575       26644 : TEST(SyntaxErrorExtensions) {
    7576          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7577          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7578           5 :       "syntaxerror", kSyntaxErrorInExtensionSource));
    7579           5 :   const char* extension_names[] = {"syntaxerror"};
    7580             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7581           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7582           5 :   CHECK(context.IsEmpty());
    7583           5 : }
    7584             : 
    7585             : 
    7586             : static const char* kExceptionInExtensionSource = "throw 42";
    7587             : 
    7588             : 
    7589             : // Test that an exception when installing an extension does not cause
    7590             : // a fatal error but results in an empty context.
    7591       26644 : TEST(ExceptionExtensions) {
    7592          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7593          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7594           5 :       "exception", kExceptionInExtensionSource));
    7595           5 :   const char* extension_names[] = {"exception"};
    7596             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7597           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7598           5 :   CHECK(context.IsEmpty());
    7599           5 : }
    7600             : 
    7601             : static const char* kNativeCallInExtensionSource =
    7602             :     "function call_runtime_last_index_of(x) {"
    7603             :     "  return %StringLastIndexOf(x, 'bob');"
    7604             :     "}";
    7605             : 
    7606             : static const char* kNativeCallTest =
    7607             :     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
    7608             : 
    7609             : // Test that a native runtime calls are supported in extensions.
    7610       26644 : TEST(NativeCallInExtensions) {
    7611          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7612          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7613           5 :       "nativecall", kNativeCallInExtensionSource));
    7614           5 :   const char* extension_names[] = {"nativecall"};
    7615             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7616           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7617             :   Context::Scope lock(context);
    7618           5 :   v8::Local<Value> result = CompileRun(kNativeCallTest);
    7619          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 24))
    7620             :             .FromJust());
    7621           5 : }
    7622             : 
    7623             : 
    7624          30 : class NativeFunctionExtension : public Extension {
    7625             :  public:
    7626             :   NativeFunctionExtension(const char* name, const char* source,
    7627             :                           v8::FunctionCallback fun = &Echo)
    7628          15 :       : Extension(name, source), function_(fun) {}
    7629             : 
    7630           5 :   v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    7631             :       v8::Isolate* isolate, v8::Local<v8::String> name) override {
    7632           5 :     return v8::FunctionTemplate::New(isolate, function_);
    7633             :   }
    7634             : 
    7635           5 :   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7636           5 :     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
    7637           5 :   }
    7638             : 
    7639             :  private:
    7640             :   v8::FunctionCallback function_;
    7641             : };
    7642             : 
    7643             : 
    7644       26644 : TEST(NativeFunctionDeclaration) {
    7645          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7646           5 :   const char* name = "nativedecl";
    7647          15 :   v8::RegisterExtension(v8::base::make_unique<NativeFunctionExtension>(
    7648           5 :       name, "native function foo();"));
    7649           5 :   const char* extension_names[] = {name};
    7650             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7651           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7652             :   Context::Scope lock(context);
    7653             :   v8::Local<Value> result = CompileRun("foo(42);");
    7654          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7655             :             .FromJust());
    7656           5 : }
    7657             : 
    7658             : 
    7659       26644 : TEST(NativeFunctionDeclarationError) {
    7660          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7661           5 :   const char* name = "nativedeclerr";
    7662             :   // Syntax error in extension code.
    7663          15 :   v8::RegisterExtension(v8::base::make_unique<NativeFunctionExtension>(
    7664           5 :       name, "native\nfunction foo();"));
    7665           5 :   const char* extension_names[] = {name};
    7666             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7667           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7668           5 :   CHECK(context.IsEmpty());
    7669           5 : }
    7670             : 
    7671             : 
    7672       26644 : TEST(NativeFunctionDeclarationErrorEscape) {
    7673          10 :   v8::HandleScope handle_scope(CcTest::isolate());
    7674           5 :   const char* name = "nativedeclerresc";
    7675             :   // Syntax error in extension code - escape code in "native" means that
    7676             :   // it's not treated as a keyword.
    7677          15 :   v8::RegisterExtension(v8::base::make_unique<NativeFunctionExtension>(
    7678           5 :       name, "nativ\\u0065 function foo();"));
    7679           5 :   const char* extension_names[] = {name};
    7680             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7681           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7682           5 :   CHECK(context.IsEmpty());
    7683           5 : }
    7684             : 
    7685             : 
    7686          30 : static void CheckDependencies(const char* name, const char* expected) {
    7687          60 :   v8::HandleScope handle_scope(CcTest::isolate());
    7688             :   v8::ExtensionConfiguration config(1, &name);
    7689          30 :   LocalContext context(&config);
    7690         180 :   CHECK(
    7691             :       v8_str(expected)
    7692             :           ->Equals(context.local(), context->Global()
    7693             :                                         ->Get(context.local(), v8_str("loaded"))
    7694             :                                         .ToLocalChecked())
    7695             :           .FromJust());
    7696          30 : }
    7697             : 
    7698             : 
    7699             : /*
    7700             :  * Configuration:
    7701             :  *
    7702             :  *     /-- B <--\
    7703             :  * A <-          -- D <-- E
    7704             :  *     \-- C <--/
    7705             :  */
    7706       26645 : THREADED_TEST(ExtensionDependency) {
    7707             :   static const char* kEDeps[] = {"D"};
    7708             :   v8::RegisterExtension(
    7709          12 :       v8::base::make_unique<Extension>("E", "this.loaded += 'E';", 1, kEDeps));
    7710             :   static const char* kDDeps[] = {"B", "C"};
    7711             :   v8::RegisterExtension(
    7712          12 :       v8::base::make_unique<Extension>("D", "this.loaded += 'D';", 2, kDDeps));
    7713             :   static const char* kBCDeps[] = {"A"};
    7714             :   v8::RegisterExtension(
    7715          12 :       v8::base::make_unique<Extension>("B", "this.loaded += 'B';", 1, kBCDeps));
    7716             :   v8::RegisterExtension(
    7717          12 :       v8::base::make_unique<Extension>("C", "this.loaded += 'C';", 1, kBCDeps));
    7718             :   v8::RegisterExtension(
    7719          12 :       v8::base::make_unique<Extension>("A", "this.loaded += 'A';"));
    7720           6 :   CheckDependencies("A", "undefinedA");
    7721           6 :   CheckDependencies("B", "undefinedAB");
    7722           6 :   CheckDependencies("C", "undefinedAC");
    7723           6 :   CheckDependencies("D", "undefinedABCD");
    7724           6 :   CheckDependencies("E", "undefinedABCDE");
    7725          12 :   v8::HandleScope handle_scope(CcTest::isolate());
    7726             :   static const char* exts[2] = {"C", "E"};
    7727             :   v8::ExtensionConfiguration config(2, exts);
    7728           6 :   LocalContext context(&config);
    7729          36 :   CHECK(
    7730             :       v8_str("undefinedACBDE")
    7731             :           ->Equals(context.local(), context->Global()
    7732             :                                         ->Get(context.local(), v8_str("loaded"))
    7733             :                                         .ToLocalChecked())
    7734             :           .FromJust());
    7735           6 : }
    7736             : 
    7737             : 
    7738             : static const char* kExtensionTestScript =
    7739             :     "native function A();"
    7740             :     "native function B();"
    7741             :     "native function C();"
    7742             :     "function Foo(i) {"
    7743             :     "  if (i == 0) return A();"
    7744             :     "  if (i == 1) return B();"
    7745             :     "  if (i == 2) return C();"
    7746             :     "}";
    7747             : 
    7748             : 
    7749         198 : static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7750         198 :   ApiTestFuzzer::Fuzz();
    7751         198 :   if (args.IsConstructCall()) {
    7752         720 :     CHECK(args.This()
    7753             :               ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
    7754             :                     args.Data())
    7755             :               .FromJust());
    7756             :     args.GetReturnValue().SetNull();
    7757         180 :     return;
    7758             :   }
    7759             :   args.GetReturnValue().Set(args.Data());
    7760             : }
    7761             : 
    7762             : 
    7763          24 : class FunctionExtension : public Extension {
    7764             :  public:
    7765          12 :   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
    7766             :   v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    7767             :       v8::Isolate* isolate, v8::Local<String> name) override;
    7768             : };
    7769             : 
    7770             : 
    7771             : static int lookup_count = 0;
    7772          33 : v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
    7773             :     v8::Isolate* isolate, v8::Local<String> name) {
    7774          33 :   lookup_count++;
    7775          66 :   if (name->StrictEquals(v8_str("A"))) {
    7776             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7777          22 :                                      v8::Integer::New(isolate, 8));
    7778          44 :   } else if (name->StrictEquals(v8_str("B"))) {
    7779             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7780          22 :                                      v8::Integer::New(isolate, 7));
    7781          22 :   } else if (name->StrictEquals(v8_str("C"))) {
    7782             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7783          22 :                                      v8::Integer::New(isolate, 6));
    7784             :   } else {
    7785           0 :     return v8::Local<v8::FunctionTemplate>();
    7786             :   }
    7787             : }
    7788             : 
    7789             : 
    7790       26645 : THREADED_TEST(FunctionLookup) {
    7791          24 :   v8::RegisterExtension(v8::base::make_unique<FunctionExtension>());
    7792          12 :   v8::HandleScope handle_scope(CcTest::isolate());
    7793             :   static const char* exts[1] = {"functiontest"};
    7794             :   v8::ExtensionConfiguration config(1, exts);
    7795           6 :   LocalContext context(&config);
    7796           6 :   CHECK_EQ(3, lookup_count);
    7797          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 8)
    7798             :             ->Equals(context.local(), CompileRun("Foo(0)"))
    7799             :             .FromJust());
    7800          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 7)
    7801             :             ->Equals(context.local(), CompileRun("Foo(1)"))
    7802             :             .FromJust());
    7803          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 6)
    7804             :             ->Equals(context.local(), CompileRun("Foo(2)"))
    7805             :             .FromJust());
    7806           6 : }
    7807             : 
    7808             : 
    7809       26645 : THREADED_TEST(NativeFunctionConstructCall) {
    7810          24 :   v8::RegisterExtension(v8::base::make_unique<FunctionExtension>());
    7811          12 :   v8::HandleScope handle_scope(CcTest::isolate());
    7812             :   static const char* exts[1] = {"functiontest"};
    7813             :   v8::ExtensionConfiguration config(1, exts);
    7814           6 :   LocalContext context(&config);
    7815         126 :   for (int i = 0; i < 10; i++) {
    7816             :     // Run a few times to ensure that allocation of objects doesn't
    7817             :     // change behavior of a constructor function.
    7818         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 8)
    7819             :               ->Equals(context.local(), CompileRun("(new A()).data"))
    7820             :               .FromJust());
    7821         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 7)
    7822             :               ->Equals(context.local(), CompileRun("(new B()).data"))
    7823             :               .FromJust());
    7824         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 6)
    7825             :               ->Equals(context.local(), CompileRun("(new C()).data"))
    7826             :               .FromJust());
    7827             :   }
    7828           6 : }
    7829             : 
    7830             : 
    7831             : static const char* last_location;
    7832             : static const char* last_message;
    7833          10 : void StoringErrorCallback(const char* location, const char* message) {
    7834          10 :   if (last_location == nullptr) {
    7835          10 :     last_location = location;
    7836          10 :     last_message = message;
    7837             :   }
    7838          10 : }
    7839             : 
    7840             : 
    7841             : // ErrorReporting creates a circular extensions configuration and
    7842             : // tests that the fatal error handler gets called.  This renders V8
    7843             : // unusable and therefore this test cannot be run in parallel.
    7844       26644 : TEST(ErrorReporting) {
    7845           5 :   CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
    7846             :   static const char* aDeps[] = {"B"};
    7847          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>("A", "", 1, aDeps));
    7848             :   static const char* bDeps[] = {"A"};
    7849          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>("B", "", 1, bDeps));
    7850           5 :   last_location = nullptr;
    7851             :   v8::ExtensionConfiguration config(1, bDeps);
    7852           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
    7853           5 :   CHECK(context.IsEmpty());
    7854           5 :   CHECK(last_location);
    7855           5 : }
    7856             : 
    7857             : static size_t dcheck_count;
    7858           0 : void DcheckErrorCallback(const char* file, int line, const char* message) {
    7859           0 :   last_message = message;
    7860           0 :   ++dcheck_count;
    7861           0 : }
    7862             : 
    7863       26644 : TEST(DcheckErrorHandler) {
    7864           5 :   V8::SetDcheckErrorHandler(DcheckErrorCallback);
    7865             : 
    7866           5 :   last_message = nullptr;
    7867           5 :   dcheck_count = 0;
    7868             : 
    7869             :   DCHECK(false && "w00t");
    7870             : #ifdef DEBUG
    7871             :   CHECK_EQ(dcheck_count, 1);
    7872             :   CHECK(last_message);
    7873             :   CHECK(std::string(last_message).find("w00t") != std::string::npos);
    7874             : #else
    7875             :   // The DCHECK should be a noop in non-DEBUG builds.
    7876             :   CHECK_EQ(dcheck_count, 0);
    7877             : #endif
    7878           5 : }
    7879             : 
    7880           6 : static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
    7881             :                                              v8::Local<Value> data) {
    7882           6 :   v8::Isolate* isolate = CcTest::isolate();
    7883           6 :   Local<Context> context = isolate->GetCurrentContext();
    7884          12 :   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
    7885          18 :   CHECK(v8::Undefined(isolate)
    7886             :             ->Equals(context, message->GetScriptOrigin().ResourceName())
    7887             :             .FromJust());
    7888          12 :   message->GetLineNumber(context).FromJust();
    7889           6 :   message->GetSourceLine(context).ToLocalChecked();
    7890           6 : }
    7891             : 
    7892             : 
    7893       26645 : THREADED_TEST(ErrorWithMissingScriptInfo) {
    7894           6 :   LocalContext context;
    7895          12 :   v8::HandleScope scope(context->GetIsolate());
    7896           6 :   context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
    7897             :   CompileRun("throw Error()");
    7898           6 :   context->GetIsolate()->RemoveMessageListeners(
    7899           6 :       MissingScriptInfoMessageListener);
    7900           6 : }
    7901             : 
    7902             : 
    7903          88 : struct FlagAndPersistent {
    7904             :   bool flag;
    7905             :   v8::Global<v8::Object> handle;
    7906             : };
    7907             : 
    7908          40 : static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7909          40 :   data.GetParameter()->flag = true;
    7910             :   data.GetParameter()->handle.Reset();
    7911          40 : }
    7912             : 
    7913          20 : static void IndependentWeakHandle(bool global_gc, bool interlinked) {
    7914          20 :   i::FLAG_stress_incremental_marking = false;
    7915             :   // Parallel scavenge introduces too much fragmentation.
    7916          20 :   i::FLAG_parallel_scavenge = false;
    7917          20 :   v8::Isolate* iso = CcTest::isolate();
    7918          40 :   v8::HandleScope scope(iso);
    7919          20 :   v8::Local<Context> context = Context::New(iso);
    7920             :   Context::Scope context_scope(context);
    7921             : 
    7922             :   FlagAndPersistent object_a, object_b;
    7923             : 
    7924             :   size_t big_heap_size = 0;
    7925             :   size_t big_array_size = 0;
    7926             : 
    7927             :   {
    7928          40 :     v8::HandleScope handle_scope(iso);
    7929          20 :     Local<Object> a(v8::Object::New(iso));
    7930          20 :     Local<Object> b(v8::Object::New(iso));
    7931             :     object_a.handle.Reset(iso, a);
    7932             :     object_b.handle.Reset(iso, b);
    7933          20 :     if (interlinked) {
    7934          30 :       a->Set(context, v8_str("x"), b).FromJust();
    7935          30 :       b->Set(context, v8_str("x"), a).FromJust();
    7936             :     }
    7937          20 :     if (global_gc) {
    7938          10 :       CcTest::CollectAllGarbage();
    7939             :     } else {
    7940          10 :       CcTest::CollectGarbage(i::NEW_SPACE);
    7941             :     }
    7942          20 :     v8::Local<Value> big_array = v8::Array::New(CcTest::isolate(), 5000);
    7943             :     // Verify that we created an array where the space was reserved up front.
    7944             :     big_array_size =
    7945             :         v8::internal::JSArray::cast(*v8::Utils::OpenHandle(*big_array))
    7946          40 :             ->elements()
    7947          20 :             ->Size();
    7948          20 :     CHECK_LE(20000, big_array_size);
    7949          60 :     a->Set(context, v8_str("y"), big_array).FromJust();
    7950          20 :     big_heap_size = CcTest::heap()->SizeOfObjects();
    7951             :   }
    7952             : 
    7953          20 :   object_a.flag = false;
    7954          20 :   object_b.flag = false;
    7955             :   object_a.handle.SetWeak(&object_a, &SetFlag,
    7956             :                           v8::WeakCallbackType::kParameter);
    7957             :   object_b.handle.SetWeak(&object_b, &SetFlag,
    7958             :                           v8::WeakCallbackType::kParameter);
    7959             : #if __clang__
    7960             : #pragma clang diagnostic push
    7961             : #pragma clang diagnostic ignored "-Wdeprecated"
    7962             : #endif
    7963             :   // MarkIndependent is marked deprecated but we still rely on it temporarily.
    7964          20 :   CHECK(!object_b.handle.IsIndependent());
    7965             :   object_a.handle.MarkIndependent();
    7966             :   object_b.handle.MarkIndependent();
    7967          20 :   CHECK(object_b.handle.IsIndependent());
    7968             : #if __clang__
    7969             : #pragma clang diagnostic pop
    7970             : #endif
    7971          20 :   if (global_gc) {
    7972          10 :     CcTest::CollectAllGarbage();
    7973             :   } else {
    7974          10 :     CcTest::CollectGarbage(i::NEW_SPACE);
    7975             :   }
    7976             :   // A single GC should be enough to reclaim the memory, since we are using
    7977             :   // phantom handles.
    7978          20 :   CHECK_GT(big_heap_size - big_array_size, CcTest::heap()->SizeOfObjects());
    7979          20 :   CHECK(object_a.flag);
    7980          20 :   CHECK(object_b.flag);
    7981          20 : }
    7982             : 
    7983       26644 : TEST(IndependentWeakHandle) {
    7984           5 :   IndependentWeakHandle(false, false);
    7985           5 :   IndependentWeakHandle(false, true);
    7986           5 :   IndependentWeakHandle(true, false);
    7987           5 :   IndependentWeakHandle(true, true);
    7988           5 : }
    7989             : 
    7990             : class Trivial {
    7991             :  public:
    7992          12 :   explicit Trivial(int x) : x_(x) {}
    7993             : 
    7994          36 :   int x() { return x_; }
    7995          12 :   void set_x(int x) { x_ = x; }
    7996             : 
    7997             :  private:
    7998             :   int x_;
    7999             : };
    8000             : 
    8001             : 
    8002             : class Trivial2 {
    8003             :  public:
    8004          12 :   Trivial2(int x, int y) : y_(y), x_(x) {}
    8005             : 
    8006             :   int x() { return x_; }
    8007          12 :   void set_x(int x) { x_ = x; }
    8008             : 
    8009             :   int y() { return y_; }
    8010             :   void set_y(int y) { y_ = y; }
    8011             : 
    8012             :  private:
    8013             :   int y_;
    8014             :   int x_;
    8015             : };
    8016             : 
    8017          12 : void CheckInternalFields(
    8018             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
    8019             :   v8::Persistent<v8::Object>* handle = data.GetParameter();
    8020             :   handle->Reset();
    8021             :   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
    8022             :   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
    8023          12 :   CHECK_EQ(42, t1->x());
    8024          12 :   CHECK_EQ(103, t2->x());
    8025             :   t1->set_x(1729);
    8026             :   t2->set_x(33550336);
    8027          12 : }
    8028             : 
    8029          12 : void InternalFieldCallback(bool global_gc) {
    8030          12 :   LocalContext env;
    8031          12 :   v8::Isolate* isolate = env->GetIsolate();
    8032          24 :   v8::HandleScope scope(isolate);
    8033             : 
    8034          12 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    8035          12 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    8036             :   Trivial* t1;
    8037             :   Trivial2* t2;
    8038          12 :   instance_templ->SetInternalFieldCount(2);
    8039             :   v8::Persistent<v8::Object> handle;
    8040             :   {
    8041          24 :     v8::HandleScope scope(isolate);
    8042          12 :     Local<v8::Object> obj = templ->GetFunction(env.local())
    8043             :                                 .ToLocalChecked()
    8044             :                                 ->NewInstance(env.local())
    8045             :                                 .ToLocalChecked();
    8046             :     handle.Reset(isolate, obj);
    8047          12 :     CHECK_EQ(2, obj->InternalFieldCount());
    8048          12 :     CHECK(obj->GetInternalField(0)->IsUndefined());
    8049          12 :     t1 = new Trivial(42);
    8050          12 :     t2 = new Trivial2(103, 9);
    8051             : 
    8052          12 :     obj->SetAlignedPointerInInternalField(0, t1);
    8053             :     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
    8054          12 :     CHECK_EQ(42, t1->x());
    8055             : 
    8056          12 :     obj->SetAlignedPointerInInternalField(1, t2);
    8057             :     t2 =
    8058             :         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
    8059          12 :     CHECK_EQ(103, t2->x());
    8060             : 
    8061             :     handle.SetWeak<v8::Persistent<v8::Object>>(
    8062             :         &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
    8063             :   }
    8064          12 :   if (global_gc) {
    8065           6 :     CcTest::CollectAllGarbage();
    8066             :   } else {
    8067           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
    8068             :   }
    8069             : 
    8070          12 :   CHECK_EQ(1729, t1->x());
    8071          12 :   CHECK_EQ(33550336, t2->x());
    8072             : 
    8073          12 :   delete t1;
    8074          12 :   delete t2;
    8075          12 : }
    8076             : 
    8077       26645 : THREADED_TEST(InternalFieldCallback) {
    8078           6 :   InternalFieldCallback(false);
    8079           6 :   InternalFieldCallback(true);
    8080           6 : }
    8081             : 
    8082          24 : static void ResetUseValueAndSetFlag(
    8083             :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8084             :   // Blink will reset the handle, and then use the other handle, so they
    8085             :   // can't use the same backing slot.
    8086             :   data.GetParameter()->handle.Reset();
    8087          24 :   data.GetParameter()->flag = true;
    8088          24 : }
    8089             : 
    8090          12 : void v8::internal::heap::HeapTester::ResetWeakHandle(bool global_gc) {
    8091             :   using v8::Context;
    8092             :   using v8::Local;
    8093             :   using v8::Object;
    8094             : 
    8095          12 :   v8::Isolate* iso = CcTest::isolate();
    8096          24 :   v8::HandleScope scope(iso);
    8097          12 :   v8::Local<Context> context = Context::New(iso);
    8098             :   Context::Scope context_scope(context);
    8099             : 
    8100             :   FlagAndPersistent object_a, object_b;
    8101             : 
    8102             :   {
    8103          24 :     v8::HandleScope handle_scope(iso);
    8104          12 :     Local<Object> a(v8::Object::New(iso));
    8105          12 :     Local<Object> b(v8::Object::New(iso));
    8106             :     object_a.handle.Reset(iso, a);
    8107             :     object_b.handle.Reset(iso, b);
    8108          12 :     if (global_gc) {
    8109           6 :       CcTest::PreciseCollectAllGarbage();
    8110             :     } else {
    8111           6 :       CcTest::CollectGarbage(i::NEW_SPACE);
    8112             :     }
    8113             :   }
    8114             : 
    8115          12 :   object_a.flag = false;
    8116          12 :   object_b.flag = false;
    8117             :   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
    8118             :                           v8::WeakCallbackType::kParameter);
    8119             :   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
    8120             :                           v8::WeakCallbackType::kParameter);
    8121          12 :   if (!global_gc) {
    8122             : #if __clang__
    8123             : #pragma clang diagnostic push
    8124             : #pragma clang diagnostic ignored "-Wdeprecated"
    8125             : #endif
    8126             :     // MarkIndependent is marked deprecated but we still rely on it temporarily.
    8127             :     object_a.handle.MarkIndependent();
    8128             :     object_b.handle.MarkIndependent();
    8129           6 :     CHECK(object_b.handle.IsIndependent());
    8130             : #if __clang__
    8131             : #pragma clang diagnostic pop
    8132             : #endif
    8133             :   }
    8134          12 :   if (global_gc) {
    8135           6 :     CcTest::PreciseCollectAllGarbage();
    8136             :   } else {
    8137           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
    8138             :   }
    8139          12 :   CHECK(object_a.flag);
    8140          12 :   CHECK(object_b.flag);
    8141          12 : }
    8142             : 
    8143       26645 : THREADED_HEAP_TEST(ResetWeakHandle) {
    8144           6 :   v8::internal::heap::HeapTester::ResetWeakHandle(false);
    8145           6 :   v8::internal::heap::HeapTester::ResetWeakHandle(true);
    8146           6 : }
    8147             : 
    8148          24 : static void InvokeScavenge() { CcTest::CollectGarbage(i::NEW_SPACE); }
    8149             : 
    8150          24 : static void InvokeMarkSweep() { CcTest::CollectAllGarbage(); }
    8151             : 
    8152          12 : static void ForceScavenge2(
    8153             :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8154          12 :   data.GetParameter()->flag = true;
    8155             :   InvokeScavenge();
    8156          12 : }
    8157             : 
    8158          12 : static void ForceScavenge1(
    8159             :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8160             :   data.GetParameter()->handle.Reset();
    8161             :   data.SetSecondPassCallback(ForceScavenge2);
    8162          12 : }
    8163             : 
    8164          12 : static void ForceMarkSweep2(
    8165             :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8166          12 :   data.GetParameter()->flag = true;
    8167             :   InvokeMarkSweep();
    8168          12 : }
    8169             : 
    8170          12 : static void ForceMarkSweep1(
    8171             :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8172             :   data.GetParameter()->handle.Reset();
    8173             :   data.SetSecondPassCallback(ForceMarkSweep2);
    8174          12 : }
    8175             : 
    8176       26645 : THREADED_TEST(GCFromWeakCallbacks) {
    8177           6 :   v8::Isolate* isolate = CcTest::isolate();
    8178          12 :   v8::Locker locker(CcTest::isolate());
    8179          12 :   v8::HandleScope scope(isolate);
    8180           6 :   v8::Local<Context> context = Context::New(isolate);
    8181             :   Context::Scope context_scope(context);
    8182             : 
    8183             :   static const int kNumberOfGCTypes = 2;
    8184             :   typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
    8185             :   Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
    8186           6 :                                                     &ForceMarkSweep1};
    8187             : 
    8188             :   typedef void (*GCInvoker)();
    8189           6 :   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
    8190             : 
    8191          30 :   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
    8192          60 :     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
    8193             :       FlagAndPersistent object;
    8194             :       {
    8195          48 :         v8::HandleScope handle_scope(isolate);
    8196          48 :         object.handle.Reset(isolate, v8::Object::New(isolate));
    8197             :       }
    8198          24 :       object.flag = false;
    8199          24 :       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
    8200             :                             v8::WeakCallbackType::kParameter);
    8201             : #if __clang__
    8202             : #pragma clang diagnostic push
    8203             : #pragma clang diagnostic ignored "-Wdeprecated"
    8204             : #endif
    8205             :       // MarkIndependent is marked deprecated but we still rely on it
    8206             :       // temporarily.
    8207             :       object.handle.MarkIndependent();
    8208             : #if __clang__
    8209             : #pragma clang diagnostic pop
    8210             : #endif
    8211          24 :       invoke_gc[outer_gc]();
    8212          24 :       EmptyMessageQueues(isolate);
    8213          24 :       CHECK(object.flag);
    8214             :     }
    8215             :   }
    8216           6 : }
    8217             : 
    8218             : v8::Local<Function> args_fun;
    8219             : 
    8220             : 
    8221           6 : static void ArgumentsTestCallback(
    8222             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    8223           6 :   ApiTestFuzzer::Fuzz();
    8224             :   v8::Isolate* isolate = args.GetIsolate();
    8225           6 :   Local<Context> context = isolate->GetCurrentContext();
    8226           6 :   CHECK_EQ(3, args.Length());
    8227          18 :   CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
    8228          18 :   CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
    8229          18 :   CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
    8230          12 :   CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
    8231          12 :   v8::HandleScope scope(args.GetIsolate());
    8232           6 :   CcTest::CollectAllGarbage();
    8233           6 : }
    8234             : 
    8235             : 
    8236       26645 : THREADED_TEST(Arguments) {
    8237           6 :   v8::Isolate* isolate = CcTest::isolate();
    8238          12 :   v8::HandleScope scope(isolate);
    8239           6 :   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
    8240          18 :   global->Set(v8_str("f"),
    8241           6 :               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
    8242           6 :   LocalContext context(nullptr, global);
    8243          12 :   args_fun = context->Global()
    8244          18 :                  ->Get(context.local(), v8_str("f"))
    8245             :                  .ToLocalChecked()
    8246           6 :                  .As<Function>();
    8247           6 :   v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
    8248           6 : }
    8249             : 
    8250             : 
    8251             : static int p_getter_count;
    8252             : static int p_getter_count2;
    8253             : 
    8254             : 
    8255         240 : static void PGetter(Local<Name> name,
    8256             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    8257         240 :   ApiTestFuzzer::Fuzz();
    8258         240 :   p_getter_count++;
    8259         240 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8260         240 :   v8::Local<v8::Object> global = context->Global();
    8261         960 :   CHECK(
    8262             :       info.Holder()
    8263             :           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
    8264             :           .FromJust());
    8265         720 :   if (name->Equals(context, v8_str("p1")).FromJust()) {
    8266         240 :     CHECK(info.This()
    8267             :               ->Equals(context,
    8268             :                        global->Get(context, v8_str("o1")).ToLocalChecked())
    8269             :               .FromJust());
    8270         540 :   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
    8271         240 :     CHECK(info.This()
    8272             :               ->Equals(context,
    8273             :                        global->Get(context, v8_str("o2")).ToLocalChecked())
    8274             :               .FromJust());
    8275         360 :   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
    8276         240 :     CHECK(info.This()
    8277             :               ->Equals(context,
    8278             :                        global->Get(context, v8_str("o3")).ToLocalChecked())
    8279             :               .FromJust());
    8280         180 :   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
    8281         240 :     CHECK(info.This()
    8282             :               ->Equals(context,
    8283             :                        global->Get(context, v8_str("o4")).ToLocalChecked())
    8284             :               .FromJust());
    8285             :   }
    8286         240 : }
    8287             : 
    8288             : 
    8289          12 : static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
    8290          12 :   ApiTestFuzzer::Fuzz();
    8291          12 :   LocalContext context;
    8292          60 :   CHECK(context->Global()
    8293             :             ->Set(context.local(), v8_str("o1"),
    8294             :                   obj->NewInstance(context.local()).ToLocalChecked())
    8295             :             .FromJust());
    8296             :   CompileRun(
    8297             :     "o1.__proto__ = { };"
    8298             :     "var o2 = { __proto__: o1 };"
    8299             :     "var o3 = { __proto__: o2 };"
    8300             :     "var o4 = { __proto__: o3 };"
    8301             :     "for (var i = 0; i < 10; i++) o4.p4;"
    8302             :     "for (var i = 0; i < 10; i++) o3.p3;"
    8303             :     "for (var i = 0; i < 10; i++) o2.p2;"
    8304             :     "for (var i = 0; i < 10; i++) o1.p1;");
    8305          12 : }
    8306             : 
    8307             : 
    8308         240 : static void PGetter2(Local<Name> name,
    8309             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
    8310         240 :   ApiTestFuzzer::Fuzz();
    8311         240 :   p_getter_count2++;
    8312         240 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8313         240 :   v8::Local<v8::Object> global = context->Global();
    8314         960 :   CHECK(
    8315             :       info.Holder()
    8316             :           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
    8317             :           .FromJust());
    8318         720 :   if (name->Equals(context, v8_str("p1")).FromJust()) {
    8319         240 :     CHECK(info.This()
    8320             :               ->Equals(context,
    8321             :                        global->Get(context, v8_str("o1")).ToLocalChecked())
    8322             :               .FromJust());
    8323         540 :   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
    8324         240 :     CHECK(info.This()
    8325             :               ->Equals(context,
    8326             :                        global->Get(context, v8_str("o2")).ToLocalChecked())
    8327             :               .FromJust());
    8328         360 :   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
    8329         240 :     CHECK(info.This()
    8330             :               ->Equals(context,
    8331             :                        global->Get(context, v8_str("o3")).ToLocalChecked())
    8332             :               .FromJust());
    8333         180 :   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
    8334         240 :     CHECK(info.This()
    8335             :               ->Equals(context,
    8336             :                        global->Get(context, v8_str("o4")).ToLocalChecked())
    8337             :               .FromJust());
    8338             :   }
    8339         240 : }
    8340             : 
    8341             : 
    8342       26645 : THREADED_TEST(GetterHolders) {
    8343           6 :   v8::Isolate* isolate = CcTest::isolate();
    8344          12 :   v8::HandleScope scope(isolate);
    8345           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8346          12 :   obj->SetAccessor(v8_str("p1"), PGetter);
    8347          12 :   obj->SetAccessor(v8_str("p2"), PGetter);
    8348          12 :   obj->SetAccessor(v8_str("p3"), PGetter);
    8349          12 :   obj->SetAccessor(v8_str("p4"), PGetter);
    8350           6 :   p_getter_count = 0;
    8351           6 :   RunHolderTest(obj);
    8352           6 :   CHECK_EQ(40, p_getter_count);
    8353           6 : }
    8354             : 
    8355             : 
    8356       26645 : THREADED_TEST(PreInterceptorHolders) {
    8357           6 :   v8::Isolate* isolate = CcTest::isolate();
    8358          12 :   v8::HandleScope scope(isolate);
    8359           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8360           6 :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
    8361           6 :   p_getter_count2 = 0;
    8362           6 :   RunHolderTest(obj);
    8363           6 :   CHECK_EQ(40, p_getter_count2);
    8364           6 : }
    8365             : 
    8366             : 
    8367       26645 : THREADED_TEST(ObjectInstantiation) {
    8368           6 :   v8::Isolate* isolate = CcTest::isolate();
    8369          12 :   v8::HandleScope scope(isolate);
    8370           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    8371          12 :   templ->SetAccessor(v8_str("t"), PGetter2);
    8372           6 :   LocalContext context;
    8373          30 :   CHECK(context->Global()
    8374             :             ->Set(context.local(), v8_str("o"),
    8375             :                   templ->NewInstance(context.local()).ToLocalChecked())
    8376             :             .FromJust());
    8377        1206 :   for (int i = 0; i < 100; i++) {
    8378        1200 :     v8::HandleScope inner_scope(CcTest::isolate());
    8379             :     v8::Local<v8::Object> obj =
    8380         600 :         templ->NewInstance(context.local()).ToLocalChecked();
    8381        3000 :     CHECK(!obj->Equals(context.local(), context->Global()
    8382             :                                             ->Get(context.local(), v8_str("o"))
    8383             :                                             .ToLocalChecked())
    8384             :                .FromJust());
    8385        2400 :     CHECK(
    8386             :         context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
    8387         600 :     v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
    8388        1200 :     CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
    8389        2400 :     CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
    8390             :   }
    8391           6 : }
    8392             : 
    8393             : 
    8394             : static int StrCmp16(uint16_t* a, uint16_t* b) {
    8395             :   while (true) {
    8396         168 :     if (*a == 0 && *b == 0) return 0;
    8397         138 :     if (*a != *b) return 0 + *a - *b;
    8398         132 :     a++;
    8399         132 :     b++;
    8400             :   }
    8401             : }
    8402             : 
    8403             : 
    8404             : static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
    8405             :   while (true) {
    8406         150 :     if (n-- == 0) return 0;
    8407         120 :     if (*a == 0 && *b == 0) return 0;
    8408         120 :     if (*a != *b) return 0 + *a - *b;
    8409         120 :     a++;
    8410         120 :     b++;
    8411             :   }
    8412             : }
    8413             : 
    8414         552 : int GetUtf8Length(v8::Isolate* isolate, Local<String> str) {
    8415         552 :   int len = str->Utf8Length(isolate);
    8416         552 :   if (len < 0) {
    8417             :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    8418           0 :     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
    8419           0 :     i::String::Flatten(i_isolate, istr);
    8420           0 :     len = str->Utf8Length(isolate);
    8421             :   }
    8422         552 :   return len;
    8423             : }
    8424             : 
    8425             : 
    8426       26645 : THREADED_TEST(StringWrite) {
    8427           6 :   LocalContext context;
    8428           6 :   v8::Isolate* isolate = context->GetIsolate();
    8429          12 :   v8::HandleScope scope(isolate);
    8430           6 :   v8::Local<String> str = v8_str("abcde");
    8431             :   // abc<Icelandic eth><Unicode snowman>.
    8432           6 :   v8::Local<String> str2 = v8_str("abc\xC3\xB0\xE2\x98\x83");
    8433             :   v8::Local<String> str3 =
    8434           6 :       v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
    8435           6 :                               v8::NewStringType::kNormal, 7)
    8436             :           .ToLocalChecked();
    8437             :   // "ab" + lead surrogate + "wx" + trail surrogate + "yz"
    8438           6 :   uint16_t orphans[8] = {0x61, 0x62, 0xD800, 0x77, 0x78, 0xDC00, 0x79, 0x7A};
    8439             :   v8::Local<String> orphans_str =
    8440           6 :       v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
    8441           6 :                                  v8::NewStringType::kNormal, 8)
    8442             :           .ToLocalChecked();
    8443             :   // single lead surrogate
    8444           6 :   uint16_t lead[1] = {0xD800};
    8445             :   v8::Local<String> lead_str =
    8446           6 :       v8::String::NewFromTwoByte(context->GetIsolate(), lead,
    8447           6 :                                  v8::NewStringType::kNormal, 1)
    8448             :           .ToLocalChecked();
    8449             :   // single trail surrogate
    8450           6 :   uint16_t trail[1] = {0xDC00};
    8451             :   v8::Local<String> trail_str =
    8452           6 :       v8::String::NewFromTwoByte(context->GetIsolate(), trail,
    8453           6 :                                  v8::NewStringType::kNormal, 1)
    8454             :           .ToLocalChecked();
    8455             :   // surrogate pair
    8456           6 :   uint16_t pair[2] = {0xD800, 0xDC00};
    8457             :   v8::Local<String> pair_str =
    8458           6 :       v8::String::NewFromTwoByte(context->GetIsolate(), pair,
    8459           6 :                                  v8::NewStringType::kNormal, 2)
    8460             :           .ToLocalChecked();
    8461             :   const int kStride = 4;  // Must match stride in for loops in JS below.
    8462             :   CompileRun(
    8463             :       "var left = '';"
    8464             :       "for (var i = 0; i < 0xD800; i += 4) {"
    8465             :       "  left = left + String.fromCharCode(i);"
    8466             :       "}");
    8467             :   CompileRun(
    8468             :       "var right = '';"
    8469             :       "for (var i = 0; i < 0xD800; i += 4) {"
    8470             :       "  right = String.fromCharCode(i) + right;"
    8471             :       "}");
    8472           6 :   v8::Local<v8::Object> global = context->Global();
    8473          18 :   Local<String> left_tree = global->Get(context.local(), v8_str("left"))
    8474             :                                 .ToLocalChecked()
    8475             :                                 .As<String>();
    8476          18 :   Local<String> right_tree = global->Get(context.local(), v8_str("right"))
    8477             :                                  .ToLocalChecked()
    8478             :                                  .As<String>();
    8479             : 
    8480           6 :   CHECK_EQ(5, str2->Length());
    8481           6 :   CHECK_EQ(0xD800 / kStride, left_tree->Length());
    8482           6 :   CHECK_EQ(0xD800 / kStride, right_tree->Length());
    8483             : 
    8484             :   char buf[100];
    8485             :   char utf8buf[0xD800 * 3];
    8486             :   uint16_t wbuf[100];
    8487             :   int len;
    8488             :   int charlen;
    8489             : 
    8490             :   memset(utf8buf, 0x1, 1000);
    8491             :   len = v8::String::Empty(isolate)->WriteUtf8(isolate, utf8buf, sizeof(utf8buf),
    8492           6 :                                               &charlen);
    8493           6 :   CHECK_EQ(1, len);
    8494           6 :   CHECK_EQ(0, charlen);
    8495           6 :   CHECK_EQ(0, strcmp(utf8buf, ""));
    8496             : 
    8497             :   memset(utf8buf, 0x1, 1000);
    8498           6 :   len = str2->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen);
    8499           6 :   CHECK_EQ(9, len);
    8500           6 :   CHECK_EQ(5, charlen);
    8501           6 :   CHECK_EQ(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8502             : 
    8503             :   memset(utf8buf, 0x1, 1000);
    8504           6 :   len = str2->WriteUtf8(isolate, utf8buf, 8, &charlen);
    8505           6 :   CHECK_EQ(8, len);
    8506           6 :   CHECK_EQ(5, charlen);
    8507           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83\x01", 9));
    8508             : 
    8509             :   memset(utf8buf, 0x1, 1000);
    8510           6 :   len = str2->WriteUtf8(isolate, utf8buf, 7, &charlen);
    8511           6 :   CHECK_EQ(5, len);
    8512           6 :   CHECK_EQ(4, charlen);
    8513           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8514             : 
    8515             :   memset(utf8buf, 0x1, 1000);
    8516           6 :   len = str2->WriteUtf8(isolate, utf8buf, 6, &charlen);
    8517           6 :   CHECK_EQ(5, len);
    8518           6 :   CHECK_EQ(4, charlen);
    8519           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8520             : 
    8521             :   memset(utf8buf, 0x1, 1000);
    8522           6 :   len = str2->WriteUtf8(isolate, utf8buf, 5, &charlen);
    8523           6 :   CHECK_EQ(5, len);
    8524           6 :   CHECK_EQ(4, charlen);
    8525           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8526             : 
    8527             :   memset(utf8buf, 0x1, 1000);
    8528           6 :   len = str2->WriteUtf8(isolate, utf8buf, 4, &charlen);
    8529           6 :   CHECK_EQ(3, len);
    8530           6 :   CHECK_EQ(3, charlen);
    8531           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\x01", 4));
    8532             : 
    8533             :   memset(utf8buf, 0x1, 1000);
    8534           6 :   len = str2->WriteUtf8(isolate, utf8buf, 3, &charlen);
    8535           6 :   CHECK_EQ(3, len);
    8536           6 :   CHECK_EQ(3, charlen);
    8537           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\x01", 4));
    8538             : 
    8539             :   memset(utf8buf, 0x1, 1000);
    8540           6 :   len = str2->WriteUtf8(isolate, utf8buf, 2, &charlen);
    8541           6 :   CHECK_EQ(2, len);
    8542           6 :   CHECK_EQ(2, charlen);
    8543           6 :   CHECK_EQ(0, strncmp(utf8buf, "ab\x01", 3));
    8544             : 
    8545             :   // allow orphan surrogates by default
    8546             :   memset(utf8buf, 0x1, 1000);
    8547           6 :   len = orphans_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen);
    8548           6 :   CHECK_EQ(13, len);
    8549           6 :   CHECK_EQ(8, charlen);
    8550           6 :   CHECK_EQ(0, strcmp(utf8buf, "ab\xED\xA0\x80wx\xED\xB0\x80yz"));
    8551             : 
    8552             :   // replace orphan surrogates with Unicode replacement character
    8553             :   memset(utf8buf, 0x1, 1000);
    8554             :   len = orphans_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8555           6 :                                String::REPLACE_INVALID_UTF8);
    8556           6 :   CHECK_EQ(13, len);
    8557           6 :   CHECK_EQ(8, charlen);
    8558           6 :   CHECK_EQ(0, strcmp(utf8buf, "ab\xEF\xBF\xBDwx\xEF\xBF\xBDyz"));
    8559             : 
    8560             :   // replace single lead surrogate with Unicode replacement character
    8561             :   memset(utf8buf, 0x1, 1000);
    8562             :   len = lead_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8563           6 :                             String::REPLACE_INVALID_UTF8);
    8564           6 :   CHECK_EQ(4, len);
    8565           6 :   CHECK_EQ(1, charlen);
    8566           6 :   CHECK_EQ(0, strcmp(utf8buf, "\xEF\xBF\xBD"));
    8567             : 
    8568             :   // replace single trail surrogate with Unicode replacement character
    8569             :   memset(utf8buf, 0x1, 1000);
    8570             :   len = trail_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8571           6 :                              String::REPLACE_INVALID_UTF8);
    8572           6 :   CHECK_EQ(4, len);
    8573           6 :   CHECK_EQ(1, charlen);
    8574           6 :   CHECK_EQ(0, strcmp(utf8buf, "\xEF\xBF\xBD"));
    8575             : 
    8576             :   // do not replace / write anything if surrogate pair does not fit the buffer
    8577             :   // space
    8578             :   memset(utf8buf, 0x1, 1000);
    8579             :   len = pair_str->WriteUtf8(isolate, utf8buf, 3, &charlen,
    8580           6 :                             String::REPLACE_INVALID_UTF8);
    8581           6 :   CHECK_EQ(0, len);
    8582           6 :   CHECK_EQ(0, charlen);
    8583             : 
    8584             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8585           6 :   len = GetUtf8Length(isolate, left_tree);
    8586             :   int utf8_expected =
    8587             :       (0x80 + (0x800 - 0x80) * 2 + (0xD800 - 0x800) * 3) / kStride;
    8588           6 :   CHECK_EQ(utf8_expected, len);
    8589           6 :   len = left_tree->WriteUtf8(isolate, utf8buf, utf8_expected, &charlen);
    8590           6 :   CHECK_EQ(utf8_expected, len);
    8591           6 :   CHECK_EQ(0xD800 / kStride, charlen);
    8592          12 :   CHECK_EQ(0xED, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
    8593          12 :   CHECK_EQ(0x9F, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
    8594          12 :   CHECK_EQ(0xC0 - kStride,
    8595             :            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
    8596           6 :   CHECK_EQ(1, utf8buf[utf8_expected]);
    8597             : 
    8598             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8599           6 :   len = GetUtf8Length(isolate, right_tree);
    8600           6 :   CHECK_EQ(utf8_expected, len);
    8601           6 :   len = right_tree->WriteUtf8(isolate, utf8buf, utf8_expected, &charlen);
    8602           6 :   CHECK_EQ(utf8_expected, len);
    8603           6 :   CHECK_EQ(0xD800 / kStride, charlen);
    8604          12 :   CHECK_EQ(0xED, static_cast<unsigned char>(utf8buf[0]));
    8605          12 :   CHECK_EQ(0x9F, static_cast<unsigned char>(utf8buf[1]));
    8606          12 :   CHECK_EQ(0xC0 - kStride, static_cast<unsigned char>(utf8buf[2]));
    8607           6 :   CHECK_EQ(1, utf8buf[utf8_expected]);
    8608             : 
    8609             :   memset(buf, 0x1, sizeof(buf));
    8610             :   memset(wbuf, 0x1, sizeof(wbuf));
    8611           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf));
    8612           6 :   CHECK_EQ(5, len);
    8613           6 :   len = str->Write(isolate, wbuf);
    8614           6 :   CHECK_EQ(5, len);
    8615           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8616           6 :   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8617           6 :   CHECK_EQ(0, StrCmp16(answer1, wbuf));
    8618             : 
    8619             :   memset(buf, 0x1, sizeof(buf));
    8620             :   memset(wbuf, 0x1, sizeof(wbuf));
    8621           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 4);
    8622           6 :   CHECK_EQ(4, len);
    8623           6 :   len = str->Write(isolate, wbuf, 0, 4);
    8624           6 :   CHECK_EQ(4, len);
    8625           6 :   CHECK_EQ(0, strncmp("abcd\x01", buf, 5));
    8626           6 :   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
    8627           6 :   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
    8628             : 
    8629             :   memset(buf, 0x1, sizeof(buf));
    8630             :   memset(wbuf, 0x1, sizeof(wbuf));
    8631           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 5);
    8632           6 :   CHECK_EQ(5, len);
    8633           6 :   len = str->Write(isolate, wbuf, 0, 5);
    8634           6 :   CHECK_EQ(5, len);
    8635           6 :   CHECK_EQ(0, strncmp("abcde\x01", buf, 6));
    8636           6 :   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
    8637           6 :   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
    8638             : 
    8639             :   memset(buf, 0x1, sizeof(buf));
    8640             :   memset(wbuf, 0x1, sizeof(wbuf));
    8641           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 6);
    8642           6 :   CHECK_EQ(5, len);
    8643           6 :   len = str->Write(isolate, wbuf, 0, 6);
    8644           6 :   CHECK_EQ(5, len);
    8645           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8646           6 :   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8647           6 :   CHECK_EQ(0, StrCmp16(answer4, wbuf));
    8648             : 
    8649             :   memset(buf, 0x1, sizeof(buf));
    8650             :   memset(wbuf, 0x1, sizeof(wbuf));
    8651           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, -1);
    8652           6 :   CHECK_EQ(1, len);
    8653           6 :   len = str->Write(isolate, wbuf, 4, -1);
    8654           6 :   CHECK_EQ(1, len);
    8655           6 :   CHECK_EQ(0, strcmp("e", buf));
    8656           6 :   uint16_t answer5[] = {'e', '\0'};
    8657           6 :   CHECK_EQ(0, StrCmp16(answer5, wbuf));
    8658             : 
    8659             :   memset(buf, 0x1, sizeof(buf));
    8660             :   memset(wbuf, 0x1, sizeof(wbuf));
    8661           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, 6);
    8662           6 :   CHECK_EQ(1, len);
    8663           6 :   len = str->Write(isolate, wbuf, 4, 6);
    8664           6 :   CHECK_EQ(1, len);
    8665           6 :   CHECK_EQ(0, strcmp("e", buf));
    8666           6 :   CHECK_EQ(0, StrCmp16(answer5, wbuf));
    8667             : 
    8668             :   memset(buf, 0x1, sizeof(buf));
    8669             :   memset(wbuf, 0x1, sizeof(wbuf));
    8670           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, 1);
    8671           6 :   CHECK_EQ(1, len);
    8672           6 :   len = str->Write(isolate, wbuf, 4, 1);
    8673           6 :   CHECK_EQ(1, len);
    8674           6 :   CHECK_EQ(0, strncmp("e\x01", buf, 2));
    8675           6 :   uint16_t answer6[] = {'e', 0x101};
    8676           6 :   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
    8677             : 
    8678             :   memset(buf, 0x1, sizeof(buf));
    8679             :   memset(wbuf, 0x1, sizeof(wbuf));
    8680           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 3, 1);
    8681           6 :   CHECK_EQ(1, len);
    8682           6 :   len = str->Write(isolate, wbuf, 3, 1);
    8683           6 :   CHECK_EQ(1, len);
    8684           6 :   CHECK_EQ(0, strncmp("d\x01", buf, 2));
    8685           6 :   uint16_t answer7[] = {'d', 0x101};
    8686           6 :   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
    8687             : 
    8688             :   memset(wbuf, 0x1, sizeof(wbuf));
    8689           6 :   wbuf[5] = 'X';
    8690           6 :   len = str->Write(isolate, wbuf, 0, 6, String::NO_NULL_TERMINATION);
    8691           6 :   CHECK_EQ(5, len);
    8692          12 :   CHECK_EQ('X', wbuf[5]);
    8693           6 :   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
    8694           6 :   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8695           6 :   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
    8696           6 :   CHECK_NE(0, StrCmp16(answer8b, wbuf));
    8697           6 :   wbuf[5] = '\0';
    8698           6 :   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
    8699             : 
    8700             :   memset(buf, 0x1, sizeof(buf));
    8701           6 :   buf[5] = 'X';
    8702             :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 6,
    8703           6 :                           String::NO_NULL_TERMINATION);
    8704           6 :   CHECK_EQ(5, len);
    8705           6 :   CHECK_EQ('X', buf[5]);
    8706           6 :   CHECK_EQ(0, strncmp("abcde", buf, 5));
    8707           6 :   CHECK_NE(0, strcmp("abcde", buf));
    8708           6 :   buf[5] = '\0';
    8709           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8710             : 
    8711             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8712           6 :   utf8buf[8] = 'X';
    8713             :   len = str2->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8714           6 :                         String::NO_NULL_TERMINATION);
    8715           6 :   CHECK_EQ(8, len);
    8716           6 :   CHECK_EQ('X', utf8buf[8]);
    8717           6 :   CHECK_EQ(5, charlen);
    8718           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83", 8));
    8719           6 :   CHECK_NE(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8720           6 :   utf8buf[8] = '\0';
    8721           6 :   CHECK_EQ(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8722             : 
    8723             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8724           6 :   utf8buf[5] = 'X';
    8725             :   len = str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8726           6 :                        String::NO_NULL_TERMINATION);
    8727           6 :   CHECK_EQ(5, len);
    8728           6 :   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
    8729           6 :   CHECK_EQ(5, charlen);
    8730           6 :   utf8buf[5] = '\0';
    8731           6 :   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
    8732             : 
    8733             :   memset(buf, 0x1, sizeof(buf));
    8734           6 :   len = str3->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf));
    8735           6 :   CHECK_EQ(7, len);
    8736           6 :   CHECK_EQ(0, strcmp("abc", buf));
    8737           6 :   CHECK_EQ(0, buf[3]);
    8738           6 :   CHECK_EQ(0, strcmp("def", buf + 4));
    8739             : 
    8740           6 :   CHECK_EQ(0, str->WriteOneByte(isolate, nullptr, 0, 0,
    8741             :                                 String::NO_NULL_TERMINATION));
    8742           6 :   CHECK_EQ(0, str->WriteUtf8(isolate, nullptr, 0, nullptr,
    8743             :                              String::NO_NULL_TERMINATION));
    8744           6 :   CHECK_EQ(0, str->Write(isolate, nullptr, 0, 0, String::NO_NULL_TERMINATION));
    8745           6 : }
    8746             : 
    8747             : 
    8748          12 : static void Utf16Helper(
    8749             :     LocalContext& context,  // NOLINT
    8750             :     const char* name,
    8751             :     const char* lengths_name,
    8752             :     int len) {
    8753             :   Local<v8::Array> a = Local<v8::Array>::Cast(
    8754          48 :       context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
    8755             :   Local<v8::Array> alens =
    8756          24 :       Local<v8::Array>::Cast(context->Global()
    8757          36 :                                  ->Get(context.local(), v8_str(lengths_name))
    8758             :                                  .ToLocalChecked());
    8759        1092 :   for (int i = 0; i < len; i++) {
    8760             :     Local<v8::String> string =
    8761        1620 :         Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
    8762             :     Local<v8::Number> expected_len = Local<v8::Number>::Cast(
    8763         540 :         alens->Get(context.local(), i).ToLocalChecked());
    8764         540 :     int length = GetUtf8Length(context->GetIsolate(), string);
    8765         540 :     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
    8766             :   }
    8767          12 : }
    8768             : 
    8769           6 : void TestUtf8DecodingAgainstReference(
    8770             :     v8::Isolate* isolate, const char* cases[],
    8771             :     const std::vector<std::vector<uint16_t>>& unicode_expected) {
    8772         126 :   for (size_t test_ix = 0; test_ix < unicode_expected.size(); ++test_ix) {
    8773          60 :     v8::Local<String> str = v8_str(cases[test_ix]);
    8774         120 :     CHECK_EQ(unicode_expected[test_ix].size(), str->Length());
    8775             : 
    8776          60 :     std::unique_ptr<uint16_t[]> buffer(new uint16_t[str->Length()]);
    8777          60 :     str->Write(isolate, buffer.get(), 0, -1, String::NO_NULL_TERMINATION);
    8778             : 
    8779         636 :     for (size_t i = 0; i < unicode_expected[test_ix].size(); ++i) {
    8780         576 :       CHECK_EQ(unicode_expected[test_ix][i], buffer[i]);
    8781             :     }
    8782             :   }
    8783           6 : }
    8784             : 
    8785       26645 : THREADED_TEST(OverlongSequencesAndSurrogates) {
    8786           6 :   LocalContext context;
    8787          12 :   v8::HandleScope scope(context->GetIsolate());
    8788             : 
    8789             :   const char* cases[] = {
    8790             :       // Overlong 2-byte sequence.
    8791             :       "X\xc0\xbfY\0",
    8792             :       // Another overlong 2-byte sequence.
    8793             :       "X\xc1\xbfY\0",
    8794             :       // Overlong 3-byte sequence.
    8795             :       "X\xe0\x9f\xbfY\0",
    8796             :       // Overlong 4-byte sequence.
    8797             :       "X\xf0\x89\xbf\xbfY\0",
    8798             :       // Invalid 3-byte sequence (reserved for surrogates).
    8799             :       "X\xed\xa0\x80Y\0",
    8800             :       // Invalid 4-bytes sequence (value out of range).
    8801             :       "X\xf4\x90\x80\x80Y\0",
    8802             : 
    8803             :       // Start of an overlong 3-byte sequence but not enough continuation bytes.
    8804             :       "X\xe0\x9fY\0",
    8805             :       // Start of an overlong 4-byte sequence but not enough continuation bytes.
    8806             :       "X\xf0\x89\xbfY\0",
    8807             :       // Start of an invalid 3-byte sequence (reserved for surrogates) but not
    8808             :       // enough continuation bytes.
    8809             :       "X\xed\xa0Y\0",
    8810             :       // Start of an invalid 4-bytes sequence (value out of range) but not
    8811             :       // enough continuation bytes.
    8812             :       "X\xf4\x90\x80Y\0",
    8813           6 :   };
    8814             :   const std::vector<std::vector<uint16_t>> unicode_expected = {
    8815             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8816             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8817             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8818             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8819             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8820             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8821             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8822             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8823             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8824             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8825          12 :   };
    8826           6 :   CHECK_EQ(unicode_expected.size(), arraysize(cases));
    8827           6 :   TestUtf8DecodingAgainstReference(context->GetIsolate(), cases,
    8828           6 :                                    unicode_expected);
    8829           6 : }
    8830             : 
    8831       26645 : THREADED_TEST(Utf16) {
    8832           6 :   LocalContext context;
    8833          12 :   v8::HandleScope scope(context->GetIsolate());
    8834             :   CompileRun(
    8835             :       "var pad = '01234567890123456789';"
    8836             :       "var p = [];"
    8837             :       "var plens = [20, 3, 3];"
    8838             :       "p.push('01234567890123456789');"
    8839             :       "var lead = 0xD800;"
    8840             :       "var trail = 0xDC00;"
    8841             :       "p.push(String.fromCharCode(0xD800));"
    8842             :       "p.push(String.fromCharCode(0xDC00));"
    8843             :       "var a = [];"
    8844             :       "var b = [];"
    8845             :       "var c = [];"
    8846             :       "var alens = [];"
    8847             :       "for (var i = 0; i < 3; i++) {"
    8848             :       "  p[1] = String.fromCharCode(lead++);"
    8849             :       "  for (var j = 0; j < 3; j++) {"
    8850             :       "    p[2] = String.fromCharCode(trail++);"
    8851             :       "    a.push(p[i] + p[j]);"
    8852             :       "    b.push(p[i] + p[j]);"
    8853             :       "    c.push(p[i] + p[j]);"
    8854             :       "    alens.push(plens[i] + plens[j]);"
    8855             :       "  }"
    8856             :       "}"
    8857             :       "alens[5] -= 2;"  // Here the surrogate pairs match up.
    8858             :       "var a2 = [];"
    8859             :       "var b2 = [];"
    8860             :       "var c2 = [];"
    8861             :       "var a2lens = [];"
    8862             :       "for (var m = 0; m < 9; m++) {"
    8863             :       "  for (var n = 0; n < 9; n++) {"
    8864             :       "    a2.push(a[m] + a[n]);"
    8865             :       "    b2.push(b[m] + b[n]);"
    8866             :       "    var newc = 'x' + c[m] + c[n] + 'y';"
    8867             :       "    c2.push(newc.substring(1, newc.length - 1));"
    8868             :       "    var utf = alens[m] + alens[n];"  // And here.
    8869             :                                             // The 'n's that start with 0xDC..
    8870             :                                             // are 6-8 The 'm's that end with
    8871             :                                             // 0xD8.. are 1, 4 and 7
    8872             :       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
    8873             :       "    a2lens.push(utf);"
    8874             :       "  }"
    8875             :       "}");
    8876           6 :   Utf16Helper(context, "a", "alens", 9);
    8877           6 :   Utf16Helper(context, "a2", "a2lens", 81);
    8878           6 : }
    8879             : 
    8880             : 
    8881             : static bool SameSymbol(Local<String> s1, Local<String> s2) {
    8882             :   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
    8883             :   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
    8884             :   return *is1 == *is2;
    8885             : }
    8886             : 
    8887             : 
    8888       26645 : THREADED_TEST(Utf16Symbol) {
    8889           6 :   LocalContext context;
    8890          12 :   v8::HandleScope scope(context->GetIsolate());
    8891             : 
    8892             :   Local<String> symbol1 =
    8893           6 :       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
    8894           6 :                               v8::NewStringType::kInternalized)
    8895             :           .ToLocalChecked();
    8896             :   Local<String> symbol2 =
    8897           6 :       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
    8898           6 :                               v8::NewStringType::kInternalized)
    8899             :           .ToLocalChecked();
    8900           6 :   CHECK(SameSymbol(symbol1, symbol2));
    8901             : 
    8902             :   CompileRun(
    8903             :       "var sym0 = 'benedictus';"
    8904             :       "var sym0b = 'S\xC3\xB8ren';"
    8905             :       "var sym1 = '\xED\xA0\x81\xED\xB0\x87';"
    8906             :       "var sym2 = '\xF0\x90\x90\x88';"
    8907             :       "var sym3 = 'x\xED\xA0\x81\xED\xB0\x87';"
    8908             :       "var sym4 = 'x\xF0\x90\x90\x88';"
    8909             :       "if (sym1.length != 2) throw sym1;"
    8910             :       "if (sym1.charCodeAt(1) != 0xDC07) throw sym1.charCodeAt(1);"
    8911             :       "if (sym2.length != 2) throw sym2;"
    8912             :       "if (sym2.charCodeAt(1) != 0xDC08) throw sym2.charCodeAt(2);"
    8913             :       "if (sym3.length != 3) throw sym3;"
    8914             :       "if (sym3.charCodeAt(2) != 0xDC07) throw sym1.charCodeAt(2);"
    8915             :       "if (sym4.length != 3) throw sym4;"
    8916             :       "if (sym4.charCodeAt(2) != 0xDC08) throw sym2.charCodeAt(2);");
    8917             :   Local<String> sym0 =
    8918           6 :       v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
    8919           6 :                               v8::NewStringType::kInternalized)
    8920             :           .ToLocalChecked();
    8921             :   Local<String> sym0b =
    8922           6 :       v8::String::NewFromUtf8(context->GetIsolate(), "S\xC3\xB8ren",
    8923           6 :                               v8::NewStringType::kInternalized)
    8924             :           .ToLocalChecked();
    8925             :   Local<String> sym1 =
    8926           6 :       v8::String::NewFromUtf8(context->GetIsolate(), "\xED\xA0\x81\xED\xB0\x87",
    8927           6 :                               v8::NewStringType::kInternalized)
    8928             :           .ToLocalChecked();
    8929             :   Local<String> sym2 =
    8930           6 :       v8::String::NewFromUtf8(context->GetIsolate(), "\xF0\x90\x90\x88",
    8931           6 :                               v8::NewStringType::kInternalized)
    8932             :           .ToLocalChecked();
    8933           6 :   Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
    8934             :                                                "x\xED\xA0\x81\xED\xB0\x87",
    8935           6 :                                                v8::NewStringType::kInternalized)
    8936             :                            .ToLocalChecked();
    8937             :   Local<String> sym4 =
    8938           6 :       v8::String::NewFromUtf8(context->GetIsolate(), "x\xF0\x90\x90\x88",
    8939           6 :                               v8::NewStringType::kInternalized)
    8940             :           .ToLocalChecked();
    8941           6 :   v8::Local<v8::Object> global = context->Global();
    8942             :   Local<Value> s0 =
    8943          18 :       global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
    8944             :   Local<Value> s0b =
    8945          18 :       global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
    8946             :   Local<Value> s1 =
    8947          18 :       global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
    8948             :   Local<Value> s2 =
    8949          18 :       global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
    8950             :   Local<Value> s3 =
    8951          18 :       global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
    8952             :   Local<Value> s4 =
    8953          18 :       global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
    8954           6 :   CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
    8955           6 :   CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
    8956           6 :   CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
    8957           6 :   CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
    8958           6 :   CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
    8959           6 :   CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
    8960           6 : }
    8961             : 
    8962             : 
    8963       26645 : THREADED_TEST(Utf16MissingTrailing) {
    8964           6 :   LocalContext context;
    8965          12 :   v8::HandleScope scope(context->GetIsolate());
    8966             : 
    8967             :   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
    8968             :   int size = 1024 * 64;
    8969           6 :   uint8_t* buffer = new uint8_t[size];
    8970      196614 :   for (int i = 0; i < size; i += 4) {
    8971       98304 :     buffer[i] = 0xF0;
    8972       98304 :     buffer[i + 1] = 0x9D;
    8973       98304 :     buffer[i + 2] = 0x80;
    8974       98304 :     buffer[i + 3] = 0x9E;
    8975             :   }
    8976             : 
    8977             :   // Now invoke the decoder without last 3 bytes
    8978             :   v8::Local<v8::String> str =
    8979           6 :       v8::String::NewFromUtf8(
    8980             :           context->GetIsolate(), reinterpret_cast<char*>(buffer),
    8981           6 :           v8::NewStringType::kNormal, size - 3).ToLocalChecked();
    8982             :   USE(str);
    8983           6 :   delete[] buffer;
    8984           6 : }
    8985             : 
    8986             : 
    8987       26645 : THREADED_TEST(Utf16Trailing3Byte) {
    8988           6 :   LocalContext context;
    8989           6 :   v8::Isolate* isolate = context->GetIsolate();
    8990          12 :   v8::HandleScope scope(isolate);
    8991             : 
    8992             :   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
    8993             :   int size = 1024 * 63;
    8994           6 :   uint8_t* buffer = new uint8_t[size];
    8995      258054 :   for (int i = 0; i < size; i += 3) {
    8996      129024 :     buffer[i] = 0xE2;
    8997      129024 :     buffer[i + 1] = 0x80;
    8998      129024 :     buffer[i + 2] = 0xA6;
    8999             :   }
    9000             : 
    9001             :   // Now invoke the decoder without last 3 bytes
    9002             :   v8::Local<v8::String> str =
    9003           6 :       v8::String::NewFromUtf8(isolate, reinterpret_cast<char*>(buffer),
    9004             :                               v8::NewStringType::kNormal, size)
    9005             :           .ToLocalChecked();
    9006             : 
    9007          12 :   v8::String::Value value(isolate, str);
    9008           6 :   CHECK_EQ(value.length(), size / 3);
    9009          12 :   CHECK_EQ((*value)[value.length() - 1], 0x2026);
    9010             : 
    9011           6 :   delete[] buffer;
    9012           6 : }
    9013             : 
    9014             : 
    9015       26645 : THREADED_TEST(ToArrayIndex) {
    9016           6 :   LocalContext context;
    9017           6 :   v8::Isolate* isolate = context->GetIsolate();
    9018          12 :   v8::HandleScope scope(isolate);
    9019             : 
    9020           6 :   v8::Local<String> str = v8_str("42");
    9021           6 :   v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
    9022           6 :   CHECK(!index.IsEmpty());
    9023          12 :   CHECK_EQ(42.0,
    9024             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    9025           6 :   str = v8_str("42asdf");
    9026           6 :   index = str->ToArrayIndex(context.local());
    9027           6 :   CHECK(index.IsEmpty());
    9028           6 :   str = v8_str("-42");
    9029           6 :   index = str->ToArrayIndex(context.local());
    9030           6 :   CHECK(index.IsEmpty());
    9031           6 :   str = v8_str("4294967294");
    9032           6 :   index = str->ToArrayIndex(context.local());
    9033           6 :   CHECK(!index.IsEmpty());
    9034          12 :   CHECK_EQ(4294967294.0,
    9035             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    9036           6 :   v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
    9037           6 :   index = num->ToArrayIndex(context.local());
    9038           6 :   CHECK(!index.IsEmpty());
    9039          12 :   CHECK_EQ(1.0,
    9040             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    9041           6 :   num = v8::Number::New(isolate, -1);
    9042           6 :   index = num->ToArrayIndex(context.local());
    9043           6 :   CHECK(index.IsEmpty());
    9044           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    9045           6 :   index = obj->ToArrayIndex(context.local());
    9046           6 :   CHECK(index.IsEmpty());
    9047           6 : }
    9048             : 
    9049           6 : static v8::MaybeLocal<Value> PrepareStackTrace42(v8::Local<Context> context,
    9050             :                                                  v8::Local<Value> error,
    9051             :                                                  v8::Local<Array> trace) {
    9052           6 :   return v8::Number::New(context->GetIsolate(), 42);
    9053             : }
    9054             : 
    9055           6 : static v8::MaybeLocal<Value> PrepareStackTraceThrow(v8::Local<Context> context,
    9056             :                                                     v8::Local<Value> error,
    9057             :                                                     v8::Local<Array> trace) {
    9058           6 :   v8::Isolate* isolate = context->GetIsolate();
    9059           6 :   v8::Local<String> message = v8_str("42");
    9060           6 :   isolate->ThrowException(v8::Exception::Error(message));
    9061           6 :   return v8::MaybeLocal<Value>();
    9062             : }
    9063             : 
    9064       26645 : THREADED_TEST(IsolatePrepareStackTrace) {
    9065           6 :   LocalContext context;
    9066           6 :   v8::Isolate* isolate = context->GetIsolate();
    9067          12 :   v8::HandleScope scope(isolate);
    9068             : 
    9069           6 :   isolate->SetPrepareStackTraceCallback(PrepareStackTrace42);
    9070             : 
    9071             :   v8::Local<Value> v = CompileRun("new Error().stack");
    9072             : 
    9073           6 :   CHECK(v->IsNumber());
    9074          12 :   CHECK_EQ(v.As<v8::Number>()->Int32Value(context.local()).FromJust(), 42);
    9075           6 : }
    9076             : 
    9077       26645 : THREADED_TEST(IsolatePrepareStackTraceThrow) {
    9078           6 :   LocalContext context;
    9079           6 :   v8::Isolate* isolate = context->GetIsolate();
    9080          12 :   v8::HandleScope scope(isolate);
    9081             : 
    9082           6 :   isolate->SetPrepareStackTraceCallback(PrepareStackTraceThrow);
    9083             : 
    9084             :   v8::Local<Value> v = CompileRun("try { new Error().stack } catch (e) { e }");
    9085             : 
    9086           6 :   CHECK(v->IsNativeError());
    9087             : 
    9088          12 :   v8::Local<String> message = v8::Exception::CreateMessage(isolate, v)->Get();
    9089             : 
    9090          12 :   CHECK(message->StrictEquals(v8_str("Uncaught Error: 42")));
    9091           6 : }
    9092             : 
    9093       26645 : THREADED_TEST(ErrorConstruction) {
    9094           6 :   LocalContext context;
    9095          12 :   v8::HandleScope scope(context->GetIsolate());
    9096             : 
    9097           6 :   v8::Local<String> foo = v8_str("foo");
    9098           6 :   v8::Local<String> message = v8_str("message");
    9099           6 :   v8::Local<Value> range_error = v8::Exception::RangeError(foo);
    9100           6 :   CHECK(range_error->IsObject());
    9101          18 :   CHECK(range_error.As<v8::Object>()
    9102             :             ->Get(context.local(), message)
    9103             :             .ToLocalChecked()
    9104             :             ->Equals(context.local(), foo)
    9105             :             .FromJust());
    9106           6 :   v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
    9107           6 :   CHECK(reference_error->IsObject());
    9108          18 :   CHECK(reference_error.As<v8::Object>()
    9109             :             ->Get(context.local(), message)
    9110             :             .ToLocalChecked()
    9111             :             ->Equals(context.local(), foo)
    9112             :             .FromJust());
    9113           6 :   v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
    9114           6 :   CHECK(syntax_error->IsObject());
    9115          18 :   CHECK(syntax_error.As<v8::Object>()
    9116             :             ->Get(context.local(), message)
    9117             :             .ToLocalChecked()
    9118             :             ->Equals(context.local(), foo)
    9119             :             .FromJust());
    9120           6 :   v8::Local<Value> type_error = v8::Exception::TypeError(foo);
    9121           6 :   CHECK(type_error->IsObject());
    9122          18 :   CHECK(type_error.As<v8::Object>()
    9123             :             ->Get(context.local(), message)
    9124             :             .ToLocalChecked()
    9125             :             ->Equals(context.local(), foo)
    9126             :             .FromJust());
    9127           6 :   v8::Local<Value> error = v8::Exception::Error(foo);
    9128           6 :   CHECK(error->IsObject());
    9129          18 :   CHECK(error.As<v8::Object>()
    9130             :             ->Get(context.local(), message)
    9131             :             .ToLocalChecked()
    9132             :             ->Equals(context.local(), foo)
    9133             :             .FromJust());
    9134           6 : }
    9135             : 
    9136             : 
    9137          12 : static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
    9138          12 :   ApiTestFuzzer::Fuzz();
    9139          12 :   v8::Local<String> foo = v8_str("foo");
    9140          12 :   v8::Local<String> message = v8_str("message");
    9141          12 :   v8::Local<Value> error = v8::Exception::Error(foo);
    9142          12 :   CHECK(error->IsObject());
    9143          12 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9144          36 :   CHECK(error.As<v8::Object>()
    9145             :             ->Get(context, message)
    9146             :             .ToLocalChecked()
    9147             :             ->Equals(context, foo)
    9148             :             .FromJust());
    9149          12 :   info.GetIsolate()->ThrowException(error);
    9150             :   info.GetReturnValue().SetUndefined();
    9151          12 : }
    9152             : 
    9153             : 
    9154       26645 : THREADED_TEST(ExceptionCreateMessage) {
    9155           6 :   LocalContext context;
    9156          12 :   v8::HandleScope scope(context->GetIsolate());
    9157           6 :   v8::Local<String> foo_str = v8_str("foo");
    9158           6 :   v8::Local<String> message_str = v8_str("message");
    9159             : 
    9160           6 :   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
    9161             : 
    9162             :   Local<v8::FunctionTemplate> fun =
    9163           6 :       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
    9164           6 :   v8::Local<v8::Object> global = context->Global();
    9165          24 :   CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
    9166             :                     fun->GetFunction(context.local()).ToLocalChecked())
    9167             :             .FromJust());
    9168             : 
    9169          12 :   TryCatch try_catch(context->GetIsolate());
    9170             :   CompileRun(
    9171             :       "function f1() {\n"
    9172             :       "  throwV8Exception();\n"
    9173             :       "};\n"
    9174             :       "f1();");
    9175           6 :   CHECK(try_catch.HasCaught());
    9176             : 
    9177           6 :   v8::Local<v8::Value> error = try_catch.Exception();
    9178           6 :   CHECK(error->IsObject());
    9179          18 :   CHECK(error.As<v8::Object>()
    9180             :             ->Get(context.local(), message_str)
    9181             :             .ToLocalChecked()
    9182             :             ->Equals(context.local(), foo_str)
    9183             :             .FromJust());
    9184             : 
    9185             :   v8::Local<v8::Message> message =
    9186           6 :       v8::Exception::CreateMessage(context->GetIsolate(), error);
    9187           6 :   CHECK(!message.IsEmpty());
    9188          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
    9189          12 :   CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
    9190             : 
    9191           6 :   v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
    9192           6 :   CHECK(!stackTrace.IsEmpty());
    9193           6 :   CHECK_EQ(2, stackTrace->GetFrameCount());
    9194             : 
    9195           6 :   stackTrace = v8::Exception::GetStackTrace(error);
    9196           6 :   CHECK(!stackTrace.IsEmpty());
    9197           6 :   CHECK_EQ(2, stackTrace->GetFrameCount());
    9198             : 
    9199           6 :   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
    9200             : 
    9201             :   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
    9202             :   // is false.
    9203           6 :   try_catch.Reset();
    9204             : 
    9205             :   CompileRun(
    9206             :       "function f2() {\n"
    9207             :       "  return throwV8Exception();\n"
    9208             :       "};\n"
    9209             :       "f2();");
    9210           6 :   CHECK(try_catch.HasCaught());
    9211             : 
    9212           6 :   error = try_catch.Exception();
    9213           6 :   CHECK(error->IsObject());
    9214          18 :   CHECK(error.As<v8::Object>()
    9215             :             ->Get(context.local(), message_str)
    9216             :             .ToLocalChecked()
    9217             :             ->Equals(context.local(), foo_str)
    9218             :             .FromJust());
    9219             : 
    9220           6 :   message = v8::Exception::CreateMessage(context->GetIsolate(), error);
    9221           6 :   CHECK(!message.IsEmpty());
    9222          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
    9223          12 :   CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
    9224             : 
    9225             :   // Should be empty stack trace.
    9226           6 :   stackTrace = message->GetStackTrace();
    9227           6 :   CHECK(stackTrace.IsEmpty());
    9228          12 :   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
    9229           6 : }
    9230             : 
    9231             : 
    9232       26645 : THREADED_TEST(ExceptionCreateMessageLength) {
    9233           6 :   LocalContext context;
    9234          12 :   v8::HandleScope scope(context->GetIsolate());
    9235             : 
    9236             :   // Test that the message is not truncated.
    9237          12 :   TryCatch try_catch(context->GetIsolate());
    9238             :   CompileRun(
    9239             :       "var message = 'm';"
    9240             :       "while (message.length < 1000) message += message;"
    9241             :       "throw message;");
    9242           6 :   CHECK(try_catch.HasCaught());
    9243             : 
    9244          18 :   CHECK_LT(1000, try_catch.Message()->Get()->Length());
    9245           6 : }
    9246             : 
    9247             : 
    9248           0 : static void YGetter(Local<String> name,
    9249             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    9250           0 :   ApiTestFuzzer::Fuzz();
    9251           0 :   info.GetReturnValue().Set(v8_num(10));
    9252           0 : }
    9253             : 
    9254             : 
    9255           6 : static void YSetter(Local<String> name,
    9256             :                     Local<Value> value,
    9257             :                     const v8::PropertyCallbackInfo<void>& info) {
    9258             :   Local<Object> this_obj = Local<Object>::Cast(info.This());
    9259           6 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9260          12 :   if (this_obj->Has(context, name).FromJust())
    9261          12 :     this_obj->Delete(context, name).FromJust();
    9262          12 :   CHECK(this_obj->Set(context, name, value).FromJust());
    9263           6 : }
    9264             : 
    9265             : 
    9266       26645 : THREADED_TEST(DeleteAccessor) {
    9267           6 :   v8::Isolate* isolate = CcTest::isolate();
    9268          12 :   v8::HandleScope scope(isolate);
    9269           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    9270           6 :   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
    9271           6 :   LocalContext context;
    9272             :   v8::Local<v8::Object> holder =
    9273           6 :       obj->NewInstance(context.local()).ToLocalChecked();
    9274          24 :   CHECK(context->Global()
    9275             :             ->Set(context.local(), v8_str("holder"), holder)
    9276             :             .FromJust());
    9277             :   v8::Local<Value> result =
    9278             :       CompileRun("holder.y = 11; holder.y = 12; holder.y");
    9279          12 :   CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
    9280           6 : }
    9281             : 
    9282             : 
    9283             : static int trouble_nesting = 0;
    9284          15 : static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    9285          15 :   ApiTestFuzzer::Fuzz();
    9286          15 :   trouble_nesting++;
    9287             : 
    9288             :   // Call a JS function that throws an uncaught exception.
    9289          15 :   Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    9290          15 :   Local<v8::Object> arg_this = context->Global();
    9291             :   Local<Value> trouble_callee =
    9292          15 :       (trouble_nesting == 3)
    9293          10 :           ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
    9294          35 :           : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
    9295          15 :   CHECK(trouble_callee->IsFunction());
    9296             :   args.GetReturnValue().Set(Function::Cast(*trouble_callee)
    9297          30 :                                 ->Call(context, arg_this, 0, nullptr)
    9298             :                                 .FromMaybe(v8::Local<v8::Value>()));
    9299          15 : }
    9300             : 
    9301             : 
    9302             : static int report_count = 0;
    9303           5 : static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
    9304             :                                              v8::Local<Value>) {
    9305           5 :   report_count++;
    9306           5 : }
    9307             : 
    9308             : 
    9309             : // Counts uncaught exceptions, but other tests running in parallel
    9310             : // also have uncaught exceptions.
    9311       26644 : TEST(ApiUncaughtException) {
    9312           5 :   report_count = 0;
    9313           5 :   LocalContext env;
    9314           5 :   v8::Isolate* isolate = env->GetIsolate();
    9315          10 :   v8::HandleScope scope(isolate);
    9316           5 :   isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
    9317             : 
    9318             :   Local<v8::FunctionTemplate> fun =
    9319           5 :       v8::FunctionTemplate::New(isolate, TroubleCallback);
    9320           5 :   v8::Local<v8::Object> global = env->Global();
    9321          20 :   CHECK(global->Set(env.local(), v8_str("trouble"),
    9322             :                     fun->GetFunction(env.local()).ToLocalChecked())
    9323             :             .FromJust());
    9324             : 
    9325             :   CompileRun(
    9326             :       "function trouble_callee() {"
    9327             :       "  var x = null;"
    9328             :       "  return x.foo;"
    9329             :       "};"
    9330             :       "function trouble_caller() {"
    9331             :       "  trouble();"
    9332             :       "};");
    9333             :   Local<Value> trouble =
    9334          15 :       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
    9335           5 :   CHECK(trouble->IsFunction());
    9336             :   Local<Value> trouble_callee =
    9337          15 :       global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
    9338           5 :   CHECK(trouble_callee->IsFunction());
    9339             :   Local<Value> trouble_caller =
    9340          15 :       global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
    9341           5 :   CHECK(trouble_caller->IsFunction());
    9342             :   Function::Cast(*trouble_caller)
    9343           5 :       ->Call(env.local(), global, 0, nullptr)
    9344             :       .FromMaybe(v8::Local<v8::Value>());
    9345           5 :   CHECK_EQ(1, report_count);
    9346           5 :   isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
    9347           5 : }
    9348             : 
    9349             : 
    9350             : static const char* script_resource_name = "ExceptionInNativeScript.js";
    9351           5 : static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
    9352             :                                                 v8::Local<Value>) {
    9353          10 :   v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
    9354          10 :   CHECK(!name_val.IsEmpty() && name_val->IsString());
    9355             :   v8::String::Utf8Value name(v8::Isolate::GetCurrent(),
    9356          15 :                              message->GetScriptOrigin().ResourceName());
    9357           5 :   CHECK_EQ(0, strcmp(script_resource_name, *name));
    9358             :   v8::Local<v8::Context> context =
    9359           5 :       v8::Isolate::GetCurrent()->GetCurrentContext();
    9360          10 :   CHECK_EQ(3, message->GetLineNumber(context).FromJust());
    9361             :   v8::String::Utf8Value source_line(
    9362             :       v8::Isolate::GetCurrent(),
    9363          15 :       message->GetSourceLine(context).ToLocalChecked());
    9364           5 :   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
    9365           5 : }
    9366             : 
    9367             : 
    9368       26644 : TEST(ExceptionInNativeScript) {
    9369           5 :   LocalContext env;
    9370           5 :   v8::Isolate* isolate = env->GetIsolate();
    9371          10 :   v8::HandleScope scope(isolate);
    9372           5 :   isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
    9373             : 
    9374             :   Local<v8::FunctionTemplate> fun =
    9375           5 :       v8::FunctionTemplate::New(isolate, TroubleCallback);
    9376           5 :   v8::Local<v8::Object> global = env->Global();
    9377          20 :   CHECK(global->Set(env.local(), v8_str("trouble"),
    9378             :                     fun->GetFunction(env.local()).ToLocalChecked())
    9379             :             .FromJust());
    9380             : 
    9381             :   CompileRunWithOrigin(
    9382             :       "function trouble() {\n"
    9383             :       "  var o = {};\n"
    9384             :       "  new o.foo();\n"
    9385             :       "};",
    9386           5 :       script_resource_name);
    9387             :   Local<Value> trouble =
    9388          15 :       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
    9389           5 :   CHECK(trouble->IsFunction());
    9390          10 :   CHECK(Function::Cast(*trouble)
    9391             :             ->Call(env.local(), global, 0, nullptr)
    9392             :             .IsEmpty());
    9393           5 :   isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
    9394           5 : }
    9395             : 
    9396             : 
    9397       26644 : TEST(CompilationErrorUsingTryCatchHandler) {
    9398           5 :   LocalContext env;
    9399          10 :   v8::HandleScope scope(env->GetIsolate());
    9400          10 :   v8::TryCatch try_catch(env->GetIsolate());
    9401             :   v8_compile("This doesn't &*&@#$&*^ compile.");
    9402          10 :   CHECK(*try_catch.Exception());
    9403           5 :   CHECK(try_catch.HasCaught());
    9404           5 : }
    9405             : 
    9406             : 
    9407       26644 : TEST(TryCatchFinallyUsingTryCatchHandler) {
    9408           5 :   LocalContext env;
    9409          10 :   v8::HandleScope scope(env->GetIsolate());
    9410          10 :   v8::TryCatch try_catch(env->GetIsolate());
    9411             :   CompileRun("try { throw ''; } catch (e) {}");
    9412           5 :   CHECK(!try_catch.HasCaught());
    9413             :   CompileRun("try { throw ''; } finally {}");
    9414           5 :   CHECK(try_catch.HasCaught());
    9415           5 :   try_catch.Reset();
    9416             :   CompileRun(
    9417             :       "(function() {"
    9418             :       "try { throw ''; } finally { return; }"
    9419             :       "})()");
    9420           5 :   CHECK(!try_catch.HasCaught());
    9421             :   CompileRun(
    9422             :       "(function()"
    9423             :       "  { try { throw ''; } finally { throw 0; }"
    9424             :       "})()");
    9425           5 :   CHECK(try_catch.HasCaught());
    9426           5 : }
    9427             : 
    9428             : 
    9429          10 : void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
    9430          20 :   v8::HandleScope scope(args.GetIsolate());
    9431             :   CompileRun(args[0]
    9432          20 :                  ->ToString(args.GetIsolate()->GetCurrentContext())
    9433          10 :                  .ToLocalChecked());
    9434          10 : }
    9435             : 
    9436             : 
    9437       26644 : TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
    9438           5 :   v8::Isolate* isolate = CcTest::isolate();
    9439          10 :   v8::HandleScope scope(isolate);
    9440           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    9441          15 :   templ->Set(v8_str("CEvaluate"),
    9442           5 :              v8::FunctionTemplate::New(isolate, CEvaluate));
    9443           5 :   LocalContext context(nullptr, templ);
    9444          10 :   v8::TryCatch try_catch(isolate);
    9445             :   CompileRun("try {"
    9446             :              "  CEvaluate('throw 1;');"
    9447             :              "} finally {"
    9448             :              "}");
    9449           5 :   CHECK(try_catch.HasCaught());
    9450          10 :   CHECK(!try_catch.Message().IsEmpty());
    9451          10 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    9452           5 :   CHECK_EQ(0, strcmp(*exception_value, "1"));
    9453           5 :   try_catch.Reset();
    9454             :   CompileRun("try {"
    9455             :              "  CEvaluate('throw 1;');"
    9456             :              "} finally {"
    9457             :              "  throw 2;"
    9458             :              "}");
    9459           5 :   CHECK(try_catch.HasCaught());
    9460          10 :   CHECK(!try_catch.Message().IsEmpty());
    9461          10 :   String::Utf8Value finally_exception_value(isolate, try_catch.Exception());
    9462           5 :   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
    9463           5 : }
    9464             : 
    9465             : 
    9466             : // For use within the TestSecurityHandler() test.
    9467             : static bool g_security_callback_result = false;
    9468          35 : static bool SecurityTestCallback(Local<v8::Context> accessing_context,
    9469             :                                  Local<v8::Object> accessed_object,
    9470             :                                  Local<v8::Value> data) {
    9471             :   printf("a\n");
    9472          35 :   CHECK(!data.IsEmpty() && data->IsInt32());
    9473          70 :   CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
    9474          35 :   return g_security_callback_result;
    9475             : }
    9476             : 
    9477             : 
    9478             : // SecurityHandler can't be run twice
    9479       26644 : TEST(SecurityHandler) {
    9480           5 :   v8::Isolate* isolate = CcTest::isolate();
    9481          10 :   v8::HandleScope scope0(isolate);
    9482             :   v8::Local<v8::ObjectTemplate> global_template =
    9483           5 :       v8::ObjectTemplate::New(isolate);
    9484          10 :   global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
    9485             :   // Create an environment
    9486           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
    9487           5 :   context0->Enter();
    9488             : 
    9489           5 :   v8::Local<v8::Object> global0 = context0->Global();
    9490             :   v8::Local<Script> script0 = v8_compile("foo = 111");
    9491           5 :   script0->Run(context0).ToLocalChecked();
    9492          15 :   CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
    9493             :   v8::Local<Value> foo0 =
    9494          15 :       global0->Get(context0, v8_str("foo")).ToLocalChecked();
    9495          10 :   CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
    9496          15 :   v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
    9497          10 :   CHECK_EQ(999, z0->Int32Value(context0).FromJust());
    9498             : 
    9499             :   // Create another environment, should fail security checks.
    9500          10 :   v8::HandleScope scope1(isolate);
    9501             : 
    9502           5 :   v8::Local<Context> context1 = Context::New(isolate, nullptr, global_template);
    9503           5 :   context1->Enter();
    9504             : 
    9505           5 :   v8::Local<v8::Object> global1 = context1->Global();
    9506          15 :   global1->Set(context1, v8_str("othercontext"), global0).FromJust();
    9507             :   // This set will fail the security check.
    9508             :   v8::Local<Script> script1 =
    9509             :       v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
    9510          10 :   CHECK(script1->Run(context1).IsEmpty());
    9511           5 :   g_security_callback_result = true;
    9512             :   // This read will pass the security check.
    9513             :   v8::Local<Value> foo1 =
    9514          15 :       global0->Get(context1, v8_str("foo")).ToLocalChecked();
    9515          10 :   CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
    9516             :   // This read will pass the security check.
    9517          15 :   v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
    9518          10 :   CHECK_EQ(999, z1->Int32Value(context1).FromJust());
    9519             : 
    9520             :   // Create another environment, should pass security checks.
    9521             :   {
    9522          10 :     v8::HandleScope scope2(isolate);
    9523           5 :     LocalContext context2;
    9524           5 :     v8::Local<v8::Object> global2 = context2->Global();
    9525          15 :     CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
    9526             :               .FromJust());
    9527             :     v8::Local<Script> script2 =
    9528             :         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
    9529           5 :     script2->Run(context2.local()).ToLocalChecked();
    9530             :     v8::Local<Value> foo2 =
    9531          15 :         global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
    9532          10 :     CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
    9533             :     v8::Local<Value> z2 =
    9534          15 :         global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
    9535          10 :     CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
    9536             :   }
    9537             : 
    9538           5 :   context1->Exit();
    9539           5 :   context0->Exit();
    9540           5 : }
    9541             : 
    9542             : 
    9543       26645 : THREADED_TEST(SecurityChecks) {
    9544           6 :   LocalContext env1;
    9545          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9546           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9547             : 
    9548           6 :   Local<Value> foo = v8_str("foo");
    9549           6 :   Local<Value> bar = v8_str("bar");
    9550             : 
    9551             :   // Set to the same domain.
    9552           6 :   env1->SetSecurityToken(foo);
    9553             : 
    9554             :   // Create a function in env1.
    9555             :   CompileRun("spy=function(){return spy;}");
    9556             :   Local<Value> spy =
    9557          24 :       env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
    9558           6 :   CHECK(spy->IsFunction());
    9559             : 
    9560             :   // Create another function accessing global objects.
    9561             :   CompileRun("spy2=function(){return new this.Array();}");
    9562             :   Local<Value> spy2 =
    9563          24 :       env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
    9564           6 :   CHECK(spy2->IsFunction());
    9565             : 
    9566             :   // Switch to env2 in the same domain and invoke spy on env2.
    9567             :   {
    9568           6 :     env2->SetSecurityToken(foo);
    9569             :     // Enter env2
    9570             :     Context::Scope scope_env2(env2);
    9571             :     Local<Value> result = Function::Cast(*spy)
    9572          18 :                               ->Call(env2, env2->Global(), 0, nullptr)
    9573             :                               .ToLocalChecked();
    9574           6 :     CHECK(result->IsFunction());
    9575             :   }
    9576             : 
    9577             :   {
    9578           6 :     env2->SetSecurityToken(bar);
    9579             :     Context::Scope scope_env2(env2);
    9580             : 
    9581             :     // Call cross_domain_call, it should throw an exception
    9582          12 :     v8::TryCatch try_catch(env1->GetIsolate());
    9583          18 :     CHECK(Function::Cast(*spy2)
    9584             :               ->Call(env2, env2->Global(), 0, nullptr)
    9585             :               .IsEmpty());
    9586           6 :     CHECK(try_catch.HasCaught());
    9587             :   }
    9588           6 : }
    9589             : 
    9590             : 
    9591             : // Regression test case for issue 1183439.
    9592       26645 : THREADED_TEST(SecurityChecksForPrototypeChain) {
    9593           6 :   LocalContext current;
    9594          12 :   v8::HandleScope scope(current->GetIsolate());
    9595           6 :   v8::Local<Context> other = Context::New(current->GetIsolate());
    9596             : 
    9597             :   // Change context to be able to get to the Object function in the
    9598             :   // other context without hitting the security checks.
    9599             :   v8::Local<Value> other_object;
    9600             :   { Context::Scope scope(other);
    9601             :     other_object =
    9602          24 :         other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
    9603          18 :     CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
    9604             :   }
    9605             : 
    9606          30 :   CHECK(current->Global()
    9607             :             ->Set(current.local(), v8_str("other"), other->Global())
    9608             :             .FromJust());
    9609          24 :   CHECK(v8_compile("other")
    9610             :             ->Run(current.local())
    9611             :             .ToLocalChecked()
    9612             :             ->Equals(current.local(), other->Global())
    9613             :             .FromJust());
    9614             : 
    9615             :   // Make sure the security check fails here and we get an undefined
    9616             :   // result instead of getting the Object function. Repeat in a loop
    9617             :   // to make sure to exercise the IC code.
    9618             :   v8::Local<Script> access_other0 = v8_compile("other.Object");
    9619             :   v8::Local<Script> access_other1 = v8_compile("other[42]");
    9620          66 :   for (int i = 0; i < 5; i++) {
    9621          60 :     CHECK(access_other0->Run(current.local()).IsEmpty());
    9622          60 :     CHECK(access_other1->Run(current.local()).IsEmpty());
    9623             :   }
    9624             : 
    9625             :   // Create an object that has 'other' in its prototype chain and make
    9626             :   // sure we cannot access the Object function indirectly through
    9627             :   // that. Repeat in a loop to make sure to exercise the IC code.
    9628             :   v8_compile(
    9629             :       "function F() { };"
    9630             :       "F.prototype = other;"
    9631             :       "var f = new F();")
    9632           6 :       ->Run(current.local())
    9633             :       .ToLocalChecked();
    9634             :   v8::Local<Script> access_f0 = v8_compile("f.Object");
    9635             :   v8::Local<Script> access_f1 = v8_compile("f[42]");
    9636          66 :   for (int j = 0; j < 5; j++) {
    9637          60 :     CHECK(access_f0->Run(current.local()).IsEmpty());
    9638          60 :     CHECK(access_f1->Run(current.local()).IsEmpty());
    9639             :   }
    9640             : 
    9641             :   // Now it gets hairy: Set the prototype for the other global object
    9642             :   // to be the current global object. The prototype chain for 'f' now
    9643             :   // goes through 'other' but ends up in the current global object.
    9644             :   { Context::Scope scope(other);
    9645          30 :     CHECK(other->Global()
    9646             :               ->Set(other, v8_str("__proto__"), current->Global())
    9647             :               .FromJust());
    9648             :   }
    9649             :   // Set a named and an index property on the current global
    9650             :   // object. To force the lookup to go through the other global object,
    9651             :   // the properties must not exist in the other global object.
    9652          24 :   CHECK(current->Global()
    9653             :             ->Set(current.local(), v8_str("foo"), v8_num(100))
    9654             :             .FromJust());
    9655          24 :   CHECK(current->Global()
    9656             :             ->Set(current.local(), v8_num(99), v8_num(101))
    9657             :             .FromJust());
    9658             :   // Try to read the properties from f and make sure that the access
    9659             :   // gets stopped by the security checks on the other global object.
    9660             :   Local<Script> access_f2 = v8_compile("f.foo");
    9661             :   Local<Script> access_f3 = v8_compile("f[99]");
    9662          66 :   for (int k = 0; k < 5; k++) {
    9663          60 :     CHECK(access_f2->Run(current.local()).IsEmpty());
    9664          60 :     CHECK(access_f3->Run(current.local()).IsEmpty());
    9665             :   }
    9666           6 : }
    9667             : 
    9668             : 
    9669             : static bool security_check_with_gc_called;
    9670             : 
    9671          10 : static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
    9672             :                                        Local<v8::Object> accessed_object,
    9673             :                                        Local<v8::Value> data) {
    9674          10 :   CcTest::CollectAllGarbage();
    9675          10 :   security_check_with_gc_called = true;
    9676          10 :   return true;
    9677             : }
    9678             : 
    9679             : 
    9680       26644 : TEST(SecurityTestGCAllowed) {
    9681           5 :   v8::Isolate* isolate = CcTest::isolate();
    9682          10 :   v8::HandleScope handle_scope(isolate);
    9683             :   v8::Local<v8::ObjectTemplate> object_template =
    9684           5 :       v8::ObjectTemplate::New(isolate);
    9685           5 :   object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
    9686             : 
    9687           5 :   v8::Local<Context> context = Context::New(isolate);
    9688             :   v8::Context::Scope context_scope(context);
    9689             : 
    9690          25 :   CHECK(context->Global()
    9691             :             ->Set(context, v8_str("obj"),
    9692             :                   object_template->NewInstance(context).ToLocalChecked())
    9693             :             .FromJust());
    9694             : 
    9695           5 :   security_check_with_gc_called = false;
    9696             :   CompileRun("obj[0] = new String(1002);");
    9697           5 :   CHECK(security_check_with_gc_called);
    9698             : 
    9699           5 :   security_check_with_gc_called = false;
    9700          20 :   CHECK(CompileRun("obj[0]")
    9701             :             ->ToString(context)
    9702             :             .ToLocalChecked()
    9703             :             ->Equals(context, v8_str("1002"))
    9704             :             .FromJust());
    9705           5 :   CHECK(security_check_with_gc_called);
    9706           5 : }
    9707             : 
    9708             : 
    9709       26645 : THREADED_TEST(CrossDomainDelete) {
    9710           6 :   LocalContext env1;
    9711          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9712           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9713             : 
    9714           6 :   Local<Value> foo = v8_str("foo");
    9715           6 :   Local<Value> bar = v8_str("bar");
    9716             : 
    9717             :   // Set to the same domain.
    9718           6 :   env1->SetSecurityToken(foo);
    9719           6 :   env2->SetSecurityToken(foo);
    9720             : 
    9721          24 :   CHECK(
    9722             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9723          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9724             : 
    9725             :   // Change env2 to a different domain and delete env1.prop.
    9726           6 :   env2->SetSecurityToken(bar);
    9727             :   {
    9728             :     Context::Scope scope_env2(env2);
    9729             :     Local<Value> result =
    9730             :         CompileRun("delete env1.prop");
    9731           6 :     CHECK(result.IsEmpty());
    9732             :   }
    9733             : 
    9734             :   // Check that env1.prop still exists.
    9735             :   Local<Value> v =
    9736          24 :       env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
    9737           6 :   CHECK(v->IsNumber());
    9738          12 :   CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
    9739           6 : }
    9740             : 
    9741             : 
    9742       26645 : THREADED_TEST(CrossDomainPropertyIsEnumerable) {
    9743           6 :   LocalContext env1;
    9744          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9745           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9746             : 
    9747           6 :   Local<Value> foo = v8_str("foo");
    9748           6 :   Local<Value> bar = v8_str("bar");
    9749             : 
    9750             :   // Set to the same domain.
    9751           6 :   env1->SetSecurityToken(foo);
    9752           6 :   env2->SetSecurityToken(foo);
    9753             : 
    9754          24 :   CHECK(
    9755             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9756          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9757             : 
    9758             :   // env1.prop is enumerable in env2.
    9759           6 :   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
    9760             :   {
    9761             :     Context::Scope scope_env2(env2);
    9762           6 :     Local<Value> result = CompileRun(test);
    9763           6 :     CHECK(result->IsTrue());
    9764             :   }
    9765             : 
    9766             :   // Change env2 to a different domain and test again.
    9767           6 :   env2->SetSecurityToken(bar);
    9768             :   {
    9769             :     Context::Scope scope_env2(env2);
    9770           6 :     Local<Value> result = CompileRun(test);
    9771           6 :     CHECK(result.IsEmpty());
    9772             :   }
    9773           6 : }
    9774             : 
    9775             : 
    9776       26645 : THREADED_TEST(CrossDomainFor) {
    9777           6 :   LocalContext env1;
    9778          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9779           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9780             : 
    9781           6 :   Local<Value> foo = v8_str("foo");
    9782           6 :   Local<Value> bar = v8_str("bar");
    9783             : 
    9784             :   // Set to the same domain.
    9785           6 :   env1->SetSecurityToken(foo);
    9786           6 :   env2->SetSecurityToken(foo);
    9787             : 
    9788          24 :   CHECK(
    9789             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9790          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9791             : 
    9792             :   // Change env2 to a different domain and set env1's global object
    9793             :   // as the __proto__ of an object in env2 and enumerate properties
    9794             :   // in for-in. It shouldn't enumerate properties on env1's global
    9795             :   // object. It shouldn't throw either, just silently ignore them.
    9796           6 :   env2->SetSecurityToken(bar);
    9797             :   {
    9798             :     Context::Scope scope_env2(env2);
    9799             :     Local<Value> result = CompileRun(
    9800             :         "(function() {"
    9801             :         "  try {"
    9802             :         "    for (var p in env1) {"
    9803             :         "      if (p == 'prop') return false;"
    9804             :         "    }"
    9805             :         "    return true;"
    9806             :         "  } catch (e) {"
    9807             :         "    return false;"
    9808             :         "  }"
    9809             :         "})()");
    9810           6 :     CHECK(result->IsTrue());
    9811             :   }
    9812           6 : }
    9813             : 
    9814             : 
    9815       26645 : THREADED_TEST(CrossDomainForInOnPrototype) {
    9816           6 :   LocalContext env1;
    9817          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9818           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9819             : 
    9820           6 :   Local<Value> foo = v8_str("foo");
    9821           6 :   Local<Value> bar = v8_str("bar");
    9822             : 
    9823             :   // Set to the same domain.
    9824           6 :   env1->SetSecurityToken(foo);
    9825           6 :   env2->SetSecurityToken(foo);
    9826             : 
    9827          24 :   CHECK(
    9828             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9829          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9830             : 
    9831             :   // Change env2 to a different domain and set env1's global object
    9832             :   // as the __proto__ of an object in env2 and enumerate properties
    9833             :   // in for-in. It shouldn't enumerate properties on env1's global
    9834             :   // object.
    9835           6 :   env2->SetSecurityToken(bar);
    9836             :   {
    9837             :     Context::Scope scope_env2(env2);
    9838             :     Local<Value> result = CompileRun(
    9839             :         "(function() {"
    9840             :         "  var obj = { '__proto__': env1 };"
    9841             :         "  try {"
    9842             :         "    for (var p in obj) {"
    9843             :         "      if (p == 'prop') return false;"
    9844             :         "    }"
    9845             :         "    return true;"
    9846             :         "  } catch (e) {"
    9847             :         "    return false;"
    9848             :         "  }"
    9849             :         "})()");
    9850           6 :     CHECK(result->IsTrue());
    9851             :   }
    9852           6 : }
    9853             : 
    9854             : 
    9855       26644 : TEST(ContextDetachGlobal) {
    9856           5 :   LocalContext env1;
    9857          10 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9858           5 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9859             : 
    9860             : 
    9861           5 :   Local<Value> foo = v8_str("foo");
    9862             : 
    9863             :   // Set to the same domain.
    9864           5 :   env1->SetSecurityToken(foo);
    9865           5 :   env2->SetSecurityToken(foo);
    9866             : 
    9867             :   // Enter env2
    9868           5 :   env2->Enter();
    9869             : 
    9870             :   // Create a function in env2 and add a reference to it in env1.
    9871           5 :   Local<v8::Object> global2 = env2->Global();
    9872          20 :   CHECK(global2->Set(env2, v8_str("prop"),
    9873             :                      v8::Integer::New(env2->GetIsolate(), 1))
    9874             :             .FromJust());
    9875             :   CompileRun("function getProp() {return prop;}");
    9876             : 
    9877          30 :   CHECK(env1->Global()
    9878             :             ->Set(env1.local(), v8_str("getProp"),
    9879             :                   global2->Get(env2, v8_str("getProp")).ToLocalChecked())
    9880             :             .FromJust());
    9881             : 
    9882             :   // Detach env2's global, and reuse the global object of env2
    9883           5 :   env2->Exit();
    9884           5 :   env2->DetachGlobal();
    9885             : 
    9886             :   v8::Local<Context> env3 = Context::New(
    9887           5 :       env1->GetIsolate(), nullptr, v8::Local<v8::ObjectTemplate>(), global2);
    9888          10 :   env3->SetSecurityToken(v8_str("bar"));
    9889             : 
    9890           5 :   env3->Enter();
    9891           5 :   Local<v8::Object> global3 = env3->Global();
    9892          10 :   CHECK(global2->Equals(env3, global3).FromJust());
    9893          15 :   CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
    9894          15 :   CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
    9895          20 :   CHECK(global3->Set(env3, v8_str("prop"),
    9896             :                      v8::Integer::New(env3->GetIsolate(), -1))
    9897             :             .FromJust());
    9898          20 :   CHECK(global3->Set(env3, v8_str("prop2"),
    9899             :                      v8::Integer::New(env3->GetIsolate(), 2))
    9900             :             .FromJust());
    9901           5 :   env3->Exit();
    9902             : 
    9903             :   // Call getProp in env1, and it should return the value 1
    9904             :   {
    9905           5 :     Local<v8::Object> global1 = env1->Global();
    9906             :     Local<Value> get_prop =
    9907          15 :         global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
    9908           5 :     CHECK(get_prop->IsFunction());
    9909          10 :     v8::TryCatch try_catch(env1->GetIsolate());
    9910             :     Local<Value> r = Function::Cast(*get_prop)
    9911          10 :                          ->Call(env1.local(), global1, 0, nullptr)
    9912             :                          .ToLocalChecked();
    9913           5 :     CHECK(!try_catch.HasCaught());
    9914          10 :     CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
    9915             :   }
    9916             : 
    9917             :   // Check that env3 is not accessible from env1
    9918             :   {
    9919          10 :     v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
    9920           5 :     CHECK(r.IsEmpty());
    9921             :   }
    9922           5 : }
    9923             : 
    9924             : 
    9925       26644 : TEST(DetachGlobal) {
    9926           5 :   LocalContext env1;
    9927          10 :   v8::HandleScope scope(env1->GetIsolate());
    9928             : 
    9929             :   // Create second environment.
    9930           5 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9931             : 
    9932           5 :   Local<Value> foo = v8_str("foo");
    9933             : 
    9934             :   // Set same security token for env1 and env2.
    9935           5 :   env1->SetSecurityToken(foo);
    9936           5 :   env2->SetSecurityToken(foo);
    9937             : 
    9938             :   // Create a property on the global object in env2.
    9939             :   {
    9940             :     v8::Context::Scope scope(env2);
    9941          25 :     CHECK(env2->Global()
    9942             :               ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
    9943             :               .FromJust());
    9944             :   }
    9945             : 
    9946             :   // Create a reference to env2 global from env1 global.
    9947          25 :   CHECK(env1->Global()
    9948             :             ->Set(env1.local(), v8_str("other"), env2->Global())
    9949             :             .FromJust());
    9950             : 
    9951             :   // Check that we have access to other.p in env2 from env1.
    9952             :   Local<Value> result = CompileRun("other.p");
    9953           5 :   CHECK(result->IsInt32());
    9954          10 :   CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
    9955             : 
    9956             :   // Hold on to global from env2 and detach global from env2.
    9957           5 :   Local<v8::Object> global2 = env2->Global();
    9958           5 :   env2->DetachGlobal();
    9959             : 
    9960             :   // Check that the global has been detached. No other.p property can
    9961             :   // be found.
    9962             :   result = CompileRun("other.p");
    9963           5 :   CHECK(result.IsEmpty());
    9964             : 
    9965             :   // Reuse global2 for env3.
    9966             :   v8::Local<Context> env3 = Context::New(
    9967           5 :       env1->GetIsolate(), nullptr, v8::Local<v8::ObjectTemplate>(), global2);
    9968          15 :   CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
    9969             : 
    9970             :   // Start by using the same security token for env3 as for env1 and env2.
    9971           5 :   env3->SetSecurityToken(foo);
    9972             : 
    9973             :   // Create a property on the global object in env3.
    9974             :   {
    9975             :     v8::Context::Scope scope(env3);
    9976          25 :     CHECK(env3->Global()
    9977             :               ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
    9978             :               .FromJust());
    9979             :   }
    9980             : 
    9981             :   // Check that other.p is now the property in env3 and that we have access.
    9982             :   result = CompileRun("other.p");
    9983           5 :   CHECK(result->IsInt32());
    9984          10 :   CHECK_EQ(24, result->Int32Value(env3).FromJust());
    9985           5 : }
    9986             : 
    9987             : 
    9988          65 : void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
    9989          65 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9990             :   info.GetReturnValue().Set(
    9991         260 :       context->Global()->Get(context, v8_str("x")).ToLocalChecked());
    9992          65 : }
    9993             : 
    9994             : 
    9995       26644 : TEST(DetachedAccesses) {
    9996           5 :   LocalContext env1;
    9997          10 :   v8::HandleScope scope(env1->GetIsolate());
    9998             : 
    9999             :   // Create second environment.
   10000             :   Local<ObjectTemplate> inner_global_template =
   10001          10 :       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
   10002          10 :   inner_global_template ->SetAccessorProperty(
   10003           5 :       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
   10004             :   v8::Local<Context> env2 =
   10005           5 :       Context::New(env1->GetIsolate(), nullptr, inner_global_template);
   10006             : 
   10007           5 :   Local<Value> foo = v8_str("foo");
   10008             : 
   10009             :   // Set same security token for env1 and env2.
   10010           5 :   env1->SetSecurityToken(foo);
   10011           5 :   env2->SetSecurityToken(foo);
   10012             : 
   10013          25 :   CHECK(env1->Global()
   10014             :             ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
   10015             :             .FromJust());
   10016             : 
   10017             :   {
   10018             :     v8::Context::Scope scope(env2);
   10019          25 :     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
   10020             :     CompileRun(
   10021             :         "function bound_x() { return x; }"
   10022             :         "function get_x()   { return this.x; }"
   10023             :         "function get_x_w() { return (function() {return this.x;})(); }");
   10024          20 :     CHECK(env1->Global()
   10025             :               ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
   10026             :               .FromJust());
   10027          20 :     CHECK(env1->Global()
   10028             :               ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
   10029             :               .FromJust());
   10030          20 :     CHECK(env1->Global()
   10031             :               ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
   10032             :               .FromJust());
   10033          10 :     env1->Global()
   10034          10 :         ->Set(env1.local(), v8_str("this_x"),
   10035          10 :               CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
   10036             :         .FromJust();
   10037             :   }
   10038             : 
   10039           5 :   Local<Object> env2_global = env2->Global();
   10040           5 :   env2->DetachGlobal();
   10041             : 
   10042             :   Local<Value> result;
   10043             :   result = CompileRun("bound_x()");
   10044          15 :   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   10045             :   result = CompileRun("get_x()");
   10046           5 :   CHECK(result.IsEmpty());
   10047             :   result = CompileRun("get_x_w()");
   10048           5 :   CHECK(result.IsEmpty());
   10049             :   result = CompileRun("this_x()");
   10050          15 :   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   10051             : 
   10052             :   // Reattach env2's proxy
   10053             :   env2 = Context::New(env1->GetIsolate(), nullptr,
   10054           5 :                       v8::Local<v8::ObjectTemplate>(), env2_global);
   10055           5 :   env2->SetSecurityToken(foo);
   10056             :   {
   10057             :     v8::Context::Scope scope(env2);
   10058          25 :     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
   10059          25 :     CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   10060             :     result = CompileRun(
   10061             :         "results = [];"
   10062             :         "for (var i = 0; i < 4; i++ ) {"
   10063             :         "  results.push(env1.bound_x());"
   10064             :         "  results.push(env1.get_x());"
   10065             :         "  results.push(env1.get_x_w());"
   10066             :         "  results.push(env1.this_x());"
   10067             :         "}"
   10068             :         "results");
   10069             :     Local<v8::Array> results = Local<v8::Array>::Cast(result);
   10070           5 :     CHECK_EQ(16u, results->Length());
   10071          45 :     for (int i = 0; i < 16; i += 4) {
   10072          80 :       CHECK(v8_str("env2_x")
   10073             :                 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
   10074             :                 .FromJust());
   10075          80 :       CHECK(v8_str("env1_x")
   10076             :                 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
   10077             :                 .FromJust());
   10078          80 :       CHECK(v8_str("env3_x")
   10079             :                 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
   10080             :                 .FromJust());
   10081          80 :       CHECK(v8_str("env2_x")
   10082             :                 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
   10083             :                 .FromJust());
   10084             :     }
   10085             :   }
   10086             : 
   10087             :   result = CompileRun(
   10088             :       "results = [];"
   10089             :       "for (var i = 0; i < 4; i++ ) {"
   10090             :       "  results.push(bound_x());"
   10091             :       "  results.push(get_x());"
   10092             :       "  results.push(get_x_w());"
   10093             :       "  results.push(this_x());"
   10094             :       "}"
   10095             :       "results");
   10096             :   Local<v8::Array> results = Local<v8::Array>::Cast(result);
   10097           5 :   CHECK_EQ(16u, results->Length());
   10098          45 :   for (int i = 0; i < 16; i += 4) {
   10099         100 :     CHECK(v8_str("env2_x")
   10100             :               ->Equals(env1.local(),
   10101             :                        results->Get(env1.local(), i + 0).ToLocalChecked())
   10102             :               .FromJust());
   10103         100 :     CHECK(v8_str("env3_x")
   10104             :               ->Equals(env1.local(),
   10105             :                        results->Get(env1.local(), i + 1).ToLocalChecked())
   10106             :               .FromJust());
   10107         100 :     CHECK(v8_str("env3_x")
   10108             :               ->Equals(env1.local(),
   10109             :                        results->Get(env1.local(), i + 2).ToLocalChecked())
   10110             :               .FromJust());
   10111         100 :     CHECK(v8_str("env2_x")
   10112             :               ->Equals(env1.local(),
   10113             :                        results->Get(env1.local(), i + 3).ToLocalChecked())
   10114             :               .FromJust());
   10115             :   }
   10116             : 
   10117             :   result = CompileRun(
   10118             :       "results = [];"
   10119             :       "for (var i = 0; i < 4; i++ ) {"
   10120             :       "  results.push(this.bound_x());"
   10121             :       "  results.push(this.get_x());"
   10122             :       "  results.push(this.get_x_w());"
   10123             :       "  results.push(this.this_x());"
   10124             :       "}"
   10125             :       "results");
   10126             :   results = Local<v8::Array>::Cast(result);
   10127           5 :   CHECK_EQ(16u, results->Length());
   10128          45 :   for (int i = 0; i < 16; i += 4) {
   10129         100 :     CHECK(v8_str("env2_x")
   10130             :               ->Equals(env1.local(),
   10131             :                        results->Get(env1.local(), i + 0).ToLocalChecked())
   10132             :               .FromJust());
   10133         100 :     CHECK(v8_str("env1_x")
   10134             :               ->Equals(env1.local(),
   10135             :                        results->Get(env1.local(), i + 1).ToLocalChecked())
   10136             :               .FromJust());
   10137         100 :     CHECK(v8_str("env3_x")
   10138             :               ->Equals(env1.local(),
   10139             :                        results->Get(env1.local(), i + 2).ToLocalChecked())
   10140             :               .FromJust());
   10141         100 :     CHECK(v8_str("env2_x")
   10142             :               ->Equals(env1.local(),
   10143             :                        results->Get(env1.local(), i + 3).ToLocalChecked())
   10144             :               .FromJust());
   10145             :   }
   10146           5 : }
   10147             : 
   10148             : 
   10149             : static bool allowed_access = false;
   10150         370 : static bool AccessBlocker(Local<v8::Context> accessing_context,
   10151             :                           Local<v8::Object> accessed_object,
   10152             :                           Local<v8::Value> data) {
   10153         370 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   10154        1110 :   return context->Global()->Equals(context, accessed_object).FromJust() ||
   10155         370 :          allowed_access;
   10156             : }
   10157             : 
   10158             : 
   10159             : static int g_echo_value = -1;
   10160             : 
   10161             : 
   10162          15 : static void EchoGetter(
   10163             :     Local<String> name,
   10164             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10165          15 :   info.GetReturnValue().Set(v8_num(g_echo_value));
   10166          15 : }
   10167             : 
   10168             : 
   10169          10 : static void EchoSetter(Local<String> name, Local<Value> value,
   10170             :                        const v8::PropertyCallbackInfo<void>& args) {
   10171          10 :   if (value->IsNumber())
   10172             :     g_echo_value =
   10173          20 :         value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   10174          10 : }
   10175             : 
   10176             : 
   10177           0 : static void UnreachableGetter(
   10178             :     Local<String> name,
   10179             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10180           0 :   UNREACHABLE();  // This function should not be called..
   10181             : }
   10182             : 
   10183             : 
   10184           0 : static void UnreachableSetter(Local<String>,
   10185             :                               Local<Value>,
   10186             :                               const v8::PropertyCallbackInfo<void>&) {
   10187           0 :   UNREACHABLE();  // This function should not be called.
   10188             : }
   10189             : 
   10190             : 
   10191           0 : static void UnreachableFunction(
   10192             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   10193           0 :   UNREACHABLE();  // This function should not be called..
   10194             : }
   10195             : 
   10196             : 
   10197       26644 : TEST(AccessControl) {
   10198           5 :   v8::Isolate* isolate = CcTest::isolate();
   10199          10 :   v8::HandleScope handle_scope(isolate);
   10200             :   v8::Local<v8::ObjectTemplate> global_template =
   10201           5 :       v8::ObjectTemplate::New(isolate);
   10202             : 
   10203           5 :   global_template->SetAccessCheckCallback(AccessBlocker);
   10204             : 
   10205             :   // Add an accessor accessible by cross-domain JS code.
   10206          10 :   global_template->SetAccessor(
   10207             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10208           5 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10209             : 
   10210             : 
   10211             :   // Add an accessor that is not accessible by cross-domain JS code.
   10212          10 :   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   10213             :                                UnreachableSetter, v8::Local<Value>(),
   10214           5 :                                v8::DEFAULT);
   10215             : 
   10216          15 :   global_template->SetAccessorProperty(
   10217             :       v8_str("blocked_js_prop"),
   10218             :       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   10219             :       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   10220             :       v8::None,
   10221           5 :       v8::DEFAULT);
   10222             : 
   10223             :   // Create an environment
   10224           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10225           5 :   context0->Enter();
   10226             : 
   10227           5 :   v8::Local<v8::Object> global0 = context0->Global();
   10228             : 
   10229             :   // Define a property with JS getter and setter.
   10230             :   CompileRun(
   10231             :       "function getter() { return 'getter'; };\n"
   10232             :       "function setter() { return 'setter'; }\n"
   10233             :       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   10234             : 
   10235             :   Local<Value> getter =
   10236          15 :       global0->Get(context0, v8_str("getter")).ToLocalChecked();
   10237             :   Local<Value> setter =
   10238          15 :       global0->Get(context0, v8_str("setter")).ToLocalChecked();
   10239             : 
   10240             :   // And define normal element.
   10241          15 :   CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
   10242             : 
   10243             :   // Define an element with JS getter and setter.
   10244             :   CompileRun(
   10245             :       "function el_getter() { return 'el_getter'; };\n"
   10246             :       "function el_setter() { return 'el_setter'; };\n"
   10247             :       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   10248             : 
   10249             :   Local<Value> el_getter =
   10250          15 :       global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
   10251             :   Local<Value> el_setter =
   10252          15 :       global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
   10253             : 
   10254          10 :   v8::HandleScope scope1(isolate);
   10255             : 
   10256           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10257           5 :   context1->Enter();
   10258             : 
   10259           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10260          15 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10261             : 
   10262             :   // Access blocked property.
   10263             :   CompileRun("other.blocked_prop = 1");
   10264             : 
   10265           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10266           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   10267             :             .IsEmpty());
   10268           5 :   CHECK(
   10269             :       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
   10270             : 
   10271             :   // Access blocked element.
   10272           5 :   CHECK(CompileRun("other[239] = 1").IsEmpty());
   10273             : 
   10274           5 :   CHECK(CompileRun("other[239]").IsEmpty());
   10275           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
   10276           5 :   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
   10277             : 
   10278           5 :   allowed_access = true;
   10279             :   // Now we can enumerate the property.
   10280             :   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   10281           5 :   allowed_access = false;
   10282             : 
   10283             :   // Access a property with JS accessor.
   10284           5 :   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
   10285             : 
   10286           5 :   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
   10287           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
   10288             :             .IsEmpty());
   10289             : 
   10290           5 :   allowed_access = true;
   10291             : 
   10292           5 :   ExpectString("other.js_accessor_p", "getter");
   10293             :   ExpectObject(
   10294           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   10295             :   ExpectObject(
   10296           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   10297             :   ExpectUndefined(
   10298           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   10299             : 
   10300           5 :   allowed_access = false;
   10301             : 
   10302             :   // Access an element with JS accessor.
   10303           5 :   CHECK(CompileRun("other[42] = 2").IsEmpty());
   10304             : 
   10305           5 :   CHECK(CompileRun("other[42]").IsEmpty());
   10306           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
   10307             : 
   10308           5 :   allowed_access = true;
   10309             : 
   10310           5 :   ExpectString("other[42]", "el_getter");
   10311           5 :   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   10312           5 :   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   10313           5 :   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   10314             : 
   10315           5 :   allowed_access = false;
   10316             : 
   10317             :   v8::Local<Value> value;
   10318             : 
   10319             :   // Access accessible property
   10320             :   value = CompileRun("other.accessible_prop = 3");
   10321           5 :   CHECK(value->IsNumber());
   10322          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10323           5 :   CHECK_EQ(3, g_echo_value);
   10324             : 
   10325             :   value = CompileRun("other.accessible_prop");
   10326           5 :   CHECK(value->IsNumber());
   10327          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10328             : 
   10329             :   value = CompileRun(
   10330             :       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   10331           5 :   CHECK(value->IsNumber());
   10332          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10333             : 
   10334             :   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   10335           5 :   CHECK(value->IsTrue());
   10336             : 
   10337             :   // Enumeration doesn't enumerate accessors from inaccessible objects in
   10338             :   // the prototype chain even if the accessors are in themselves accessible.
   10339             :   // Enumeration doesn't throw, it silently ignores what it can't access.
   10340             :   value = CompileRun(
   10341             :       "(function() {"
   10342             :       "  var obj = { '__proto__': other };"
   10343             :       "  try {"
   10344             :       "    for (var p in obj) {"
   10345             :       "      if (p == 'accessible_prop' ||"
   10346             :       "          p == 'blocked_js_prop' ||"
   10347             :       "          p == 'blocked_js_prop') {"
   10348             :       "        return false;"
   10349             :       "      }"
   10350             :       "    }"
   10351             :       "    return true;"
   10352             :       "  } catch (e) {"
   10353             :       "    return false;"
   10354             :       "  }"
   10355             :       "})()");
   10356           5 :   CHECK(value->IsTrue());
   10357             : 
   10358             :   // Test that preventExtensions fails on a non-accessible object even if that
   10359             :   // object is already non-extensible.
   10360          20 :   CHECK(global1->Set(context1, v8_str("checked_object"),
   10361             :                      global_template->NewInstance(context1).ToLocalChecked())
   10362             :             .FromJust());
   10363           5 :   allowed_access = true;
   10364             :   CompileRun("Object.preventExtensions(checked_object)");
   10365             :   ExpectFalse("Object.isExtensible(checked_object)");
   10366           5 :   allowed_access = false;
   10367           5 :   CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
   10368             : 
   10369           5 :   context1->Exit();
   10370           5 :   context0->Exit();
   10371           5 : }
   10372             : 
   10373             : 
   10374       26644 : TEST(AccessControlES5) {
   10375           5 :   v8::Isolate* isolate = CcTest::isolate();
   10376          10 :   v8::HandleScope handle_scope(isolate);
   10377             :   v8::Local<v8::ObjectTemplate> global_template =
   10378           5 :       v8::ObjectTemplate::New(isolate);
   10379             : 
   10380           5 :   global_template->SetAccessCheckCallback(AccessBlocker);
   10381             : 
   10382             :   // Add accessible accessor.
   10383          10 :   global_template->SetAccessor(
   10384             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10385           5 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10386             : 
   10387             : 
   10388             :   // Add an accessor that is not accessible by cross-domain JS code.
   10389          10 :   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   10390             :                                UnreachableSetter, v8::Local<Value>(),
   10391           5 :                                v8::DEFAULT);
   10392             : 
   10393             :   // Create an environment
   10394           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10395           5 :   context0->Enter();
   10396             : 
   10397           5 :   v8::Local<v8::Object> global0 = context0->Global();
   10398             : 
   10399           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10400           5 :   context1->Enter();
   10401           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10402          15 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10403             : 
   10404             :   // Regression test for issue 1154.
   10405           5 :   CHECK(CompileRun("Object.keys(other).length == 1")->BooleanValue(isolate));
   10406           5 :   CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
   10407             :             ->BooleanValue(isolate));
   10408           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10409             : 
   10410             :   // Regression test for issue 1027.
   10411             :   CompileRun("Object.defineProperty(\n"
   10412             :              "  other, 'blocked_prop', {configurable: false})");
   10413           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10414           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   10415             :             .IsEmpty());
   10416             : 
   10417             :   // Regression test for issue 1171.
   10418             :   ExpectTrue("Object.isExtensible(other)");
   10419             :   CompileRun("Object.preventExtensions(other)");
   10420             :   ExpectTrue("Object.isExtensible(other)");
   10421             : 
   10422             :   // Object.seal and Object.freeze.
   10423             :   CompileRun("Object.freeze(other)");
   10424             :   ExpectTrue("Object.isExtensible(other)");
   10425             : 
   10426             :   CompileRun("Object.seal(other)");
   10427             :   ExpectTrue("Object.isExtensible(other)");
   10428             : 
   10429             :   // Regression test for issue 1250.
   10430             :   // Make sure that we can set the accessible accessors value using normal
   10431             :   // assignment.
   10432             :   CompileRun("other.accessible_prop = 42");
   10433           5 :   CHECK_EQ(42, g_echo_value);
   10434             : 
   10435             :   // [[DefineOwnProperty]] always throws for access-checked objects.
   10436           5 :   CHECK(
   10437             :       CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
   10438             :           .IsEmpty());
   10439           5 :   CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
   10440           5 :   CHECK_EQ(42, g_echo_value);  // Make sure we didn't call the setter.
   10441           5 : }
   10442             : 
   10443         233 : static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
   10444             :                                 Local<v8::Object> global,
   10445             :                                 Local<v8::Value> data) {
   10446         233 :   i::PrintF("Access blocked.\n");
   10447         233 :   return false;
   10448             : }
   10449             : 
   10450           5 : static bool AccessAlwaysAllowed(Local<v8::Context> accessing_context,
   10451             :                                 Local<v8::Object> global,
   10452             :                                 Local<v8::Value> data) {
   10453           5 :   i::PrintF("Access allowed.\n");
   10454           5 :   return true;
   10455             : }
   10456             : 
   10457       26645 : THREADED_TEST(AccessControlGetOwnPropertyNames) {
   10458           6 :   v8::Isolate* isolate = CcTest::isolate();
   10459          12 :   v8::HandleScope handle_scope(isolate);
   10460           6 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10461             : 
   10462          18 :   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10463           6 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10464             : 
   10465             :   // Add an accessor accessible by cross-domain JS code.
   10466          12 :   obj_template->SetAccessor(
   10467             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10468           6 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10469             : 
   10470             :   // Create an environment
   10471           6 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, obj_template);
   10472           6 :   context0->Enter();
   10473             : 
   10474           6 :   v8::Local<v8::Object> global0 = context0->Global();
   10475             : 
   10476          12 :   v8::HandleScope scope1(CcTest::isolate());
   10477             : 
   10478           6 :   v8::Local<Context> context1 = Context::New(isolate);
   10479           6 :   context1->Enter();
   10480             : 
   10481           6 :   v8::Local<v8::Object> global1 = context1->Global();
   10482          18 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10483          24 :   CHECK(global1->Set(context1, v8_str("object"),
   10484             :                      obj_template->NewInstance(context1).ToLocalChecked())
   10485             :             .FromJust());
   10486             : 
   10487             :   v8::Local<Value> value;
   10488             : 
   10489             :   // Attempt to get the property names of the other global object and
   10490             :   // of an object that requires access checks.  Accessing the other
   10491             :   // global object should be blocked by access checks on the global
   10492             :   // proxy object.  Accessing the object that requires access checks
   10493             :   // is blocked by the access checks on the object itself.
   10494             :   value = CompileRun(
   10495             :       "var names = Object.getOwnPropertyNames(other);"
   10496             :       "names.length == 1 && names[0] == 'accessible_prop';");
   10497           6 :   CHECK(value->BooleanValue(isolate));
   10498             : 
   10499             :   value = CompileRun(
   10500             :       "var names = Object.getOwnPropertyNames(object);"
   10501             :       "names.length == 1 && names[0] == 'accessible_prop';");
   10502           6 :   CHECK(value->BooleanValue(isolate));
   10503             : 
   10504           6 :   context1->Exit();
   10505           6 :   context0->Exit();
   10506           6 : }
   10507             : 
   10508             : 
   10509       26644 : TEST(Regress470113) {
   10510           5 :   v8::Isolate* isolate = CcTest::isolate();
   10511          10 :   v8::HandleScope handle_scope(isolate);
   10512           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10513           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10514           5 :   LocalContext env;
   10515          25 :   CHECK(env->Global()
   10516             :             ->Set(env.local(), v8_str("prohibited"),
   10517             :                   obj_template->NewInstance(env.local()).ToLocalChecked())
   10518             :             .FromJust());
   10519             : 
   10520             :   {
   10521          10 :     v8::TryCatch try_catch(isolate);
   10522             :     CompileRun(
   10523             :         "'use strict';\n"
   10524             :         "class C extends Object {\n"
   10525             :         "   m() { super.powned = 'Powned!'; }\n"
   10526             :         "}\n"
   10527             :         "let c = new C();\n"
   10528             :         "c.m.call(prohibited)");
   10529             : 
   10530           5 :     CHECK(try_catch.HasCaught());
   10531             :   }
   10532           5 : }
   10533             : 
   10534             : 
   10535           6 : static void ConstTenGetter(Local<String> name,
   10536             :                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   10537           6 :   info.GetReturnValue().Set(v8_num(10));
   10538           6 : }
   10539             : 
   10540             : 
   10541       26645 : THREADED_TEST(CrossDomainAccessors) {
   10542           6 :   v8::Isolate* isolate = CcTest::isolate();
   10543          12 :   v8::HandleScope handle_scope(isolate);
   10544             : 
   10545             :   v8::Local<v8::FunctionTemplate> func_template =
   10546           6 :       v8::FunctionTemplate::New(isolate);
   10547             : 
   10548             :   v8::Local<v8::ObjectTemplate> global_template =
   10549           6 :       func_template->InstanceTemplate();
   10550             : 
   10551             :   v8::Local<v8::ObjectTemplate> proto_template =
   10552           6 :       func_template->PrototypeTemplate();
   10553             : 
   10554             :   // Add an accessor to proto that's accessible by cross-domain JS code.
   10555          12 :   proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, nullptr,
   10556           6 :                               v8::Local<Value>(), v8::ALL_CAN_READ);
   10557             : 
   10558             :   // Add an accessor that is not accessible by cross-domain JS code.
   10559          12 :   global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter,
   10560           6 :                                nullptr, v8::Local<Value>(), v8::DEFAULT);
   10561             : 
   10562           6 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10563           6 :   context0->Enter();
   10564             : 
   10565           6 :   Local<v8::Object> global = context0->Global();
   10566             :   // Add a normal property that shadows 'accessible'
   10567          18 :   CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
   10568             : 
   10569             :   // Enter a new context.
   10570          12 :   v8::HandleScope scope1(CcTest::isolate());
   10571           6 :   v8::Local<Context> context1 = Context::New(isolate);
   10572           6 :   context1->Enter();
   10573             : 
   10574           6 :   v8::Local<v8::Object> global1 = context1->Global();
   10575          18 :   CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
   10576             : 
   10577             :   // Should return 10, instead of 11
   10578             :   v8::Local<Value> value =
   10579           6 :       v8_compile("other.accessible")->Run(context1).ToLocalChecked();
   10580           6 :   CHECK(value->IsNumber());
   10581          12 :   CHECK_EQ(10, value->Int32Value(context1).FromJust());
   10582             : 
   10583             :   v8::MaybeLocal<v8::Value> maybe_value =
   10584           6 :       v8_compile("other.unreachable")->Run(context1);
   10585           6 :   CHECK(maybe_value.IsEmpty());
   10586             : 
   10587           6 :   context1->Exit();
   10588           6 :   context0->Exit();
   10589           6 : }
   10590             : 
   10591             : 
   10592             : static int access_count = 0;
   10593             : 
   10594         820 : static bool AccessCounter(Local<v8::Context> accessing_context,
   10595             :                           Local<v8::Object> accessed_object,
   10596             :                           Local<v8::Value> data) {
   10597         820 :   access_count++;
   10598         820 :   return true;
   10599             : }
   10600             : 
   10601             : 
   10602             : // This one is too easily disturbed by other tests.
   10603       26644 : TEST(AccessControlIC) {
   10604           5 :   access_count = 0;
   10605             : 
   10606           5 :   v8::Isolate* isolate = CcTest::isolate();
   10607          10 :   v8::HandleScope handle_scope(isolate);
   10608             : 
   10609             :   // Create an environment.
   10610           5 :   v8::Local<Context> context0 = Context::New(isolate);
   10611           5 :   context0->Enter();
   10612             : 
   10613             :   // Create an object that requires access-check functions to be
   10614             :   // called for cross-domain access.
   10615             :   v8::Local<v8::ObjectTemplate> object_template =
   10616           5 :       v8::ObjectTemplate::New(isolate);
   10617           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   10618             :   Local<v8::Object> object =
   10619           5 :       object_template->NewInstance(context0).ToLocalChecked();
   10620             : 
   10621          10 :   v8::HandleScope scope1(isolate);
   10622             : 
   10623             :   // Create another environment.
   10624           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10625           5 :   context1->Enter();
   10626             : 
   10627             :   // Make easy access to the object from the other environment.
   10628           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10629          15 :   CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
   10630             : 
   10631             :   v8::Local<Value> value;
   10632             : 
   10633             :   // Check that the named access-control function is called every time.
   10634             :   CompileRun("function testProp(obj) {"
   10635             :              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   10636             :              "  for (var j = 0; j < 10; j++) obj.prop;"
   10637             :              "  return obj.prop"
   10638             :              "}");
   10639             :   value = CompileRun("testProp(obj)");
   10640           5 :   CHECK(value->IsNumber());
   10641          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10642           5 :   CHECK_EQ(21, access_count);
   10643             : 
   10644             :   // Check that the named access-control function is called every time.
   10645             :   CompileRun("var p = 'prop';"
   10646             :              "function testKeyed(obj) {"
   10647             :              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   10648             :              "  for (var j = 0; j < 10; j++) obj[p];"
   10649             :              "  return obj[p];"
   10650             :              "}");
   10651             :   // Use obj which requires access checks.  No inline caching is used
   10652             :   // in that case.
   10653             :   value = CompileRun("testKeyed(obj)");
   10654           5 :   CHECK(value->IsNumber());
   10655          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10656           5 :   CHECK_EQ(42, access_count);
   10657             :   // Force the inline caches into generic state and try again.
   10658             :   CompileRun("testKeyed({ a: 0 })");
   10659             :   CompileRun("testKeyed({ b: 0 })");
   10660             :   value = CompileRun("testKeyed(obj)");
   10661           5 :   CHECK(value->IsNumber());
   10662          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10663           5 :   CHECK_EQ(63, access_count);
   10664             : 
   10665             :   // Check that the indexed access-control function is called every time.
   10666           5 :   access_count = 0;
   10667             : 
   10668             :   CompileRun("function testIndexed(obj) {"
   10669             :              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   10670             :              "  for (var j = 0; j < 10; j++) obj[0];"
   10671             :              "  return obj[0]"
   10672             :              "}");
   10673             :   value = CompileRun("testIndexed(obj)");
   10674           5 :   CHECK(value->IsNumber());
   10675          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10676           5 :   CHECK_EQ(21, access_count);
   10677             :   // Force the inline caches into generic state.
   10678             :   CompileRun("testIndexed(new Array(1))");
   10679             :   // Test that the indexed access check is called.
   10680             :   value = CompileRun("testIndexed(obj)");
   10681           5 :   CHECK(value->IsNumber());
   10682          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10683           5 :   CHECK_EQ(42, access_count);
   10684             : 
   10685           5 :   access_count = 0;
   10686             :   // Check that the named access check is called when invoking
   10687             :   // functions on an object that requires access checks.
   10688             :   CompileRun("obj.f = function() {}");
   10689             :   CompileRun("function testCallNormal(obj) {"
   10690             :              "  for (var i = 0; i < 10; i++) obj.f();"
   10691             :              "}");
   10692             :   CompileRun("testCallNormal(obj)");
   10693           5 :   printf("%i\n", access_count);
   10694           5 :   CHECK_EQ(11, access_count);
   10695             : 
   10696             :   // Force obj into slow case.
   10697             :   value = CompileRun("delete obj.prop");
   10698           5 :   CHECK(value->BooleanValue(isolate));
   10699             :   // Force inline caches into dictionary probing mode.
   10700             :   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   10701             :   // Test that the named access check is called.
   10702             :   value = CompileRun("testProp(obj);");
   10703           5 :   CHECK(value->IsNumber());
   10704          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10705           5 :   CHECK_EQ(33, access_count);
   10706             : 
   10707             :   // Force the call inline cache into dictionary probing mode.
   10708             :   CompileRun("o.f = function() {}; testCallNormal(o)");
   10709             :   // Test that the named access check is still called for each
   10710             :   // invocation of the function.
   10711             :   value = CompileRun("testCallNormal(obj)");
   10712           5 :   CHECK_EQ(43, access_count);
   10713             : 
   10714           5 :   context1->Exit();
   10715           5 :   context0->Exit();
   10716           5 : }
   10717             : 
   10718             : 
   10719       26645 : THREADED_TEST(Version) { v8::V8::GetVersion(); }
   10720             : 
   10721             : 
   10722          18 : static void InstanceFunctionCallback(
   10723             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10724          18 :   ApiTestFuzzer::Fuzz();
   10725          18 :   args.GetReturnValue().Set(v8_num(12));
   10726          18 : }
   10727             : 
   10728             : 
   10729       26645 : THREADED_TEST(InstanceProperties) {
   10730           6 :   LocalContext context;
   10731           6 :   v8::Isolate* isolate = context->GetIsolate();
   10732          12 :   v8::HandleScope handle_scope(isolate);
   10733             : 
   10734           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10735           6 :   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10736             : 
   10737          18 :   instance->Set(v8_str("x"), v8_num(42));
   10738          18 :   instance->Set(v8_str("f"),
   10739           6 :                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
   10740             : 
   10741           6 :   Local<Value> o = t->GetFunction(context.local())
   10742             :                        .ToLocalChecked()
   10743             :                        ->NewInstance(context.local())
   10744             :                        .ToLocalChecked();
   10745             : 
   10746          24 :   CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
   10747             :   Local<Value> value = CompileRun("i.x");
   10748          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10749             : 
   10750             :   value = CompileRun("i.f()");
   10751          12 :   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10752           6 : }
   10753             : 
   10754             : 
   10755         696 : static void GlobalObjectInstancePropertiesGet(
   10756             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
   10757         696 :   ApiTestFuzzer::Fuzz();
   10758         696 : }
   10759             : 
   10760             : 
   10761       26645 : THREADED_TEST(GlobalObjectInstanceProperties) {
   10762           6 :   v8::Isolate* isolate = CcTest::isolate();
   10763          12 :   v8::HandleScope handle_scope(isolate);
   10764             : 
   10765             :   Local<Value> global_object;
   10766             : 
   10767           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10768          12 :   t->InstanceTemplate()->SetHandler(
   10769           6 :       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
   10770           6 :   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10771          18 :   instance_template->Set(v8_str("x"), v8_num(42));
   10772          18 :   instance_template->Set(v8_str("f"),
   10773             :                          v8::FunctionTemplate::New(isolate,
   10774           6 :                                                    InstanceFunctionCallback));
   10775             : 
   10776             :   // The script to check how TurboFan compiles missing global function
   10777             :   // invocations.  function g is not defined and should throw on call.
   10778             :   const char* script =
   10779             :       "function wrapper(call) {"
   10780             :       "  var x = 0, y = 1;"
   10781             :       "  for (var i = 0; i < 1000; i++) {"
   10782             :       "    x += i * 100;"
   10783             :       "    y += i * 100;"
   10784             :       "  }"
   10785             :       "  if (call) g();"
   10786             :       "}"
   10787             :       "for (var i = 0; i < 17; i++) wrapper(false);"
   10788             :       "var thrown = 0;"
   10789             :       "try { wrapper(true); } catch (e) { thrown = 1; };"
   10790             :       "thrown";
   10791             : 
   10792             :   {
   10793           6 :     LocalContext env(nullptr, instance_template);
   10794             :     // Hold on to the global object so it can be used again in another
   10795             :     // environment initialization.
   10796           6 :     global_object = env->Global();
   10797             : 
   10798             :     Local<Value> value = CompileRun("x");
   10799          12 :     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10800             :     value = CompileRun("f()");
   10801          12 :     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10802             :     value = CompileRun(script);
   10803          12 :     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10804             :   }
   10805             : 
   10806             :   {
   10807             :     // Create new environment reusing the global object.
   10808           6 :     LocalContext env(nullptr, instance_template, global_object);
   10809             :     Local<Value> value = CompileRun("x");
   10810          12 :     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10811             :     value = CompileRun("f()");
   10812          12 :     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10813             :     value = CompileRun(script);
   10814          12 :     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10815             :   }
   10816           6 : }
   10817             : 
   10818       26645 : THREADED_TEST(ObjectGetOwnPropertyNames) {
   10819           6 :   LocalContext context;
   10820           6 :   v8::Isolate* isolate = context->GetIsolate();
   10821          12 :   v8::HandleScope handle_scope(isolate);
   10822             : 
   10823             :   v8::Local<v8::Object> value = v8::Local<v8::Object>::Cast(
   10824           6 :       v8::StringObject::New(CcTest::isolate(), v8_str("test")));
   10825             :   v8::Local<v8::Array> properties;
   10826             : 
   10827          12 :   CHECK(value
   10828             :             ->GetOwnPropertyNames(context.local(),
   10829             :                                   static_cast<v8::PropertyFilter>(
   10830             :                                       v8::PropertyFilter::ALL_PROPERTIES |
   10831             :                                       v8::PropertyFilter::SKIP_SYMBOLS),
   10832             :                                   v8::KeyConversionMode::kKeepNumbers)
   10833             :             .ToLocal(&properties));
   10834           6 :   CHECK_EQ(5u, properties->Length());
   10835             :   v8::Local<v8::Value> property;
   10836          18 :   CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
   10837             :         property->IsString());
   10838          18 :   CHECK(property.As<v8::String>()
   10839             :             ->Equals(context.local(), v8_str("length"))
   10840             :             .FromMaybe(false));
   10841          54 :   for (int i = 0; i < 4; ++i) {
   10842             :     v8::Local<v8::Value> property;
   10843          72 :     CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
   10844             :           property->IsInt32());
   10845          24 :     CHECK_EQ(property.As<v8::Int32>()->Value(), i);
   10846             :   }
   10847             : 
   10848          12 :   CHECK(value
   10849             :             ->GetOwnPropertyNames(context.local(),
   10850             :                                   v8::PropertyFilter::ONLY_ENUMERABLE,
   10851             :                                   v8::KeyConversionMode::kKeepNumbers)
   10852             :             .ToLocal(&properties));
   10853             :   v8::Local<v8::Array> number_properties;
   10854          12 :   CHECK(value
   10855             :             ->GetOwnPropertyNames(context.local(),
   10856             :                                   v8::PropertyFilter::ONLY_ENUMERABLE,
   10857             :                                   v8::KeyConversionMode::kConvertToString)
   10858             :             .ToLocal(&number_properties));
   10859           6 :   CHECK_EQ(4u, properties->Length());
   10860          54 :   for (int i = 0; i < 4; ++i) {
   10861             :     v8::Local<v8::Value> property_index;
   10862             :     v8::Local<v8::Value> property_name;
   10863             : 
   10864          72 :     CHECK(number_properties->Get(context.local(), i).ToLocal(&property_name));
   10865          24 :     CHECK(property_name->IsString());
   10866             : 
   10867          48 :     CHECK(properties->Get(context.local(), i).ToLocal(&property_index));
   10868          24 :     CHECK(property_index->IsInt32());
   10869             : 
   10870          24 :     CHECK_EQ(property_index.As<v8::Int32>()->Value(), i);
   10871          48 :     CHECK_EQ(property_name->ToNumber(context.local())
   10872             :                  .ToLocalChecked()
   10873             :                  .As<v8::Int32>()
   10874             :                  ->Value(),
   10875             :              i);
   10876             :   }
   10877             : 
   10878           6 :   value = value->GetPrototype().As<v8::Object>();
   10879          12 :   CHECK(value
   10880             :             ->GetOwnPropertyNames(context.local(),
   10881             :                                   static_cast<v8::PropertyFilter>(
   10882             :                                       v8::PropertyFilter::ALL_PROPERTIES |
   10883             :                                       v8::PropertyFilter::SKIP_SYMBOLS))
   10884             :             .ToLocal(&properties));
   10885             :   bool concat_found = false;
   10886             :   bool starts_with_found = false;
   10887         582 :   for (uint32_t i = 0; i < properties->Length(); ++i) {
   10888             :     v8::Local<v8::Value> property;
   10889         576 :     CHECK(properties->Get(context.local(), i).ToLocal(&property));
   10890         288 :     if (!property->IsString()) continue;
   10891         288 :     if (!concat_found)
   10892             :       concat_found = property.As<v8::String>()
   10893         180 :                          ->Equals(context.local(), v8_str("concat"))
   10894             :                          .FromMaybe(false);
   10895         288 :     if (!starts_with_found)
   10896             :       starts_with_found = property.As<v8::String>()
   10897         648 :                               ->Equals(context.local(), v8_str("startsWith"))
   10898             :                               .FromMaybe(false);
   10899             :   }
   10900           6 :   CHECK(concat_found && starts_with_found);
   10901           6 : }
   10902             : 
   10903       26645 : THREADED_TEST(CallKnownGlobalReceiver) {
   10904           6 :   v8::Isolate* isolate = CcTest::isolate();
   10905          12 :   v8::HandleScope handle_scope(isolate);
   10906             : 
   10907             :   Local<Value> global_object;
   10908             : 
   10909           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10910           6 :   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10911             : 
   10912             :   // The script to check that we leave global object not
   10913             :   // global object proxy on stack when we deoptimize from inside
   10914             :   // arguments evaluation.
   10915             :   // To provoke error we need to both force deoptimization
   10916             :   // from arguments evaluation and to force CallIC to take
   10917             :   // CallIC_Miss code path that can't cope with global proxy.
   10918             :   const char* script =
   10919             :       "function bar(x, y) { try { } finally { } }"
   10920             :       "function baz(x) { try { } finally { } }"
   10921             :       "function bom(x) { try { } finally { } }"
   10922             :       "function foo(x) { bar([x], bom(2)); }"
   10923             :       "for (var i = 0; i < 10000; i++) foo(1);"
   10924             :       "foo";
   10925             : 
   10926             :   Local<Value> foo;
   10927             :   {
   10928           6 :     LocalContext env(nullptr, instance_template);
   10929             :     // Hold on to the global object so it can be used again in another
   10930             :     // environment initialization.
   10931           6 :     global_object = env->Global();
   10932           6 :     foo = CompileRun(script);
   10933             :   }
   10934             : 
   10935             :   {
   10936             :     // Create new environment reusing the global object.
   10937           6 :     LocalContext env(nullptr, instance_template, global_object);
   10938          24 :     CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
   10939             :     CompileRun("foo()");
   10940             :   }
   10941           6 : }
   10942             : 
   10943             : 
   10944           6 : static void ShadowFunctionCallback(
   10945             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10946           6 :   ApiTestFuzzer::Fuzz();
   10947           6 :   args.GetReturnValue().Set(v8_num(42));
   10948           6 : }
   10949             : 
   10950             : 
   10951             : static int shadow_y;
   10952             : static int shadow_y_setter_call_count;
   10953             : static int shadow_y_getter_call_count;
   10954             : 
   10955             : 
   10956           6 : static void ShadowYSetter(Local<String>,
   10957             :                           Local<Value>,
   10958             :                           const v8::PropertyCallbackInfo<void>&) {
   10959           6 :   shadow_y_setter_call_count++;
   10960           6 :   shadow_y = 42;
   10961           6 : }
   10962             : 
   10963             : 
   10964           6 : static void ShadowYGetter(Local<String> name,
   10965             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   10966           6 :   ApiTestFuzzer::Fuzz();
   10967           6 :   shadow_y_getter_call_count++;
   10968           6 :   info.GetReturnValue().Set(v8_num(shadow_y));
   10969           6 : }
   10970             : 
   10971             : 
   10972           0 : static void ShadowIndexedGet(uint32_t index,
   10973             :                              const v8::PropertyCallbackInfo<v8::Value>&) {
   10974           0 : }
   10975             : 
   10976             : 
   10977          42 : static void ShadowNamedGet(Local<Name> key,
   10978          42 :                            const v8::PropertyCallbackInfo<v8::Value>&) {}
   10979             : 
   10980       26645 : THREADED_TEST(ShadowObject) {
   10981           6 :   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   10982           6 :   v8::Isolate* isolate = CcTest::isolate();
   10983          12 :   v8::HandleScope handle_scope(isolate);
   10984             : 
   10985           6 :   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   10986           6 :   LocalContext context(nullptr, global_template);
   10987             : 
   10988           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10989          12 :   t->InstanceTemplate()->SetHandler(
   10990           6 :       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   10991          12 :   t->InstanceTemplate()->SetHandler(
   10992           6 :       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
   10993           6 :   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   10994           6 :   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10995             : 
   10996          18 :   proto->Set(v8_str("f"),
   10997             :              v8::FunctionTemplate::New(isolate,
   10998             :                                        ShadowFunctionCallback,
   10999           6 :                                        Local<Value>()));
   11000          18 :   proto->Set(v8_str("x"), v8_num(12));
   11001             : 
   11002          12 :   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   11003             : 
   11004           6 :   Local<Value> o = t->GetFunction(context.local())
   11005             :                        .ToLocalChecked()
   11006             :                        ->NewInstance(context.local())
   11007             :                        .ToLocalChecked();
   11008          24 :   CHECK(context->Global()
   11009             :             ->Set(context.local(), v8_str("__proto__"), o)
   11010             :             .FromJust());
   11011             : 
   11012             :   Local<Value> value =
   11013             :       CompileRun("this.propertyIsEnumerable(0)");
   11014           6 :   CHECK(value->IsBoolean());
   11015           6 :   CHECK(!value->BooleanValue(isolate));
   11016             : 
   11017             :   value = CompileRun("x");
   11018          12 :   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   11019             : 
   11020             :   value = CompileRun("f()");
   11021          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11022             : 
   11023             :   CompileRun("y = 43");
   11024           6 :   CHECK_EQ(1, shadow_y_setter_call_count);
   11025             :   value = CompileRun("y");
   11026           6 :   CHECK_EQ(1, shadow_y_getter_call_count);
   11027          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11028           6 : }
   11029             : 
   11030       26645 : THREADED_TEST(ShadowObjectAndDataProperty) {
   11031             :   // Lite mode doesn't make use of feedback vectors, which is what we
   11032             :   // want to ensure has the correct form.
   11033             :   if (i::FLAG_lite_mode) return;
   11034             :   // This test mimics the kind of shadow property the Chromium embedder
   11035             :   // uses for undeclared globals. The IC subsystem has special handling
   11036             :   // for this case, using a PREMONOMORPHIC state to delay entering
   11037             :   // MONOMORPHIC state until enough information is available to support
   11038             :   // efficient access and good feedback for optimization.
   11039           6 :   v8::Isolate* isolate = CcTest::isolate();
   11040          12 :   v8::HandleScope handle_scope(isolate);
   11041             : 
   11042           6 :   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   11043           6 :   LocalContext context(nullptr, global_template);
   11044             : 
   11045           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11046          12 :   t->InstanceTemplate()->SetHandler(
   11047           6 :       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   11048             : 
   11049           6 :   Local<Value> o = t->GetFunction(context.local())
   11050             :                        .ToLocalChecked()
   11051             :                        ->NewInstance(context.local())
   11052             :                        .ToLocalChecked();
   11053          24 :   CHECK(context->Global()
   11054             :             ->Set(context.local(), v8_str("__proto__"), o)
   11055             :             .FromJust());
   11056             : 
   11057             :   CompileRun(
   11058             :       "function foo(x) { i = x; }"
   11059             :       "foo(0)");
   11060             : 
   11061             :   i::Handle<i::JSFunction> foo(i::Handle<i::JSFunction>::cast(
   11062          12 :       v8::Utils::OpenHandle(*context->Global()
   11063          18 :                                  ->Get(context.local(), v8_str("foo"))
   11064             :                                  .ToLocalChecked())));
   11065           6 :   CHECK(foo->has_feedback_vector());
   11066             :   i::FeedbackSlot slot = i::FeedbackVector::ToSlot(0);
   11067             :   i::FeedbackNexus nexus(foo->feedback_vector(), slot);
   11068           6 :   CHECK_EQ(i::FeedbackSlotKind::kStoreGlobalSloppy, nexus.kind());
   11069           6 :   CHECK_EQ(i::PREMONOMORPHIC, nexus.ic_state());
   11070             :   CompileRun("foo(1)");
   11071           6 :   CHECK_EQ(i::MONOMORPHIC, nexus.ic_state());
   11072             :   // We go a bit further, checking that the form of monomorphism is
   11073             :   // a PropertyCell in the vector. This is because we want to make sure
   11074             :   // we didn't settle for a "poor man's monomorphism," such as a
   11075             :   // slow_stub bailout which would mean a trip to the runtime on all
   11076             :   // subsequent stores, and a lack of feedback for the optimizing
   11077             :   // compiler downstream.
   11078             :   i::HeapObject heap_object;
   11079          12 :   CHECK(nexus.GetFeedback().GetHeapObject(&heap_object));
   11080           6 :   CHECK(heap_object->IsPropertyCell());
   11081             : }
   11082             : 
   11083       26645 : THREADED_TEST(ShadowObjectAndDataPropertyTurbo) {
   11084             :   // This test is the same as the previous one except that it triggers
   11085             :   // optimization of {foo} after its first invocation.
   11086           6 :   i::FLAG_allow_natives_syntax = true;
   11087             : 
   11088             :   if (i::FLAG_lite_mode) return;
   11089           6 :   v8::Isolate* isolate = CcTest::isolate();
   11090          12 :   v8::HandleScope handle_scope(isolate);
   11091             : 
   11092           6 :   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   11093           6 :   LocalContext context(nullptr, global_template);
   11094             : 
   11095           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11096          12 :   t->InstanceTemplate()->SetHandler(
   11097           6 :       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   11098             : 
   11099           6 :   Local<Value> o = t->GetFunction(context.local())
   11100             :                        .ToLocalChecked()
   11101             :                        ->NewInstance(context.local())
   11102             :                        .ToLocalChecked();
   11103          24 :   CHECK(context->Global()
   11104             :             ->Set(context.local(), v8_str("__proto__"), o)
   11105             :             .FromJust());
   11106             : 
   11107             :   CompileRun(
   11108             :       "function foo(x) { i = x; }"
   11109             :       "foo(0)");
   11110             : 
   11111             :   i::Handle<i::JSFunction> foo(i::Handle<i::JSFunction>::cast(
   11112          12 :       v8::Utils::OpenHandle(*context->Global()
   11113          18 :                                  ->Get(context.local(), v8_str("foo"))
   11114             :                                  .ToLocalChecked())));
   11115           6 :   CHECK(foo->has_feedback_vector());
   11116             :   i::FeedbackSlot slot = i::FeedbackVector::ToSlot(0);
   11117             :   i::FeedbackNexus nexus(foo->feedback_vector(), slot);
   11118           6 :   CHECK_EQ(i::FeedbackSlotKind::kStoreGlobalSloppy, nexus.kind());
   11119           6 :   CHECK_EQ(i::PREMONOMORPHIC, nexus.ic_state());
   11120             :   CompileRun("%OptimizeFunctionOnNextCall(foo); foo(1)");
   11121           6 :   CHECK_EQ(i::MONOMORPHIC, nexus.ic_state());
   11122             :   i::HeapObject heap_object;
   11123          12 :   CHECK(nexus.GetFeedback().GetHeapObject(&heap_object));
   11124           6 :   CHECK(heap_object->IsPropertyCell());
   11125             : }
   11126             : 
   11127       26645 : THREADED_TEST(SetPrototype) {
   11128           6 :   LocalContext context;
   11129           6 :   v8::Isolate* isolate = context->GetIsolate();
   11130          12 :   v8::HandleScope handle_scope(isolate);
   11131             : 
   11132           6 :   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   11133          24 :   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   11134           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11135          24 :   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   11136           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11137          24 :   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   11138           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11139          24 :   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   11140             : 
   11141           6 :   Local<v8::Object> o0 = t0->GetFunction(context.local())
   11142             :                              .ToLocalChecked()
   11143             :                              ->NewInstance(context.local())
   11144             :                              .ToLocalChecked();
   11145           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11146             :                              .ToLocalChecked()
   11147             :                              ->NewInstance(context.local())
   11148             :                              .ToLocalChecked();
   11149           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11150             :                              .ToLocalChecked()
   11151             :                              ->NewInstance(context.local())
   11152             :                              .ToLocalChecked();
   11153           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11154             :                              .ToLocalChecked()
   11155             :                              ->NewInstance(context.local())
   11156             :                              .ToLocalChecked();
   11157             : 
   11158          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11159             :                   .ToLocalChecked()
   11160             :                   ->Int32Value(context.local())
   11161             :                   .FromJust());
   11162          12 :   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   11163          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11164             :                   .ToLocalChecked()
   11165             :                   ->Int32Value(context.local())
   11166             :                   .FromJust());
   11167          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11168             :                   .ToLocalChecked()
   11169             :                   ->Int32Value(context.local())
   11170             :                   .FromJust());
   11171          12 :   CHECK(o1->SetPrototype(context.local(), o2).FromJust());
   11172          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11173             :                   .ToLocalChecked()
   11174             :                   ->Int32Value(context.local())
   11175             :                   .FromJust());
   11176          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11177             :                   .ToLocalChecked()
   11178             :                   ->Int32Value(context.local())
   11179             :                   .FromJust());
   11180          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   11181             :                   .ToLocalChecked()
   11182             :                   ->Int32Value(context.local())
   11183             :                   .FromJust());
   11184          12 :   CHECK(o2->SetPrototype(context.local(), o3).FromJust());
   11185          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11186             :                   .ToLocalChecked()
   11187             :                   ->Int32Value(context.local())
   11188             :                   .FromJust());
   11189          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11190             :                   .ToLocalChecked()
   11191             :                   ->Int32Value(context.local())
   11192             :                   .FromJust());
   11193          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   11194             :                   .ToLocalChecked()
   11195             :                   ->Int32Value(context.local())
   11196             :                   .FromJust());
   11197          24 :   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   11198             :                   .ToLocalChecked()
   11199             :                   ->Int32Value(context.local())
   11200             :                   .FromJust());
   11201             : 
   11202             :   Local<Value> proto =
   11203          18 :       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   11204           6 :   CHECK(proto->IsObject());
   11205          12 :   CHECK(proto.As<v8::Object>()->Equals(context.local(), o1).FromJust());
   11206             : 
   11207           6 :   Local<Value> proto0 = o0->GetPrototype();
   11208           6 :   CHECK(proto0->IsObject());
   11209          12 :   CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
   11210             : 
   11211           6 :   Local<Value> proto1 = o1->GetPrototype();
   11212           6 :   CHECK(proto1->IsObject());
   11213          12 :   CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
   11214             : 
   11215           6 :   Local<Value> proto2 = o2->GetPrototype();
   11216           6 :   CHECK(proto2->IsObject());
   11217          12 :   CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   11218           6 : }
   11219             : 
   11220             : 
   11221             : // Getting property names of an object with a prototype chain that
   11222             : // triggers dictionary elements in GetOwnPropertyNames() shouldn't
   11223             : // crash the runtime.
   11224       26645 : THREADED_TEST(Regress91517) {
   11225           6 :   i::FLAG_allow_natives_syntax = true;
   11226           6 :   LocalContext context;
   11227           6 :   v8::Isolate* isolate = context->GetIsolate();
   11228          12 :   v8::HandleScope handle_scope(isolate);
   11229             : 
   11230           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11231          24 :   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   11232           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11233          24 :   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   11234          24 :   t2->InstanceTemplate()->Set(v8_str("objects"),
   11235           6 :                               v8::ObjectTemplate::New(isolate));
   11236          24 :   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   11237           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11238          24 :   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   11239           6 :   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
   11240          24 :   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   11241             : 
   11242             :   // Force dictionary-based properties.
   11243             :   i::ScopedVector<char> name_buf(1024);
   11244       12006 :   for (int i = 1; i <= 1000; i++) {
   11245        6000 :     i::SNPrintF(name_buf, "sdf%d", i);
   11246       24000 :     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   11247             :   }
   11248             : 
   11249           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11250             :                              .ToLocalChecked()
   11251             :                              ->NewInstance(context.local())
   11252             :                              .ToLocalChecked();
   11253           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11254             :                              .ToLocalChecked()
   11255             :                              ->NewInstance(context.local())
   11256             :                              .ToLocalChecked();
   11257           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11258             :                              .ToLocalChecked()
   11259             :                              ->NewInstance(context.local())
   11260             :                              .ToLocalChecked();
   11261           6 :   Local<v8::Object> o4 = t4->GetFunction(context.local())
   11262             :                              .ToLocalChecked()
   11263             :                              ->NewInstance(context.local())
   11264             :                              .ToLocalChecked();
   11265             : 
   11266          12 :   CHECK(o4->SetPrototype(context.local(), o3).FromJust());
   11267          12 :   CHECK(o3->SetPrototype(context.local(), o2).FromJust());
   11268          12 :   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   11269             : 
   11270             :   // Call the runtime version of GetOwnPropertyNames() on the natively
   11271             :   // created object through JavaScript.
   11272          24 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
   11273             :   // PROPERTY_FILTER_NONE = 0
   11274             :   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   11275             : 
   11276           6 :   ExpectInt32("names.length", 1);
   11277             :   ExpectTrue("names.indexOf(\"baz\") >= 0");
   11278             :   ExpectFalse("names.indexOf(\"boo\") >= 0");
   11279             :   ExpectFalse("names.indexOf(\"foo\") >= 0");
   11280             :   ExpectFalse("names.indexOf(\"fuz1\") >= 0");
   11281             :   ExpectFalse("names.indexOf(\"objects\") >= 0");
   11282             :   ExpectFalse("names.indexOf(\"fuz2\") >= 0");
   11283             :   ExpectTrue("names[1005] == undefined");
   11284           6 : }
   11285             : 
   11286             : 
   11287       26645 : THREADED_TEST(FunctionReadOnlyPrototype) {
   11288           6 :   LocalContext context;
   11289           6 :   v8::Isolate* isolate = context->GetIsolate();
   11290          12 :   v8::HandleScope handle_scope(isolate);
   11291             : 
   11292           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11293          24 :   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11294           6 :   t1->ReadOnlyPrototype();
   11295          30 :   CHECK(context->Global()
   11296             :             ->Set(context.local(), v8_str("func1"),
   11297             :                   t1->GetFunction(context.local()).ToLocalChecked())
   11298             :             .FromJust());
   11299             :   // Configured value of ReadOnly flag.
   11300           6 :   CHECK(
   11301             :       CompileRun(
   11302             :           "(function() {"
   11303             :           "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   11304             :           "  return (descriptor['writable'] == false);"
   11305             :           "})()")
   11306             :           ->BooleanValue(isolate));
   11307          12 :   CHECK_EQ(
   11308             :       42,
   11309             :       CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
   11310          12 :   CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
   11311             :                    ->Int32Value(context.local())
   11312             :                    .FromJust());
   11313             : 
   11314           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11315          24 :   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11316          30 :   CHECK(context->Global()
   11317             :             ->Set(context.local(), v8_str("func2"),
   11318             :                   t2->GetFunction(context.local()).ToLocalChecked())
   11319             :             .FromJust());
   11320             :   // Default value of ReadOnly flag.
   11321           6 :   CHECK(
   11322             :       CompileRun(
   11323             :           "(function() {"
   11324             :           "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   11325             :           "  return (descriptor['writable'] == true);"
   11326             :           "})()")
   11327             :           ->BooleanValue(isolate));
   11328          12 :   CHECK_EQ(
   11329             :       42,
   11330             :       CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
   11331           6 : }
   11332             : 
   11333             : 
   11334       26645 : THREADED_TEST(SetPrototypeThrows) {
   11335           6 :   LocalContext context;
   11336           6 :   v8::Isolate* isolate = context->GetIsolate();
   11337          12 :   v8::HandleScope handle_scope(isolate);
   11338             : 
   11339           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11340             : 
   11341           6 :   Local<v8::Object> o0 = t->GetFunction(context.local())
   11342             :                              .ToLocalChecked()
   11343             :                              ->NewInstance(context.local())
   11344             :                              .ToLocalChecked();
   11345           6 :   Local<v8::Object> o1 = t->GetFunction(context.local())
   11346             :                              .ToLocalChecked()
   11347             :                              ->NewInstance(context.local())
   11348             :                              .ToLocalChecked();
   11349             : 
   11350          12 :   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   11351             :   // If setting the prototype leads to the cycle, SetPrototype should
   11352             :   // return false and keep VM in sane state.
   11353          12 :   v8::TryCatch try_catch(isolate);
   11354          12 :   CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
   11355           6 :   CHECK(!try_catch.HasCaught());
   11356           6 :   CHECK(!CcTest::i_isolate()->has_pending_exception());
   11357             : 
   11358          12 :   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
   11359             :                    ->Int32Value(context.local())
   11360             :                    .FromJust());
   11361           6 : }
   11362             : 
   11363             : 
   11364       26645 : THREADED_TEST(FunctionRemovePrototype) {
   11365           6 :   LocalContext context;
   11366           6 :   v8::Isolate* isolate = context->GetIsolate();
   11367          12 :   v8::HandleScope handle_scope(isolate);
   11368             : 
   11369           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11370           6 :   t1->RemovePrototype();
   11371           6 :   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
   11372           6 :   CHECK(!fun->IsConstructor());
   11373          24 :   CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
   11374           6 :   CHECK(!CompileRun("'prototype' in fun")->BooleanValue(isolate));
   11375             : 
   11376          12 :   v8::TryCatch try_catch(isolate);
   11377             :   CompileRun("new fun()");
   11378           6 :   CHECK(try_catch.HasCaught());
   11379             : 
   11380           6 :   try_catch.Reset();
   11381           6 :   CHECK(fun->NewInstance(context.local()).IsEmpty());
   11382           6 :   CHECK(try_catch.HasCaught());
   11383           6 : }
   11384             : 
   11385             : 
   11386       26645 : THREADED_TEST(GetterSetterExceptions) {
   11387           6 :   LocalContext context;
   11388           6 :   v8::Isolate* isolate = context->GetIsolate();
   11389          12 :   v8::HandleScope handle_scope(isolate);
   11390             :   CompileRun(
   11391             :       "function Foo() { };"
   11392             :       "function Throw() { throw 5; };"
   11393             :       "var x = { };"
   11394             :       "x.__defineSetter__('set', Throw);"
   11395             :       "x.__defineGetter__('get', Throw);");
   11396             :   Local<v8::Object> x = Local<v8::Object>::Cast(
   11397          24 :       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
   11398          12 :   v8::TryCatch try_catch(isolate);
   11399          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11400             :             .IsNothing());
   11401          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11402          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11403             :             .IsNothing());
   11404          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11405          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11406             :             .IsNothing());
   11407          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11408          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11409             :             .IsNothing());
   11410          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11411           6 : }
   11412             : 
   11413             : 
   11414       26645 : THREADED_TEST(Constructor) {
   11415           6 :   LocalContext context;
   11416           6 :   v8::Isolate* isolate = context->GetIsolate();
   11417          12 :   v8::HandleScope handle_scope(isolate);
   11418           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11419           6 :   templ->SetClassName(v8_str("Fun"));
   11420           6 :   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11421          24 :   CHECK(
   11422             :       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11423             :   Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
   11424             :   i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
   11425           6 :   CHECK(obj->IsJSObject());
   11426             :   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   11427           6 :   CHECK(value->BooleanValue(isolate));
   11428           6 : }
   11429             : 
   11430             : 
   11431       26645 : THREADED_TEST(FunctionDescriptorException) {
   11432           6 :   LocalContext context;
   11433           6 :   v8::Isolate* isolate = context->GetIsolate();
   11434          12 :   v8::HandleScope handle_scope(isolate);
   11435           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11436           6 :   templ->SetClassName(v8_str("Fun"));
   11437           6 :   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11438          24 :   CHECK(
   11439             :       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11440             :   Local<Value> value = CompileRun(
   11441             :       "function test() {"
   11442             :       "  try {"
   11443             :       "    (new Fun()).blah()"
   11444             :       "  } catch (e) {"
   11445             :       "    var str = String(e);"
   11446             :       // "    if (str.indexOf('TypeError') == -1) return 1;"
   11447             :       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
   11448             :       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
   11449             :       "    return 0;"
   11450             :       "  }"
   11451             :       "  return 4;"
   11452             :       "}"
   11453             :       "test();");
   11454          12 :   CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
   11455           6 : }
   11456             : 
   11457             : 
   11458       26645 : THREADED_TEST(EvalAliasedDynamic) {
   11459           6 :   LocalContext current;
   11460          12 :   v8::HandleScope scope(current->GetIsolate());
   11461             : 
   11462             :   // Tests where aliased eval can only be resolved dynamically.
   11463             :   Local<Script> script = v8_compile(
   11464             :       "function f(x) { "
   11465             :       "  var foo = 2;"
   11466             :       "  with (x) { return eval('foo'); }"
   11467             :       "}"
   11468             :       "foo = 0;"
   11469             :       "result1 = f(new Object());"
   11470             :       "result2 = f(this);"
   11471             :       "var x = new Object();"
   11472             :       "x.eval = function(x) { return 1; };"
   11473             :       "result3 = f(x);");
   11474           6 :   script->Run(current.local()).ToLocalChecked();
   11475          30 :   CHECK_EQ(2, current->Global()
   11476             :                   ->Get(current.local(), v8_str("result1"))
   11477             :                   .ToLocalChecked()
   11478             :                   ->Int32Value(current.local())
   11479             :                   .FromJust());
   11480          30 :   CHECK_EQ(0, current->Global()
   11481             :                   ->Get(current.local(), v8_str("result2"))
   11482             :                   .ToLocalChecked()
   11483             :                   ->Int32Value(current.local())
   11484             :                   .FromJust());
   11485          30 :   CHECK_EQ(1, current->Global()
   11486             :                   ->Get(current.local(), v8_str("result3"))
   11487             :                   .ToLocalChecked()
   11488             :                   ->Int32Value(current.local())
   11489             :                   .FromJust());
   11490             : 
   11491          12 :   v8::TryCatch try_catch(current->GetIsolate());
   11492             :   script = v8_compile(
   11493             :       "function f(x) { "
   11494             :       "  var bar = 2;"
   11495             :       "  with (x) { return eval('bar'); }"
   11496             :       "}"
   11497             :       "result4 = f(this)");
   11498           6 :   script->Run(current.local()).ToLocalChecked();
   11499           6 :   CHECK(!try_catch.HasCaught());
   11500          30 :   CHECK_EQ(2, current->Global()
   11501             :                   ->Get(current.local(), v8_str("result4"))
   11502             :                   .ToLocalChecked()
   11503             :                   ->Int32Value(current.local())
   11504             :                   .FromJust());
   11505             : 
   11506           6 :   try_catch.Reset();
   11507           6 : }
   11508             : 
   11509             : 
   11510       26645 : THREADED_TEST(CrossEval) {
   11511          12 :   v8::HandleScope scope(CcTest::isolate());
   11512           6 :   LocalContext other;
   11513           6 :   LocalContext current;
   11514             : 
   11515           6 :   Local<String> token = v8_str("<security token>");
   11516           6 :   other->SetSecurityToken(token);
   11517           6 :   current->SetSecurityToken(token);
   11518             : 
   11519             :   // Set up reference from current to other.
   11520          30 :   CHECK(current->Global()
   11521             :             ->Set(current.local(), v8_str("other"), other->Global())
   11522             :             .FromJust());
   11523             : 
   11524             :   // Check that new variables are introduced in other context.
   11525             :   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
   11526           6 :   script->Run(current.local()).ToLocalChecked();
   11527             :   Local<Value> foo =
   11528          24 :       other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
   11529          12 :   CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
   11530          24 :   CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
   11531             : 
   11532             :   // Check that writing to non-existing properties introduces them in
   11533             :   // the other context.
   11534             :   script = v8_compile("other.eval('na = 1234')");
   11535           6 :   script->Run(current.local()).ToLocalChecked();
   11536          30 :   CHECK_EQ(1234, other->Global()
   11537             :                      ->Get(current.local(), v8_str("na"))
   11538             :                      .ToLocalChecked()
   11539             :                      ->Int32Value(other.local())
   11540             :                      .FromJust());
   11541          24 :   CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
   11542             : 
   11543             :   // Check that global variables in current context are not visible in other
   11544             :   // context.
   11545          12 :   v8::TryCatch try_catch(CcTest::isolate());
   11546             :   script = v8_compile("var bar = 42; other.eval('bar');");
   11547          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11548           6 :   CHECK(try_catch.HasCaught());
   11549           6 :   try_catch.Reset();
   11550             : 
   11551             :   // Check that local variables in current context are not visible in other
   11552             :   // context.
   11553             :   script = v8_compile(
   11554             :       "(function() { "
   11555             :       "  var baz = 87;"
   11556             :       "  return other.eval('baz');"
   11557             :       "})();");
   11558          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11559           6 :   CHECK(try_catch.HasCaught());
   11560           6 :   try_catch.Reset();
   11561             : 
   11562             :   // Check that global variables in the other environment are visible
   11563             :   // when evaluting code.
   11564          24 :   CHECK(other->Global()
   11565             :             ->Set(other.local(), v8_str("bis"), v8_num(1234))
   11566             :             .FromJust());
   11567             :   script = v8_compile("other.eval('bis')");
   11568          18 :   CHECK_EQ(1234, script->Run(current.local())
   11569             :                      .ToLocalChecked()
   11570             :                      ->Int32Value(current.local())
   11571             :                      .FromJust());
   11572           6 :   CHECK(!try_catch.HasCaught());
   11573             : 
   11574             :   // Check that the 'this' pointer points to the global object evaluating
   11575             :   // code.
   11576          30 :   CHECK(other->Global()
   11577             :             ->Set(current.local(), v8_str("t"), other->Global())
   11578             :             .FromJust());
   11579             :   script = v8_compile("other.eval('this == t')");
   11580           6 :   Local<Value> result = script->Run(current.local()).ToLocalChecked();
   11581           6 :   CHECK(result->IsTrue());
   11582           6 :   CHECK(!try_catch.HasCaught());
   11583             : 
   11584             :   // Check that variables introduced in with-statement are not visible in
   11585             :   // other context.
   11586             :   script = v8_compile("with({x:2}){other.eval('x')}");
   11587          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11588           6 :   CHECK(try_catch.HasCaught());
   11589           6 :   try_catch.Reset();
   11590             : 
   11591             :   // Check that you cannot use 'eval.call' with another object than the
   11592             :   // current global object.
   11593             :   script = v8_compile("other.y = 1; eval.call(other, 'y')");
   11594          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11595           6 :   CHECK(try_catch.HasCaught());
   11596           6 : }
   11597             : 
   11598             : 
   11599             : // Test that calling eval in a context which has been detached from
   11600             : // its global proxy works.
   11601       26645 : THREADED_TEST(EvalInDetachedGlobal) {
   11602           6 :   v8::Isolate* isolate = CcTest::isolate();
   11603          12 :   v8::HandleScope scope(isolate);
   11604             : 
   11605           6 :   v8::Local<Context> context0 = Context::New(isolate);
   11606           6 :   v8::Local<Context> context1 = Context::New(isolate);
   11607           6 :   Local<String> token = v8_str("<security token>");
   11608           6 :   context0->SetSecurityToken(token);
   11609           6 :   context1->SetSecurityToken(token);
   11610             : 
   11611             :   // Set up function in context0 that uses eval from context0.
   11612           6 :   context0->Enter();
   11613             :   v8::Local<v8::Value> fun = CompileRun(
   11614             :       "var x = 42;"
   11615             :       "(function() {"
   11616             :       "  var e = eval;"
   11617             :       "  return function(s) { return e(s); }"
   11618           6 :       "})()");
   11619           6 :   context0->Exit();
   11620             : 
   11621             :   // Put the function into context1 and call it before and after
   11622             :   // detaching the global.  Before detaching, the call succeeds and
   11623             :   // after detaching undefined is returned.
   11624           6 :   context1->Enter();
   11625          24 :   CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
   11626             :   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   11627          12 :   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   11628           6 :   context0->DetachGlobal();
   11629             :   x_value = CompileRun("fun('x')");
   11630           6 :   CHECK(x_value->IsUndefined());
   11631           6 :   context1->Exit();
   11632           6 : }
   11633             : 
   11634             : 
   11635       26645 : THREADED_TEST(CrossLazyLoad) {
   11636          12 :   v8::HandleScope scope(CcTest::isolate());
   11637           6 :   LocalContext other;
   11638           6 :   LocalContext current;
   11639             : 
   11640           6 :   Local<String> token = v8_str("<security token>");
   11641           6 :   other->SetSecurityToken(token);
   11642           6 :   current->SetSecurityToken(token);
   11643             : 
   11644             :   // Set up reference from current to other.
   11645          30 :   CHECK(current->Global()
   11646             :             ->Set(current.local(), v8_str("other"), other->Global())
   11647             :             .FromJust());
   11648             : 
   11649             :   // Trigger lazy loading in other context.
   11650             :   Local<Script> script = v8_compile("other.eval('new Date(42)')");
   11651           6 :   Local<Value> value = script->Run(current.local()).ToLocalChecked();
   11652          12 :   CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
   11653           6 : }
   11654             : 
   11655             : 
   11656          48 : static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11657          48 :   ApiTestFuzzer::Fuzz();
   11658          48 :   if (args.IsConstructCall()) {
   11659           6 :     if (args[0]->IsInt32()) {
   11660           6 :       args.GetReturnValue().Set(
   11661             :           v8_num(-args[0]
   11662          18 :                       ->Int32Value(args.GetIsolate()->GetCurrentContext())
   11663             :                       .FromJust()));
   11664           6 :       return;
   11665             :     }
   11666             :   }
   11667             : 
   11668             :   args.GetReturnValue().Set(args[0]);
   11669             : }
   11670             : 
   11671             : 
   11672             : // Test that a call handler can be set for objects which will allow
   11673             : // non-function objects created through the API to be called as
   11674             : // functions.
   11675       26645 : THREADED_TEST(CallAsFunction) {
   11676           6 :   LocalContext context;
   11677           6 :   v8::Isolate* isolate = context->GetIsolate();
   11678          12 :   v8::HandleScope scope(isolate);
   11679             : 
   11680             :   {
   11681           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11682           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11683           6 :     instance_template->SetCallAsFunctionHandler(call_as_function);
   11684           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11685             :                                      .ToLocalChecked()
   11686             :                                      ->NewInstance(context.local())
   11687             :                                      .ToLocalChecked();
   11688          24 :     CHECK(context->Global()
   11689             :               ->Set(context.local(), v8_str("obj"), instance)
   11690             :               .FromJust());
   11691          12 :     v8::TryCatch try_catch(isolate);
   11692             :     Local<Value> value;
   11693           6 :     CHECK(!try_catch.HasCaught());
   11694             : 
   11695             :     value = CompileRun("obj(42)");
   11696           6 :     CHECK(!try_catch.HasCaught());
   11697          12 :     CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11698             : 
   11699             :     value = CompileRun("(function(o){return o(49)})(obj)");
   11700           6 :     CHECK(!try_catch.HasCaught());
   11701          12 :     CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
   11702             : 
   11703             :     // test special case of call as function
   11704             :     value = CompileRun("[obj]['0'](45)");
   11705           6 :     CHECK(!try_catch.HasCaught());
   11706          12 :     CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
   11707             : 
   11708             :     value = CompileRun(
   11709             :         "obj.call = Function.prototype.call;"
   11710             :         "obj.call(null, 87)");
   11711           6 :     CHECK(!try_catch.HasCaught());
   11712          12 :     CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
   11713             : 
   11714             :     // Regression tests for bug #1116356: Calling call through call/apply
   11715             :     // must work for non-function receivers.
   11716             :     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   11717             :     value = CompileRun(apply_99);
   11718           6 :     CHECK(!try_catch.HasCaught());
   11719          12 :     CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
   11720             : 
   11721             :     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   11722             :     value = CompileRun(call_17);
   11723           6 :     CHECK(!try_catch.HasCaught());
   11724          12 :     CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
   11725             : 
   11726             :     // Check that the call-as-function handler can be called through new.
   11727             :     value = CompileRun("new obj(43)");
   11728           6 :     CHECK(!try_catch.HasCaught());
   11729          12 :     CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
   11730             : 
   11731             :     // Check that the call-as-function handler can be called through
   11732             :     // the API.
   11733           6 :     v8::Local<Value> args[] = {v8_num(28)};
   11734          12 :     value = instance->CallAsFunction(context.local(), instance, 1, args)
   11735             :                 .ToLocalChecked();
   11736           6 :     CHECK(!try_catch.HasCaught());
   11737          12 :     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11738             :   }
   11739             : 
   11740             :   {
   11741           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11742           6 :     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   11743             :     USE(instance_template);
   11744           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11745             :                                      .ToLocalChecked()
   11746             :                                      ->NewInstance(context.local())
   11747             :                                      .ToLocalChecked();
   11748          24 :     CHECK(context->Global()
   11749             :               ->Set(context.local(), v8_str("obj2"), instance)
   11750             :               .FromJust());
   11751          12 :     v8::TryCatch try_catch(isolate);
   11752             :     Local<Value> value;
   11753           6 :     CHECK(!try_catch.HasCaught());
   11754             : 
   11755             :     // Call an object without call-as-function handler through the JS
   11756             :     value = CompileRun("obj2(28)");
   11757           6 :     CHECK(value.IsEmpty());
   11758           6 :     CHECK(try_catch.HasCaught());
   11759          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11760             :     // TODO(verwaest): Better message
   11761           6 :     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
   11762           6 :     try_catch.Reset();
   11763             : 
   11764             :     // Call an object without call-as-function handler through the API
   11765           6 :     v8::Local<Value> args[] = {v8_num(28)};
   11766          12 :     CHECK(
   11767             :         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11768           6 :     CHECK(try_catch.HasCaught());
   11769          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11770           6 :     CHECK_EQ(0,
   11771             :              strcmp("TypeError: object is not a function", *exception_value2));
   11772           6 :     try_catch.Reset();
   11773             :   }
   11774             : 
   11775             :   {
   11776           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11777           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11778           6 :     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11779           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11780             :                                      .ToLocalChecked()
   11781             :                                      ->NewInstance(context.local())
   11782             :                                      .ToLocalChecked();
   11783          24 :     CHECK(context->Global()
   11784             :               ->Set(context.local(), v8_str("obj3"), instance)
   11785             :               .FromJust());
   11786          12 :     v8::TryCatch try_catch(isolate);
   11787             :     Local<Value> value;
   11788           6 :     CHECK(!try_catch.HasCaught());
   11789             : 
   11790             :     // Catch the exception which is thrown by call-as-function handler
   11791             :     value = CompileRun("obj3(22)");
   11792           6 :     CHECK(try_catch.HasCaught());
   11793          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11794           6 :     CHECK_EQ(0, strcmp("22", *exception_value1));
   11795           6 :     try_catch.Reset();
   11796             : 
   11797           6 :     v8::Local<Value> args[] = {v8_num(23)};
   11798          12 :     CHECK(
   11799             :         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11800           6 :     CHECK(try_catch.HasCaught());
   11801          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11802           6 :     CHECK_EQ(0, strcmp("23", *exception_value2));
   11803           6 :     try_catch.Reset();
   11804             :   }
   11805             : 
   11806             :   {
   11807           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11808           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11809           6 :     instance_template->SetCallAsFunctionHandler(ReturnThis);
   11810           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11811             :                                      .ToLocalChecked()
   11812             :                                      ->NewInstance(context.local())
   11813             :                                      .ToLocalChecked();
   11814             : 
   11815             :     Local<v8::Value> a1 =
   11816             :         instance
   11817           6 :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11818           6 :                              nullptr)
   11819             :             .ToLocalChecked();
   11820           6 :     CHECK(a1->StrictEquals(instance));
   11821             :     Local<v8::Value> a2 =
   11822          12 :         instance->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11823             :             .ToLocalChecked();
   11824           6 :     CHECK(a2->StrictEquals(instance));
   11825             :     Local<v8::Value> a3 =
   11826          12 :         instance->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11827             :             .ToLocalChecked();
   11828           6 :     CHECK(a3->StrictEquals(instance));
   11829             :     Local<v8::Value> a4 =
   11830          18 :         instance->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11831             :             .ToLocalChecked();
   11832           6 :     CHECK(a4->StrictEquals(instance));
   11833             :     Local<v8::Value> a5 =
   11834          12 :         instance->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11835             :             .ToLocalChecked();
   11836           6 :     CHECK(a5->StrictEquals(instance));
   11837             :   }
   11838             : 
   11839             :   {
   11840             :     CompileRun(
   11841             :         "function ReturnThisSloppy() {"
   11842             :         "  return this;"
   11843             :         "}"
   11844             :         "function ReturnThisStrict() {"
   11845             :         "  'use strict';"
   11846             :         "  return this;"
   11847             :         "}");
   11848             :     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
   11849          12 :         context->Global()
   11850          18 :             ->Get(context.local(), v8_str("ReturnThisSloppy"))
   11851             :             .ToLocalChecked());
   11852             :     Local<Function> ReturnThisStrict = Local<Function>::Cast(
   11853          12 :         context->Global()
   11854          18 :             ->Get(context.local(), v8_str("ReturnThisStrict"))
   11855             :             .ToLocalChecked());
   11856             : 
   11857             :     Local<v8::Value> a1 =
   11858             :         ReturnThisSloppy
   11859           6 :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11860           6 :                              nullptr)
   11861             :             .ToLocalChecked();
   11862          12 :     CHECK(a1->StrictEquals(context->Global()));
   11863             :     Local<v8::Value> a2 =
   11864             :         ReturnThisSloppy
   11865          12 :             ->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11866             :             .ToLocalChecked();
   11867          12 :     CHECK(a2->StrictEquals(context->Global()));
   11868             :     Local<v8::Value> a3 =
   11869             :         ReturnThisSloppy
   11870          12 :             ->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11871             :             .ToLocalChecked();
   11872           6 :     CHECK(a3->IsNumberObject());
   11873           6 :     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
   11874             :     Local<v8::Value> a4 =
   11875             :         ReturnThisSloppy
   11876          18 :             ->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11877             :             .ToLocalChecked();
   11878           6 :     CHECK(a4->IsStringObject());
   11879          18 :     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   11880             :     Local<v8::Value> a5 =
   11881             :         ReturnThisSloppy
   11882          12 :             ->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11883             :             .ToLocalChecked();
   11884           6 :     CHECK(a5->IsBooleanObject());
   11885           6 :     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
   11886             : 
   11887             :     Local<v8::Value> a6 =
   11888             :         ReturnThisStrict
   11889           6 :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11890           6 :                              nullptr)
   11891             :             .ToLocalChecked();
   11892           6 :     CHECK(a6->IsUndefined());
   11893             :     Local<v8::Value> a7 =
   11894             :         ReturnThisStrict
   11895          12 :             ->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11896             :             .ToLocalChecked();
   11897           6 :     CHECK(a7->IsNull());
   11898             :     Local<v8::Value> a8 =
   11899             :         ReturnThisStrict
   11900          12 :             ->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11901             :             .ToLocalChecked();
   11902           6 :     CHECK(a8->StrictEquals(v8_num(42)));
   11903             :     Local<v8::Value> a9 =
   11904             :         ReturnThisStrict
   11905          18 :             ->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11906             :             .ToLocalChecked();
   11907          12 :     CHECK(a9->StrictEquals(v8_str("hello")));
   11908             :     Local<v8::Value> a10 =
   11909             :         ReturnThisStrict
   11910          12 :             ->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11911             :             .ToLocalChecked();
   11912           6 :     CHECK(a10->StrictEquals(v8::True(isolate)));
   11913             :   }
   11914           6 : }
   11915             : 
   11916             : 
   11917             : // Check whether a non-function object is callable.
   11918       26645 : THREADED_TEST(CallableObject) {
   11919           6 :   LocalContext context;
   11920           6 :   v8::Isolate* isolate = context->GetIsolate();
   11921          12 :   v8::HandleScope scope(isolate);
   11922             : 
   11923             :   {
   11924           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11925           6 :     instance_template->SetCallAsFunctionHandler(call_as_function);
   11926             :     Local<Object> instance =
   11927           6 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   11928          12 :     v8::TryCatch try_catch(isolate);
   11929             : 
   11930           6 :     CHECK(instance->IsCallable());
   11931           6 :     CHECK(!try_catch.HasCaught());
   11932             :   }
   11933             : 
   11934             :   {
   11935           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11936             :     Local<Object> instance =
   11937           6 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   11938          12 :     v8::TryCatch try_catch(isolate);
   11939             : 
   11940           6 :     CHECK(!instance->IsCallable());
   11941           6 :     CHECK(!try_catch.HasCaught());
   11942             :   }
   11943             : 
   11944             :   {
   11945             :     Local<FunctionTemplate> function_template =
   11946           6 :         FunctionTemplate::New(isolate, call_as_function);
   11947             :     Local<Function> function =
   11948           6 :         function_template->GetFunction(context.local()).ToLocalChecked();
   11949             :     Local<Object> instance = function;
   11950          12 :     v8::TryCatch try_catch(isolate);
   11951             : 
   11952           6 :     CHECK(instance->IsCallable());
   11953           6 :     CHECK(!try_catch.HasCaught());
   11954             :   }
   11955             : 
   11956             :   {
   11957           6 :     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
   11958             :     Local<Function> function =
   11959           6 :         function_template->GetFunction(context.local()).ToLocalChecked();
   11960             :     Local<Object> instance = function;
   11961          12 :     v8::TryCatch try_catch(isolate);
   11962             : 
   11963           6 :     CHECK(instance->IsCallable());
   11964           6 :     CHECK(!try_catch.HasCaught());
   11965             :   }
   11966           6 : }
   11967             : 
   11968             : 
   11969       26645 : THREADED_TEST(Regress567998) {
   11970           6 :   LocalContext env;
   11971          12 :   v8::HandleScope scope(env->GetIsolate());
   11972             : 
   11973             :   Local<v8::FunctionTemplate> desc =
   11974           6 :       v8::FunctionTemplate::New(env->GetIsolate());
   11975          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   11976          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
   11977             : 
   11978           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
   11979             :                               .ToLocalChecked()
   11980             :                               ->NewInstance(env.local())
   11981             :                               .ToLocalChecked();
   11982          24 :   CHECK(
   11983             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   11984             : 
   11985           6 :   ExpectString("undetectable.toString()", "[object Object]");
   11986           6 :   ExpectString("typeof undetectable", "undefined");
   11987           6 :   ExpectString("typeof(undetectable)", "undefined");
   11988           6 :   ExpectBoolean("typeof undetectable == 'undefined'", true);
   11989           6 :   ExpectBoolean("typeof undetectable == 'object'", false);
   11990           6 :   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   11991           6 :   ExpectBoolean("!undetectable", true);
   11992             : 
   11993           6 :   ExpectObject("true&&undetectable", obj);
   11994           6 :   ExpectBoolean("false&&undetectable", false);
   11995           6 :   ExpectBoolean("true||undetectable", true);
   11996           6 :   ExpectObject("false||undetectable", obj);
   11997             : 
   11998           6 :   ExpectObject("undetectable&&true", obj);
   11999           6 :   ExpectObject("undetectable&&false", obj);
   12000           6 :   ExpectBoolean("undetectable||true", true);
   12001           6 :   ExpectBoolean("undetectable||false", false);
   12002             : 
   12003           6 :   ExpectBoolean("undetectable==null", true);
   12004           6 :   ExpectBoolean("null==undetectable", true);
   12005           6 :   ExpectBoolean("undetectable==undefined", true);
   12006           6 :   ExpectBoolean("undefined==undetectable", true);
   12007           6 :   ExpectBoolean("undetectable==undetectable", true);
   12008             : 
   12009           6 :   ExpectBoolean("undetectable===null", false);
   12010           6 :   ExpectBoolean("null===undetectable", false);
   12011           6 :   ExpectBoolean("undetectable===undefined", false);
   12012           6 :   ExpectBoolean("undefined===undetectable", false);
   12013           6 :   ExpectBoolean("undetectable===undetectable", true);
   12014           6 : }
   12015             : 
   12016             : 
   12017        1206 : static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
   12018        2412 :   v8::HandleScope scope(isolate);
   12019        1206 :   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
   12020     1201200 :   for (int i = 0; i < iterations; i++) {
   12021      600000 :     Local<v8::Number> n(v8::Integer::New(isolate, 42));
   12022             :   }
   12023        1200 :   return Recurse(isolate, depth - 1, iterations);
   12024             : }
   12025             : 
   12026             : 
   12027       26645 : THREADED_TEST(HandleIteration) {
   12028             :   static const int kIterations = 500;
   12029             :   static const int kNesting = 200;
   12030           6 :   LocalContext context;
   12031           6 :   v8::Isolate* isolate = context->GetIsolate();
   12032          12 :   v8::HandleScope scope0(isolate);
   12033           6 :   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12034             :   {
   12035          12 :     v8::HandleScope scope1(isolate);
   12036           6 :     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12037        3006 :     for (int i = 0; i < kIterations; i++) {
   12038        3000 :       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12039        3000 :       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
   12040             :     }
   12041             : 
   12042           6 :     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12043             :     {
   12044          12 :       v8::HandleScope scope2(CcTest::isolate());
   12045        6006 :       for (int j = 0; j < kIterations; j++) {
   12046        3000 :         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12047        3000 :         CHECK_EQ(j + 1 + kIterations,
   12048             :                  v8::HandleScope::NumberOfHandles(isolate));
   12049             :       }
   12050             :     }
   12051           6 :     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12052             :   }
   12053           6 :   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12054           6 :   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
   12055           6 : }
   12056             : 
   12057             : 
   12058        1100 : static void InterceptorCallICFastApi(
   12059             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12060        1100 :   ApiTestFuzzer::Fuzz();
   12061        1100 :   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   12062             :   int* call_count =
   12063        1100 :       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   12064        1100 :   ++(*call_count);
   12065        1100 :   if ((*call_count) % 20 == 0) {
   12066          55 :     CcTest::CollectAllGarbage();
   12067             :   }
   12068        1100 : }
   12069             : 
   12070        2200 : static void FastApiCallback_TrivialSignature(
   12071             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12072        2200 :   ApiTestFuzzer::Fuzz();
   12073        2200 :   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   12074        2200 :   v8::Isolate* isolate = CcTest::isolate();
   12075        2200 :   CHECK_EQ(isolate, args.GetIsolate());
   12076        6600 :   CHECK(args.This()
   12077             :             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12078             :             .FromJust());
   12079        8800 :   CHECK(args.Data()
   12080             :             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12081             :             .FromJust());
   12082        2200 :   args.GetReturnValue().Set(
   12083        6600 :       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12084        2200 : }
   12085             : 
   12086             : static void FastApiCallback_SimpleSignature(
   12087             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12088             :   ApiTestFuzzer::Fuzz();
   12089             :   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   12090             :   v8::Isolate* isolate = CcTest::isolate();
   12091             :   CHECK_EQ(isolate, args.GetIsolate());
   12092             :   CHECK(args.This()
   12093             :             ->GetPrototype()
   12094             :             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12095             :             .FromJust());
   12096             :   CHECK(args.Data()
   12097             :             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12098             :             .FromJust());
   12099             :   // Note, we're using HasRealNamedProperty instead of Has to avoid
   12100             :   // invoking the interceptor again.
   12101             :   CHECK(args.Holder()
   12102             :             ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
   12103             :             .FromJust());
   12104             :   args.GetReturnValue().Set(
   12105             :       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12106             : }
   12107             : 
   12108             : 
   12109             : // Helper to maximize the odds of object moving.
   12110         192 : static void GenerateSomeGarbage() {
   12111             :   CompileRun(
   12112             :       "var garbage;"
   12113             :       "for (var i = 0; i < 1000; i++) {"
   12114             :       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   12115             :       "}"
   12116             :       "garbage = undefined;");
   12117         192 : }
   12118             : 
   12119             : 
   12120         180 : void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12121             :   static int count = 0;
   12122         180 :   if (count++ % 3 == 0) {
   12123          60 :     CcTest::CollectAllGarbage();
   12124             :     // This should move the stub
   12125          60 :     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   12126             :   }
   12127         180 : }
   12128             : 
   12129             : 
   12130       26645 : THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   12131           6 :   LocalContext context;
   12132           6 :   v8::Isolate* isolate = context->GetIsolate();
   12133          12 :   v8::HandleScope scope(isolate);
   12134             :   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12135           6 :       v8::ObjectTemplate::New(isolate);
   12136          12 :   nativeobject_templ->Set(isolate, "callback",
   12137             :                           v8::FunctionTemplate::New(isolate,
   12138             :                                                     DirectApiCallback));
   12139             :   v8::Local<v8::Object> nativeobject_obj =
   12140           6 :       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12141          24 :   CHECK(context->Global()
   12142             :             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12143             :             .FromJust());
   12144             :   // call the api function multiple times to ensure direct call stub creation.
   12145             :   CompileRun(
   12146             :       "function f() {"
   12147             :       "  for (var i = 1; i <= 30; i++) {"
   12148             :       "    nativeobject.callback();"
   12149             :       "  }"
   12150             :       "}"
   12151             :       "f();");
   12152           6 : }
   12153             : 
   12154          30 : void ThrowingDirectApiCallback(
   12155             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12156          60 :   args.GetIsolate()->ThrowException(v8_str("g"));
   12157          30 : }
   12158             : 
   12159       26645 : THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   12160           6 :   LocalContext context;
   12161           6 :   v8::Isolate* isolate = context->GetIsolate();
   12162          12 :   v8::HandleScope scope(isolate);
   12163             :   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12164           6 :       v8::ObjectTemplate::New(isolate);
   12165          12 :   nativeobject_templ->Set(
   12166             :       isolate, "callback",
   12167             :       v8::FunctionTemplate::New(isolate, ThrowingDirectApiCallback));
   12168             :   v8::Local<v8::Object> nativeobject_obj =
   12169           6 :       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12170          24 :   CHECK(context->Global()
   12171             :             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12172             :             .FromJust());
   12173             :   // call the api function multiple times to ensure direct call stub creation.
   12174             :   v8::Local<Value> result = CompileRun(
   12175             :       "var result = '';"
   12176             :       "function f() {"
   12177             :       "  for (var i = 1; i <= 5; i++) {"
   12178             :       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   12179             :       "  }"
   12180             :       "}"
   12181           6 :       "f(); result;");
   12182          18 :   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12183           6 : }
   12184             : 
   12185             : static int p_getter_count_3;
   12186             : 
   12187         341 : static Local<Value> DoDirectGetter() {
   12188         341 :   if (++p_getter_count_3 % 3 == 0) {
   12189         110 :     CcTest::CollectAllGarbage();
   12190         110 :     GenerateSomeGarbage();
   12191             :   }
   12192         341 :   return v8_str("Direct Getter Result");
   12193             : }
   12194             : 
   12195         341 : static void DirectGetterCallback(
   12196             :     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12197         341 :   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   12198         341 :   info.GetReturnValue().Set(DoDirectGetter());
   12199         341 : }
   12200             : 
   12201             : template <typename Accessor>
   12202          11 : static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   12203          11 :   LocalContext context;
   12204          11 :   v8::Isolate* isolate = context->GetIsolate();
   12205          22 :   v8::HandleScope scope(isolate);
   12206          11 :   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12207          11 :   obj->SetAccessor(v8_str("p1"), accessor);
   12208          55 :   CHECK(context->Global()
   12209             :             ->Set(context.local(), v8_str("o1"),
   12210             :                   obj->NewInstance(context.local()).ToLocalChecked())
   12211             :             .FromJust());
   12212          11 :   p_getter_count_3 = 0;
   12213             :   v8::Local<v8::Value> result = CompileRun(
   12214             :       "function f() {"
   12215             :       "  for (var i = 0; i < 30; i++) o1.p1;"
   12216             :       "  return o1.p1"
   12217             :       "}"
   12218          11 :       "f();");
   12219          33 :   CHECK(v8_str("Direct Getter Result")
   12220             :             ->Equals(context.local(), result)
   12221             :             .FromJust());
   12222          11 :   CHECK_EQ(31, p_getter_count_3);
   12223          11 : }
   12224             : 
   12225       53294 : THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   12226          11 :   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   12227          11 : }
   12228             : 
   12229          30 : void ThrowingDirectGetterCallback(
   12230             :     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12231          60 :   info.GetIsolate()->ThrowException(v8_str("g"));
   12232          30 : }
   12233             : 
   12234       26645 : THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   12235           6 :   LocalContext context;
   12236           6 :   v8::Isolate* isolate = context->GetIsolate();
   12237          12 :   v8::HandleScope scope(isolate);
   12238           6 :   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12239           6 :   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   12240          30 :   CHECK(context->Global()
   12241             :             ->Set(context.local(), v8_str("o1"),
   12242             :                   obj->NewInstance(context.local()).ToLocalChecked())
   12243             :             .FromJust());
   12244             :   v8::Local<Value> result = CompileRun(
   12245             :       "var result = '';"
   12246             :       "for (var i = 0; i < 5; i++) {"
   12247             :       "    try { o1.p1; } catch (e) { result += e; }"
   12248             :       "}"
   12249           6 :       "result;");
   12250          18 :   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12251           6 : }
   12252             : 
   12253       53294 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   12254          11 :   int interceptor_call_count = 0;
   12255          11 :   v8::Isolate* isolate = CcTest::isolate();
   12256          22 :   v8::HandleScope scope(isolate);
   12257             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12258          11 :       v8::FunctionTemplate::New(isolate);
   12259             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12260             :       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12261          22 :       v8::Local<v8::Signature>());
   12262          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12263          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12264          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12265          22 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12266             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12267          11 :       v8::External::New(isolate, &interceptor_call_count)));
   12268          11 :   LocalContext context;
   12269             :   v8::Local<v8::Function> fun =
   12270          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12271          11 :   GenerateSomeGarbage();
   12272          44 :   CHECK(context->Global()
   12273             :             ->Set(context.local(), v8_str("o"),
   12274             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12275             :             .FromJust());
   12276             :   CompileRun(
   12277             :       "var result = 0;"
   12278             :       "for (var i = 0; i < 100; i++) {"
   12279             :       "  result = o.method(41);"
   12280             :       "}");
   12281          55 :   CHECK_EQ(42, context->Global()
   12282             :                    ->Get(context.local(), v8_str("result"))
   12283             :                    .ToLocalChecked()
   12284             :                    ->Int32Value(context.local())
   12285             :                    .FromJust());
   12286          11 :   CHECK_EQ(100, interceptor_call_count);
   12287          11 : }
   12288             : 
   12289       53294 : THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   12290          11 :   v8::Isolate* isolate = CcTest::isolate();
   12291          22 :   v8::HandleScope scope(isolate);
   12292             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12293          11 :       v8::FunctionTemplate::New(isolate);
   12294             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12295             :       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12296          22 :       v8::Local<v8::Signature>());
   12297          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12298          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12299          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12300             :   USE(templ);
   12301          11 :   LocalContext context;
   12302             :   v8::Local<v8::Function> fun =
   12303          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12304          11 :   GenerateSomeGarbage();
   12305          44 :   CHECK(context->Global()
   12306             :             ->Set(context.local(), v8_str("o"),
   12307             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12308             :             .FromJust());
   12309             :   CompileRun(
   12310             :       "var result = 0;"
   12311             :       "for (var i = 0; i < 100; i++) {"
   12312             :       "  result = o.method(41);"
   12313             :       "}");
   12314             : 
   12315          55 :   CHECK_EQ(42, context->Global()
   12316             :                    ->Get(context.local(), v8_str("result"))
   12317             :                    .ToLocalChecked()
   12318             :                    ->Int32Value(context.local())
   12319             :                    .FromJust());
   12320          11 : }
   12321             : 
   12322          24 : static void ThrowingGetter(Local<String> name,
   12323             :                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   12324          24 :   ApiTestFuzzer::Fuzz();
   12325          24 :   info.GetIsolate()->ThrowException(Local<Value>());
   12326             :   info.GetReturnValue().SetUndefined();
   12327          24 : }
   12328             : 
   12329             : 
   12330       26645 : THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   12331           6 :   LocalContext context;
   12332          12 :   HandleScope scope(context->GetIsolate());
   12333             : 
   12334           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   12335           6 :   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12336          12 :   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   12337             : 
   12338           6 :   Local<Object> instance = templ->GetFunction(context.local())
   12339             :                                .ToLocalChecked()
   12340             :                                ->NewInstance(context.local())
   12341             :                                .ToLocalChecked();
   12342             : 
   12343           6 :   Local<Object> another = Object::New(context->GetIsolate());
   12344          12 :   CHECK(another->SetPrototype(context.local(), instance).FromJust());
   12345             : 
   12346             :   Local<Object> with_js_getter = CompileRun(
   12347             :       "o = {};\n"
   12348             :       "o.__defineGetter__('f', function() { throw undefined; });\n"
   12349             :       "o\n").As<Object>();
   12350           6 :   CHECK(!with_js_getter.IsEmpty());
   12351             : 
   12352          12 :   TryCatch try_catch(context->GetIsolate());
   12353             : 
   12354             :   v8::MaybeLocal<Value> result =
   12355          12 :       instance->GetRealNamedProperty(context.local(), v8_str("f"));
   12356           6 :   CHECK(try_catch.HasCaught());
   12357           6 :   try_catch.Reset();
   12358           6 :   CHECK(result.IsEmpty());
   12359             : 
   12360             :   Maybe<PropertyAttribute> attr =
   12361          12 :       instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12362           6 :   CHECK(!try_catch.HasCaught());
   12363           6 :   CHECK(Just(None) == attr);
   12364             : 
   12365          12 :   result = another->GetRealNamedProperty(context.local(), v8_str("f"));
   12366           6 :   CHECK(try_catch.HasCaught());
   12367           6 :   try_catch.Reset();
   12368           6 :   CHECK(result.IsEmpty());
   12369             : 
   12370          12 :   attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12371           6 :   CHECK(!try_catch.HasCaught());
   12372           6 :   CHECK(Just(None) == attr);
   12373             : 
   12374             :   result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
   12375          12 :                                                          v8_str("f"));
   12376           6 :   CHECK(try_catch.HasCaught());
   12377           6 :   try_catch.Reset();
   12378           6 :   CHECK(result.IsEmpty());
   12379             : 
   12380             :   attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
   12381          12 :       context.local(), v8_str("f"));
   12382           6 :   CHECK(!try_catch.HasCaught());
   12383           6 :   CHECK(Just(None) == attr);
   12384             : 
   12385          12 :   result = another->Get(context.local(), v8_str("f"));
   12386           6 :   CHECK(try_catch.HasCaught());
   12387           6 :   try_catch.Reset();
   12388           6 :   CHECK(result.IsEmpty());
   12389             : 
   12390          12 :   result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
   12391           6 :   CHECK(try_catch.HasCaught());
   12392           6 :   try_catch.Reset();
   12393           6 :   CHECK(result.IsEmpty());
   12394             : 
   12395             :   attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
   12396          12 :                                                         v8_str("f"));
   12397           6 :   CHECK(!try_catch.HasCaught());
   12398           6 :   CHECK(Just(None) == attr);
   12399             : 
   12400          12 :   result = with_js_getter->Get(context.local(), v8_str("f"));
   12401           6 :   CHECK(try_catch.HasCaught());
   12402           6 :   try_catch.Reset();
   12403           6 :   CHECK(result.IsEmpty());
   12404             : 
   12405             :   Local<Object> target = CompileRun("({})").As<Object>();
   12406           6 :   Local<Object> handler = CompileRun("({})").As<Object>();
   12407             :   Local<v8::Proxy> proxy =
   12408           6 :       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   12409             : 
   12410          12 :   result = target->GetRealNamedProperty(context.local(), v8_str("f"));
   12411           6 :   CHECK(!try_catch.HasCaught());
   12412           6 :   CHECK(result.IsEmpty());
   12413             : 
   12414          12 :   result = proxy->GetRealNamedProperty(context.local(), v8_str("f"));
   12415           6 :   CHECK(!try_catch.HasCaught());
   12416           6 :   CHECK(result.IsEmpty());
   12417           6 : }
   12418             : 
   12419             : 
   12420          30 : static void ThrowingCallbackWithTryCatch(
   12421             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12422          60 :   TryCatch try_catch(args.GetIsolate());
   12423             :   // Verboseness is important: it triggers message delivery which can call into
   12424             :   // external code.
   12425          30 :   try_catch.SetVerbose(true);
   12426             :   CompileRun("throw 'from JS';");
   12427          30 :   CHECK(try_catch.HasCaught());
   12428          30 :   CHECK(!CcTest::i_isolate()->has_pending_exception());
   12429          30 :   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   12430          30 : }
   12431             : 
   12432             : 
   12433             : static int call_depth;
   12434             : 
   12435             : 
   12436           6 : static void WithTryCatch(Local<Message> message, Local<Value> data) {
   12437           6 :   TryCatch try_catch(CcTest::isolate());
   12438           6 : }
   12439             : 
   12440             : 
   12441           6 : static void ThrowFromJS(Local<Message> message, Local<Value> data) {
   12442           6 :   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   12443           6 : }
   12444             : 
   12445             : 
   12446           6 : static void ThrowViaApi(Local<Message> message, Local<Value> data) {
   12447          12 :   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
   12448           6 : }
   12449             : 
   12450             : 
   12451           6 : static void WebKitLike(Local<Message> message, Local<Value> data) {
   12452           6 :   Local<String> errorMessageString = message->Get();
   12453           6 :   CHECK(!errorMessageString.IsEmpty());
   12454           6 :   message->GetStackTrace();
   12455           6 :   message->GetScriptOrigin().ResourceName();
   12456           6 : }
   12457             : 
   12458             : 
   12459       26645 : THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   12460           6 :   LocalContext context;
   12461           6 :   v8::Isolate* isolate = context->GetIsolate();
   12462          12 :   HandleScope scope(isolate);
   12463             : 
   12464             :   Local<Function> func =
   12465          12 :       FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
   12466           6 :           ->GetFunction(context.local())
   12467             :           .ToLocalChecked();
   12468          24 :   CHECK(
   12469             :       context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
   12470             : 
   12471             :   MessageCallback callbacks[] = {nullptr, WebKitLike, ThrowViaApi, ThrowFromJS,
   12472           6 :                                  WithTryCatch};
   12473          66 :   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   12474          30 :     MessageCallback callback = callbacks[i];
   12475          30 :     if (callback != nullptr) {
   12476          24 :       isolate->AddMessageListener(callback);
   12477             :     }
   12478             :     // Some small number to control number of times message handler should
   12479             :     // throw an exception.
   12480          30 :     call_depth = 5;
   12481             :     ExpectFalse(
   12482             :         "var thrown = false;\n"
   12483             :         "try { func(); } catch(e) { thrown = true; }\n"
   12484             :         "thrown\n");
   12485          30 :     if (callback != nullptr) {
   12486          24 :       isolate->RemoveMessageListeners(callback);
   12487             :     }
   12488             :   }
   12489           6 : }
   12490             : 
   12491             : 
   12492           6 : static void ParentGetter(Local<String> name,
   12493             :                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   12494           6 :   ApiTestFuzzer::Fuzz();
   12495           6 :   info.GetReturnValue().Set(v8_num(1));
   12496           6 : }
   12497             : 
   12498             : 
   12499          18 : static void ChildGetter(Local<String> name,
   12500             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   12501          18 :   ApiTestFuzzer::Fuzz();
   12502          18 :   info.GetReturnValue().Set(v8_num(42));
   12503          18 : }
   12504             : 
   12505             : 
   12506       26645 : THREADED_TEST(Overriding) {
   12507           6 :   LocalContext context;
   12508           6 :   v8::Isolate* isolate = context->GetIsolate();
   12509          12 :   v8::HandleScope scope(isolate);
   12510             : 
   12511             :   // Parent template.
   12512           6 :   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
   12513             :   Local<ObjectTemplate> parent_instance_templ =
   12514           6 :       parent_templ->InstanceTemplate();
   12515          12 :   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   12516             : 
   12517             :   // Template that inherits from the parent template.
   12518           6 :   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
   12519             :   Local<ObjectTemplate> child_instance_templ =
   12520           6 :       child_templ->InstanceTemplate();
   12521           6 :   child_templ->Inherit(parent_templ);
   12522             :   // Override 'f'.  The child version of 'f' should get called for child
   12523             :   // instances.
   12524           6 :   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   12525             :   // Add 'g' twice.  The 'g' added last should get called for instances.
   12526           6 :   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   12527           6 :   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   12528             : 
   12529             :   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   12530             :   // so 'h' can be shadowed on the instance object.
   12531           6 :   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   12532          12 :   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, nullptr,
   12533           6 :                                  v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
   12534             : 
   12535             :   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   12536             :   // but the attribute does not have effect because it is duplicated with
   12537             :   // nullptr setter.
   12538          12 :   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, nullptr,
   12539             :                                     v8::Local<Value>(), v8::DEFAULT,
   12540           6 :                                     v8::ReadOnly);
   12541             : 
   12542             :   // Instantiate the child template.
   12543           6 :   Local<v8::Object> instance = child_templ->GetFunction(context.local())
   12544             :                                    .ToLocalChecked()
   12545             :                                    ->NewInstance(context.local())
   12546             :                                    .ToLocalChecked();
   12547             : 
   12548             :   // Check that the child function overrides the parent one.
   12549          24 :   CHECK(context->Global()
   12550             :             ->Set(context.local(), v8_str("o"), instance)
   12551             :             .FromJust());
   12552           6 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   12553             :   // Check that the 'g' that was added last is hit.
   12554          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12555           6 :   value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
   12556          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12557             : 
   12558             :   // Check that 'h' cannot be shadowed.
   12559           6 :   value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
   12560          12 :   CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
   12561             : 
   12562             :   // Check that 'i' cannot be shadowed or changed.
   12563           6 :   value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
   12564          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12565           6 : }
   12566             : 
   12567             : 
   12568          24 : static void ShouldThrowOnErrorGetter(
   12569             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12570          24 :   ApiTestFuzzer::Fuzz();
   12571             :   v8::Isolate* isolate = info.GetIsolate();
   12572             :   Local<Boolean> should_throw_on_error =
   12573             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12574             :   info.GetReturnValue().Set(should_throw_on_error);
   12575          24 : }
   12576             : 
   12577             : 
   12578             : template <typename T>
   12579          24 : static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
   12580             :                                      const v8::PropertyCallbackInfo<T>& info) {
   12581          24 :   ApiTestFuzzer::Fuzz();
   12582             :   v8::Isolate* isolate = info.GetIsolate();
   12583          24 :   auto context = isolate->GetCurrentContext();
   12584             :   Local<Boolean> should_throw_on_error_value =
   12585             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12586         120 :   CHECK(context->Global()
   12587             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
   12588             :                   should_throw_on_error_value)
   12589             :             .FromJust());
   12590          24 : }
   12591             : 
   12592             : 
   12593       26645 : THREADED_TEST(AccessorShouldThrowOnError) {
   12594           6 :   LocalContext context;
   12595           6 :   v8::Isolate* isolate = context->GetIsolate();
   12596          12 :   v8::HandleScope scope(isolate);
   12597           6 :   Local<Object> global = context->Global();
   12598             : 
   12599           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12600           6 :   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12601          12 :   instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
   12602           6 :                               ShouldThrowOnErrorSetter<void>);
   12603             : 
   12604           6 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   12605             :                                    .ToLocalChecked()
   12606             :                                    ->NewInstance(context.local())
   12607             :                                    .ToLocalChecked();
   12608             : 
   12609          18 :   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   12610             : 
   12611             :   // SLOPPY mode
   12612           6 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   12613           6 :   CHECK(value->IsFalse());
   12614           6 :   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   12615          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   12616             :               .ToLocalChecked();
   12617           6 :   CHECK(value->IsFalse());
   12618             : 
   12619             :   // STRICT mode
   12620           6 :   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   12621           6 :   CHECK(value->IsFalse());
   12622           6 :   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   12623          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   12624             :               .ToLocalChecked();
   12625           6 :   CHECK(value->IsTrue());
   12626           6 : }
   12627             : 
   12628             : 
   12629           0 : static void ShouldThrowOnErrorQuery(
   12630             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   12631           0 :   ApiTestFuzzer::Fuzz();
   12632             :   v8::Isolate* isolate = info.GetIsolate();
   12633             :   info.GetReturnValue().Set(v8::None);
   12634             : 
   12635           0 :   auto context = isolate->GetCurrentContext();
   12636             :   Local<Boolean> should_throw_on_error_value =
   12637             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12638           0 :   CHECK(context->Global()
   12639             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
   12640             :                   should_throw_on_error_value)
   12641             :             .FromJust());
   12642           0 : }
   12643             : 
   12644             : 
   12645          12 : static void ShouldThrowOnErrorDeleter(
   12646             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   12647          12 :   ApiTestFuzzer::Fuzz();
   12648             :   v8::Isolate* isolate = info.GetIsolate();
   12649             :   info.GetReturnValue().Set(v8::True(isolate));
   12650             : 
   12651          12 :   auto context = isolate->GetCurrentContext();
   12652             :   Local<Boolean> should_throw_on_error_value =
   12653             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12654          60 :   CHECK(context->Global()
   12655             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
   12656             :                   should_throw_on_error_value)
   12657             :             .FromJust());
   12658          12 : }
   12659             : 
   12660             : 
   12661          12 : static void ShouldThrowOnErrorPropertyEnumerator(
   12662             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
   12663          12 :   ApiTestFuzzer::Fuzz();
   12664             :   v8::Isolate* isolate = info.GetIsolate();
   12665          12 :   Local<v8::Array> names = v8::Array::New(isolate, 1);
   12666          36 :   CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
   12667             :   info.GetReturnValue().Set(names);
   12668             : 
   12669          12 :   auto context = isolate->GetCurrentContext();
   12670             :   Local<Boolean> should_throw_on_error_value =
   12671             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12672          60 :   CHECK(context->Global()
   12673             :             ->Set(isolate->GetCurrentContext(),
   12674             :                   v8_str("should_throw_enumerator"),
   12675             :                   should_throw_on_error_value)
   12676             :             .FromJust());
   12677          12 : }
   12678             : 
   12679             : 
   12680       26645 : THREADED_TEST(InterceptorShouldThrowOnError) {
   12681           6 :   LocalContext context;
   12682           6 :   v8::Isolate* isolate = context->GetIsolate();
   12683          12 :   v8::HandleScope scope(isolate);
   12684           6 :   Local<Object> global = context->Global();
   12685             : 
   12686           6 :   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
   12687             :   v8::NamedPropertyHandlerConfiguration handler(
   12688             :       ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
   12689             :       ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
   12690             :       ShouldThrowOnErrorPropertyEnumerator);
   12691           6 :   interceptor_templ->SetHandler(handler);
   12692             : 
   12693             :   Local<v8::Object> instance =
   12694           6 :       interceptor_templ->NewInstance(context.local()).ToLocalChecked();
   12695             : 
   12696          18 :   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   12697             : 
   12698             :   // SLOPPY mode
   12699           6 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   12700           6 :   CHECK(value->IsFalse());
   12701           6 :   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   12702          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   12703             :               .ToLocalChecked();
   12704           6 :   CHECK(value->IsFalse());
   12705             : 
   12706           6 :   v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
   12707          18 :   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   12708             :               .ToLocalChecked();
   12709           6 :   CHECK(value->IsFalse());
   12710             : 
   12711             :   v8_compile("Object.getOwnPropertyNames(o)")
   12712           6 :       ->Run(context.local())
   12713             :       .ToLocalChecked();
   12714          18 :   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   12715             :               .ToLocalChecked();
   12716           6 :   CHECK(value->IsFalse());
   12717             : 
   12718             :   // STRICT mode
   12719           6 :   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   12720           6 :   CHECK(value->IsFalse());
   12721           6 :   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   12722          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   12723             :               .ToLocalChecked();
   12724           6 :   CHECK(value->IsTrue());
   12725             : 
   12726           6 :   v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
   12727          18 :   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   12728             :               .ToLocalChecked();
   12729           6 :   CHECK(value->IsTrue());
   12730             : 
   12731             :   v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
   12732           6 :       ->Run(context.local())
   12733             :       .ToLocalChecked();
   12734          18 :   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   12735             :               .ToLocalChecked();
   12736           6 :   CHECK(value->IsFalse());
   12737           6 : }
   12738             : 
   12739          55 : static void EmptyHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {}
   12740             : 
   12741       26644 : TEST(CallHandlerHasNoSideEffect) {
   12742           5 :   v8::Isolate* isolate = CcTest::isolate();
   12743          10 :   v8::HandleScope scope(isolate);
   12744           5 :   LocalContext context;
   12745             : 
   12746             :   // Function template with call handler.
   12747           5 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12748           5 :   templ->SetCallHandler(EmptyHandler);
   12749          25 :   CHECK(context->Global()
   12750             :             ->Set(context.local(), v8_str("f"),
   12751             :                   templ->GetFunction(context.local()).ToLocalChecked())
   12752             :             .FromJust());
   12753          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12754          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   12755             : 
   12756             :   // Side-effect-free version.
   12757           5 :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
   12758           5 :   templ2->SetCallHandler(EmptyHandler, v8::Local<Value>(),
   12759           5 :                          v8::SideEffectType::kHasNoSideEffect);
   12760          25 :   CHECK(context->Global()
   12761             :             ->Set(context.local(), v8_str("f2"),
   12762             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   12763             :             .FromJust());
   12764           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12765           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   12766           5 : }
   12767             : 
   12768       26644 : TEST(FunctionTemplateNewHasNoSideEffect) {
   12769           5 :   v8::Isolate* isolate = CcTest::isolate();
   12770          10 :   v8::HandleScope scope(isolate);
   12771           5 :   LocalContext context;
   12772             : 
   12773             :   // Function template with call handler.
   12774             :   Local<v8::FunctionTemplate> templ =
   12775           5 :       v8::FunctionTemplate::New(isolate, EmptyHandler);
   12776          25 :   CHECK(context->Global()
   12777             :             ->Set(context.local(), v8_str("f"),
   12778             :                   templ->GetFunction(context.local()).ToLocalChecked())
   12779             :             .FromJust());
   12780          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12781          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   12782             : 
   12783             :   // Side-effect-free version.
   12784             :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(
   12785             :       isolate, EmptyHandler, v8::Local<Value>(), v8::Local<v8::Signature>(), 0,
   12786           5 :       v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
   12787          25 :   CHECK(context->Global()
   12788             :             ->Set(context.local(), v8_str("f2"),
   12789             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   12790             :             .FromJust());
   12791           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12792           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   12793           5 : }
   12794             : 
   12795       26644 : TEST(FunctionTemplateNewWithCacheHasNoSideEffect) {
   12796           5 :   v8::Isolate* isolate = CcTest::isolate();
   12797          10 :   v8::HandleScope scope(isolate);
   12798           5 :   LocalContext context;
   12799             :   v8::Local<v8::Private> priv =
   12800           5 :       v8::Private::ForApi(isolate, v8_str("Foo#draft"));
   12801             : 
   12802             :   // Function template with call handler.
   12803             :   Local<v8::FunctionTemplate> templ =
   12804           5 :       v8::FunctionTemplate::NewWithCache(isolate, EmptyHandler, priv);
   12805          25 :   CHECK(context->Global()
   12806             :             ->Set(context.local(), v8_str("f"),
   12807             :                   templ->GetFunction(context.local()).ToLocalChecked())
   12808             :             .FromJust());
   12809          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12810          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   12811             : 
   12812             :   // Side-effect-free version.
   12813             :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::NewWithCache(
   12814             :       isolate, EmptyHandler, priv, v8::Local<Value>(),
   12815           5 :       v8::Local<v8::Signature>(), 0, v8::SideEffectType::kHasNoSideEffect);
   12816          25 :   CHECK(context->Global()
   12817             :             ->Set(context.local(), v8_str("f2"),
   12818             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   12819             :             .FromJust());
   12820           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12821           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   12822           5 : }
   12823             : 
   12824       26644 : TEST(FunctionNewHasNoSideEffect) {
   12825           5 :   v8::Isolate* isolate = CcTest::isolate();
   12826          10 :   v8::HandleScope scope(isolate);
   12827           5 :   LocalContext context;
   12828             : 
   12829             :   // Function with side-effect.
   12830             :   Local<Function> func =
   12831          10 :       Function::New(context.local(), EmptyHandler).ToLocalChecked();
   12832          20 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func).FromJust());
   12833          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12834          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   12835             : 
   12836             :   // Side-effect-free version.
   12837             :   Local<Function> func2 =
   12838           5 :       Function::New(context.local(), EmptyHandler, Local<Value>(), 0,
   12839             :                     v8::ConstructorBehavior::kAllow,
   12840           5 :                     v8::SideEffectType::kHasNoSideEffect)
   12841             :           .ToLocalChecked();
   12842          20 :   CHECK(
   12843             :       context->Global()->Set(context.local(), v8_str("f2"), func2).FromJust());
   12844           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12845           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   12846           5 : }
   12847             : 
   12848             : // These handlers instantiate a function the embedder considers safe in some
   12849             : // cases (e.g. "building object wrappers"), but those functions themselves were
   12850             : // not explicitly marked as side-effect-free.
   12851           5 : static void DefaultConstructHandler(
   12852             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   12853           5 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   12854             :   v8::Context::Scope context_scope(context);
   12855          10 :   v8::MaybeLocal<v8::Object> instance = Function::New(context, EmptyHandler)
   12856             :                                             .ToLocalChecked()
   12857           5 :                                             ->NewInstance(context, 0, nullptr);
   12858             :   USE(instance);
   12859           5 : }
   12860             : 
   12861          10 : static void NoSideEffectConstructHandler(
   12862             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   12863          10 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   12864             :   v8::Context::Scope context_scope(context);
   12865             :   v8::MaybeLocal<v8::Object> instance =
   12866          20 :       Function::New(context, EmptyHandler)
   12867             :           .ToLocalChecked()
   12868             :           ->NewInstanceWithSideEffectType(context, 0, nullptr,
   12869          10 :                                           v8::SideEffectType::kHasNoSideEffect);
   12870             :   USE(instance);
   12871          10 : }
   12872             : 
   12873           5 : static void NoSideEffectAndSideEffectConstructHandler(
   12874             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   12875           5 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   12876             :   v8::Context::Scope context_scope(context);
   12877             :   // Constructs an instance in a side-effect-free way, followed by another with
   12878             :   // side effects.
   12879             :   v8::MaybeLocal<v8::Object> instance =
   12880          10 :       Function::New(context, EmptyHandler)
   12881             :           .ToLocalChecked()
   12882             :           ->NewInstanceWithSideEffectType(context, 0, nullptr,
   12883           5 :                                           v8::SideEffectType::kHasNoSideEffect);
   12884          10 :   v8::MaybeLocal<v8::Object> instance2 = Function::New(context, EmptyHandler)
   12885             :                                              .ToLocalChecked()
   12886           5 :                                              ->NewInstance(context, 0, nullptr);
   12887             :   USE(instance);
   12888             :   USE(instance2);
   12889           5 : }
   12890             : 
   12891       26644 : TEST(FunctionNewInstanceHasNoSideEffect) {
   12892           5 :   v8::Isolate* isolate = CcTest::isolate();
   12893          10 :   v8::HandleScope scope(isolate);
   12894           5 :   LocalContext context;
   12895             : 
   12896             :   // A whitelisted function that creates a new object with both side-effect
   12897             :   // free/full instantiations. Should throw.
   12898             :   Local<Function> func0 =
   12899           5 :       Function::New(context.local(), NoSideEffectAndSideEffectConstructHandler,
   12900             :                     Local<Value>(), 0, v8::ConstructorBehavior::kAllow,
   12901           5 :                     v8::SideEffectType::kHasNoSideEffect)
   12902             :           .ToLocalChecked();
   12903          20 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func0).FromJust());
   12904          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12905             : 
   12906             :   // A whitelisted function that creates a new object. Should throw.
   12907             :   Local<Function> func =
   12908           5 :       Function::New(context.local(), DefaultConstructHandler, Local<Value>(), 0,
   12909             :                     v8::ConstructorBehavior::kAllow,
   12910           5 :                     v8::SideEffectType::kHasNoSideEffect)
   12911             :           .ToLocalChecked();
   12912          20 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func).FromJust());
   12913          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12914             : 
   12915             :   // A whitelisted function that creates a new object with explicit intent to
   12916             :   // have no side-effects (e.g. building an "object wrapper"). Should not throw.
   12917             :   Local<Function> func2 =
   12918           5 :       Function::New(context.local(), NoSideEffectConstructHandler,
   12919             :                     Local<Value>(), 0, v8::ConstructorBehavior::kAllow,
   12920           5 :                     v8::SideEffectType::kHasNoSideEffect)
   12921             :           .ToLocalChecked();
   12922          20 :   CHECK(
   12923             :       context->Global()->Set(context.local(), v8_str("f2"), func2).FromJust());
   12924           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12925             : 
   12926             :   // Check that side effect skipping did not leak outside to future evaluations.
   12927             :   Local<Function> func3 =
   12928          10 :       Function::New(context.local(), EmptyHandler).ToLocalChecked();
   12929          20 :   CHECK(
   12930             :       context->Global()->Set(context.local(), v8_str("f3"), func3).FromJust());
   12931          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f3()"), true).IsEmpty());
   12932             : 
   12933             :   // Check that using side effect free NewInstance works in normal evaluation
   12934             :   // (without throwOnSideEffect).
   12935           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), false).ToLocalChecked();
   12936           5 : }
   12937             : 
   12938       26644 : TEST(CallHandlerAsFunctionHasNoSideEffectNotSupported) {
   12939           5 :   v8::Isolate* isolate = CcTest::isolate();
   12940          10 :   v8::HandleScope scope(isolate);
   12941           5 :   LocalContext context;
   12942             : 
   12943             :   // Object template with call as function handler.
   12944           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12945           5 :   templ->SetCallAsFunctionHandler(EmptyHandler);
   12946           5 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   12947          20 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   12948          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj()"), true).IsEmpty());
   12949             : 
   12950             :   // Side-effect-free version is not supported.
   12951             :   i::FunctionTemplateInfo cons = i::FunctionTemplateInfo::cast(
   12952             :       v8::Utils::OpenHandle(*templ)->constructor());
   12953             :   i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
   12954             :   i::CallHandlerInfo handler_info =
   12955           5 :       i::CallHandlerInfo::cast(cons->GetInstanceCallHandler());
   12956           5 :   CHECK(!handler_info->IsSideEffectFreeCallHandlerInfo());
   12957             :   handler_info->set_map(
   12958           5 :       i::ReadOnlyRoots(heap).side_effect_free_call_handler_info_map());
   12959          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj()"), true).IsEmpty());
   12960           5 : }
   12961             : 
   12962          12 : static void IsConstructHandler(
   12963             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12964          12 :   ApiTestFuzzer::Fuzz();
   12965             :   args.GetReturnValue().Set(args.IsConstructCall());
   12966          12 : }
   12967             : 
   12968             : 
   12969       26645 : THREADED_TEST(IsConstructCall) {
   12970           6 :   v8::Isolate* isolate = CcTest::isolate();
   12971          12 :   v8::HandleScope scope(isolate);
   12972             : 
   12973             :   // Function template with call handler.
   12974           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12975           6 :   templ->SetCallHandler(IsConstructHandler);
   12976             : 
   12977           6 :   LocalContext context;
   12978             : 
   12979          30 :   CHECK(context->Global()
   12980             :             ->Set(context.local(), v8_str("f"),
   12981             :                   templ->GetFunction(context.local()).ToLocalChecked())
   12982             :             .FromJust());
   12983           6 :   Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
   12984           6 :   CHECK(!value->BooleanValue(isolate));
   12985           6 :   value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
   12986           6 :   CHECK(value->BooleanValue(isolate));
   12987           6 : }
   12988             : 
   12989          24 : static void NewTargetHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12990          24 :   ApiTestFuzzer::Fuzz();
   12991             :   args.GetReturnValue().Set(args.NewTarget());
   12992          24 : }
   12993             : 
   12994       26645 : THREADED_TEST(NewTargetHandler) {
   12995           6 :   v8::Isolate* isolate = CcTest::isolate();
   12996          12 :   v8::HandleScope scope(isolate);
   12997             : 
   12998             :   // Function template with call handler.
   12999           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13000           6 :   templ->SetCallHandler(NewTargetHandler);
   13001             : 
   13002           6 :   LocalContext context;
   13003             : 
   13004             :   Local<Function> function =
   13005           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   13006          24 :   CHECK(context->Global()
   13007             :             ->Set(context.local(), v8_str("f"), function)
   13008             :             .FromJust());
   13009             :   Local<Value> value = CompileRun("f()");
   13010           6 :   CHECK(value->IsUndefined());
   13011             :   value = CompileRun("new f()");
   13012           6 :   CHECK(value->IsFunction());
   13013           6 :   CHECK(value == function);
   13014             :   Local<Value> subclass = CompileRun("var g = class extends f { }; g");
   13015           6 :   CHECK(subclass->IsFunction());
   13016             :   value = CompileRun("new g()");
   13017           6 :   CHECK(value->IsFunction());
   13018           6 :   CHECK(value == subclass);
   13019             :   value = CompileRun("Reflect.construct(f, [], Array)");
   13020           6 :   CHECK(value->IsFunction());
   13021          24 :   CHECK(value ==
   13022             :         context->Global()
   13023             :             ->Get(context.local(), v8_str("Array"))
   13024             :             .ToLocalChecked());
   13025           6 : }
   13026             : 
   13027       26645 : THREADED_TEST(ObjectProtoToString) {
   13028           6 :   v8::Isolate* isolate = CcTest::isolate();
   13029          12 :   v8::HandleScope scope(isolate);
   13030           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13031           6 :   templ->SetClassName(v8_str("MyClass"));
   13032             : 
   13033           6 :   LocalContext context;
   13034             : 
   13035           6 :   Local<String> customized_tostring = v8_str("customized toString");
   13036             : 
   13037             :   // Replace Object.prototype.toString
   13038             :   v8_compile(
   13039             :       "Object.prototype.toString = function() {"
   13040             :       "  return 'customized toString';"
   13041             :       "}")
   13042           6 :       ->Run(context.local())
   13043             :       .ToLocalChecked();
   13044             : 
   13045             :   // Normal ToString call should call replaced Object.prototype.toString
   13046           6 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13047             :                                    .ToLocalChecked()
   13048             :                                    ->NewInstance(context.local())
   13049             :                                    .ToLocalChecked();
   13050           6 :   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13051          18 :   CHECK(value->IsString() &&
   13052             :         value->Equals(context.local(), customized_tostring).FromJust());
   13053             : 
   13054             :   // ObjectProtoToString should not call replace toString function.
   13055           6 :   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13056          18 :   CHECK(value->IsString() &&
   13057             :         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13058             : 
   13059             :   // Check global
   13060             :   value =
   13061          18 :       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13062          18 :   CHECK(value->IsString() &&
   13063             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13064             : 
   13065             :   // Check ordinary object
   13066             :   Local<Value> object =
   13067           6 :       v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
   13068             :   value = object.As<v8::Object>()
   13069           6 :               ->ObjectProtoToString(context.local())
   13070             :               .ToLocalChecked();
   13071          18 :   CHECK(value->IsString() &&
   13072             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13073           6 : }
   13074             : 
   13075             : 
   13076       26644 : TEST(ObjectProtoToStringES6) {
   13077           5 :   LocalContext context;
   13078           5 :   v8::Isolate* isolate = CcTest::isolate();
   13079          10 :   v8::HandleScope scope(isolate);
   13080           5 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13081           5 :   templ->SetClassName(v8_str("MyClass"));
   13082             : 
   13083           5 :   Local<String> customized_tostring = v8_str("customized toString");
   13084             : 
   13085             :   // Replace Object.prototype.toString
   13086             :   CompileRun(
   13087             :       "Object.prototype.toString = function() {"
   13088             :       "  return 'customized toString';"
   13089             :       "}");
   13090             : 
   13091             :   // Normal ToString call should call replaced Object.prototype.toString
   13092           5 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13093             :                                    .ToLocalChecked()
   13094             :                                    ->NewInstance(context.local())
   13095             :                                    .ToLocalChecked();
   13096           5 :   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13097          15 :   CHECK(value->IsString() &&
   13098             :         value->Equals(context.local(), customized_tostring).FromJust());
   13099             : 
   13100             :   // ObjectProtoToString should not call replace toString function.
   13101           5 :   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13102          15 :   CHECK(value->IsString() &&
   13103             :         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13104             : 
   13105             :   // Check global
   13106             :   value =
   13107          15 :       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13108          15 :   CHECK(value->IsString() &&
   13109             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13110             : 
   13111             :   // Check ordinary object
   13112             :   Local<Value> object = CompileRun("new Object()");
   13113             :   value = object.As<v8::Object>()
   13114           5 :               ->ObjectProtoToString(context.local())
   13115             :               .ToLocalChecked();
   13116          15 :   CHECK(value->IsString() &&
   13117             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13118             : 
   13119             :   // Check that ES6 semantics using @@toStringTag work
   13120           5 :   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
   13121             : 
   13122             : #define TEST_TOSTRINGTAG(type, tag, expected)                              \
   13123             :   do {                                                                     \
   13124             :     object = CompileRun("new " #type "()");                                \
   13125             :     CHECK(object.As<v8::Object>()                                          \
   13126             :               ->Set(context.local(), toStringTag, v8_str(#tag))            \
   13127             :               .FromJust());                                                \
   13128             :     value = object.As<v8::Object>()                                        \
   13129             :                 ->ObjectProtoToString(context.local())                     \
   13130             :                 .ToLocalChecked();                                         \
   13131             :     CHECK(value->IsString() &&                                             \
   13132             :           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13133             :               .FromJust());                                                \
   13134             :   } while (false)
   13135             : 
   13136          35 :   TEST_TOSTRINGTAG(Array, Object, Object);
   13137          35 :   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
   13138          35 :   TEST_TOSTRINGTAG(Object, Array, Array);
   13139          35 :   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
   13140          35 :   TEST_TOSTRINGTAG(Object, Date, Date);
   13141          35 :   TEST_TOSTRINGTAG(Object, Error, Error);
   13142          35 :   TEST_TOSTRINGTAG(Object, Function, Function);
   13143          35 :   TEST_TOSTRINGTAG(Object, Number, Number);
   13144          35 :   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
   13145          35 :   TEST_TOSTRINGTAG(Object, String, String);
   13146          35 :   TEST_TOSTRINGTAG(Object, Foo, Foo);
   13147             : 
   13148             : #undef TEST_TOSTRINGTAG
   13149             : 
   13150             :   Local<v8::RegExp> valueRegExp =
   13151          10 :       v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
   13152             :           .ToLocalChecked();
   13153           5 :   Local<Value> valueNumber = v8_num(123);
   13154           5 :   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
   13155             :   Local<v8::Function> valueFunction =
   13156             :       CompileRun("(function fn() {})").As<v8::Function>();
   13157           5 :   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
   13158           5 :   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
   13159           5 :   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
   13160             : 
   13161             : #define TEST_TOSTRINGTAG(type, tagValue, expected)                         \
   13162             :   do {                                                                     \
   13163             :     object = CompileRun("new " #type "()");                                \
   13164             :     CHECK(object.As<v8::Object>()                                          \
   13165             :               ->Set(context.local(), toStringTag, tagValue)                \
   13166             :               .FromJust());                                                \
   13167             :     value = object.As<v8::Object>()                                        \
   13168             :                 ->ObjectProtoToString(context.local())                     \
   13169             :                 .ToLocalChecked();                                         \
   13170             :     CHECK(value->IsString() &&                                             \
   13171             :           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13172             :               .FromJust());                                                \
   13173             :   } while (false)
   13174             : 
   13175             : #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
   13176             :   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
   13177             :   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
   13178             :   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
   13179             :   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
   13180             :   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
   13181             :   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
   13182             : 
   13183             :   // Test non-String-valued @@toStringTag
   13184         180 :   TEST_TOSTRINGTAG_TYPES(valueRegExp);
   13185         180 :   TEST_TOSTRINGTAG_TYPES(valueNumber);
   13186         180 :   TEST_TOSTRINGTAG_TYPES(valueSymbol);
   13187         180 :   TEST_TOSTRINGTAG_TYPES(valueFunction);
   13188         180 :   TEST_TOSTRINGTAG_TYPES(valueObject);
   13189         180 :   TEST_TOSTRINGTAG_TYPES(valueNull);
   13190         180 :   TEST_TOSTRINGTAG_TYPES(valueUndef);
   13191             : 
   13192             : #undef TEST_TOSTRINGTAG
   13193             : #undef TEST_TOSTRINGTAG_TYPES
   13194             : 
   13195             :   // @@toStringTag getter throws
   13196           5 :   Local<Value> obj = v8::Object::New(isolate);
   13197             :   obj.As<v8::Object>()
   13198          10 :       ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
   13199             :       .FromJust();
   13200             :   {
   13201          10 :     TryCatch try_catch(isolate);
   13202          10 :     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13203           5 :     CHECK(try_catch.HasCaught());
   13204             :   }
   13205             : 
   13206             :   // @@toStringTag getter does not throw
   13207           5 :   obj = v8::Object::New(isolate);
   13208             :   obj.As<v8::Object>()
   13209          10 :       ->SetAccessor(context.local(), toStringTag,
   13210          10 :                     SymbolAccessorGetterReturnsDefault, nullptr, v8_str("Test"))
   13211             :       .FromJust();
   13212             :   {
   13213          10 :     TryCatch try_catch(isolate);
   13214             :     value = obj.As<v8::Object>()
   13215           5 :                 ->ObjectProtoToString(context.local())
   13216             :                 .ToLocalChecked();
   13217          15 :     CHECK(value->IsString() &&
   13218             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13219           5 :     CHECK(!try_catch.HasCaught());
   13220             :   }
   13221             : 
   13222             :   // JS @@toStringTag value
   13223             :   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
   13224             :   {
   13225          10 :     TryCatch try_catch(isolate);
   13226             :     value = obj.As<v8::Object>()
   13227           5 :                 ->ObjectProtoToString(context.local())
   13228             :                 .ToLocalChecked();
   13229          15 :     CHECK(value->IsString() &&
   13230             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13231           5 :     CHECK(!try_catch.HasCaught());
   13232             :   }
   13233             : 
   13234             :   // JS @@toStringTag getter throws
   13235             :   obj = CompileRun(
   13236             :       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13237             :       "  get: function() { throw 'Test'; }"
   13238             :       "}); obj");
   13239             :   {
   13240          10 :     TryCatch try_catch(isolate);
   13241          10 :     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13242           5 :     CHECK(try_catch.HasCaught());
   13243             :   }
   13244             : 
   13245             :   // JS @@toStringTag getter does not throw
   13246             :   obj = CompileRun(
   13247             :       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13248             :       "  get: function() { return 'Test'; }"
   13249             :       "}); obj");
   13250             :   {
   13251          10 :     TryCatch try_catch(isolate);
   13252             :     value = obj.As<v8::Object>()
   13253           5 :                 ->ObjectProtoToString(context.local())
   13254             :                 .ToLocalChecked();
   13255          15 :     CHECK(value->IsString() &&
   13256             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13257           5 :     CHECK(!try_catch.HasCaught());
   13258             :   }
   13259           5 : }
   13260             : 
   13261             : 
   13262       26645 : THREADED_TEST(ObjectGetConstructorName) {
   13263           6 :   v8::Isolate* isolate = CcTest::isolate();
   13264           6 :   LocalContext context;
   13265          12 :   v8::HandleScope scope(isolate);
   13266             :   v8_compile(
   13267             :       "function Parent() {};"
   13268             :       "function Child() {};"
   13269             :       "Child.prototype = new Parent();"
   13270             :       "Child.prototype.constructor = Child;"
   13271             :       "var outer = { inner: (0, function() { }) };"
   13272             :       "var p = new Parent();"
   13273             :       "var c = new Child();"
   13274             :       "var x = new outer.inner();"
   13275             :       "var proto = Child.prototype;")
   13276           6 :       ->Run(context.local())
   13277             :       .ToLocalChecked();
   13278             : 
   13279             :   Local<v8::Value> p =
   13280          24 :       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13281          30 :   CHECK(p->IsObject() &&
   13282             :         p->ToObject(context.local())
   13283             :             .ToLocalChecked()
   13284             :             ->GetConstructorName()
   13285             :             ->Equals(context.local(), v8_str("Parent"))
   13286             :             .FromJust());
   13287             : 
   13288             :   Local<v8::Value> c =
   13289          24 :       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13290          30 :   CHECK(c->IsObject() &&
   13291             :         c->ToObject(context.local())
   13292             :             .ToLocalChecked()
   13293             :             ->GetConstructorName()
   13294             :             ->Equals(context.local(), v8_str("Child"))
   13295             :             .FromJust());
   13296             : 
   13297             :   Local<v8::Value> x =
   13298          24 :       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
   13299          30 :   CHECK(x->IsObject() &&
   13300             :         x->ToObject(context.local())
   13301             :             .ToLocalChecked()
   13302             :             ->GetConstructorName()
   13303             :             ->Equals(context.local(), v8_str("outer.inner"))
   13304             :             .FromJust());
   13305             : 
   13306             :   Local<v8::Value> child_prototype =
   13307          24 :       context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
   13308          30 :   CHECK(child_prototype->IsObject() &&
   13309             :         child_prototype->ToObject(context.local())
   13310             :             .ToLocalChecked()
   13311             :             ->GetConstructorName()
   13312             :             ->Equals(context.local(), v8_str("Parent"))
   13313             :             .FromJust());
   13314           6 : }
   13315             : 
   13316             : 
   13317       26645 : THREADED_TEST(SubclassGetConstructorName) {
   13318           6 :   v8::Isolate* isolate = CcTest::isolate();
   13319           6 :   LocalContext context;
   13320          12 :   v8::HandleScope scope(isolate);
   13321             :   v8_compile(
   13322             :       "\"use strict\";"
   13323             :       "class Parent {}"
   13324             :       "class Child extends Parent {}"
   13325             :       "var p = new Parent();"
   13326             :       "var c = new Child();")
   13327           6 :       ->Run(context.local())
   13328             :       .ToLocalChecked();
   13329             : 
   13330             :   Local<v8::Value> p =
   13331          24 :       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13332          30 :   CHECK(p->IsObject() &&
   13333             :         p->ToObject(context.local())
   13334             :             .ToLocalChecked()
   13335             :             ->GetConstructorName()
   13336             :             ->Equals(context.local(), v8_str("Parent"))
   13337             :             .FromJust());
   13338             : 
   13339             :   Local<v8::Value> c =
   13340          24 :       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13341          30 :   CHECK(c->IsObject() &&
   13342             :         c->ToObject(context.local())
   13343             :             .ToLocalChecked()
   13344             :             ->GetConstructorName()
   13345             :             ->Equals(context.local(), v8_str("Child"))
   13346             :             .FromJust());
   13347           6 : }
   13348             : 
   13349             : 
   13350             : bool ApiTestFuzzer::fuzzing_ = false;
   13351       26639 : v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
   13352             : int ApiTestFuzzer::active_tests_;
   13353             : int ApiTestFuzzer::tests_being_run_;
   13354             : int ApiTestFuzzer::current_;
   13355             : 
   13356             : 
   13357             : // We are in a callback and want to switch to another thread (if we
   13358             : // are currently running the thread fuzzing test).
   13359      514722 : void ApiTestFuzzer::Fuzz() {
   13360      514722 :   if (!fuzzing_) return;
   13361       85307 :   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   13362       85307 :   test->ContextSwitch();
   13363             : }
   13364             : 
   13365             : 
   13366             : // Let the next thread go.  Since it is also waiting on the V8 lock it may
   13367             : // not start immediately.
   13368       85787 : bool ApiTestFuzzer::NextThread() {
   13369       85787 :   int test_position = GetNextTestNumber();
   13370       85787 :   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   13371       85787 :   if (test_position == current_) {
   13372             :     if (kLogThreading)
   13373             :       printf("Stay with %s\n", test_name);
   13374             :     return false;
   13375             :   }
   13376             :   if (kLogThreading) {
   13377             :     printf("Switch from %s to %s\n",
   13378             :            test_name,
   13379             :            RegisterThreadedTest::nth(test_position)->name());
   13380             :   }
   13381       31793 :   current_ = test_position;
   13382       31793 :   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
   13383       31793 :   return true;
   13384             : }
   13385             : 
   13386             : 
   13387         477 : void ApiTestFuzzer::Run() {
   13388             :   // When it is our turn...
   13389         477 :   gate_.Wait();
   13390             :   {
   13391             :     // ... get the V8 lock and start running the test.
   13392         960 :     v8::Locker locker(CcTest::isolate());
   13393         480 :     CallTest();
   13394             :   }
   13395             :   // This test finished.
   13396         480 :   active_ = false;
   13397         480 :   active_tests_--;
   13398             :   // If it was the last then signal that fact.
   13399         480 :   if (active_tests_ == 0) {
   13400           8 :     all_tests_done_.Signal();
   13401             :   } else {
   13402             :     // Otherwise select a new test and start that.
   13403         472 :     NextThread();
   13404             :   }
   13405         480 : }
   13406             : 
   13407             : 
   13408             : static unsigned linear_congruential_generator;
   13409             : 
   13410             : 
   13411           8 : void ApiTestFuzzer::SetUp(PartOfTest part) {
   13412           8 :   linear_congruential_generator = i::FLAG_testing_prng_seed;
   13413           8 :   fuzzing_ = true;
   13414             :   int count = RegisterThreadedTest::count();
   13415           8 :   int start =  count * part / (LAST_PART + 1);
   13416           8 :   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   13417           8 :   active_tests_ = tests_being_run_ = end - start + 1;
   13418         968 :   for (int i = 0; i < tests_being_run_; i++) {
   13419         480 :     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   13420             :   }
   13421         968 :   for (int i = 0; i < active_tests_; i++) {
   13422         480 :     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   13423             :   }
   13424           8 : }
   13425             : 
   13426             : 
   13427             : static void CallTestNumber(int test_number) {
   13428         480 :   (RegisterThreadedTest::nth(test_number)->callback())();
   13429             : }
   13430             : 
   13431             : 
   13432           0 : void ApiTestFuzzer::RunAllTests() {
   13433             :   // Set off the first test.
   13434           8 :   current_ = -1;
   13435           8 :   NextThread();
   13436             :   // Wait till they are all done.
   13437           8 :   all_tests_done_.Wait();
   13438           0 : }
   13439             : 
   13440             : 
   13441       85787 : int ApiTestFuzzer::GetNextTestNumber() {
   13442             :   int next_test;
   13443     3249266 :   do {
   13444     3249266 :     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   13445     3249266 :     linear_congruential_generator *= 1664525u;
   13446     3249266 :     linear_congruential_generator += 1013904223u;
   13447     3249266 :   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   13448       85787 :   return next_test;
   13449             : }
   13450             : 
   13451             : 
   13452       85307 : void ApiTestFuzzer::ContextSwitch() {
   13453             :   // If the new thread is the same as the current thread there is nothing to do.
   13454       85307 :   if (NextThread()) {
   13455             :     // Now it can start.
   13456       62626 :     v8::Unlocker unlocker(CcTest::isolate());
   13457             :     // Wait till someone starts us again.
   13458       31313 :     gate_.Wait();
   13459             :     // And we're off.
   13460             :   }
   13461       85307 : }
   13462             : 
   13463             : 
   13464           8 : void ApiTestFuzzer::TearDown() {
   13465           8 :   fuzzing_ = false;
   13466        7688 :   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   13467        3840 :     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   13468        3840 :     if (fuzzer != nullptr) fuzzer->Join();
   13469             :   }
   13470           8 : }
   13471             : 
   13472         480 : void ApiTestFuzzer::CallTest() {
   13473         480 :   v8::Isolate::Scope scope(CcTest::isolate());
   13474             :   if (kLogThreading)
   13475             :     printf("Start test %s #%d\n",
   13476             :            RegisterThreadedTest::nth(test_number_)->name(), test_number_);
   13477         480 :   CallTestNumber(test_number_);
   13478             :   if (kLogThreading)
   13479             :     printf("End test %s #%d\n", RegisterThreadedTest::nth(test_number_)->name(),
   13480             :            test_number_);
   13481         480 : }
   13482             : 
   13483             : #define THREADING_TEST(INDEX, NAME)            \
   13484             :   TEST(Threading##INDEX) {                     \
   13485             :     ApiTestFuzzer::SetUp(ApiTestFuzzer::NAME); \
   13486             :     ApiTestFuzzer::RunAllTests();              \
   13487             :     ApiTestFuzzer::TearDown();                 \
   13488             :   }
   13489             : 
   13490       26641 : THREADING_TEST(1, FIRST_PART)
   13491       26641 : THREADING_TEST(2, SECOND_PART)
   13492       26641 : THREADING_TEST(3, THIRD_PART)
   13493       26641 : THREADING_TEST(4, FOURTH_PART)
   13494       26641 : THREADING_TEST(5, FIFTH_PART)
   13495       26641 : THREADING_TEST(6, SIXTH_PART)
   13496       26641 : THREADING_TEST(7, SEVENTH_PART)
   13497       26641 : THREADING_TEST(8, EIGHTH_PART)
   13498             : 
   13499             : #undef THREADING_TEST
   13500             : 
   13501           5 : static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13502             :   v8::Isolate* isolate = args.GetIsolate();
   13503           5 :   CHECK(v8::Locker::IsLocked(isolate));
   13504           5 :   ApiTestFuzzer::Fuzz();
   13505           5 :   v8::Unlocker unlocker(isolate);
   13506             :   const char* code = "throw 7;";
   13507             :   {
   13508           5 :     v8::Locker nested_locker(isolate);
   13509          10 :     v8::HandleScope scope(isolate);
   13510             :     v8::Local<Value> exception;
   13511             :     {
   13512          10 :       v8::TryCatch try_catch(isolate);
   13513             :       v8::Local<Value> value = CompileRun(code);
   13514           5 :       CHECK(value.IsEmpty());
   13515           5 :       CHECK(try_catch.HasCaught());
   13516             :       // Make sure to wrap the exception in a new handle because
   13517             :       // the handle returned from the TryCatch is destroyed
   13518             :       // when the TryCatch is destroyed.
   13519          10 :       exception = Local<Value>::New(isolate, try_catch.Exception());
   13520             :     }
   13521           5 :     args.GetIsolate()->ThrowException(exception);
   13522             :   }
   13523           5 : }
   13524             : 
   13525             : 
   13526           5 : static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13527           5 :   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13528           5 :   ApiTestFuzzer::Fuzz();
   13529          10 :   v8::Unlocker unlocker(CcTest::isolate());
   13530             :   const char* code = "throw 7;";
   13531             :   {
   13532          10 :     v8::Locker nested_locker(CcTest::isolate());
   13533          10 :     v8::HandleScope scope(args.GetIsolate());
   13534             :     v8::Local<Value> value = CompileRun(code);
   13535           5 :     CHECK(value.IsEmpty());
   13536           5 :     args.GetReturnValue().Set(v8_str("foo"));
   13537             :   }
   13538           5 : }
   13539             : 
   13540             : 
   13541             : // These are locking tests that don't need to be run again
   13542             : // as part of the locking aggregation tests.
   13543       26644 : TEST(NestedLockers) {
   13544           5 :   v8::Isolate* isolate = CcTest::isolate();
   13545           5 :   v8::Locker locker(isolate);
   13546           5 :   CHECK(v8::Locker::IsLocked(isolate));
   13547           5 :   LocalContext env;
   13548          10 :   v8::HandleScope scope(env->GetIsolate());
   13549             :   Local<v8::FunctionTemplate> fun_templ =
   13550           5 :       v8::FunctionTemplate::New(isolate, ThrowInJS);
   13551           5 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13552          20 :   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13553             :   Local<Script> script = v8_compile("(function () {"
   13554             :                                     "  try {"
   13555             :                                     "    throw_in_js();"
   13556             :                                     "    return 42;"
   13557             :                                     "  } catch (e) {"
   13558             :                                     "    return e * 13;"
   13559             :                                     "  }"
   13560             :                                     "})();");
   13561          15 :   CHECK_EQ(91, script->Run(env.local())
   13562             :                    .ToLocalChecked()
   13563             :                    ->Int32Value(env.local())
   13564             :                    .FromJust());
   13565           5 : }
   13566             : 
   13567             : 
   13568             : // These are locking tests that don't need to be run again
   13569             : // as part of the locking aggregation tests.
   13570       26644 : TEST(NestedLockersNoTryCatch) {
   13571          10 :   v8::Locker locker(CcTest::isolate());
   13572           5 :   LocalContext env;
   13573          10 :   v8::HandleScope scope(env->GetIsolate());
   13574             :   Local<v8::FunctionTemplate> fun_templ =
   13575           5 :       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
   13576           5 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13577          20 :   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13578             :   Local<Script> script = v8_compile("(function () {"
   13579             :                                     "  try {"
   13580             :                                     "    throw_in_js();"
   13581             :                                     "    return 42;"
   13582             :                                     "  } catch (e) {"
   13583             :                                     "    return e * 13;"
   13584             :                                     "  }"
   13585             :                                     "})();");
   13586          15 :   CHECK_EQ(91, script->Run(env.local())
   13587             :                    .ToLocalChecked()
   13588             :                    ->Int32Value(env.local())
   13589             :                    .FromJust());
   13590           5 : }
   13591             : 
   13592             : 
   13593       26645 : THREADED_TEST(RecursiveLocking) {
   13594          12 :   v8::Locker locker(CcTest::isolate());
   13595             :   {
   13596          12 :     v8::Locker locker2(CcTest::isolate());
   13597           6 :     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13598             :   }
   13599           6 : }
   13600             : 
   13601             : 
   13602          12 : static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13603          12 :   ApiTestFuzzer::Fuzz();
   13604          24 :   v8::Unlocker unlocker(CcTest::isolate());
   13605          12 : }
   13606             : 
   13607             : 
   13608       26645 : THREADED_TEST(LockUnlockLock) {
   13609             :   {
   13610          12 :     v8::Locker locker(CcTest::isolate());
   13611          12 :     v8::HandleScope scope(CcTest::isolate());
   13612           6 :     LocalContext env;
   13613             :     Local<v8::FunctionTemplate> fun_templ =
   13614           6 :         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13615           6 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13616          24 :     CHECK(env->Global()
   13617             :               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13618             :               .FromJust());
   13619             :     Local<Script> script = v8_compile("(function () {"
   13620             :                                       "  unlock_for_a_moment();"
   13621             :                                       "  return 42;"
   13622             :                                       "})();");
   13623          18 :     CHECK_EQ(42, script->Run(env.local())
   13624             :                      .ToLocalChecked()
   13625             :                      ->Int32Value(env.local())
   13626             :                      .FromJust());
   13627             :   }
   13628             :   {
   13629          12 :     v8::Locker locker(CcTest::isolate());
   13630          12 :     v8::HandleScope scope(CcTest::isolate());
   13631           6 :     LocalContext env;
   13632             :     Local<v8::FunctionTemplate> fun_templ =
   13633           6 :         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13634           6 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13635          24 :     CHECK(env->Global()
   13636             :               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13637             :               .FromJust());
   13638             :     Local<Script> script = v8_compile("(function () {"
   13639             :                                       "  unlock_for_a_moment();"
   13640             :                                       "  return 42;"
   13641             :                                       "})();");
   13642          18 :     CHECK_EQ(42, script->Run(env.local())
   13643             :                      .ToLocalChecked()
   13644             :                      ->Int32Value(env.local())
   13645             :                      .FromJust());
   13646             :   }
   13647           6 : }
   13648             : 
   13649             : 
   13650         130 : static int GetGlobalObjectsCount() {
   13651             :   int count = 0;
   13652         260 :   i::HeapIterator it(CcTest::heap());
   13653      705689 :   for (i::HeapObject object = it.next(); !object.is_null();
   13654             :        object = it.next()) {
   13655      705559 :     if (object->IsJSGlobalObject()) {
   13656             :       i::JSGlobalObject g = i::JSGlobalObject::cast(object);
   13657             :       // Skip dummy global object.
   13658          30 :       if (g->global_dictionary()->NumberOfElements() != 0) {
   13659          30 :         count++;
   13660             :       }
   13661             :     }
   13662             :   }
   13663         130 :   return count;
   13664             : }
   13665             : 
   13666             : 
   13667         100 : static void CheckSurvivingGlobalObjectsCount(int expected) {
   13668             :   // We need to collect all garbage twice to be sure that everything
   13669             :   // has been collected.  This is because inline caches are cleared in
   13670             :   // the first garbage collection but some of the maps have already
   13671             :   // been marked at that point.  Therefore some of the maps are not
   13672             :   // collected until the second garbage collection.
   13673         100 :   CcTest::CollectAllGarbage();
   13674         100 :   CcTest::CollectAllGarbage();
   13675         100 :   int count = GetGlobalObjectsCount();
   13676         100 :   CHECK_EQ(expected, count);
   13677         100 : }
   13678             : 
   13679             : 
   13680       26644 : TEST(DontLeakGlobalObjects) {
   13681             :   // Regression test for issues 1139850 and 1174891.
   13682             : 
   13683           5 :   i::FLAG_expose_gc = true;
   13684           5 :   v8::V8::Initialize();
   13685             : 
   13686          55 :   for (int i = 0; i < 5; i++) {
   13687          50 :     { v8::HandleScope scope(CcTest::isolate());
   13688          25 :       LocalContext context;
   13689             :     }
   13690          25 :     CcTest::isolate()->ContextDisposedNotification();
   13691          25 :     CheckSurvivingGlobalObjectsCount(0);
   13692             : 
   13693          50 :     { v8::HandleScope scope(CcTest::isolate());
   13694          25 :       LocalContext context;
   13695          25 :       v8_compile("Date")->Run(context.local()).ToLocalChecked();
   13696             :     }
   13697          25 :     CcTest::isolate()->ContextDisposedNotification();
   13698          25 :     CheckSurvivingGlobalObjectsCount(0);
   13699             : 
   13700          50 :     { v8::HandleScope scope(CcTest::isolate());
   13701          25 :       LocalContext context;
   13702          25 :       v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
   13703             :     }
   13704          25 :     CcTest::isolate()->ContextDisposedNotification();
   13705          25 :     CheckSurvivingGlobalObjectsCount(0);
   13706             : 
   13707          50 :     { v8::HandleScope scope(CcTest::isolate());
   13708          25 :       const char* extension_list[] = { "v8/gc" };
   13709             :       v8::ExtensionConfiguration extensions(1, extension_list);
   13710          25 :       LocalContext context(&extensions);
   13711          25 :       v8_compile("gc();")->Run(context.local()).ToLocalChecked();
   13712             :     }
   13713          25 :     CcTest::isolate()->ContextDisposedNotification();
   13714          25 :     CheckSurvivingGlobalObjectsCount(0);
   13715             :   }
   13716           5 : }
   13717             : 
   13718             : 
   13719       26644 : TEST(CopyablePersistent) {
   13720           5 :   LocalContext context;
   13721           5 :   v8::Isolate* isolate = context->GetIsolate();
   13722             :   i::GlobalHandles* globals =
   13723             :       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13724             :   size_t initial_handles = globals->handles_count();
   13725             :   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
   13726             :       CopyableObject;
   13727             :   {
   13728             :     CopyableObject handle1;
   13729             :     {
   13730          10 :       v8::HandleScope scope(isolate);
   13731          10 :       handle1.Reset(isolate, v8::Object::New(isolate));
   13732             :     }
   13733           5 :     CHECK_EQ(initial_handles + 1, globals->handles_count());
   13734             :     CopyableObject  handle2;
   13735             :     handle2 = handle1;
   13736           5 :     CHECK(handle1 == handle2);
   13737           5 :     CHECK_EQ(initial_handles + 2, globals->handles_count());
   13738             :     CopyableObject handle3(handle2);
   13739           5 :     CHECK(handle1 == handle3);
   13740           5 :     CHECK_EQ(initial_handles + 3, globals->handles_count());
   13741             :   }
   13742             :   // Verify autodispose
   13743           5 :   CHECK_EQ(initial_handles, globals->handles_count());
   13744           5 : }
   13745             : 
   13746             : 
   13747           5 : static void WeakApiCallback(
   13748             :     const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
   13749             :   data.GetParameter()->Reset();
   13750          10 :   delete data.GetParameter();
   13751           5 : }
   13752             : 
   13753             : 
   13754       26644 : TEST(WeakCallbackApi) {
   13755           5 :   LocalContext context;
   13756           5 :   v8::Isolate* isolate = context->GetIsolate();
   13757             :   i::GlobalHandles* globals =
   13758             :       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13759             :   size_t initial_handles = globals->handles_count();
   13760             :   {
   13761          10 :     v8::HandleScope scope(isolate);
   13762           5 :     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   13763          20 :     CHECK(
   13764             :         obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
   13765             :             .FromJust());
   13766             :     v8::Persistent<v8::Object>* handle =
   13767           5 :         new v8::Persistent<v8::Object>(isolate, obj);
   13768             :     handle->SetWeak<v8::Persistent<v8::Object>>(
   13769             :         handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
   13770             :   }
   13771           5 :   CcTest::PreciseCollectAllGarbage();
   13772             :   // Verify disposed.
   13773           5 :   CHECK_EQ(initial_handles, globals->handles_count());
   13774           5 : }
   13775             : 
   13776             : 
   13777       26639 : v8::Persistent<v8::Object> some_object;
   13778       26639 : v8::Persistent<v8::Object> bad_handle;
   13779             : 
   13780             : 
   13781           6 : void NewPersistentHandleCallback2(
   13782             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13783          12 :   v8::HandleScope scope(data.GetIsolate());
   13784             :   bad_handle.Reset(data.GetIsolate(), some_object);
   13785           6 : }
   13786             : 
   13787             : 
   13788           6 : void NewPersistentHandleCallback1(
   13789             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13790             :   data.GetParameter()->Reset();
   13791             :   data.SetSecondPassCallback(NewPersistentHandleCallback2);
   13792           6 : }
   13793             : 
   13794             : 
   13795       26645 : THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   13796           6 :   LocalContext context;
   13797           6 :   v8::Isolate* isolate = context->GetIsolate();
   13798             : 
   13799             :   v8::Persistent<v8::Object> handle1, handle2;
   13800             :   {
   13801          12 :     v8::HandleScope scope(isolate);
   13802          12 :     some_object.Reset(isolate, v8::Object::New(isolate));
   13803          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   13804          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   13805             :   }
   13806             :   // Note: order is implementation dependent alas: currently
   13807             :   // global handle nodes are processed by PostGarbageCollectionProcessing
   13808             :   // in reverse allocation order, so if second allocated handle is deleted,
   13809             :   // weak callback of the first handle would be able to 'reallocate' it.
   13810             :   handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
   13811             :                   v8::WeakCallbackType::kParameter);
   13812             :   handle2.Reset();
   13813           6 :   CcTest::CollectAllGarbage();
   13814           6 : }
   13815             : 
   13816             : 
   13817       26639 : v8::Persistent<v8::Object> to_be_disposed;
   13818             : 
   13819             : 
   13820           6 : void DisposeAndForceGcCallback2(
   13821             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13822             :   to_be_disposed.Reset();
   13823           6 :   CcTest::CollectAllGarbage();
   13824           6 : }
   13825             : 
   13826             : 
   13827           6 : void DisposeAndForceGcCallback1(
   13828             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13829             :   data.GetParameter()->Reset();
   13830             :   data.SetSecondPassCallback(DisposeAndForceGcCallback2);
   13831           6 : }
   13832             : 
   13833             : 
   13834       26645 : THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   13835           6 :   LocalContext context;
   13836           6 :   v8::Isolate* isolate = context->GetIsolate();
   13837             : 
   13838             :   v8::Persistent<v8::Object> handle1, handle2;
   13839             :   {
   13840          12 :     v8::HandleScope scope(isolate);
   13841          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   13842          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   13843             :   }
   13844             :   handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
   13845             :                   v8::WeakCallbackType::kParameter);
   13846             :   to_be_disposed.Reset(isolate, handle2);
   13847           6 :   CcTest::CollectAllGarbage();
   13848           6 : }
   13849             : 
   13850           6 : void DisposingCallback(
   13851             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13852             :   data.GetParameter()->Reset();
   13853           6 : }
   13854             : 
   13855           6 : void HandleCreatingCallback2(
   13856             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13857          12 :   v8::HandleScope scope(data.GetIsolate());
   13858           6 :   v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
   13859           6 : }
   13860             : 
   13861             : 
   13862           6 : void HandleCreatingCallback1(
   13863             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13864             :   data.GetParameter()->Reset();
   13865             :   data.SetSecondPassCallback(HandleCreatingCallback2);
   13866           6 : }
   13867             : 
   13868             : 
   13869       26645 : THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   13870          12 :   v8::Locker locker(CcTest::isolate());
   13871           6 :   LocalContext context;
   13872           6 :   v8::Isolate* isolate = context->GetIsolate();
   13873             : 
   13874             :   v8::Persistent<v8::Object> handle1, handle2, handle3;
   13875             :   {
   13876          12 :     v8::HandleScope scope(isolate);
   13877          12 :     handle3.Reset(isolate, v8::Object::New(isolate));
   13878          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   13879          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   13880             :   }
   13881             :   handle2.SetWeak(&handle2, DisposingCallback,
   13882             :                   v8::WeakCallbackType::kParameter);
   13883             :   handle3.SetWeak(&handle3, HandleCreatingCallback1,
   13884             :                   v8::WeakCallbackType::kParameter);
   13885           6 :   CcTest::CollectAllGarbage();
   13886           6 :   EmptyMessageQueues(isolate);
   13887           6 : }
   13888             : 
   13889             : 
   13890       26645 : THREADED_TEST(CheckForCrossContextObjectLiterals) {
   13891           6 :   v8::V8::Initialize();
   13892             : 
   13893             :   const int nof = 2;
   13894             :   const char* sources[nof] = {
   13895             :     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   13896             :     "Object()"
   13897           6 :   };
   13898             : 
   13899          30 :   for (int i = 0; i < nof; i++) {
   13900          12 :     const char* source = sources[i];
   13901          24 :     { v8::HandleScope scope(CcTest::isolate());
   13902          12 :       LocalContext context;
   13903             :       CompileRun(source);
   13904             :     }
   13905          24 :     { v8::HandleScope scope(CcTest::isolate());
   13906          12 :       LocalContext context;
   13907             :       CompileRun(source);
   13908             :     }
   13909             :   }
   13910           6 : }
   13911             : 
   13912             : 
   13913           6 : static v8::Local<Value> NestedScope(v8::Local<Context> env) {
   13914           6 :   v8::EscapableHandleScope inner(env->GetIsolate());
   13915           6 :   env->Enter();
   13916           6 :   v8::Local<Value> three = v8_num(3);
   13917             :   v8::Local<Value> value = inner.Escape(three);
   13918           6 :   env->Exit();
   13919          12 :   return value;
   13920             : }
   13921             : 
   13922             : 
   13923       26645 : THREADED_TEST(NestedHandleScopeAndContexts) {
   13924           6 :   v8::Isolate* isolate = CcTest::isolate();
   13925          12 :   v8::HandleScope outer(isolate);
   13926           6 :   v8::Local<Context> env = Context::New(isolate);
   13927           6 :   env->Enter();
   13928           6 :   v8::Local<Value> value = NestedScope(env);
   13929           6 :   v8::Local<String> str(value->ToString(env).ToLocalChecked());
   13930           6 :   CHECK(!str.IsEmpty());
   13931           6 :   env->Exit();
   13932           6 : }
   13933             : 
   13934             : static v8::base::HashMap* code_map = nullptr;
   13935             : static v8::base::HashMap* jitcode_line_info = nullptr;
   13936             : static int saw_bar = 0;
   13937             : static int move_events = 0;
   13938             : 
   13939             : 
   13940        5441 : static bool FunctionNameIs(const char* expected,
   13941             :                            const v8::JitCodeEvent* event) {
   13942             :   // Log lines for functions are of the general form:
   13943             :   // "LazyCompile:<type><function_name>" or Function:<type><function_name>,
   13944             :   // where the type is one of "*", "~" or "".
   13945             :   static const char* kPreamble;
   13946        5441 :   if (!i::FLAG_lazy) {
   13947           0 :     kPreamble = "Function:";
   13948             :   } else {
   13949        5441 :     kPreamble = "LazyCompile:";
   13950             :   }
   13951        5441 :   static size_t kPreambleLen = strlen(kPreamble);
   13952             : 
   13953       10827 :   if (event->name.len < kPreambleLen ||
   13954        5386 :       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   13955             :     return false;
   13956             :   }
   13957             : 
   13958         153 :   const char* tail = event->name.str + kPreambleLen;
   13959         153 :   size_t tail_len = event->name.len - kPreambleLen;
   13960         153 :   size_t expected_len = strlen(expected);
   13961         153 :   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   13962         148 :     --tail_len;
   13963         148 :     ++tail;
   13964             :   }
   13965             : 
   13966             :   // Check for tails like 'bar :1'.
   13967         285 :   if (tail_len > expected_len + 2 &&
   13968         264 :       tail[expected_len] == ' ' &&
   13969         264 :       tail[expected_len + 1] == ':' &&
   13970         264 :       tail[expected_len + 2] &&
   13971         132 :       !strncmp(tail, expected, expected_len)) {
   13972             :     return true;
   13973             :   }
   13974             : 
   13975          87 :   if (tail_len != expected_len)
   13976             :     return false;
   13977             : 
   13978          21 :   return strncmp(tail, expected, expected_len) == 0;
   13979             : }
   13980             : 
   13981             : 
   13982        7769 : static void event_handler(const v8::JitCodeEvent* event) {
   13983        7769 :   CHECK_NOT_NULL(event);
   13984        7769 :   CHECK_NOT_NULL(code_map);
   13985        7769 :   CHECK_NOT_NULL(jitcode_line_info);
   13986             : 
   13987             :   class DummyJitCodeLineInfo {
   13988             :   };
   13989             : 
   13990        7769 :   switch (event->type) {
   13991             :     case v8::JitCodeEvent::CODE_ADDED: {
   13992        5441 :       CHECK_NOT_NULL(event->code_start);
   13993        5441 :       CHECK_NE(0, static_cast<int>(event->code_len));
   13994        5441 :       CHECK_NOT_NULL(event->name.str);
   13995        5441 :       v8::base::HashMap::Entry* entry = code_map->LookupOrInsert(
   13996             :           event->code_start, i::ComputePointerHash(event->code_start));
   13997        5441 :       entry->value = reinterpret_cast<void*>(event->code_len);
   13998             : 
   13999        5441 :       if (FunctionNameIs("bar", event)) {
   14000          66 :         ++saw_bar;
   14001             :         }
   14002             :       }
   14003             :       break;
   14004             : 
   14005             :     case v8::JitCodeEvent::CODE_MOVED: {
   14006         198 :         uint32_t hash = i::ComputePointerHash(event->code_start);
   14007             :         // We would like to never see code move that we haven't seen before,
   14008             :         // but the code creation event does not happen until the line endings
   14009             :         // have been calculated (this is so that we can report the line in the
   14010             :         // script at which the function source is found, see
   14011             :         // Compiler::RecordFunctionCompilation) and the line endings
   14012             :         // calculations can cause a GC, which can move the newly created code
   14013             :         // before its existence can be logged.
   14014             :         v8::base::HashMap::Entry* entry =
   14015             :             code_map->Lookup(event->code_start, hash);
   14016         198 :         if (entry != nullptr) {
   14017         198 :           ++move_events;
   14018             : 
   14019         198 :           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   14020         198 :           code_map->Remove(event->code_start, hash);
   14021             : 
   14022         198 :           entry = code_map->LookupOrInsert(
   14023             :               event->new_code_start,
   14024         198 :               i::ComputePointerHash(event->new_code_start));
   14025         198 :           entry->value = reinterpret_cast<void*>(event->code_len);
   14026             :         }
   14027             :       }
   14028             :       break;
   14029             : 
   14030             :     case v8::JitCodeEvent::CODE_REMOVED:
   14031             :       // Object/code removal events are currently not dispatched from the GC.
   14032           0 :       UNREACHABLE();
   14033             : 
   14034             :     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   14035             :     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   14036             :     // record it in jitcode_line_info.
   14037             :     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   14038         180 :         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   14039             :         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   14040         180 :         temp_event->user_data = line_info;
   14041         360 :         v8::base::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
   14042             :             line_info, i::ComputePointerHash(line_info));
   14043         180 :         entry->value = reinterpret_cast<void*>(line_info);
   14044             :       }
   14045         180 :       break;
   14046             :     // For these two events, we will check whether the event->user_data
   14047             :     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   14048             :     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   14049             :     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   14050         180 :       CHECK_NOT_NULL(event->user_data);
   14051             :       uint32_t hash = i::ComputePointerHash(event->user_data);
   14052             :       v8::base::HashMap::Entry* entry =
   14053             :           jitcode_line_info->Lookup(event->user_data, hash);
   14054         180 :       CHECK_NOT_NULL(entry);
   14055         180 :       delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   14056             :       }
   14057         180 :       break;
   14058             : 
   14059             :     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   14060        1770 :       CHECK_NOT_NULL(event->user_data);
   14061             :       uint32_t hash = i::ComputePointerHash(event->user_data);
   14062             :       v8::base::HashMap::Entry* entry =
   14063             :           jitcode_line_info->Lookup(event->user_data, hash);
   14064        1770 :       CHECK_NOT_NULL(entry);
   14065             :       }
   14066             :       break;
   14067             : 
   14068             :     default:
   14069             :       // Impossible event.
   14070           0 :       UNREACHABLE();
   14071             :   }
   14072        7769 : }
   14073             : 
   14074             : 
   14075       26644 : UNINITIALIZED_TEST(SetJitCodeEventHandler) {
   14076           5 :   i::FLAG_stress_compaction = true;
   14077           5 :   i::FLAG_incremental_marking = false;
   14078           5 :   if (i::FLAG_never_compact) return;
   14079             :   const char* script =
   14080             :       "function bar() {"
   14081             :       "  var sum = 0;"
   14082             :       "  for (i = 0; i < 10; ++i)"
   14083             :       "    sum = foo(i);"
   14084             :       "  return sum;"
   14085             :       "}"
   14086             :       "function foo(i) { return i; };"
   14087             :       "bar();";
   14088             : 
   14089             :   // Run this test in a new isolate to make sure we don't
   14090             :   // have remnants of state from other code.
   14091             :   v8::Isolate::CreateParams create_params;
   14092           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14093           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14094           5 :   isolate->Enter();
   14095             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   14096             :   i::Heap* heap = i_isolate->heap();
   14097             : 
   14098             :   // Start with a clean slate.
   14099           5 :   heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
   14100             : 
   14101             :   {
   14102          10 :     v8::HandleScope scope(isolate);
   14103             :     v8::base::HashMap code;
   14104           5 :     code_map = &code;
   14105             : 
   14106             :     v8::base::HashMap lineinfo;
   14107           5 :     jitcode_line_info = &lineinfo;
   14108             : 
   14109           5 :     saw_bar = 0;
   14110           5 :     move_events = 0;
   14111             : 
   14112           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   14113             : 
   14114             :     // Generate new code objects sparsely distributed across several
   14115             :     // different fragmented code-space pages.
   14116             :     const int kIterations = 10;
   14117         105 :     for (int i = 0; i < kIterations; ++i) {
   14118          50 :       LocalContext env(isolate);
   14119             :       i::AlwaysAllocateScope always_allocate(i_isolate);
   14120             :       CompileRun(script);
   14121             : 
   14122             :       // Keep a strong reference to the code object in the handle scope.
   14123             :       i::Handle<i::JSFunction> bar(i::Handle<i::JSFunction>::cast(
   14124         100 :           v8::Utils::OpenHandle(*env->Global()
   14125         150 :                                      ->Get(env.local(), v8_str("bar"))
   14126             :                                      .ToLocalChecked())));
   14127             :       i::Handle<i::JSFunction> foo(i::Handle<i::JSFunction>::cast(
   14128         100 :           v8::Utils::OpenHandle(*env->Global()
   14129         150 :                                      ->Get(env.local(), v8_str("foo"))
   14130             :                                      .ToLocalChecked())));
   14131             : 
   14132             :       i::PagedSpace* foo_owning_space = reinterpret_cast<i::PagedSpace*>(
   14133         100 :           i::Page::FromHeapObject(foo->abstract_code())->owner());
   14134             :       i::PagedSpace* bar_owning_space = reinterpret_cast<i::PagedSpace*>(
   14135         100 :           i::Page::FromHeapObject(bar->abstract_code())->owner());
   14136          50 :       CHECK_EQ(foo_owning_space, bar_owning_space);
   14137          50 :       i::heap::SimulateFullSpace(foo_owning_space);
   14138             : 
   14139             :       // Clear the compilation cache to get more wastage.
   14140          50 :       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
   14141             :     }
   14142             : 
   14143             :     // Force code movement.
   14144           5 :     heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
   14145             : 
   14146           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, nullptr);
   14147             : 
   14148           5 :     CHECK_LE(kIterations, saw_bar);
   14149           5 :     CHECK_LT(0, move_events);
   14150             : 
   14151           5 :     code_map = nullptr;
   14152           5 :     jitcode_line_info = nullptr;
   14153             :   }
   14154             : 
   14155           5 :   isolate->Exit();
   14156           5 :   isolate->Dispose();
   14157             : 
   14158             :   // Do this in a new isolate.
   14159           5 :   isolate = v8::Isolate::New(create_params);
   14160           5 :   isolate->Enter();
   14161             : 
   14162             :   // Verify that we get callbacks for existing code objects when we
   14163             :   // request enumeration of existing code.
   14164             :   {
   14165          10 :     v8::HandleScope scope(isolate);
   14166           5 :     LocalContext env(isolate);
   14167             :     CompileRun(script);
   14168             : 
   14169             :     // Now get code through initial iteration.
   14170             :     v8::base::HashMap code;
   14171           5 :     code_map = &code;
   14172             : 
   14173             :     v8::base::HashMap lineinfo;
   14174           5 :     jitcode_line_info = &lineinfo;
   14175             : 
   14176             :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
   14177           5 :                                     event_handler);
   14178           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, nullptr);
   14179             : 
   14180           5 :     jitcode_line_info = nullptr;
   14181             :     // We expect that we got some events. Note that if we could get code removal
   14182             :     // notifications, we could compare two collections, one created by listening
   14183             :     // from the time of creation of an isolate, and the other by subscribing
   14184             :     // with EnumExisting.
   14185           5 :     CHECK_LT(0u, code.occupancy());
   14186             : 
   14187           5 :     code_map = nullptr;
   14188             :   }
   14189             : 
   14190           5 :   isolate->Exit();
   14191           5 :   isolate->Dispose();
   14192             : }
   14193             : 
   14194       26644 : TEST(ExternalAllocatedMemory) {
   14195           5 :   v8::Isolate* isolate = CcTest::isolate();
   14196          10 :   v8::HandleScope outer(isolate);
   14197           5 :   v8::Local<Context> env(Context::New(isolate));
   14198           5 :   CHECK(!env.IsEmpty());
   14199             :   const int64_t kSize = 1024*1024;
   14200             :   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
   14201           5 :   CHECK_EQ(baseline + kSize,
   14202             :            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   14203           5 :   CHECK_EQ(baseline,
   14204             :            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
   14205             :   const int64_t kTriggerGCSize =
   14206           5 :       CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
   14207           5 :   CHECK_EQ(baseline + kTriggerGCSize,
   14208             :            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
   14209          10 :   CHECK_EQ(baseline,
   14210             :            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
   14211           5 : }
   14212             : 
   14213             : 
   14214       26644 : TEST(Regress51719) {
   14215           5 :   i::FLAG_incremental_marking = false;
   14216           5 :   CcTest::InitializeVM();
   14217             : 
   14218             :   const int64_t kTriggerGCSize =
   14219           5 :       CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
   14220           5 :   v8::Isolate* isolate = CcTest::isolate();
   14221             :   isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
   14222           5 : }
   14223             : 
   14224             : // Regression test for issue 54, object templates with embedder fields
   14225             : // but no accessors or interceptors did not get their embedder field
   14226             : // count set on instances.
   14227       26645 : THREADED_TEST(Regress54) {
   14228           6 :   LocalContext context;
   14229           6 :   v8::Isolate* isolate = context->GetIsolate();
   14230          12 :   v8::HandleScope outer(isolate);
   14231          12 :   static v8::Persistent<v8::ObjectTemplate> templ;
   14232           6 :   if (templ.IsEmpty()) {
   14233           6 :     v8::EscapableHandleScope inner(isolate);
   14234           6 :     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
   14235           6 :     local->SetInternalFieldCount(1);
   14236             :     templ.Reset(isolate, inner.Escape(local));
   14237             :   }
   14238             :   v8::Local<v8::Object> result =
   14239             :       v8::Local<v8::ObjectTemplate>::New(isolate, templ)
   14240           6 :           ->NewInstance(context.local())
   14241             :           .ToLocalChecked();
   14242           6 :   CHECK_EQ(1, result->InternalFieldCount());
   14243           6 : }
   14244             : 
   14245             : 
   14246             : // If part of the threaded tests, this test makes ThreadingTest fail
   14247             : // on mac.
   14248       26644 : TEST(CatchStackOverflow) {
   14249           5 :   LocalContext context;
   14250          10 :   v8::HandleScope scope(context->GetIsolate());
   14251          10 :   v8::TryCatch try_catch(context->GetIsolate());
   14252             :   v8::Local<v8::Value> result = CompileRun(
   14253             :       "function f() {"
   14254             :       "  return f();"
   14255             :       "}"
   14256             :       ""
   14257             :       "f();");
   14258           5 :   CHECK(result.IsEmpty());
   14259           5 : }
   14260             : 
   14261             : 
   14262          18 : static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
   14263             :                                     const char* resource_name,
   14264             :                                     int line_offset) {
   14265          36 :   v8::HandleScope scope(CcTest::isolate());
   14266          36 :   v8::TryCatch try_catch(CcTest::isolate());
   14267          18 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   14268          36 :   CHECK(script->Run(context).IsEmpty());
   14269          18 :   CHECK(try_catch.HasCaught());
   14270          18 :   v8::Local<v8::Message> message = try_catch.Message();
   14271          18 :   CHECK(!message.IsEmpty());
   14272          36 :   CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
   14273          18 :   CHECK_EQ(91, message->GetStartPosition());
   14274          18 :   CHECK_EQ(92, message->GetEndPosition());
   14275          36 :   CHECK_EQ(2, message->GetStartColumn(context).FromJust());
   14276          36 :   CHECK_EQ(3, message->GetEndColumn(context).FromJust());
   14277             :   v8::String::Utf8Value line(CcTest::isolate(),
   14278          54 :                              message->GetSourceLine(context).ToLocalChecked());
   14279          18 :   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
   14280             :   v8::String::Utf8Value name(CcTest::isolate(),
   14281          54 :                              message->GetScriptOrigin().ResourceName());
   14282          18 :   CHECK_EQ(0, strcmp(resource_name, *name));
   14283          18 : }
   14284             : 
   14285             : 
   14286       26645 : THREADED_TEST(TryCatchSourceInfo) {
   14287           6 :   LocalContext context;
   14288          12 :   v8::HandleScope scope(context->GetIsolate());
   14289             :   v8::Local<v8::String> source = v8_str(
   14290             :       "function Foo() {\n"
   14291             :       "  return Bar();\n"
   14292             :       "}\n"
   14293             :       "\n"
   14294             :       "function Bar() {\n"
   14295             :       "  return Baz();\n"
   14296             :       "}\n"
   14297             :       "\n"
   14298             :       "function Baz() {\n"
   14299             :       "  throw 'nirk';\n"
   14300             :       "}\n"
   14301             :       "\n"
   14302           6 :       "Foo();\n");
   14303             : 
   14304             :   const char* resource_name;
   14305             :   v8::Local<v8::Script> script;
   14306             :   resource_name = "test.js";
   14307           6 :   script = CompileWithOrigin(source, resource_name, false);
   14308           6 :   CheckTryCatchSourceInfo(script, resource_name, 0);
   14309             : 
   14310             :   resource_name = "test1.js";
   14311           6 :   v8::ScriptOrigin origin1(v8_str(resource_name));
   14312             :   script =
   14313          12 :       v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
   14314           6 :   CheckTryCatchSourceInfo(script, resource_name, 0);
   14315             : 
   14316             :   resource_name = "test2.js";
   14317             :   v8::ScriptOrigin origin2(v8_str(resource_name),
   14318           6 :                            v8::Integer::New(context->GetIsolate(), 7));
   14319             :   script =
   14320          12 :       v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
   14321           6 :   CheckTryCatchSourceInfo(script, resource_name, 7);
   14322           6 : }
   14323             : 
   14324             : 
   14325       26645 : THREADED_TEST(TryCatchSourceInfoForEOSError) {
   14326           6 :   LocalContext context;
   14327          12 :   v8::HandleScope scope(context->GetIsolate());
   14328          12 :   v8::TryCatch try_catch(context->GetIsolate());
   14329          18 :   CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
   14330           6 :   CHECK(try_catch.HasCaught());
   14331           6 :   v8::Local<v8::Message> message = try_catch.Message();
   14332          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   14333          12 :   CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
   14334           6 : }
   14335             : 
   14336             : 
   14337       26645 : THREADED_TEST(CompilationCache) {
   14338           6 :   LocalContext context;
   14339          12 :   v8::HandleScope scope(context->GetIsolate());
   14340           6 :   v8::Local<v8::String> source0 = v8_str("1234");
   14341           6 :   v8::Local<v8::String> source1 = v8_str("1234");
   14342           6 :   v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js", false);
   14343           6 :   v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js", false);
   14344           6 :   v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
   14345             :                                       .ToLocalChecked();  // different origin
   14346          18 :   CHECK_EQ(1234, script0->Run(context.local())
   14347             :                      .ToLocalChecked()
   14348             :                      ->Int32Value(context.local())
   14349             :                      .FromJust());
   14350          18 :   CHECK_EQ(1234, script1->Run(context.local())
   14351             :                      .ToLocalChecked()
   14352             :                      ->Int32Value(context.local())
   14353             :                      .FromJust());
   14354          18 :   CHECK_EQ(1234, script2->Run(context.local())
   14355             :                      .ToLocalChecked()
   14356             :                      ->Int32Value(context.local())
   14357             :                      .FromJust());
   14358           6 : }
   14359             : 
   14360             : 
   14361           0 : static void FunctionNameCallback(
   14362             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   14363           0 :   ApiTestFuzzer::Fuzz();
   14364           0 :   args.GetReturnValue().Set(v8_num(42));
   14365           0 : }
   14366             : 
   14367             : 
   14368       26645 : THREADED_TEST(CallbackFunctionName) {
   14369           6 :   LocalContext context;
   14370           6 :   v8::Isolate* isolate = context->GetIsolate();
   14371          12 :   v8::HandleScope scope(isolate);
   14372           6 :   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   14373          18 :   t->Set(v8_str("asdf"),
   14374           6 :          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
   14375          30 :   CHECK(context->Global()
   14376             :             ->Set(context.local(), v8_str("obj"),
   14377             :                   t->NewInstance(context.local()).ToLocalChecked())
   14378             :             .FromJust());
   14379             :   v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
   14380           6 :   CHECK(value->IsString());
   14381          12 :   v8::String::Utf8Value name(isolate, value);
   14382           6 :   CHECK_EQ(0, strcmp("asdf", *name));
   14383           6 : }
   14384             : 
   14385             : 
   14386       26645 : THREADED_TEST(DateAccess) {
   14387           6 :   LocalContext context;
   14388          12 :   v8::HandleScope scope(context->GetIsolate());
   14389             :   v8::Local<v8::Value> date =
   14390           6 :       v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
   14391           6 :   CHECK(date->IsDate());
   14392           6 :   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   14393           6 : }
   14394             : 
   14395          48 : void CheckIsSymbolAt(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   14396             :                      unsigned index, const char* name) {
   14397          48 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14398             :   v8::Local<v8::Value> value =
   14399         144 :       properties->Get(context, v8::Integer::New(isolate, index))
   14400             :           .ToLocalChecked();
   14401          48 :   CHECK(value->IsSymbol());
   14402             :   v8::String::Utf8Value symbol_name(isolate,
   14403          96 :                                     Local<Symbol>::Cast(value)->Name());
   14404          48 :   if (strcmp(name, *symbol_name) != 0) {
   14405             :     FATAL("properties[%u] was Symbol('%s') instead of Symbol('%s').", index,
   14406           0 :           name, *symbol_name);
   14407             :   }
   14408          48 : }
   14409             : 
   14410         150 : void CheckStringArray(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   14411             :                       unsigned length, const char* names[]) {
   14412         150 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14413         150 :   CHECK_EQ(length, properties->Length());
   14414        1998 :   for (unsigned i = 0; i < length; i++) {
   14415             :     v8::Local<v8::Value> value =
   14416        2772 :         properties->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
   14417         924 :     if (names[i] == nullptr) {
   14418             :       DCHECK(value->IsSymbol());
   14419             :     } else {
   14420        1752 :       v8::String::Utf8Value elm(isolate, value);
   14421         876 :       if (strcmp(names[i], *elm) != 0) {
   14422           0 :         FATAL("properties[%u] was '%s' instead of '%s'.", i, *elm, names[i]);
   14423             :       }
   14424             :     }
   14425             :   }
   14426         150 : }
   14427             : 
   14428          42 : void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   14429             :                      unsigned length, const char* names[]) {
   14430          42 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14431             :   v8::Local<v8::Object> obj = val.As<v8::Object>();
   14432          84 :   v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
   14433          42 :   CheckStringArray(isolate, props, length, names);
   14434          42 : }
   14435             : 
   14436             : 
   14437          24 : void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   14438             :                         unsigned elmc, const char* elmv[]) {
   14439          24 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14440             :   v8::Local<v8::Object> obj = val.As<v8::Object>();
   14441             :   v8::Local<v8::Array> props =
   14442          24 :       obj->GetOwnPropertyNames(context).ToLocalChecked();
   14443          24 :   CHECK_EQ(elmc, props->Length());
   14444         108 :   for (unsigned i = 0; i < elmc; i++) {
   14445             :     v8::String::Utf8Value elm(
   14446             :         isolate,
   14447         168 :         props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
   14448          42 :     CHECK_EQ(0, strcmp(elmv[i], *elm));
   14449             :   }
   14450          24 : }
   14451             : 
   14452             : 
   14453       26645 : THREADED_TEST(PropertyEnumeration) {
   14454           6 :   LocalContext context;
   14455           6 :   v8::Isolate* isolate = context->GetIsolate();
   14456          12 :   v8::HandleScope scope(isolate);
   14457             :   v8::Local<v8::Value> obj = CompileRun(
   14458             :       "var result = [];"
   14459             :       "result[0] = {};"
   14460             :       "result[1] = {a: 1, b: 2};"
   14461             :       "result[2] = [1, 2, 3];"
   14462             :       "var proto = {x: 1, y: 2, z: 3};"
   14463             :       "var x = { __proto__: proto, w: 0, z: 1 };"
   14464             :       "result[3] = x;"
   14465             :       "result[4] = {21350:1};"
   14466             :       "x = Object.create(null);"
   14467             :       "x.a = 1; x[12345678] = 1;"
   14468             :       "result[5] = x;"
   14469             :       "result;");
   14470             :   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   14471           6 :   CHECK_EQ(6u, elms->Length());
   14472             :   int elmc0 = 0;
   14473             :   const char** elmv0 = nullptr;
   14474             :   CheckProperties(
   14475             :       isolate,
   14476          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14477           6 :       elmc0, elmv0);
   14478             :   CheckOwnProperties(
   14479             :       isolate,
   14480          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14481           6 :       elmc0, elmv0);
   14482             :   int elmc1 = 2;
   14483           6 :   const char* elmv1[] = {"a", "b"};
   14484             :   CheckProperties(
   14485             :       isolate,
   14486          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   14487           6 :       elmc1, elmv1);
   14488             :   CheckOwnProperties(
   14489             :       isolate,
   14490          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   14491           6 :       elmc1, elmv1);
   14492             :   int elmc2 = 3;
   14493           6 :   const char* elmv2[] = {"0", "1", "2"};
   14494             :   CheckProperties(
   14495             :       isolate,
   14496          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   14497           6 :       elmc2, elmv2);
   14498             :   CheckOwnProperties(
   14499             :       isolate,
   14500          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   14501           6 :       elmc2, elmv2);
   14502             :   int elmc3 = 4;
   14503           6 :   const char* elmv3[] = {"w", "z", "x", "y"};
   14504             :   CheckProperties(
   14505             :       isolate,
   14506          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   14507           6 :       elmc3, elmv3);
   14508             :   int elmc4 = 2;
   14509           6 :   const char* elmv4[] = {"w", "z"};
   14510             :   CheckOwnProperties(
   14511             :       isolate,
   14512          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   14513           6 :       elmc4, elmv4);
   14514             :   // Dictionary elements.
   14515             :   int elmc5 = 1;
   14516           6 :   const char* elmv5[] = {"21350"};
   14517             :   CheckProperties(
   14518             :       isolate,
   14519          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 4)).ToLocalChecked(),
   14520           6 :       elmc5, elmv5);
   14521             :   // Dictionary properties.
   14522             :   int elmc6 = 2;
   14523           6 :   const char* elmv6[] = {"12345678", "a"};
   14524             :   CheckProperties(
   14525             :       isolate,
   14526          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 5)).ToLocalChecked(),
   14527           6 :       elmc6, elmv6);
   14528           6 : }
   14529             : 
   14530             : 
   14531       26645 : THREADED_TEST(PropertyEnumeration2) {
   14532           6 :   LocalContext context;
   14533           6 :   v8::Isolate* isolate = context->GetIsolate();
   14534          12 :   v8::HandleScope scope(isolate);
   14535             :   v8::Local<v8::Value> obj = CompileRun(
   14536             :       "var result = [];"
   14537             :       "result[0] = {};"
   14538             :       "result[1] = {a: 1, b: 2};"
   14539             :       "result[2] = [1, 2, 3];"
   14540             :       "var proto = {x: 1, y: 2, z: 3};"
   14541             :       "var x = { __proto__: proto, w: 0, z: 1 };"
   14542             :       "result[3] = x;"
   14543             :       "result;");
   14544             :   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   14545           6 :   CHECK_EQ(4u, elms->Length());
   14546             :   int elmc0 = 0;
   14547             :   const char** elmv0 = nullptr;
   14548             :   CheckProperties(
   14549             :       isolate,
   14550          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14551           6 :       elmc0, elmv0);
   14552             : 
   14553             :   v8::Local<v8::Value> val =
   14554          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
   14555             :   v8::Local<v8::Array> props =
   14556           6 :       val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
   14557           6 :   CHECK_EQ(0u, props->Length());
   14558           6 :   for (uint32_t i = 0; i < props->Length(); i++) {
   14559             :     printf("p[%u]\n", i);
   14560             :   }
   14561           6 : }
   14562             : 
   14563       26645 : THREADED_TEST(GetPropertyNames) {
   14564           6 :   LocalContext context;
   14565           6 :   v8::Isolate* isolate = context->GetIsolate();
   14566          12 :   v8::HandleScope scope(isolate);
   14567             :   v8::Local<v8::Value> result = CompileRun(
   14568             :       "var result = {0: 0, 1: 1, a: 2, b: 3};"
   14569             :       "result[2**32] = '4294967296';"
   14570             :       "result[2**32-1] = '4294967295';"
   14571             :       "result[2**32-2] = '4294967294';"
   14572             :       "result[Symbol('symbol')] = true;"
   14573             :       "result.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
   14574             :       "result;");
   14575             :   v8::Local<v8::Object> object = result.As<v8::Object>();
   14576             :   v8::PropertyFilter default_filter =
   14577             :       static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
   14578             :   v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
   14579             : 
   14580             :   v8::Local<v8::Array> properties =
   14581          12 :       object->GetPropertyNames(context.local()).ToLocalChecked();
   14582             :   const char* expected_properties1[] = {"0", "1",          "4294967294", "a",
   14583             :                                         "b", "4294967296", "4294967295", "2",
   14584           6 :                                         "3", "c",          "d"};
   14585           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   14586             : 
   14587             :   properties =
   14588             :       object
   14589           6 :           ->GetPropertyNames(context.local(),
   14590             :                              v8::KeyCollectionMode::kIncludePrototypes,
   14591             :                              default_filter, v8::IndexFilter::kIncludeIndices)
   14592           6 :           .ToLocalChecked();
   14593           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   14594             : 
   14595             :   properties = object
   14596           6 :                    ->GetPropertyNames(context.local(),
   14597             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   14598             :                                       include_symbols_filter,
   14599             :                                       v8::IndexFilter::kIncludeIndices)
   14600           6 :                    .ToLocalChecked();
   14601             :   const char* expected_properties1_1[] = {
   14602             :       "0",          "1",     "4294967294", "a", "b", "4294967296",
   14603           6 :       "4294967295", nullptr, "2",          "3", "c", "d"};
   14604           6 :   CheckStringArray(isolate, properties, 12, expected_properties1_1);
   14605           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   14606             : 
   14607             :   properties =
   14608             :       object
   14609           6 :           ->GetPropertyNames(context.local(),
   14610             :                              v8::KeyCollectionMode::kIncludePrototypes,
   14611             :                              default_filter, v8::IndexFilter::kSkipIndices)
   14612           6 :           .ToLocalChecked();
   14613             :   const char* expected_properties2[] = {"a",          "b", "4294967296",
   14614           6 :                                         "4294967295", "c", "d"};
   14615           6 :   CheckStringArray(isolate, properties, 6, expected_properties2);
   14616             : 
   14617             :   properties = object
   14618           6 :                    ->GetPropertyNames(context.local(),
   14619             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   14620             :                                       include_symbols_filter,
   14621             :                                       v8::IndexFilter::kSkipIndices)
   14622           6 :                    .ToLocalChecked();
   14623             :   const char* expected_properties2_1[] = {
   14624           6 :       "a", "b", "4294967296", "4294967295", nullptr, "c", "d"};
   14625           6 :   CheckStringArray(isolate, properties, 7, expected_properties2_1);
   14626           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   14627             : 
   14628             :   properties =
   14629             :       object
   14630           6 :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   14631             :                              default_filter, v8::IndexFilter::kIncludeIndices)
   14632           6 :           .ToLocalChecked();
   14633             :   const char* expected_properties3[] = {
   14634             :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295",
   14635           6 :   };
   14636           6 :   CheckStringArray(isolate, properties, 7, expected_properties3);
   14637             : 
   14638             :   properties = object
   14639           6 :                    ->GetPropertyNames(
   14640             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   14641             :                        include_symbols_filter, v8::IndexFilter::kIncludeIndices)
   14642           6 :                    .ToLocalChecked();
   14643             :   const char* expected_properties3_1[] = {
   14644           6 :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295", nullptr};
   14645           6 :   CheckStringArray(isolate, properties, 8, expected_properties3_1);
   14646           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   14647             : 
   14648             :   properties =
   14649             :       object
   14650           6 :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   14651             :                              default_filter, v8::IndexFilter::kSkipIndices)
   14652           6 :           .ToLocalChecked();
   14653           6 :   const char* expected_properties4[] = {"a", "b", "4294967296", "4294967295"};
   14654           6 :   CheckStringArray(isolate, properties, 4, expected_properties4);
   14655             : 
   14656             :   properties = object
   14657           6 :                    ->GetPropertyNames(
   14658             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   14659             :                        include_symbols_filter, v8::IndexFilter::kSkipIndices)
   14660           6 :                    .ToLocalChecked();
   14661             :   const char* expected_properties4_1[] = {"a", "b", "4294967296", "4294967295",
   14662           6 :                                           nullptr};
   14663           6 :   CheckStringArray(isolate, properties, 5, expected_properties4_1);
   14664           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   14665           6 : }
   14666             : 
   14667       26645 : THREADED_TEST(ProxyGetPropertyNames) {
   14668           6 :   LocalContext context;
   14669           6 :   v8::Isolate* isolate = context->GetIsolate();
   14670          12 :   v8::HandleScope scope(isolate);
   14671             :   v8::Local<v8::Value> result = CompileRun(
   14672             :       "var target = {0: 0, 1: 1, a: 2, b: 3};"
   14673             :       "target[2**32] = '4294967296';"
   14674             :       "target[2**32-1] = '4294967295';"
   14675             :       "target[2**32-2] = '4294967294';"
   14676             :       "target[Symbol('symbol')] = true;"
   14677             :       "target.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
   14678             :       "var result = new Proxy(target, {});"
   14679             :       "result;");
   14680             :   v8::Local<v8::Object> object = result.As<v8::Object>();
   14681             :   v8::PropertyFilter default_filter =
   14682             :       static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
   14683             :   v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
   14684             : 
   14685             :   v8::Local<v8::Array> properties =
   14686          12 :       object->GetPropertyNames(context.local()).ToLocalChecked();
   14687             :   const char* expected_properties1[] = {"0", "1",          "4294967294", "a",
   14688             :                                         "b", "4294967296", "4294967295", "2",
   14689           6 :                                         "3", "c",          "d"};
   14690           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   14691             : 
   14692             :   properties =
   14693             :       object
   14694           6 :           ->GetPropertyNames(context.local(),
   14695             :                              v8::KeyCollectionMode::kIncludePrototypes,
   14696             :                              default_filter, v8::IndexFilter::kIncludeIndices)
   14697           6 :           .ToLocalChecked();
   14698           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   14699             : 
   14700             :   properties = object
   14701           6 :                    ->GetPropertyNames(context.local(),
   14702             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   14703             :                                       include_symbols_filter,
   14704             :                                       v8::IndexFilter::kIncludeIndices)
   14705           6 :                    .ToLocalChecked();
   14706             :   const char* expected_properties1_1[] = {
   14707             :       "0",          "1",     "4294967294", "a", "b", "4294967296",
   14708           6 :       "4294967295", nullptr, "2",          "3", "c", "d"};
   14709           6 :   CheckStringArray(isolate, properties, 12, expected_properties1_1);
   14710           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   14711             : 
   14712             :   properties =
   14713             :       object
   14714           6 :           ->GetPropertyNames(context.local(),
   14715             :                              v8::KeyCollectionMode::kIncludePrototypes,
   14716             :                              default_filter, v8::IndexFilter::kSkipIndices)
   14717           6 :           .ToLocalChecked();
   14718             :   const char* expected_properties2[] = {"a",          "b", "4294967296",
   14719           6 :                                         "4294967295", "c", "d"};
   14720           6 :   CheckStringArray(isolate, properties, 6, expected_properties2);
   14721             : 
   14722             :   properties = object
   14723           6 :                    ->GetPropertyNames(context.local(),
   14724             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   14725             :                                       include_symbols_filter,
   14726             :                                       v8::IndexFilter::kSkipIndices)
   14727           6 :                    .ToLocalChecked();
   14728             :   const char* expected_properties2_1[] = {
   14729           6 :       "a", "b", "4294967296", "4294967295", nullptr, "c", "d"};
   14730           6 :   CheckStringArray(isolate, properties, 7, expected_properties2_1);
   14731           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   14732             : 
   14733             :   properties =
   14734             :       object
   14735           6 :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   14736             :                              default_filter, v8::IndexFilter::kIncludeIndices)
   14737           6 :           .ToLocalChecked();
   14738             :   const char* expected_properties3[] = {"0", "1",          "4294967294", "a",
   14739           6 :                                         "b", "4294967296", "4294967295"};
   14740           6 :   CheckStringArray(isolate, properties, 7, expected_properties3);
   14741             : 
   14742             :   properties = object
   14743           6 :                    ->GetPropertyNames(
   14744             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   14745             :                        include_symbols_filter, v8::IndexFilter::kIncludeIndices)
   14746           6 :                    .ToLocalChecked();
   14747             :   const char* expected_properties3_1[] = {
   14748           6 :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295", nullptr};
   14749           6 :   CheckStringArray(isolate, properties, 8, expected_properties3_1);
   14750           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   14751             : 
   14752             :   properties =
   14753             :       object
   14754           6 :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   14755             :                              default_filter, v8::IndexFilter::kSkipIndices)
   14756           6 :           .ToLocalChecked();
   14757           6 :   const char* expected_properties4[] = {"a", "b", "4294967296", "4294967295"};
   14758           6 :   CheckStringArray(isolate, properties, 4, expected_properties4);
   14759             : 
   14760             :   properties = object
   14761           6 :                    ->GetPropertyNames(
   14762             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   14763             :                        include_symbols_filter, v8::IndexFilter::kSkipIndices)
   14764           6 :                    .ToLocalChecked();
   14765             :   const char* expected_properties4_1[] = {"a", "b", "4294967296", "4294967295",
   14766           6 :                                           nullptr};
   14767           6 :   CheckStringArray(isolate, properties, 5, expected_properties4_1);
   14768           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   14769           6 : }
   14770             : 
   14771       26645 : THREADED_TEST(AccessChecksReenabledCorrectly) {
   14772           6 :   LocalContext context;
   14773           6 :   v8::Isolate* isolate = context->GetIsolate();
   14774          12 :   v8::HandleScope scope(isolate);
   14775           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   14776           6 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   14777          18 :   templ->Set(v8_str("a"), v8_str("a"));
   14778             :   // Add more than 8 (see kMaxFastProperties) properties
   14779             :   // so that the constructor will force copying map.
   14780             :   // Cannot sprintf, gcc complains unsafety.
   14781             :   char buf[4];
   14782         126 :   for (char i = '0'; i <= '9' ; i++) {
   14783          60 :     buf[0] = i;
   14784        1260 :     for (char j = '0'; j <= '9'; j++) {
   14785         600 :       buf[1] = j;
   14786       12600 :       for (char k = '0'; k <= '9'; k++) {
   14787        6000 :         buf[2] = k;
   14788        6000 :         buf[3] = 0;
   14789       18000 :         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
   14790             :       }
   14791             :     }
   14792             :   }
   14793             : 
   14794             :   Local<v8::Object> instance_1 =
   14795           6 :       templ->NewInstance(context.local()).ToLocalChecked();
   14796          24 :   CHECK(context->Global()
   14797             :             ->Set(context.local(), v8_str("obj_1"), instance_1)
   14798             :             .FromJust());
   14799             : 
   14800             :   Local<Value> value_1 = CompileRun("obj_1.a");
   14801           6 :   CHECK(value_1.IsEmpty());
   14802             : 
   14803             :   Local<v8::Object> instance_2 =
   14804           6 :       templ->NewInstance(context.local()).ToLocalChecked();
   14805          24 :   CHECK(context->Global()
   14806             :             ->Set(context.local(), v8_str("obj_2"), instance_2)
   14807             :             .FromJust());
   14808             : 
   14809             :   Local<Value> value_2 = CompileRun("obj_2.a");
   14810           6 :   CHECK(value_2.IsEmpty());
   14811           6 : }
   14812             : 
   14813             : 
   14814             : // This tests that we do not allow dictionary load/call inline caches
   14815             : // to use functions that have not yet been compiled.  The potential
   14816             : // problem of loading a function that has not yet been compiled can
   14817             : // arise because we share code between contexts via the compilation
   14818             : // cache.
   14819       26645 : THREADED_TEST(DictionaryICLoadedFunction) {
   14820          12 :   v8::HandleScope scope(CcTest::isolate());
   14821             :   // Test LoadIC.
   14822          30 :   for (int i = 0; i < 2; i++) {
   14823          12 :     LocalContext context;
   14824          60 :     CHECK(context->Global()
   14825             :               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   14826             :               .FromJust());
   14827          48 :     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   14828             :     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   14829             :   }
   14830             :   // Test CallIC.
   14831          30 :   for (int i = 0; i < 2; i++) {
   14832          12 :     LocalContext context;
   14833          60 :     CHECK(context->Global()
   14834             :               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   14835             :               .FromJust());
   14836          48 :     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   14837             :     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   14838             :   }
   14839           6 : }
   14840             : 
   14841             : 
   14842             : // Test that cross-context new calls use the context of the callee to
   14843             : // create the new JavaScript object.
   14844       26645 : THREADED_TEST(CrossContextNew) {
   14845           6 :   v8::Isolate* isolate = CcTest::isolate();
   14846          12 :   v8::HandleScope scope(isolate);
   14847           6 :   v8::Local<Context> context0 = Context::New(isolate);
   14848           6 :   v8::Local<Context> context1 = Context::New(isolate);
   14849             : 
   14850             :   // Allow cross-domain access.
   14851           6 :   Local<String> token = v8_str("<security token>");
   14852           6 :   context0->SetSecurityToken(token);
   14853           6 :   context1->SetSecurityToken(token);
   14854             : 
   14855             :   // Set an 'x' property on the Object prototype and define a
   14856             :   // constructor function in context0.
   14857           6 :   context0->Enter();
   14858             :   CompileRun("Object.prototype.x = 42; function C() {};");
   14859           6 :   context0->Exit();
   14860             : 
   14861             :   // Call the constructor function from context0 and check that the
   14862             :   // result has the 'x' property.
   14863           6 :   context1->Enter();
   14864          30 :   CHECK(context1->Global()
   14865             :             ->Set(context1, v8_str("other"), context0->Global())
   14866             :             .FromJust());
   14867             :   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   14868           6 :   CHECK(value->IsInt32());
   14869          12 :   CHECK_EQ(42, value->Int32Value(context1).FromJust());
   14870           6 :   context1->Exit();
   14871           6 : }
   14872             : 
   14873             : 
   14874             : // Verify that we can clone an object
   14875       26644 : TEST(ObjectClone) {
   14876           5 :   LocalContext env;
   14877           5 :   v8::Isolate* isolate = env->GetIsolate();
   14878          10 :   v8::HandleScope scope(isolate);
   14879             : 
   14880             :   const char* sample =
   14881             :     "var rv = {};"      \
   14882             :     "rv.alpha = 'hello';" \
   14883             :     "rv.beta = 123;"     \
   14884             :     "rv;";
   14885             : 
   14886             :   // Create an object, verify basics.
   14887             :   Local<Value> val = CompileRun(sample);
   14888           5 :   CHECK(val->IsObject());
   14889             :   Local<v8::Object> obj = val.As<v8::Object>();
   14890          20 :   obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
   14891             : 
   14892          25 :   CHECK(v8_str("hello")
   14893             :             ->Equals(env.local(),
   14894             :                      obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   14895             :             .FromJust());
   14896          25 :   CHECK(v8::Integer::New(isolate, 123)
   14897             :             ->Equals(env.local(),
   14898             :                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14899             :             .FromJust());
   14900          25 :   CHECK(v8_str("cloneme")
   14901             :             ->Equals(env.local(),
   14902             :                      obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   14903             :             .FromJust());
   14904             : 
   14905             :   // Clone it.
   14906           5 :   Local<v8::Object> clone = obj->Clone();
   14907          25 :   CHECK(v8_str("hello")
   14908             :             ->Equals(env.local(),
   14909             :                      clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   14910             :             .FromJust());
   14911          25 :   CHECK(v8::Integer::New(isolate, 123)
   14912             :             ->Equals(env.local(),
   14913             :                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14914             :             .FromJust());
   14915          25 :   CHECK(v8_str("cloneme")
   14916             :             ->Equals(env.local(),
   14917             :                      clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   14918             :             .FromJust());
   14919             : 
   14920             :   // Set a property on the clone, verify each object.
   14921          20 :   CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
   14922             :             .FromJust());
   14923          25 :   CHECK(v8::Integer::New(isolate, 123)
   14924             :             ->Equals(env.local(),
   14925             :                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14926             :             .FromJust());
   14927          25 :   CHECK(v8::Integer::New(isolate, 456)
   14928             :             ->Equals(env.local(),
   14929             :                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14930             :             .FromJust());
   14931           5 : }
   14932             : 
   14933             : 
   14934             : class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
   14935             :  public:
   14936             :   explicit OneByteVectorResource(i::Vector<const char> vector)
   14937       26645 :       : data_(vector) {}
   14938       53290 :   ~OneByteVectorResource() override = default;
   14939          58 :   size_t length() const override { return data_.length(); }
   14940      106729 :   const char* data() const override { return data_.start(); }
   14941           5 :   void Dispose() override {}
   14942             : 
   14943             :  private:
   14944             :   i::Vector<const char> data_;
   14945             : };
   14946             : 
   14947             : 
   14948             : class UC16VectorResource : public v8::String::ExternalStringResource {
   14949             :  public:
   14950             :   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   14951       26645 :       : data_(vector) {}
   14952       53290 :   ~UC16VectorResource() override = default;
   14953          34 :   size_t length() const override { return data_.length(); }
   14954      108562 :   const i::uc16* data() const override { return data_.start(); }
   14955           5 :   void Dispose() override {}
   14956             : 
   14957             :  private:
   14958             :   i::Vector<const i::uc16> data_;
   14959             : };
   14960             : 
   14961          12 : static void MorphAString(i::String string,
   14962             :                          OneByteVectorResource* one_byte_resource,
   14963             :                          UC16VectorResource* uc16_resource) {
   14964             :   i::Isolate* isolate = CcTest::i_isolate();
   14965          12 :   CHECK(i::StringShape(string).IsExternal());
   14966          12 :   i::ReadOnlyRoots roots(CcTest::heap());
   14967          12 :   if (string->IsOneByteRepresentation()) {
   14968             :     // Check old map is not internalized or long.
   14969          12 :     CHECK(string->map() == roots.external_one_byte_string_map());
   14970             :     // Morph external string to be TwoByte string.
   14971          12 :     string->set_map(roots.external_string_map());
   14972          12 :     i::ExternalTwoByteString morphed = i::ExternalTwoByteString::cast(string);
   14973          12 :     CcTest::heap()->UpdateExternalString(morphed, string->length(), 0);
   14974          12 :     morphed->SetResource(isolate, uc16_resource);
   14975             :   } else {
   14976             :     // Check old map is not internalized or long.
   14977           0 :     CHECK(string->map() == roots.external_string_map());
   14978             :     // Morph external string to be one-byte string.
   14979           0 :     string->set_map(roots.external_one_byte_string_map());
   14980           0 :     i::ExternalOneByteString morphed = i::ExternalOneByteString::cast(string);
   14981           0 :     CcTest::heap()->UpdateExternalString(morphed, string->length(), 0);
   14982           0 :     morphed->SetResource(isolate, one_byte_resource);
   14983             :   }
   14984          12 : }
   14985             : 
   14986             : // Test that we can still flatten a string if the components it is built up
   14987             : // from have been turned into 16 bit strings in the mean time.
   14988       26645 : THREADED_TEST(MorphCompositeStringTest) {
   14989             :   char utf_buffer[129];
   14990             :   const char* c_string = "Now is the time for all good men"
   14991             :                          " to come to the aid of the party";
   14992           6 :   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   14993             :   {
   14994           6 :     LocalContext env;
   14995             :     i::Factory* factory = CcTest::i_isolate()->factory();
   14996           6 :     v8::Isolate* isolate = env->GetIsolate();
   14997             :     i::Isolate* i_isolate = CcTest::i_isolate();
   14998          12 :     v8::HandleScope scope(isolate);
   14999             :     OneByteVectorResource one_byte_resource(
   15000             :         i::Vector<const char>(c_string, i::StrLength(c_string)));
   15001             :     UC16VectorResource uc16_resource(
   15002             :         i::Vector<const uint16_t>(two_byte_string, i::StrLength(c_string)));
   15003             : 
   15004             :     Local<String> lhs(v8::Utils::ToLocal(
   15005          12 :         factory->NewExternalStringFromOneByte(&one_byte_resource)
   15006             :             .ToHandleChecked()));
   15007             :     Local<String> rhs(v8::Utils::ToLocal(
   15008          12 :         factory->NewExternalStringFromOneByte(&one_byte_resource)
   15009             :             .ToHandleChecked()));
   15010             : 
   15011          24 :     CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
   15012          24 :     CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
   15013             : 
   15014             :     CompileRun(
   15015             :         "var cons = lhs + rhs;"
   15016             :         "var slice = lhs.substring(1, lhs.length - 1);"
   15017             :         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   15018             : 
   15019           6 :     CHECK(lhs->IsOneByte());
   15020           6 :     CHECK(rhs->IsOneByte());
   15021             : 
   15022             :     i::String ilhs = *v8::Utils::OpenHandle(*lhs);
   15023             :     i::String irhs = *v8::Utils::OpenHandle(*rhs);
   15024           6 :     MorphAString(ilhs, &one_byte_resource, &uc16_resource);
   15025           6 :     MorphAString(irhs, &one_byte_resource, &uc16_resource);
   15026             : 
   15027             :     // This should UTF-8 without flattening, since everything is ASCII.
   15028             :     Local<String> cons =
   15029           6 :         v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
   15030           6 :     CHECK_EQ(128, cons->Utf8Length(isolate));
   15031           6 :     int nchars = -1;
   15032           6 :     CHECK_EQ(129, cons->WriteUtf8(isolate, utf_buffer, -1, &nchars));
   15033           6 :     CHECK_EQ(128, nchars);
   15034           6 :     CHECK_EQ(0, strcmp(
   15035             :         utf_buffer,
   15036             :         "Now is the time for all good men to come to the aid of the party"
   15037             :         "Now is the time for all good men to come to the aid of the party"));
   15038             : 
   15039             :     // Now do some stuff to make sure the strings are flattened, etc.
   15040             :     CompileRun(
   15041             :         "/[^a-z]/.test(cons);"
   15042             :         "/[^a-z]/.test(slice);"
   15043             :         "/[^a-z]/.test(slice_on_cons);");
   15044             :     const char* expected_cons =
   15045             :         "Now is the time for all good men to come to the aid of the party"
   15046             :         "Now is the time for all good men to come to the aid of the party";
   15047             :     const char* expected_slice =
   15048             :         "ow is the time for all good men to come to the aid of the part";
   15049             :     const char* expected_slice_on_cons =
   15050             :         "ow is the time for all good men to come to the aid of the party"
   15051             :         "Now is the time for all good men to come to the aid of the part";
   15052          36 :     CHECK(v8_str(expected_cons)
   15053             :               ->Equals(env.local(), env->Global()
   15054             :                                         ->Get(env.local(), v8_str("cons"))
   15055             :                                         .ToLocalChecked())
   15056             :               .FromJust());
   15057          36 :     CHECK(v8_str(expected_slice)
   15058             :               ->Equals(env.local(), env->Global()
   15059             :                                         ->Get(env.local(), v8_str("slice"))
   15060             :                                         .ToLocalChecked())
   15061             :               .FromJust());
   15062          36 :     CHECK(v8_str(expected_slice_on_cons)
   15063             :               ->Equals(env.local(),
   15064             :                        env->Global()
   15065             :                            ->Get(env.local(), v8_str("slice_on_cons"))
   15066             :                            .ToLocalChecked())
   15067             :               .FromJust());
   15068             : 
   15069             :     // This avoids the GC from trying to free a stack allocated resource.
   15070           6 :     if (ilhs->IsExternalOneByteString())
   15071           0 :       i::ExternalOneByteString::cast(ilhs)->SetResource(i_isolate, nullptr);
   15072             :     else
   15073           6 :       i::ExternalTwoByteString::cast(ilhs)->SetResource(i_isolate, nullptr);
   15074           6 :     if (irhs->IsExternalOneByteString())
   15075           0 :       i::ExternalOneByteString::cast(irhs)->SetResource(i_isolate, nullptr);
   15076             :     else
   15077           6 :       i::ExternalTwoByteString::cast(irhs)->SetResource(i_isolate, nullptr);
   15078             :   }
   15079             :   i::DeleteArray(two_byte_string);
   15080           6 : }
   15081             : 
   15082             : 
   15083       26644 : TEST(CompileExternalTwoByteSource) {
   15084           5 :   LocalContext context;
   15085          10 :   v8::HandleScope scope(context->GetIsolate());
   15086             : 
   15087             :   // This is a very short list of sources, which currently is to check for a
   15088             :   // regression caused by r2703.
   15089             :   const char* one_byte_sources[] = {
   15090             :       "0.5",
   15091             :       "-0.5",   // This mainly testes PushBack in the Scanner.
   15092             :       "--0.5",  // This mainly testes PushBack in the Scanner.
   15093           5 :       nullptr};
   15094             : 
   15095             :   // Compile the sources as external two byte strings.
   15096          35 :   for (int i = 0; one_byte_sources[i] != nullptr; i++) {
   15097          15 :     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
   15098          15 :     TestResource* uc16_resource = new TestResource(two_byte_string);
   15099             :     v8::Local<v8::String> source =
   15100          15 :         v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
   15101          15 :             .ToLocalChecked();
   15102          15 :     v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
   15103             :   }
   15104           5 : }
   15105             : 
   15106             : // Test that we cannot set a property on the global object if there
   15107             : // is a read-only property in the prototype chain.
   15108       26644 : TEST(ReadOnlyPropertyInGlobalProto) {
   15109           5 :   v8::Isolate* isolate = CcTest::isolate();
   15110          10 :   v8::HandleScope scope(isolate);
   15111           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15112           5 :   LocalContext context(nullptr, templ);
   15113           5 :   v8::Local<v8::Object> global = context->Global();
   15114             :   v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
   15115          15 :       global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
   15116          10 :   global_proto->DefineOwnProperty(context.local(), v8_str("x"),
   15117          15 :                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15118             :       .FromJust();
   15119          10 :   global_proto->DefineOwnProperty(context.local(), v8_str("y"),
   15120          15 :                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15121             :       .FromJust();
   15122             :   // Check without 'eval' or 'with'.
   15123             :   v8::Local<v8::Value> res =
   15124           5 :       CompileRun("function f() { x = 42; return x; }; f()");
   15125          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15126             :   // Check with 'eval'.
   15127           5 :   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   15128          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15129             :   // Check with 'with'.
   15130           5 :   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   15131          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15132           5 : }
   15133             : 
   15134             : 
   15135       26644 : TEST(CreateDataProperty) {
   15136           5 :   LocalContext env;
   15137           5 :   v8::Isolate* isolate = env->GetIsolate();
   15138          10 :   v8::HandleScope handle_scope(isolate);
   15139             : 
   15140             :   CompileRun(
   15141             :       "var a = {};"
   15142             :       "var b = [];"
   15143             :       "Object.defineProperty(a, 'foo', {value: 23});"
   15144             :       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15145             : 
   15146             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15147          20 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15148             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15149          20 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15150             :   {
   15151             :     // Can't change a non-configurable properties.
   15152          10 :     v8::TryCatch try_catch(isolate);
   15153          20 :     CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
   15154             :                                    v8::Integer::New(isolate, 42)).FromJust());
   15155           5 :     CHECK(!try_catch.HasCaught());
   15156          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
   15157             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15158           5 :     CHECK(!try_catch.HasCaught());
   15159             :     v8::Local<v8::Value> val =
   15160          15 :         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15161           5 :     CHECK(val->IsNumber());
   15162          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15163             :   }
   15164             : 
   15165             :   {
   15166             :     // Set a regular property.
   15167          10 :     v8::TryCatch try_catch(isolate);
   15168          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
   15169             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15170           5 :     CHECK(!try_catch.HasCaught());
   15171             :     v8::Local<v8::Value> val =
   15172          15 :         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15173           5 :     CHECK(val->IsNumber());
   15174          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15175             :   }
   15176             : 
   15177             :   {
   15178             :     // Set an indexed property.
   15179          10 :     v8::TryCatch try_catch(isolate);
   15180          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
   15181             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15182           5 :     CHECK(!try_catch.HasCaught());
   15183           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15184           5 :     CHECK(val->IsNumber());
   15185          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15186             :   }
   15187             : 
   15188             :   {
   15189             :     // Special cases for arrays.
   15190          10 :     v8::TryCatch try_catch(isolate);
   15191          20 :     CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
   15192             :                                    v8::Integer::New(isolate, 1)).FromJust());
   15193           5 :     CHECK(!try_catch.HasCaught());
   15194             :   }
   15195             :   {
   15196             :     // Special cases for arrays: index exceeds the array's length
   15197          10 :     v8::TryCatch try_catch(isolate);
   15198          15 :     CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
   15199             :               .FromJust());
   15200           5 :     CHECK(!try_catch.HasCaught());
   15201           5 :     CHECK_EQ(2U, arr->Length());
   15202           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15203           5 :     CHECK(val->IsNumber());
   15204          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15205             : 
   15206             :     // Set an existing entry.
   15207          15 :     CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
   15208             :               .FromJust());
   15209           5 :     CHECK(!try_catch.HasCaught());
   15210           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15211           5 :     CHECK(val->IsNumber());
   15212          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15213             :   }
   15214             : 
   15215             :   CompileRun("Object.freeze(a);");
   15216             :   {
   15217             :     // Can't change non-extensible objects.
   15218          10 :     v8::TryCatch try_catch(isolate);
   15219          20 :     CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
   15220             :                                    v8::Integer::New(isolate, 42)).FromJust());
   15221           5 :     CHECK(!try_catch.HasCaught());
   15222             :   }
   15223             : 
   15224           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15225           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15226             :   v8::Local<v8::Object> access_checked =
   15227           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15228             :   {
   15229          10 :     v8::TryCatch try_catch(isolate);
   15230          20 :     CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
   15231             :                                              v8::Integer::New(isolate, 42))
   15232             :               .IsNothing());
   15233           5 :     CHECK(try_catch.HasCaught());
   15234             :   }
   15235           5 : }
   15236             : 
   15237             : 
   15238       26644 : TEST(DefineOwnProperty) {
   15239           5 :   LocalContext env;
   15240           5 :   v8::Isolate* isolate = env->GetIsolate();
   15241          10 :   v8::HandleScope handle_scope(isolate);
   15242             : 
   15243             :   CompileRun(
   15244             :       "var a = {};"
   15245             :       "var b = [];"
   15246             :       "Object.defineProperty(a, 'foo', {value: 23});"
   15247             :       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15248             : 
   15249             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15250          20 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15251             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15252          20 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15253             :   {
   15254             :     // Can't change a non-configurable properties.
   15255          10 :     v8::TryCatch try_catch(isolate);
   15256          20 :     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
   15257             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15258           5 :     CHECK(!try_catch.HasCaught());
   15259          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
   15260             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15261           5 :     CHECK(!try_catch.HasCaught());
   15262             :     v8::Local<v8::Value> val =
   15263          15 :         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15264           5 :     CHECK(val->IsNumber());
   15265          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15266             :   }
   15267             : 
   15268             :   {
   15269             :     // Set a regular property.
   15270          10 :     v8::TryCatch try_catch(isolate);
   15271          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
   15272             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15273           5 :     CHECK(!try_catch.HasCaught());
   15274             :     v8::Local<v8::Value> val =
   15275          15 :         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15276           5 :     CHECK(val->IsNumber());
   15277          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15278             :   }
   15279             : 
   15280             :   {
   15281             :     // Set an indexed property.
   15282          10 :     v8::TryCatch try_catch(isolate);
   15283          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
   15284             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15285           5 :     CHECK(!try_catch.HasCaught());
   15286           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15287           5 :     CHECK(val->IsNumber());
   15288          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15289             :   }
   15290             : 
   15291             :   {
   15292             :     // Special cases for arrays.
   15293          10 :     v8::TryCatch try_catch(isolate);
   15294          20 :     CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
   15295             :                                   v8::Integer::New(isolate, 1)).FromJust());
   15296           5 :     CHECK(!try_catch.HasCaught());
   15297             :   }
   15298             :   {
   15299             :     // Special cases for arrays: index exceeds the array's length
   15300          10 :     v8::TryCatch try_catch(isolate);
   15301          20 :     CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
   15302             :                                  v8::Integer::New(isolate, 23)).FromJust());
   15303           5 :     CHECK(!try_catch.HasCaught());
   15304           5 :     CHECK_EQ(2U, arr->Length());
   15305           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15306           5 :     CHECK(val->IsNumber());
   15307          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15308             : 
   15309             :     // Set an existing entry.
   15310          20 :     CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
   15311             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15312           5 :     CHECK(!try_catch.HasCaught());
   15313           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15314           5 :     CHECK(val->IsNumber());
   15315          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15316             :   }
   15317             : 
   15318             :   {
   15319             :     // Set a non-writable property.
   15320          10 :     v8::TryCatch try_catch(isolate);
   15321          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
   15322             :                                  v8::Integer::New(isolate, 42),
   15323             :                                  v8::ReadOnly).FromJust());
   15324           5 :     CHECK(!try_catch.HasCaught());
   15325             :     v8::Local<v8::Value> val =
   15326          15 :         obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
   15327           5 :     CHECK(val->IsNumber());
   15328          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15329          15 :     CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
   15330             :                                     env.local(), v8_str("lala")).FromJust());
   15331           5 :     CHECK(!try_catch.HasCaught());
   15332             :   }
   15333             : 
   15334             :   CompileRun("Object.freeze(a);");
   15335             :   {
   15336             :     // Can't change non-extensible objects.
   15337          10 :     v8::TryCatch try_catch(isolate);
   15338          20 :     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
   15339             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15340           5 :     CHECK(!try_catch.HasCaught());
   15341             :   }
   15342             : 
   15343           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15344           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15345             :   v8::Local<v8::Object> access_checked =
   15346           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15347             :   {
   15348          10 :     v8::TryCatch try_catch(isolate);
   15349          20 :     CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
   15350             :                                             v8::Integer::New(isolate, 42))
   15351             :               .IsNothing());
   15352           5 :     CHECK(try_catch.HasCaught());
   15353             :   }
   15354           5 : }
   15355             : 
   15356       26644 : TEST(DefineProperty) {
   15357           5 :   LocalContext env;
   15358           5 :   v8::Isolate* isolate = env->GetIsolate();
   15359          10 :   v8::HandleScope handle_scope(isolate);
   15360             : 
   15361             :   v8::Local<v8::Name> p;
   15362             : 
   15363             :   CompileRun(
   15364             :       "var a = {};"
   15365             :       "var b = [];"
   15366             :       "Object.defineProperty(a, 'v1', {value: 23});"
   15367             :       "Object.defineProperty(a, 'v2', {value: 23, configurable: true});");
   15368             : 
   15369             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15370          20 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15371             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15372          20 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15373             : 
   15374          10 :   v8::PropertyDescriptor desc(v8_num(42));
   15375             :   {
   15376             :     // Use a data descriptor.
   15377             : 
   15378             :     // Cannot change a non-configurable property.
   15379           5 :     p = v8_str("v1");
   15380          10 :     v8::TryCatch try_catch(isolate);
   15381          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc).FromJust());
   15382           5 :     CHECK(!try_catch.HasCaught());
   15383          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15384           5 :     CHECK(val->IsNumber());
   15385          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15386             : 
   15387             :     // Change a configurable property.
   15388           5 :     p = v8_str("v2");
   15389          10 :     obj->DefineProperty(env.local(), p, desc).FromJust();
   15390          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15391           5 :     CHECK(!try_catch.HasCaught());
   15392          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15393           5 :     CHECK(val->IsNumber());
   15394          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15395             : 
   15396             :     // Check that missing writable has default value false.
   15397           5 :     p = v8_str("v12");
   15398          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15399           5 :     CHECK(!try_catch.HasCaught());
   15400          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15401           5 :     CHECK(val->IsNumber());
   15402          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15403          10 :     v8::PropertyDescriptor desc2(v8_num(43));
   15404          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc2).FromJust());
   15405          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15406          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15407           5 :     CHECK(!try_catch.HasCaught());
   15408             :   }
   15409             : 
   15410             :   {
   15411             :     // Set a regular property.
   15412           5 :     p = v8_str("v3");
   15413          10 :     v8::TryCatch try_catch(isolate);
   15414          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15415           5 :     CHECK(!try_catch.HasCaught());
   15416          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15417           5 :     CHECK(val->IsNumber());
   15418          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15419             :   }
   15420             : 
   15421             :   {
   15422             :     // Set an indexed property.
   15423          10 :     v8::TryCatch try_catch(isolate);
   15424          15 :     CHECK(obj->DefineProperty(env.local(), v8_str("1"), desc).FromJust());
   15425           5 :     CHECK(!try_catch.HasCaught());
   15426           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15427           5 :     CHECK(val->IsNumber());
   15428          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15429             :   }
   15430             : 
   15431             :   {
   15432             :     // No special case when changing array length.
   15433          10 :     v8::TryCatch try_catch(isolate);
   15434             :     // Use a writable descriptor, otherwise the next test, that changes
   15435             :     // the array length will fail.
   15436          10 :     v8::PropertyDescriptor desc(v8_num(42), true);
   15437          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("length"), desc).FromJust());
   15438           5 :     CHECK(!try_catch.HasCaught());
   15439             :   }
   15440             : 
   15441             :   {
   15442             :     // Special cases for arrays: index exceeds the array's length.
   15443          10 :     v8::TryCatch try_catch(isolate);
   15444          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("100"), desc).FromJust());
   15445           5 :     CHECK(!try_catch.HasCaught());
   15446           5 :     CHECK_EQ(101U, arr->Length());
   15447           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 100).ToLocalChecked();
   15448           5 :     CHECK(val->IsNumber());
   15449          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15450             : 
   15451             :     // Set an existing entry.
   15452          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("0"), desc).FromJust());
   15453           5 :     CHECK(!try_catch.HasCaught());
   15454           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15455           5 :     CHECK(val->IsNumber());
   15456          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15457             :   }
   15458             : 
   15459             :   {
   15460             :     // Use a generic descriptor.
   15461          10 :     v8::PropertyDescriptor desc_generic;
   15462             : 
   15463           5 :     p = v8_str("v4");
   15464          10 :     v8::TryCatch try_catch(isolate);
   15465          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_generic).FromJust());
   15466           5 :     CHECK(!try_catch.HasCaught());
   15467          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15468           5 :     CHECK(val->IsUndefined());
   15469             : 
   15470          15 :     obj->Set(env.local(), p, v8_num(1)).FromJust();
   15471           5 :     CHECK(!try_catch.HasCaught());
   15472             : 
   15473          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15474           5 :     CHECK(val->IsUndefined());
   15475           5 :     CHECK(!try_catch.HasCaught());
   15476             :   }
   15477             : 
   15478             :   {
   15479             :     // Use a data descriptor with undefined value.
   15480          10 :     v8::PropertyDescriptor desc_empty(v8::Undefined(isolate));
   15481             : 
   15482          10 :     v8::TryCatch try_catch(isolate);
   15483          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   15484           5 :     CHECK(!try_catch.HasCaught());
   15485          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15486           5 :     CHECK(val->IsUndefined());
   15487           5 :     CHECK(!try_catch.HasCaught());
   15488             :   }
   15489             : 
   15490             :   {
   15491             :     // Use a descriptor with attribute == v8::ReadOnly.
   15492          10 :     v8::PropertyDescriptor desc_read_only(v8_num(42), false);
   15493           5 :     desc_read_only.set_enumerable(true);
   15494           5 :     desc_read_only.set_configurable(true);
   15495             : 
   15496           5 :     p = v8_str("v5");
   15497          10 :     v8::TryCatch try_catch(isolate);
   15498          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_read_only).FromJust());
   15499           5 :     CHECK(!try_catch.HasCaught());
   15500          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15501           5 :     CHECK(val->IsNumber());
   15502          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15503          10 :     CHECK_EQ(v8::ReadOnly,
   15504             :              obj->GetPropertyAttributes(env.local(), p).FromJust());
   15505           5 :     CHECK(!try_catch.HasCaught());
   15506             :   }
   15507             : 
   15508             :   {
   15509             :     // Use an accessor descriptor with empty handles.
   15510             :     v8::PropertyDescriptor desc_empty(v8::Undefined(isolate),
   15511          10 :                                       v8::Undefined(isolate));
   15512             : 
   15513           5 :     p = v8_str("v6");
   15514          10 :     v8::TryCatch try_catch(isolate);
   15515          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   15516           5 :     CHECK(!try_catch.HasCaught());
   15517          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15518           5 :     CHECK(val->IsUndefined());
   15519           5 :     CHECK(!try_catch.HasCaught());
   15520             :   }
   15521             : 
   15522             :   {
   15523             :     // Use an accessor descriptor.
   15524             :     CompileRun(
   15525             :         "var set = function(x) {this.val = 2*x;};"
   15526             :         "var get = function() {return this.val || 0;};");
   15527             : 
   15528             :     v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
   15529          20 :         env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
   15530             :     v8::Local<v8::Function> set = v8::Local<v8::Function>::Cast(
   15531          20 :         env->Global()->Get(env.local(), v8_str("set")).ToLocalChecked());
   15532          10 :     v8::PropertyDescriptor desc(get, set);
   15533             : 
   15534           5 :     p = v8_str("v7");
   15535          10 :     v8::TryCatch try_catch(isolate);
   15536          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15537           5 :     CHECK(!try_catch.HasCaught());
   15538             : 
   15539          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15540           5 :     CHECK(val->IsNumber());
   15541          10 :     CHECK_EQ(0.0, val->NumberValue(env.local()).FromJust());
   15542           5 :     CHECK(!try_catch.HasCaught());
   15543             : 
   15544          15 :     obj->Set(env.local(), p, v8_num(7)).FromJust();
   15545           5 :     CHECK(!try_catch.HasCaught());
   15546             : 
   15547          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15548           5 :     CHECK(val->IsNumber());
   15549          10 :     CHECK_EQ(14.0, val->NumberValue(env.local()).FromJust());
   15550           5 :     CHECK(!try_catch.HasCaught());
   15551             :   }
   15552             : 
   15553             :   {
   15554             :     // Redefine an existing property.
   15555             : 
   15556             :     // desc = {value: 42, enumerable: true}
   15557          10 :     v8::PropertyDescriptor desc(v8_num(42));
   15558           5 :     desc.set_enumerable(true);
   15559             : 
   15560           5 :     p = v8_str("v8");
   15561          10 :     v8::TryCatch try_catch(isolate);
   15562          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15563           5 :     CHECK(!try_catch.HasCaught());
   15564             : 
   15565             :     // desc = {enumerable: true}
   15566          10 :     v8::PropertyDescriptor desc_true((v8::Local<v8::Value>()));
   15567           5 :     desc_true.set_enumerable(true);
   15568             : 
   15569             :     // Successful redefinition because all present attributes have the same
   15570             :     // value as the current descriptor.
   15571          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_true).FromJust());
   15572           5 :     CHECK(!try_catch.HasCaught());
   15573             : 
   15574             :     // desc = {}
   15575          10 :     v8::PropertyDescriptor desc_empty;
   15576             :     // Successful redefinition because no attributes are overwritten in the
   15577             :     // current descriptor.
   15578          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   15579           5 :     CHECK(!try_catch.HasCaught());
   15580             : 
   15581             :     // desc = {enumerable: false}
   15582          10 :     v8::PropertyDescriptor desc_false((v8::Local<v8::Value>()));
   15583           5 :     desc_false.set_enumerable(false);
   15584             :     // Not successful because we cannot define a different value for enumerable.
   15585          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc_false).FromJust());
   15586           5 :     CHECK(!try_catch.HasCaught());
   15587             :   }
   15588             : 
   15589             :   {
   15590             :     // Redefine a property that has a getter.
   15591             :     CompileRun("var get = function() {};");
   15592             :     v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
   15593          20 :         env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
   15594             : 
   15595             :     // desc = {get: function() {}}
   15596          10 :     v8::PropertyDescriptor desc(get, v8::Local<v8::Function>());
   15597          10 :     v8::TryCatch try_catch(isolate);
   15598             : 
   15599           5 :     p = v8_str("v9");
   15600          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15601           5 :     CHECK(!try_catch.HasCaught());
   15602             : 
   15603             :     // desc_empty = {}
   15604             :     // Successful because we are not redefining the current getter.
   15605          10 :     v8::PropertyDescriptor desc_empty;
   15606          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   15607           5 :     CHECK(!try_catch.HasCaught());
   15608             : 
   15609             :     // desc = {get: function() {}}
   15610             :     // Successful because we redefine the getter with its current value.
   15611          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15612           5 :     CHECK(!try_catch.HasCaught());
   15613             : 
   15614             :     // desc = {get: undefined}
   15615             :     v8::PropertyDescriptor desc_undefined(v8::Undefined(isolate),
   15616          10 :                                           v8::Local<v8::Function>());
   15617             :     // Not successful because we cannot redefine with the current value of get
   15618             :     // with undefined.
   15619          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc_undefined).FromJust());
   15620           5 :     CHECK(!try_catch.HasCaught());
   15621             :   }
   15622             : 
   15623             :   CompileRun("Object.freeze(a);");
   15624             :   {
   15625             :     // We cannot change non-extensible objects.
   15626          10 :     v8::TryCatch try_catch(isolate);
   15627          15 :     CHECK(!obj->DefineProperty(env.local(), v8_str("v10"), desc).FromJust());
   15628           5 :     CHECK(!try_catch.HasCaught());
   15629             :   }
   15630             : 
   15631           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15632           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15633             :   v8::Local<v8::Object> access_checked =
   15634           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15635             :   {
   15636          10 :     v8::TryCatch try_catch(isolate);
   15637          15 :     CHECK(access_checked->DefineProperty(env.local(), v8_str("v11"), desc)
   15638             :               .IsNothing());
   15639           5 :     CHECK(try_catch.HasCaught());
   15640             :   }
   15641           5 : }
   15642             : 
   15643       26645 : THREADED_TEST(GetCurrentContextWhenNotInContext) {
   15644             :   i::Isolate* isolate = CcTest::i_isolate();
   15645           6 :   CHECK_NOT_NULL(isolate);
   15646           6 :   CHECK(isolate->context().is_null());
   15647             :   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   15648          12 :   v8::HandleScope scope(v8_isolate);
   15649             :   // The following should not crash, but return an empty handle.
   15650           6 :   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   15651           6 :   CHECK(current.IsEmpty());
   15652           6 : }
   15653             : 
   15654             : 
   15655             : // Check that a variable declaration with no explicit initialization
   15656             : // value does shadow an existing property in the prototype chain.
   15657       26645 : THREADED_TEST(InitGlobalVarInProtoChain) {
   15658           6 :   LocalContext context;
   15659          12 :   v8::HandleScope scope(context->GetIsolate());
   15660             :   // Introduce a variable in the prototype chain.
   15661             :   CompileRun("__proto__.x = 42");
   15662             :   v8::Local<v8::Value> result = CompileRun("var x = 43; x");
   15663           6 :   CHECK(!result->IsUndefined());
   15664          12 :   CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
   15665           6 : }
   15666             : 
   15667             : 
   15668             : // Regression test for issue 398.
   15669             : // If a function is added to an object, creating a constant function
   15670             : // field, and the result is cloned, replacing the constant function on the
   15671             : // original should not affect the clone.
   15672             : // See http://code.google.com/p/v8/issues/detail?id=398
   15673       26645 : THREADED_TEST(ReplaceConstantFunction) {
   15674           6 :   LocalContext context;
   15675           6 :   v8::Isolate* isolate = context->GetIsolate();
   15676          12 :   v8::HandleScope scope(isolate);
   15677           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   15678             :   v8::Local<v8::FunctionTemplate> func_templ =
   15679           6 :       v8::FunctionTemplate::New(isolate);
   15680           6 :   v8::Local<v8::String> foo_string = v8_str("foo");
   15681          12 :   obj->Set(context.local(), foo_string,
   15682          12 :            func_templ->GetFunction(context.local()).ToLocalChecked())
   15683             :       .FromJust();
   15684           6 :   v8::Local<v8::Object> obj_clone = obj->Clone();
   15685          18 :   obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
   15686          12 :   CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
   15687           6 : }
   15688             : 
   15689             : 
   15690         504 : static void CheckElementValue(i::Isolate* isolate,
   15691             :                               int expected,
   15692             :                               i::Handle<i::Object> obj,
   15693             :                               int offset) {
   15694             :   i::Object element =
   15695        1008 :       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
   15696         504 :   CHECK_EQ(expected, i::Smi::ToInt(element));
   15697         504 : }
   15698             : 
   15699             : 
   15700             : template <class ExternalArrayClass, class ElementType>
   15701         162 : static void ObjectWithExternalArrayTestHelper(Local<Context> context,
   15702             :                                               v8::Local<Object> obj,
   15703             :                                               int element_count,
   15704             :                                               i::ExternalArrayType array_type,
   15705             :                                               int64_t low, int64_t high) {
   15706             :   i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
   15707         162 :   v8::Isolate* v8_isolate = context->GetIsolate();
   15708             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
   15709         486 :   obj->Set(context, v8_str("field"), v8::Int32::New(v8_isolate, 1503))
   15710         324 :       .FromJust();
   15711         648 :   CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
   15712             :   v8::Local<v8::Value> result = CompileRun("ext_array.field");
   15713         324 :   CHECK_EQ(1503, result->Int32Value(context).FromJust());
   15714             :   result = CompileRun("ext_array[1]");
   15715         324 :   CHECK_EQ(1, result->Int32Value(context).FromJust());
   15716             : 
   15717             :   // Check assigned smis
   15718             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15719             :                       "  ext_array[i] = i;"
   15720             :                       "}"
   15721             :                       "var sum = 0;"
   15722             :                       "for (var i = 0; i < 8; i++) {"
   15723             :                       "  sum += ext_array[i];"
   15724             :                       "}"
   15725             :                       "sum;");
   15726             : 
   15727         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15728             :   // Check pass through of assigned smis
   15729             :   result = CompileRun("var sum = 0;"
   15730             :                       "for (var i = 0; i < 8; i++) {"
   15731             :                       "  sum += ext_array[i] = ext_array[i] = -i;"
   15732             :                       "}"
   15733             :                       "sum;");
   15734         324 :   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   15735             : 
   15736             : 
   15737             :   // Check assigned smis in reverse order
   15738             :   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   15739             :                       "  ext_array[i] = i;"
   15740             :                       "}"
   15741             :                       "var sum = 0;"
   15742             :                       "for (var i = 0; i < 8; i++) {"
   15743             :                       "  sum += ext_array[i];"
   15744             :                       "}"
   15745             :                       "sum;");
   15746         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15747             : 
   15748             :   // Check pass through of assigned HeapNumbers
   15749             :   result = CompileRun("var sum = 0;"
   15750             :                       "for (var i = 0; i < 16; i+=2) {"
   15751             :                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   15752             :                       "}"
   15753             :                       "sum;");
   15754         324 :   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   15755             : 
   15756             :   // Check assigned HeapNumbers
   15757             :   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   15758             :                       "  ext_array[i] = (i * 0.5);"
   15759             :                       "}"
   15760             :                       "var sum = 0;"
   15761             :                       "for (var i = 0; i < 16; i+=2) {"
   15762             :                       "  sum += ext_array[i];"
   15763             :                       "}"
   15764             :                       "sum;");
   15765         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15766             : 
   15767             :   // Check assigned HeapNumbers in reverse order
   15768             :   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   15769             :                       "  ext_array[i] = (i * 0.5);"
   15770             :                       "}"
   15771             :                       "var sum = 0;"
   15772             :                       "for (var i = 0; i < 16; i+=2) {"
   15773             :                       "  sum += ext_array[i];"
   15774             :                       "}"
   15775             :                       "sum;");
   15776         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15777             : 
   15778             :   i::ScopedVector<char> test_buf(1024);
   15779             : 
   15780             :   // Check legal boundary conditions.
   15781             :   // The repeated loads and stores ensure the ICs are exercised.
   15782             :   const char* boundary_program =
   15783             :       "var res = 0;"
   15784             :       "for (var i = 0; i < 16; i++) {"
   15785             :       "  ext_array[i] = %lld;"
   15786             :       "  if (i > 8) {"
   15787             :       "    res = ext_array[i];"
   15788             :       "  }"
   15789             :       "}"
   15790             :       "res;";
   15791         162 :   i::SNPrintF(test_buf,
   15792             :               boundary_program,
   15793             :               low);
   15794             :   result = CompileRun(test_buf.start());
   15795         324 :   CHECK_EQ(low, result->IntegerValue(context).FromJust());
   15796             : 
   15797         162 :   i::SNPrintF(test_buf,
   15798             :               boundary_program,
   15799             :               high);
   15800             :   result = CompileRun(test_buf.start());
   15801         324 :   CHECK_EQ(high, result->IntegerValue(context).FromJust());
   15802             : 
   15803             :   // Check misprediction of type in IC.
   15804             :   result = CompileRun("var tmp_array = ext_array;"
   15805             :                       "var sum = 0;"
   15806             :                       "for (var i = 0; i < 8; i++) {"
   15807             :                       "  tmp_array[i] = i;"
   15808             :                       "  sum += tmp_array[i];"
   15809             :                       "  if (i == 4) {"
   15810             :                       "    tmp_array = {};"
   15811             :                       "  }"
   15812             :                       "}"
   15813             :                       "sum;");
   15814             :   // Force GC to trigger verification.
   15815         162 :   CcTest::CollectAllGarbage();
   15816         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15817             : 
   15818             :   // Make sure out-of-range loads do not throw.
   15819         162 :   i::SNPrintF(test_buf,
   15820             :               "var caught_exception = false;"
   15821             :               "try {"
   15822             :               "  ext_array[%d];"
   15823             :               "} catch (e) {"
   15824             :               "  caught_exception = true;"
   15825             :               "}"
   15826             :               "caught_exception;",
   15827             :               element_count);
   15828             :   result = CompileRun(test_buf.start());
   15829         162 :   CHECK(!result->BooleanValue(v8_isolate));
   15830             : 
   15831             :   // Make sure out-of-range stores do not throw.
   15832         162 :   i::SNPrintF(test_buf,
   15833             :               "var caught_exception = false;"
   15834             :               "try {"
   15835             :               "  ext_array[%d] = 1;"
   15836             :               "} catch (e) {"
   15837             :               "  caught_exception = true;"
   15838             :               "}"
   15839             :               "caught_exception;",
   15840             :               element_count);
   15841             :   result = CompileRun(test_buf.start());
   15842         162 :   CHECK(!result->BooleanValue(v8_isolate));
   15843             : 
   15844             :   // Check other boundary conditions, values and operations.
   15845             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15846             :                       "  ext_array[7] = undefined;"
   15847             :                       "}"
   15848             :                       "ext_array[7];");
   15849         324 :   CHECK_EQ(0, result->Int32Value(context).FromJust());
   15850         162 :   if (array_type == i::kExternalFloat64Array ||
   15851             :       array_type == i::kExternalFloat32Array) {
   15852          72 :     CHECK(std::isnan(
   15853             :         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
   15854             :   } else {
   15855         126 :     CheckElementValue(isolate, 0, jsobj, 7);
   15856             :   }
   15857             : 
   15858             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15859             :                       "  ext_array[6] = '2.3';"
   15860             :                       "}"
   15861             :                       "ext_array[6];");
   15862         324 :   CHECK_EQ(2, result->Int32Value(context).FromJust());
   15863         324 :   CHECK_EQ(2,
   15864             :            static_cast<int>(
   15865             :                i::Object::GetElement(
   15866             :                    isolate, jsobj, 6).ToHandleChecked()->Number()));
   15867             : 
   15868         162 :   if (array_type != i::kExternalFloat32Array &&
   15869             :       array_type != i::kExternalFloat64Array) {
   15870             :     // Though the specification doesn't state it, be explicit about
   15871             :     // converting NaNs and +/-Infinity to zero.
   15872             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15873             :                         "  ext_array[i] = 5;"
   15874             :                         "}"
   15875             :                         "for (var i = 0; i < 8; i++) {"
   15876             :                         "  ext_array[i] = NaN;"
   15877             :                         "}"
   15878             :                         "ext_array[5];");
   15879         252 :     CHECK_EQ(0, result->Int32Value(context).FromJust());
   15880         126 :     CheckElementValue(isolate, 0, jsobj, 5);
   15881             : 
   15882             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15883             :                         "  ext_array[i] = 5;"
   15884             :                         "}"
   15885             :                         "for (var i = 0; i < 8; i++) {"
   15886             :                         "  ext_array[i] = Infinity;"
   15887             :                         "}"
   15888             :                         "ext_array[5];");
   15889             :     int expected_value =
   15890         126 :         (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
   15891         252 :     CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
   15892         126 :     CheckElementValue(isolate, expected_value, jsobj, 5);
   15893             : 
   15894             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15895             :                         "  ext_array[i] = 5;"
   15896             :                         "}"
   15897             :                         "for (var i = 0; i < 8; i++) {"
   15898             :                         "  ext_array[i] = -Infinity;"
   15899             :                         "}"
   15900             :                         "ext_array[5];");
   15901         252 :     CHECK_EQ(0, result->Int32Value(context).FromJust());
   15902         126 :     CheckElementValue(isolate, 0, jsobj, 5);
   15903             : 
   15904             :     // Check truncation behavior of integral arrays.
   15905             :     const char* unsigned_data =
   15906             :         "var source_data = [0.6, 10.6];"
   15907             :         "var expected_results = [0, 10];";
   15908             :     const char* signed_data =
   15909             :         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   15910             :         "var expected_results = [0, 10, 0, -10];";
   15911             :     const char* pixel_data =
   15912             :         "var source_data = [0.6, 10.6];"
   15913             :         "var expected_results = [1, 11];";
   15914             :     bool is_unsigned = (array_type == i::kExternalUint8Array ||
   15915             :                         array_type == i::kExternalUint16Array ||
   15916         126 :                         array_type == i::kExternalUint32Array);
   15917             :     bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
   15918             : 
   15919         126 :     i::SNPrintF(test_buf,
   15920             :                 "%s"
   15921             :                 "var all_passed = true;"
   15922             :                 "for (var i = 0; i < source_data.length; i++) {"
   15923             :                 "  for (var j = 0; j < 8; j++) {"
   15924             :                 "    ext_array[j] = source_data[i];"
   15925             :                 "  }"
   15926             :                 "  all_passed = all_passed &&"
   15927             :                 "               (ext_array[5] == expected_results[i]);"
   15928             :                 "}"
   15929             :                 "all_passed;",
   15930             :                 (is_unsigned ?
   15931             :                      unsigned_data :
   15932             :                      (is_pixel_data ? pixel_data : signed_data)));
   15933             :     result = CompileRun(test_buf.start());
   15934         126 :     CHECK(result->BooleanValue(v8_isolate));
   15935             :   }
   15936             : 
   15937             :   i::Handle<ExternalArrayClass> array(
   15938             :       ExternalArrayClass::cast(i::Handle<i::JSObject>::cast(jsobj)->elements()),
   15939             :       isolate);
   15940       39042 :   for (int i = 0; i < element_count; i++) {
   15941       36720 :     array->set(i, static_cast<ElementType>(i));
   15942             :   }
   15943             : 
   15944         162 :   bool old_natives_flag_sentry = i::FLAG_allow_natives_syntax;
   15945         162 :   i::FLAG_allow_natives_syntax = true;
   15946             : 
   15947             :   // Test complex assignments
   15948             :   result = CompileRun(
   15949             :       "function ee_op_test_complex_func(sum) {"
   15950             :       " for (var i = 0; i < 40; ++i) {"
   15951             :       "   sum += (ext_array[i] += 1);"
   15952             :       "   sum += (ext_array[i] -= 1);"
   15953             :       " } "
   15954             :       " return sum;"
   15955             :       "}"
   15956             :       "sum=0;"
   15957             :       "sum=ee_op_test_complex_func(sum);"
   15958             :       "sum=ee_op_test_complex_func(sum);"
   15959             :       "%OptimizeFunctionOnNextCall(ee_op_test_complex_func);"
   15960             :       "sum=ee_op_test_complex_func(sum);"
   15961             :       "sum;");
   15962         324 :   CHECK_EQ(4800, result->Int32Value(context).FromJust());
   15963             : 
   15964             :   // Test count operations
   15965             :   result = CompileRun(
   15966             :       "function ee_op_test_count_func(sum) {"
   15967             :       " for (var i = 0; i < 40; ++i) {"
   15968             :       "   sum += (++ext_array[i]);"
   15969             :       "   sum += (--ext_array[i]);"
   15970             :       " } "
   15971             :       " return sum;"
   15972             :       "}"
   15973             :       "sum=0;"
   15974             :       "sum=ee_op_test_count_func(sum);"
   15975             :       "sum=ee_op_test_count_func(sum);"
   15976             :       "%OptimizeFunctionOnNextCall(ee_op_test_count_func);"
   15977             :       "sum=ee_op_test_count_func(sum);"
   15978             :       "sum;");
   15979         324 :   CHECK_EQ(4800, result->Int32Value(context).FromJust());
   15980             : 
   15981         162 :   i::FLAG_allow_natives_syntax = old_natives_flag_sentry;
   15982             : 
   15983             :   result = CompileRun("ext_array[3] = 33;"
   15984             :                       "delete ext_array[3];"
   15985             :                       "ext_array[3];");
   15986         324 :   CHECK_EQ(33, result->Int32Value(context).FromJust());
   15987             : 
   15988             :   result = CompileRun(
   15989             :       "ext_array[0] = 10; ext_array[1] = 11;"
   15990             :       "ext_array[2] = 12; ext_array[3] = 13;"
   15991             :       "try { ext_array.__defineGetter__('2', function() { return 120; }); }"
   15992             :       "catch (e) { }"
   15993             :       "ext_array[2];");
   15994         324 :   CHECK_EQ(12, result->Int32Value(context).FromJust());
   15995             : 
   15996             :   result = CompileRun("var js_array = new Array(40);"
   15997             :                       "js_array[0] = 77;"
   15998             :                       "js_array;");
   15999         648 :   CHECK_EQ(77, v8::Object::Cast(*result)
   16000             :                    ->Get(context, v8_str("0"))
   16001             :                    .ToLocalChecked()
   16002             :                    ->Int32Value(context)
   16003             :                    .FromJust());
   16004             : 
   16005             :   result = CompileRun("ext_array[1] = 23;"
   16006             :                       "ext_array.__proto__ = [];"
   16007             :                       "js_array.__proto__ = ext_array;"
   16008             :                       "js_array.concat(ext_array);");
   16009         648 :   CHECK_EQ(77, v8::Object::Cast(*result)
   16010             :                    ->Get(context, v8_str("0"))
   16011             :                    .ToLocalChecked()
   16012             :                    ->Int32Value(context)
   16013             :                    .FromJust());
   16014         648 :   CHECK_EQ(23, v8::Object::Cast(*result)
   16015             :                    ->Get(context, v8_str("1"))
   16016             :                    .ToLocalChecked()
   16017             :                    ->Int32Value(context)
   16018             :                    .FromJust());
   16019             : 
   16020             :   result = CompileRun("ext_array[1] = 23;");
   16021         324 :   CHECK_EQ(23, result->Int32Value(context).FromJust());
   16022         162 : }
   16023             : 
   16024             : 
   16025             : template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
   16026             :           class ElementType>
   16027          54 : static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
   16028             :                                       ElementType low, ElementType high) {
   16029          54 :   i::FLAG_allow_natives_syntax = true;
   16030          54 :   LocalContext context;
   16031             :   i::Isolate* isolate = CcTest::i_isolate();
   16032             :   i::Factory* factory = isolate->factory();
   16033         108 :   v8::HandleScope scope(context->GetIsolate());
   16034             :   const int kElementCount = 260;
   16035             :   i::Handle<i::JSTypedArray> jsobj =
   16036          54 :       factory->NewJSTypedArray(elements_kind, kElementCount);
   16037             :   i::Handle<FixedTypedArrayClass> fixed_array(
   16038             :       FixedTypedArrayClass::cast(jsobj->elements()), isolate);
   16039          54 :   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
   16040             :            fixed_array->map()->instance_type());
   16041          54 :   CHECK_EQ(kElementCount, fixed_array->length());
   16042          54 :   CcTest::CollectAllGarbage();
   16043       28134 :   for (int i = 0; i < kElementCount; i++) {
   16044       26520 :     fixed_array->set(i, static_cast<ElementType>(i));
   16045             :   }
   16046             :   // Force GC to trigger verification.
   16047          54 :   CcTest::CollectAllGarbage();
   16048       28134 :   for (int i = 0; i < kElementCount; i++) {
   16049       14040 :     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
   16050             :              static_cast<int64_t>(fixed_array->get_scalar(i)));
   16051             :   }
   16052             :   v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
   16053             : 
   16054         108 :   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
   16055             :       context.local(), obj, kElementCount, array_type,
   16056             :       static_cast<int64_t>(low),
   16057             :       static_cast<int64_t>(high));
   16058          54 : }
   16059             : 
   16060             : 
   16061       26645 : THREADED_TEST(FixedUint8Array) {
   16062             :   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
   16063           6 :       i::kExternalUint8Array, 0x0, 0xFF);
   16064           6 : }
   16065             : 
   16066             : 
   16067       26645 : THREADED_TEST(FixedUint8ClampedArray) {
   16068             :   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
   16069             :                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
   16070           6 :       i::kExternalUint8ClampedArray, 0x0, 0xFF);
   16071           6 : }
   16072             : 
   16073             : 
   16074       26645 : THREADED_TEST(FixedInt8Array) {
   16075             :   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
   16076           6 :       i::kExternalInt8Array, -0x80, 0x7F);
   16077           6 : }
   16078             : 
   16079             : 
   16080       26645 : THREADED_TEST(FixedUint16Array) {
   16081             :   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
   16082           6 :       i::kExternalUint16Array, 0x0, 0xFFFF);
   16083           6 : }
   16084             : 
   16085             : 
   16086       26645 : THREADED_TEST(FixedInt16Array) {
   16087             :   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
   16088           6 :       i::kExternalInt16Array, -0x8000, 0x7FFF);
   16089           6 : }
   16090             : 
   16091             : 
   16092       26645 : THREADED_TEST(FixedUint32Array) {
   16093             :   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
   16094           6 :       i::kExternalUint32Array, 0x0, UINT_MAX);
   16095           6 : }
   16096             : 
   16097             : 
   16098       26645 : THREADED_TEST(FixedInt32Array) {
   16099             :   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
   16100           6 :       i::kExternalInt32Array, INT_MIN, INT_MAX);
   16101           6 : }
   16102             : 
   16103             : 
   16104       26645 : THREADED_TEST(FixedFloat32Array) {
   16105             :   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
   16106           6 :       i::kExternalFloat32Array, -500, 500);
   16107           6 : }
   16108             : 
   16109             : 
   16110       26645 : THREADED_TEST(FixedFloat64Array) {
   16111             :   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
   16112           6 :       i::kExternalFloat64Array, -500, 500);
   16113           6 : }
   16114             : 
   16115             : 
   16116             : template <typename ElementType, typename TypedArray, class ExternalArrayClass,
   16117             :           class ArrayBufferType>
   16118         108 : void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
   16119             :                           int64_t high) {
   16120             :   const int kElementCount = 50;
   16121             : 
   16122             :   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   16123             : 
   16124         108 :   LocalContext env;
   16125         108 :   v8::Isolate* isolate = env->GetIsolate();
   16126         216 :   v8::HandleScope handle_scope(isolate);
   16127             : 
   16128             :   Local<ArrayBufferType> ab =
   16129             :       ArrayBufferType::New(isolate, backing_store.start(),
   16130         108 :                            (kElementCount + 2) * sizeof(ElementType));
   16131             :   Local<TypedArray> ta =
   16132         108 :       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   16133         108 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   16134         108 :   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   16135         108 :   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
   16136         108 :   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
   16137         324 :   CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
   16138             : 
   16139             :   ElementType* data = backing_store.start() + 2;
   16140       10908 :   for (int i = 0; i < kElementCount; i++) {
   16141        5400 :     data[i] = static_cast<ElementType>(i);
   16142             :   }
   16143             : 
   16144         108 :   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16145             :       env.local(), ta, kElementCount, array_type, low, high);
   16146         108 : }
   16147             : 
   16148             : 
   16149       26645 : THREADED_TEST(Uint8Array) {
   16150             :   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16151           6 :                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16152           6 : }
   16153             : 
   16154             : 
   16155       26645 : THREADED_TEST(Int8Array) {
   16156             :   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16157           6 :                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
   16158           6 : }
   16159             : 
   16160             : 
   16161       26645 : THREADED_TEST(Uint16Array) {
   16162             :   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16163           6 :                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
   16164           6 : }
   16165             : 
   16166             : 
   16167       26645 : THREADED_TEST(Int16Array) {
   16168             :   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16169             :                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16170           6 :                                         0x7FFF);
   16171           6 : }
   16172             : 
   16173             : 
   16174       26645 : THREADED_TEST(Uint32Array) {
   16175             :   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16176           6 :                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
   16177           6 : }
   16178             : 
   16179             : 
   16180       26645 : THREADED_TEST(Int32Array) {
   16181             :   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16182             :                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16183           6 :                                         INT_MAX);
   16184           6 : }
   16185             : 
   16186             : 
   16187       26645 : THREADED_TEST(Float32Array) {
   16188             :   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16189           6 :                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
   16190           6 : }
   16191             : 
   16192             : 
   16193       26645 : THREADED_TEST(Float64Array) {
   16194             :   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16195           6 :                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
   16196           6 : }
   16197             : 
   16198             : 
   16199       26645 : THREADED_TEST(Uint8ClampedArray) {
   16200             :   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16201             :                        i::FixedUint8ClampedArray, v8::ArrayBuffer>(
   16202           6 :       i::kExternalUint8ClampedArray, 0, 0xFF);
   16203           6 : }
   16204             : 
   16205             : 
   16206       26645 : THREADED_TEST(DataView) {
   16207             :   const int kSize = 50;
   16208             : 
   16209             :   i::ScopedVector<uint8_t> backing_store(kSize+2);
   16210             : 
   16211           6 :   LocalContext env;
   16212           6 :   v8::Isolate* isolate = env->GetIsolate();
   16213          12 :   v8::HandleScope handle_scope(isolate);
   16214             : 
   16215             :   Local<v8::ArrayBuffer> ab =
   16216           6 :       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16217           6 :   Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
   16218           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16219           6 :   CHECK_EQ(2u, dv->ByteOffset());
   16220           6 :   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16221          18 :   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16222           6 : }
   16223             : 
   16224             : 
   16225       26645 : THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
   16226           6 :   LocalContext env;
   16227           6 :   v8::Isolate* isolate = env->GetIsolate();
   16228          12 :   v8::HandleScope handle_scope(isolate);
   16229             : 
   16230             :   // Make sure the pointer looks like a heap object
   16231             :   uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
   16232             : 
   16233             :   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16234           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16235             : 
   16236             :   // Should not crash
   16237           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16238           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
   16239           6 :   CcTest::CollectAllGarbage();
   16240           6 :   CcTest::CollectAllGarbage();
   16241             : 
   16242             :   // Should not move the pointer
   16243           6 :   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16244           6 : }
   16245             : 
   16246             : 
   16247       26645 : THREADED_TEST(SkipArrayBufferDuringScavenge) {
   16248           6 :   LocalContext env;
   16249           6 :   v8::Isolate* isolate = env->GetIsolate();
   16250          12 :   v8::HandleScope handle_scope(isolate);
   16251             : 
   16252             :   // Make sure the pointer looks like a heap object
   16253           6 :   Local<v8::Object> tmp = v8::Object::New(isolate);
   16254             :   uint8_t* store_ptr =
   16255           6 :       reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
   16256             : 
   16257             :   // Make `store_ptr` point to from space
   16258           6 :   CcTest::CollectGarbage(i::NEW_SPACE);
   16259             : 
   16260             :   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16261           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16262             : 
   16263             :   // Should not crash,
   16264             :   // i.e. backing store pointer should not be treated as a heap object pointer
   16265           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16266           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
   16267             : 
   16268             :   // Use `ab` to silence compiler warning
   16269           6 :   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16270           6 : }
   16271             : 
   16272             : 
   16273       26645 : THREADED_TEST(SharedUint8Array) {
   16274           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16275             :   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16276           6 :                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16277           6 : }
   16278             : 
   16279             : 
   16280       26645 : THREADED_TEST(SharedInt8Array) {
   16281           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16282             :   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16283             :                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
   16284           6 :                                               0x7F);
   16285           6 : }
   16286             : 
   16287             : 
   16288       26645 : THREADED_TEST(SharedUint16Array) {
   16289           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16290             :   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16291             :                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
   16292           6 :                                               0xFFFF);
   16293           6 : }
   16294             : 
   16295             : 
   16296       26645 : THREADED_TEST(SharedInt16Array) {
   16297           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16298             :   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16299             :                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16300           6 :                                               0x7FFF);
   16301           6 : }
   16302             : 
   16303             : 
   16304       26645 : THREADED_TEST(SharedUint32Array) {
   16305           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16306             :   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16307             :                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
   16308           6 :                                               UINT_MAX);
   16309           6 : }
   16310             : 
   16311             : 
   16312       26645 : THREADED_TEST(SharedInt32Array) {
   16313           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16314             :   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16315             :                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16316           6 :                                               INT_MAX);
   16317           6 : }
   16318             : 
   16319             : 
   16320       26645 : THREADED_TEST(SharedFloat32Array) {
   16321           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16322             :   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16323             :                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
   16324           6 :                                               500);
   16325           6 : }
   16326             : 
   16327             : 
   16328       26645 : THREADED_TEST(SharedFloat64Array) {
   16329           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16330             :   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16331             :                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
   16332           6 :                                               500);
   16333           6 : }
   16334             : 
   16335             : 
   16336       26645 : THREADED_TEST(SharedUint8ClampedArray) {
   16337           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16338             :   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16339             :                        i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
   16340           6 :       i::kExternalUint8ClampedArray, 0, 0xFF);
   16341           6 : }
   16342             : 
   16343             : 
   16344       26645 : THREADED_TEST(SharedDataView) {
   16345           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16346             :   const int kSize = 50;
   16347             : 
   16348             :   i::ScopedVector<uint8_t> backing_store(kSize + 2);
   16349             : 
   16350           6 :   LocalContext env;
   16351           6 :   v8::Isolate* isolate = env->GetIsolate();
   16352          12 :   v8::HandleScope handle_scope(isolate);
   16353             : 
   16354             :   Local<v8::SharedArrayBuffer> ab =
   16355           6 :       v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16356             :   Local<v8::DataView> dv =
   16357           6 :       v8::DataView::New(ab, 2, kSize);
   16358           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16359           6 :   CHECK_EQ(2u, dv->ByteOffset());
   16360           6 :   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16361          18 :   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16362           6 : }
   16363             : 
   16364             : #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                     \
   16365             :   THREADED_TEST(Is##View) {                                                 \
   16366             :     LocalContext env;                                                       \
   16367             :     v8::Isolate* isolate = env->GetIsolate();                               \
   16368             :     v8::HandleScope handle_scope(isolate);                                  \
   16369             :                                                                             \
   16370             :     Local<Value> result = CompileRun(                                       \
   16371             :         "var ab = new ArrayBuffer(128);"                                    \
   16372             :         "new " #View "(ab)");                                               \
   16373             :     CHECK(result->IsArrayBufferView());                                     \
   16374             :     CHECK(result->Is##View());                                              \
   16375             :     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
   16376             :   }
   16377             : 
   16378       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   16379       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   16380       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   16381       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   16382       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   16383       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   16384       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   16385       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   16386       26663 : IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   16387       26663 : IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   16388             : 
   16389             : #undef IS_ARRAY_BUFFER_VIEW_TEST
   16390             : 
   16391             : 
   16392             : 
   16393       26645 : THREADED_TEST(ScriptContextDependence) {
   16394           6 :   LocalContext c1;
   16395          12 :   v8::HandleScope scope(c1->GetIsolate());
   16396             :   const char *source = "foo";
   16397             :   v8::Local<v8::Script> dep = v8_compile(source);
   16398             :   v8::ScriptCompiler::Source script_source(
   16399           6 :       v8::String::NewFromUtf8(c1->GetIsolate(), source,
   16400           6 :                               v8::NewStringType::kNormal)
   16401             :           .ToLocalChecked());
   16402             :   v8::Local<v8::UnboundScript> indep =
   16403           6 :       v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
   16404             :           .ToLocalChecked();
   16405          12 :   c1->Global()
   16406          18 :       ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
   16407           6 :                                                 v8::NewStringType::kNormal)
   16408             :                             .ToLocalChecked(),
   16409          12 :             v8::Integer::New(c1->GetIsolate(), 100))
   16410             :       .FromJust();
   16411          18 :   CHECK_EQ(
   16412             :       dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
   16413             :       100);
   16414          24 :   CHECK_EQ(indep->BindToCurrentContext()
   16415             :                ->Run(c1.local())
   16416             :                .ToLocalChecked()
   16417             :                ->Int32Value(c1.local())
   16418             :                .FromJust(),
   16419             :            100);
   16420           6 :   LocalContext c2;
   16421          12 :   c2->Global()
   16422          18 :       ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
   16423           6 :                                                 v8::NewStringType::kNormal)
   16424             :                             .ToLocalChecked(),
   16425          12 :             v8::Integer::New(c2->GetIsolate(), 101))
   16426             :       .FromJust();
   16427          18 :   CHECK_EQ(
   16428             :       dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
   16429             :       100);
   16430          24 :   CHECK_EQ(indep->BindToCurrentContext()
   16431             :                ->Run(c2.local())
   16432             :                .ToLocalChecked()
   16433             :                ->Int32Value(c2.local())
   16434             :                .FromJust(),
   16435             :            101);
   16436           6 : }
   16437             : 
   16438             : 
   16439       26645 : THREADED_TEST(StackTrace) {
   16440           6 :   LocalContext context;
   16441          12 :   v8::HandleScope scope(context->GetIsolate());
   16442          12 :   v8::TryCatch try_catch(context->GetIsolate());
   16443             :   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   16444           6 :   v8::Local<v8::String> src = v8_str(source);
   16445           6 :   v8::Local<v8::String> origin = v8_str("stack-trace-test");
   16446             :   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
   16447          24 :   CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
   16448             :                                                  &script_source)
   16449             :             .ToLocalChecked()
   16450             :             ->BindToCurrentContext()
   16451             :             ->Run(context.local())
   16452             :             .IsEmpty());
   16453           6 :   CHECK(try_catch.HasCaught());
   16454             :   v8::String::Utf8Value stack(
   16455             :       context->GetIsolate(),
   16456          18 :       try_catch.StackTrace(context.local()).ToLocalChecked());
   16457           6 :   CHECK_NOT_NULL(strstr(*stack, "at foo (stack-trace-test"));
   16458           6 : }
   16459             : 
   16460             : 
   16461             : // Checks that a StackFrame has certain expected values.
   16462         100 : void checkStackFrame(const char* expected_script_name,
   16463             :                      const char* expected_func_name, int expected_line_number,
   16464             :                      int expected_column, bool is_eval, bool is_constructor,
   16465             :                      v8::Local<v8::StackFrame> frame) {
   16466         200 :   v8::HandleScope scope(CcTest::isolate());
   16467         300 :   v8::String::Utf8Value func_name(CcTest::isolate(), frame->GetFunctionName());
   16468         300 :   v8::String::Utf8Value script_name(CcTest::isolate(), frame->GetScriptName());
   16469         100 :   if (*script_name == nullptr) {
   16470             :     // The situation where there is no associated script, like for evals.
   16471          35 :     CHECK_NULL(expected_script_name);
   16472             :   } else {
   16473          65 :     CHECK_NOT_NULL(strstr(*script_name, expected_script_name));
   16474             :   }
   16475         100 :   CHECK_NOT_NULL(strstr(*func_name, expected_func_name));
   16476         100 :   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   16477         100 :   CHECK_EQ(expected_column, frame->GetColumn());
   16478         100 :   CHECK_EQ(is_eval, frame->IsEval());
   16479         100 :   CHECK_EQ(is_constructor, frame->IsConstructor());
   16480         100 : }
   16481             : 
   16482             : 
   16483          35 : void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   16484          70 :   v8::HandleScope scope(args.GetIsolate());
   16485             :   const char* origin = "capture-stack-trace-test";
   16486             :   const int kOverviewTest = 1;
   16487             :   const int kDetailedTest = 2;
   16488             :   const int kFunctionName = 3;
   16489             :   const int kDisplayName = 4;
   16490             :   const int kFunctionNameAndDisplayName = 5;
   16491             :   const int kDisplayNameIsNotString = 6;
   16492             :   const int kFunctionNameIsNotString = 7;
   16493             : 
   16494          35 :   CHECK_EQ(args.Length(), 1);
   16495             : 
   16496          35 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   16497             :   v8::Isolate* isolate = args.GetIsolate();
   16498          70 :   int testGroup = args[0]->Int32Value(context).FromJust();
   16499          35 :   if (testGroup == kOverviewTest) {
   16500             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16501           5 :         args.GetIsolate(), 10, v8::StackTrace::kOverview);
   16502           5 :     CHECK_EQ(4, stackTrace->GetFrameCount());
   16503           5 :     checkStackFrame(origin, "bar", 2, 10, false, false,
   16504           5 :                     stackTrace->GetFrame(args.GetIsolate(), 0));
   16505           5 :     checkStackFrame(origin, "foo", 6, 3, false, true,
   16506           5 :                     stackTrace->GetFrame(isolate, 1));
   16507             :     // This is the source string inside the eval which has the call to foo.
   16508           5 :     checkStackFrame(nullptr, "", 1, 1, true, false,
   16509           5 :                     stackTrace->GetFrame(isolate, 2));
   16510             :     // The last frame is an anonymous function which has the initial eval call.
   16511           5 :     checkStackFrame(origin, "", 8, 7, false, false,
   16512           5 :                     stackTrace->GetFrame(isolate, 3));
   16513          30 :   } else if (testGroup == kDetailedTest) {
   16514             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16515           5 :         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   16516           5 :     CHECK_EQ(4, stackTrace->GetFrameCount());
   16517           5 :     checkStackFrame(origin, "bat", 4, 22, false, false,
   16518           5 :                     stackTrace->GetFrame(isolate, 0));
   16519           5 :     checkStackFrame(origin, "baz", 8, 3, false, true,
   16520           5 :                     stackTrace->GetFrame(isolate, 1));
   16521             :     bool is_eval = true;
   16522             :     // This is the source string inside the eval which has the call to baz.
   16523           5 :     checkStackFrame(nullptr, "", 1, 1, is_eval, false,
   16524           5 :                     stackTrace->GetFrame(isolate, 2));
   16525             :     // The last frame is an anonymous function which has the initial eval call.
   16526           5 :     checkStackFrame(origin, "", 10, 1, false, false,
   16527           5 :                     stackTrace->GetFrame(isolate, 3));
   16528          25 :   } else if (testGroup == kFunctionName) {
   16529             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16530           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16531           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16532           5 :     checkStackFrame(nullptr, "function.name", 3, 1, true, false,
   16533           5 :                     stackTrace->GetFrame(isolate, 0));
   16534          20 :   } else if (testGroup == kDisplayName) {
   16535             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16536           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16537           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16538           5 :     checkStackFrame(nullptr, "function.displayName", 3, 1, true, false,
   16539           5 :                     stackTrace->GetFrame(isolate, 0));
   16540          15 :   } else if (testGroup == kFunctionNameAndDisplayName) {
   16541             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16542           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16543           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16544           5 :     checkStackFrame(nullptr, "function.displayName", 3, 1, true, false,
   16545           5 :                     stackTrace->GetFrame(isolate, 0));
   16546          10 :   } else if (testGroup == kDisplayNameIsNotString) {
   16547             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16548           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16549           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16550           5 :     checkStackFrame(nullptr, "function.name", 3, 1, true, false,
   16551           5 :                     stackTrace->GetFrame(isolate, 0));
   16552           5 :   } else if (testGroup == kFunctionNameIsNotString) {
   16553             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16554           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16555           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16556           5 :     checkStackFrame(nullptr, "", 3, 1, true, false,
   16557           5 :                     stackTrace->GetFrame(isolate, 0));
   16558             :   }
   16559          35 : }
   16560             : 
   16561             : 
   16562             : // Tests the C++ StackTrace API.
   16563             : // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   16564             : // THREADED_TEST(CaptureStackTrace) {
   16565       26644 : TEST(CaptureStackTrace) {
   16566           5 :   v8::Isolate* isolate = CcTest::isolate();
   16567          10 :   v8::HandleScope scope(isolate);
   16568           5 :   v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
   16569           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   16570          15 :   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   16571           5 :              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
   16572           5 :   LocalContext context(nullptr, templ);
   16573             : 
   16574             :   // Test getting OVERVIEW information. Should ignore information that is not
   16575             :   // script name, function name, line number, and column offset.
   16576             :   const char *overview_source =
   16577             :     "function bar() {\n"
   16578             :     "  var y; AnalyzeStackInNativeCode(1);\n"
   16579             :     "}\n"
   16580             :     "function foo() {\n"
   16581             :     "\n"
   16582             :     "  bar();\n"
   16583             :     "}\n"
   16584             :     "var x;eval('new foo();');";
   16585           5 :   v8::Local<v8::String> overview_src = v8_str(overview_source);
   16586             :   v8::ScriptCompiler::Source script_source(overview_src,
   16587             :                                            v8::ScriptOrigin(origin));
   16588             :   v8::Local<Value> overview_result(
   16589           5 :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
   16590             :           .ToLocalChecked()
   16591          10 :           ->BindToCurrentContext()
   16592           5 :           ->Run(context.local())
   16593             :           .ToLocalChecked());
   16594           5 :   CHECK(!overview_result.IsEmpty());
   16595           5 :   CHECK(overview_result->IsObject());
   16596             : 
   16597             :   // Test getting DETAILED information.
   16598             :   const char *detailed_source =
   16599             :     "function bat() {AnalyzeStackInNativeCode(2);\n"
   16600             :     "}\n"
   16601             :     "\n"
   16602             :     "function baz() {\n"
   16603             :     "  bat();\n"
   16604             :     "}\n"
   16605             :     "eval('new baz();');";
   16606           5 :   v8::Local<v8::String> detailed_src = v8_str(detailed_source);
   16607             :   // Make the script using a non-zero line and column offset.
   16608           5 :   v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
   16609           5 :   v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
   16610             :   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   16611             :   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
   16612             :   v8::Local<v8::UnboundScript> detailed_script(
   16613           5 :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
   16614             :           .ToLocalChecked());
   16615          10 :   v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
   16616           5 :                                        ->Run(context.local())
   16617             :                                        .ToLocalChecked());
   16618           5 :   CHECK(!detailed_result.IsEmpty());
   16619           5 :   CHECK(detailed_result->IsObject());
   16620             : 
   16621             :   // Test using function.name and function.displayName in stack trace
   16622             :   const char* function_name_source =
   16623             :       "function bar(function_name, display_name, testGroup) {\n"
   16624             :       "  var f = new Function(`AnalyzeStackInNativeCode(${testGroup});`);\n"
   16625             :       "  if (function_name) {\n"
   16626             :       "    Object.defineProperty(f, 'name', { value: function_name });\n"
   16627             :       "  }\n"
   16628             :       "  if (display_name) {\n"
   16629             :       "    f.displayName = display_name;"
   16630             :       "  }\n"
   16631             :       "  f()\n"
   16632             :       "}\n"
   16633             :       "bar('function.name', undefined, 3);\n"
   16634             :       "bar(undefined, 'function.displayName', 4);\n"
   16635             :       "bar('function.name', 'function.displayName', 5);\n"
   16636             :       "bar('function.name', 239, 6);\n"
   16637             :       "bar(239, undefined, 7);\n";
   16638             :   v8::Local<v8::String> function_name_src =
   16639           5 :       v8::String::NewFromUtf8(isolate, function_name_source,
   16640             :                               v8::NewStringType::kNormal)
   16641             :           .ToLocalChecked();
   16642             :   v8::ScriptCompiler::Source script_source3(function_name_src,
   16643             :                                             v8::ScriptOrigin(origin));
   16644             :   v8::Local<Value> function_name_result(
   16645           5 :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
   16646             :           .ToLocalChecked()
   16647          10 :           ->BindToCurrentContext()
   16648           5 :           ->Run(context.local())
   16649             :           .ToLocalChecked());
   16650           5 :   CHECK(!function_name_result.IsEmpty());
   16651           5 : }
   16652             : 
   16653             : 
   16654           5 : static void StackTraceForUncaughtExceptionListener(
   16655             :     v8::Local<v8::Message> message, v8::Local<Value>) {
   16656           5 :   report_count++;
   16657           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16658           5 :   CHECK_EQ(2, stack_trace->GetFrameCount());
   16659           5 :   checkStackFrame("origin", "foo", 2, 3, false, false,
   16660           5 :                   stack_trace->GetFrame(message->GetIsolate(), 0));
   16661           5 :   checkStackFrame("origin", "bar", 5, 3, false, false,
   16662           5 :                   stack_trace->GetFrame(message->GetIsolate(), 1));
   16663           5 : }
   16664             : 
   16665             : 
   16666       26644 : TEST(CaptureStackTraceForUncaughtException) {
   16667           5 :   report_count = 0;
   16668           5 :   LocalContext env;
   16669           5 :   v8::Isolate* isolate = env->GetIsolate();
   16670          10 :   v8::HandleScope scope(isolate);
   16671           5 :   isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
   16672           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16673             : 
   16674             :   CompileRunWithOrigin(
   16675             :       "function foo() {\n"
   16676             :       "  throw 1;\n"
   16677             :       "};\n"
   16678             :       "function bar() {\n"
   16679             :       "  foo();\n"
   16680             :       "};",
   16681             :       "origin");
   16682           5 :   v8::Local<v8::Object> global = env->Global();
   16683             :   Local<Value> trouble =
   16684          15 :       global->Get(env.local(), v8_str("bar")).ToLocalChecked();
   16685           5 :   CHECK(trouble->IsFunction());
   16686          10 :   CHECK(Function::Cast(*trouble)
   16687             :             ->Call(env.local(), global, 0, nullptr)
   16688             :             .IsEmpty());
   16689           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16690           5 :   isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   16691           5 :   CHECK_EQ(1, report_count);
   16692           5 : }
   16693             : 
   16694       26644 : TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   16695           5 :   LocalContext env;
   16696           5 :   v8::Isolate* isolate = env->GetIsolate();
   16697          10 :   v8::HandleScope scope(isolate);
   16698             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
   16699           5 :                                                      v8::StackTrace::kDetailed);
   16700             : 
   16701             :   CompileRun(
   16702             :       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   16703             :       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   16704             :       "    'isConstructor'];\n"
   16705             :       "for (var i = 0; i < setters.length; i++) {\n"
   16706             :       "  var prop = setters[i];\n"
   16707             :       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   16708             :       "}\n");
   16709             :   CompileRun("throw 'exception';");
   16710           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16711           5 : }
   16712             : 
   16713             : static int asm_warning_triggered = 0;
   16714             : 
   16715           5 : static void AsmJsWarningListener(v8::Local<v8::Message> message,
   16716             :                                  v8::Local<Value>) {
   16717             :   DCHECK_EQ(v8::Isolate::kMessageWarning, message->ErrorLevel());
   16718           5 :   asm_warning_triggered = 1;
   16719           5 : }
   16720             : 
   16721       26644 : TEST(AsmJsWarning) {
   16722           5 :   i::FLAG_validate_asm = true;
   16723           5 :   if (i::FLAG_suppress_asm_messages) return;
   16724             : 
   16725           5 :   LocalContext env;
   16726           5 :   v8::Isolate* isolate = env->GetIsolate();
   16727          10 :   v8::HandleScope scope(isolate);
   16728             : 
   16729           5 :   asm_warning_triggered = 0;
   16730           5 :   isolate->AddMessageListenerWithErrorLevel(AsmJsWarningListener,
   16731           5 :                                             v8::Isolate::kMessageAll);
   16732             :   CompileRun(
   16733             :       "function module() {\n"
   16734             :       "  'use asm';\n"
   16735             :       "  var x = 'hi';\n"
   16736             :       "  return {};\n"
   16737             :       "}\n"
   16738             :       "module();");
   16739             :   DCHECK_EQ(1, asm_warning_triggered);
   16740           5 :   isolate->RemoveMessageListeners(AsmJsWarningListener);
   16741             : }
   16742             : 
   16743             : static int error_level_message_count = 0;
   16744             : static int expected_error_level = 0;
   16745             : 
   16746          20 : static void ErrorLevelListener(v8::Local<v8::Message> message,
   16747             :                                v8::Local<Value>) {
   16748             :   DCHECK_EQ(expected_error_level, message->ErrorLevel());
   16749          20 :   ++error_level_message_count;
   16750          20 : }
   16751             : 
   16752       26644 : TEST(ErrorLevelWarning) {
   16753           5 :   LocalContext env;
   16754           5 :   v8::Isolate* isolate = env->GetIsolate();
   16755             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   16756          10 :   v8::HandleScope scope(isolate);
   16757             : 
   16758             :   const char* source = "fake = 1;";
   16759           5 :   v8::Local<v8::Script> lscript = CompileWithOrigin(source, "test", false);
   16760             :   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   16761          10 :       v8::Utils::OpenHandle(*lscript->GetUnboundScript()));
   16762          10 :   CHECK(obj->script()->IsScript());
   16763          10 :   i::Handle<i::Script> script(i::Script::cast(obj->script()), i_isolate);
   16764             : 
   16765             :   int levels[] = {
   16766             :       v8::Isolate::kMessageLog, v8::Isolate::kMessageInfo,
   16767             :       v8::Isolate::kMessageDebug, v8::Isolate::kMessageWarning,
   16768           5 :   };
   16769           5 :   error_level_message_count = 0;
   16770           5 :   isolate->AddMessageListenerWithErrorLevel(ErrorLevelListener,
   16771           5 :                                             v8::Isolate::kMessageAll);
   16772          45 :   for (size_t i = 0; i < arraysize(levels); i++) {
   16773          20 :     i::MessageLocation location(script, 0, 0);
   16774             :     i::Handle<i::String> msg(i_isolate->factory()->InternalizeOneByteString(
   16775          20 :         i::StaticCharVector("test")));
   16776             :     i::Handle<i::JSMessageObject> message =
   16777             :         i::MessageHandler::MakeMessageObject(
   16778             :             i_isolate, i::MessageTemplate::kAsmJsInvalid, &location, msg,
   16779          20 :             i::Handle<i::FixedArray>::null());
   16780          20 :     message->set_error_level(levels[i]);
   16781          20 :     expected_error_level = levels[i];
   16782          20 :     i::MessageHandler::ReportMessage(i_isolate, &location, message);
   16783             :   }
   16784           5 :   isolate->RemoveMessageListeners(ErrorLevelListener);
   16785             :   DCHECK_EQ(arraysize(levels), error_level_message_count);
   16786           5 : }
   16787             : 
   16788           5 : static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
   16789             :                                            v8::Local<Value>) {
   16790           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16791           5 :   v8::Isolate* isolate = message->GetIsolate();
   16792           5 :   CHECK_EQ(5, stack_trace->GetFrameCount());
   16793           5 :   checkStackFrame("origin", "foo:0", 4, 7, false, false,
   16794           5 :                   stack_trace->GetFrame(isolate, 0));
   16795           5 :   checkStackFrame("origin", "foo:1", 5, 27, false, false,
   16796           5 :                   stack_trace->GetFrame(isolate, 1));
   16797           5 :   checkStackFrame("origin", "foo", 5, 27, false, false,
   16798           5 :                   stack_trace->GetFrame(isolate, 2));
   16799           5 :   checkStackFrame("origin", "foo", 5, 27, false, false,
   16800           5 :                   stack_trace->GetFrame(isolate, 3));
   16801           5 :   checkStackFrame("origin", "", 1, 14, false, false,
   16802           5 :                   stack_trace->GetFrame(isolate, 4));
   16803           5 : }
   16804             : 
   16805             : 
   16806       26644 : TEST(GetStackTraceContainsFunctionsWithFunctionName) {
   16807           5 :   LocalContext env;
   16808           5 :   v8::Isolate* isolate = env->GetIsolate();
   16809          10 :   v8::HandleScope scope(isolate);
   16810             : 
   16811             :   CompileRunWithOrigin(
   16812             :       "function gen(name, counter) {\n"
   16813             :       "  var f = function foo() {\n"
   16814             :       "    if (counter === 0)\n"
   16815             :       "      throw 1;\n"
   16816             :       "    gen(name, counter - 1)();\n"
   16817             :       "  };\n"
   16818             :       "  if (counter == 3) {\n"
   16819             :       "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
   16820             :       "  } else {\n"
   16821             :       "    Object.defineProperty(f, 'name', {writable:true});\n"
   16822             :       "    if (counter == 2)\n"
   16823             :       "      f.name = 42;\n"
   16824             :       "    else\n"
   16825             :       "      f.name = name + ':' + counter;\n"
   16826             :       "  }\n"
   16827             :       "  return f;\n"
   16828             :       "};",
   16829             :       "origin");
   16830             : 
   16831           5 :   isolate->AddMessageListener(StackTraceFunctionNameListener);
   16832           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16833             :   CompileRunWithOrigin("gen('foo', 3)();", "origin");
   16834           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16835           5 :   isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
   16836           5 : }
   16837             : 
   16838             : 
   16839           5 : static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
   16840             :                                      v8::Local<v8::Value> data) {
   16841             :   // Use the frame where JavaScript is called from.
   16842           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16843           5 :   CHECK(!stack_trace.IsEmpty());
   16844           5 :   int frame_count = stack_trace->GetFrameCount();
   16845           5 :   CHECK_EQ(3, frame_count);
   16846           5 :   int line_number[] = {1, 2, 5};
   16847          35 :   for (int i = 0; i < frame_count; i++) {
   16848          30 :     CHECK_EQ(line_number[i],
   16849             :              stack_trace->GetFrame(message->GetIsolate(), i)->GetLineNumber());
   16850             :   }
   16851           5 : }
   16852             : 
   16853             : 
   16854             : // Test that we only return the stack trace at the site where the exception
   16855             : // is first thrown (not where it is rethrown).
   16856       26644 : TEST(RethrowStackTrace) {
   16857           5 :   LocalContext env;
   16858           5 :   v8::Isolate* isolate = env->GetIsolate();
   16859          10 :   v8::HandleScope scope(isolate);
   16860             :   // We make sure that
   16861             :   // - the stack trace of the ReferenceError in g() is reported.
   16862             :   // - the stack trace is not overwritten when e1 is rethrown by t().
   16863             :   // - the stack trace of e2 does not overwrite that of e1.
   16864             :   const char* source =
   16865             :       "function g() { error; }          \n"
   16866             :       "function f() { g(); }            \n"
   16867             :       "function t(e) { throw e; }       \n"
   16868             :       "try {                            \n"
   16869             :       "  f();                           \n"
   16870             :       "} catch (e1) {                   \n"
   16871             :       "  try {                          \n"
   16872             :       "    error;                       \n"
   16873             :       "  } catch (e2) {                 \n"
   16874             :       "    t(e1);                       \n"
   16875             :       "  }                              \n"
   16876             :       "}                                \n";
   16877           5 :   isolate->AddMessageListener(RethrowStackTraceHandler);
   16878           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16879             :   CompileRun(source);
   16880           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16881           5 :   isolate->RemoveMessageListeners(RethrowStackTraceHandler);
   16882           5 : }
   16883             : 
   16884             : 
   16885           5 : static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
   16886             :                                               v8::Local<v8::Value> data) {
   16887           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16888           5 :   CHECK(!stack_trace.IsEmpty());
   16889           5 :   int frame_count = stack_trace->GetFrameCount();
   16890           5 :   CHECK_EQ(2, frame_count);
   16891           5 :   int line_number[] = {3, 7};
   16892          25 :   for (int i = 0; i < frame_count; i++) {
   16893          20 :     CHECK_EQ(line_number[i],
   16894             :              stack_trace->GetFrame(message->GetIsolate(), i)->GetLineNumber());
   16895             :   }
   16896           5 : }
   16897             : 
   16898             : 
   16899             : // Test that we do not recognize identity for primitive exceptions.
   16900       26644 : TEST(RethrowPrimitiveStackTrace) {
   16901           5 :   LocalContext env;
   16902           5 :   v8::Isolate* isolate = env->GetIsolate();
   16903          10 :   v8::HandleScope scope(isolate);
   16904             :   // We do not capture stack trace for non Error objects on creation time.
   16905             :   // Instead, we capture the stack trace on last throw.
   16906             :   const char* source =
   16907             :       "function g() { throw 404; }      \n"
   16908             :       "function f() { g(); }            \n"
   16909             :       "function t(e) { throw e; }       \n"
   16910             :       "try {                            \n"
   16911             :       "  f();                           \n"
   16912             :       "} catch (e1) {                   \n"
   16913             :       "  t(e1)                          \n"
   16914             :       "}                                \n";
   16915           5 :   isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
   16916           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16917             :   CompileRun(source);
   16918           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16919           5 :   isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   16920           5 : }
   16921             : 
   16922             : 
   16923           5 : static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
   16924             :                                              v8::Local<v8::Value> data) {
   16925             :   // Use the frame where JavaScript is called from.
   16926           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16927           5 :   CHECK(!stack_trace.IsEmpty());
   16928           5 :   CHECK_EQ(1, stack_trace->GetFrameCount());
   16929          10 :   CHECK_EQ(1, stack_trace->GetFrame(message->GetIsolate(), 0)->GetLineNumber());
   16930           5 : }
   16931             : 
   16932             : 
   16933             : // Test that the stack trace is captured when the error object is created and
   16934             : // not where it is thrown.
   16935       26644 : TEST(RethrowExistingStackTrace) {
   16936           5 :   LocalContext env;
   16937           5 :   v8::Isolate* isolate = env->GetIsolate();
   16938          10 :   v8::HandleScope scope(isolate);
   16939             :   const char* source =
   16940             :       "var e = new Error();           \n"
   16941             :       "throw e;                       \n";
   16942           5 :   isolate->AddMessageListener(RethrowExistingStackTraceHandler);
   16943           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16944             :   CompileRun(source);
   16945           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16946           5 :   isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
   16947           5 : }
   16948             : 
   16949             : 
   16950           5 : static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
   16951             :                                                v8::Local<v8::Value> data) {
   16952             :   // Use the frame where JavaScript is called from.
   16953           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16954           5 :   CHECK(!stack_trace.IsEmpty());
   16955           5 :   CHECK_EQ(1, stack_trace->GetFrameCount());
   16956          10 :   CHECK_EQ(2, stack_trace->GetFrame(message->GetIsolate(), 0)->GetLineNumber());
   16957           5 : }
   16958             : 
   16959             : 
   16960             : // Test that the stack trace is captured where the bogus Error object is thrown.
   16961       26644 : TEST(RethrowBogusErrorStackTrace) {
   16962           5 :   LocalContext env;
   16963           5 :   v8::Isolate* isolate = env->GetIsolate();
   16964          10 :   v8::HandleScope scope(isolate);
   16965             :   const char* source =
   16966             :       "var e = {__proto__: new Error()} \n"
   16967             :       "throw e;                         \n";
   16968           5 :   isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
   16969           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16970             :   CompileRun(source);
   16971           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16972           5 :   isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   16973           5 : }
   16974             : 
   16975             : 
   16976             : v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
   16977             : int promise_reject_counter = 0;
   16978             : int promise_revoke_counter = 0;
   16979             : int promise_reject_after_resolved_counter = 0;
   16980             : int promise_resolve_after_resolved_counter = 0;
   16981             : int promise_reject_msg_line_number = -1;
   16982             : int promise_reject_msg_column_number = -1;
   16983             : int promise_reject_line_number = -1;
   16984             : int promise_reject_column_number = -1;
   16985             : int promise_reject_frame_count = -1;
   16986             : bool promise_reject_is_shared_cross_origin = false;
   16987             : 
   16988         140 : void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
   16989         140 :   v8::Local<v8::Object> global = CcTest::global();
   16990         140 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   16991         140 :   CHECK_NE(v8::Promise::PromiseState::kPending,
   16992             :            reject_message.GetPromise()->State());
   16993         140 :   switch (reject_message.GetEvent()) {
   16994             :     case v8::kPromiseRejectWithNoHandler: {
   16995          95 :       promise_reject_counter++;
   16996         285 :       global->Set(context, v8_str("rejected"), reject_message.GetPromise())
   16997             :           .FromJust();
   16998         285 :       global->Set(context, v8_str("value"), reject_message.GetValue())
   16999             :           .FromJust();
   17000             :       v8::Local<v8::Message> message = v8::Exception::CreateMessage(
   17001          95 :           CcTest::isolate(), reject_message.GetValue());
   17002          95 :       v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17003             : 
   17004             :       promise_reject_msg_line_number =
   17005         190 :           message->GetLineNumber(context).FromJust();
   17006             :       promise_reject_msg_column_number =
   17007         190 :           message->GetStartColumn(context).FromJust() + 1;
   17008             :       promise_reject_is_shared_cross_origin =
   17009          95 :           message->IsSharedCrossOrigin();
   17010             : 
   17011          95 :       if (!stack_trace.IsEmpty()) {
   17012          35 :         promise_reject_frame_count = stack_trace->GetFrameCount();
   17013          35 :         if (promise_reject_frame_count > 0) {
   17014         150 :           CHECK(stack_trace->GetFrame(CcTest::isolate(), 0)
   17015             :                     ->GetScriptName()
   17016             :                     ->Equals(context, v8_str("pro"))
   17017             :                     .FromJust());
   17018             :           promise_reject_line_number =
   17019          60 :               stack_trace->GetFrame(CcTest::isolate(), 0)->GetLineNumber();
   17020             :           promise_reject_column_number =
   17021          60 :               stack_trace->GetFrame(CcTest::isolate(), 0)->GetColumn();
   17022             :         } else {
   17023           5 :           promise_reject_line_number = -1;
   17024           5 :           promise_reject_column_number = -1;
   17025             :         }
   17026             :       }
   17027             :       break;
   17028             :     }
   17029             :     case v8::kPromiseHandlerAddedAfterReject: {
   17030          30 :       promise_revoke_counter++;
   17031          90 :       global->Set(context, v8_str("revoked"), reject_message.GetPromise())
   17032             :           .FromJust();
   17033          30 :       CHECK(reject_message.GetValue().IsEmpty());
   17034             :       break;
   17035             :     }
   17036             :     case v8::kPromiseRejectAfterResolved: {
   17037          10 :       promise_reject_after_resolved_counter++;
   17038          10 :       break;
   17039             :     }
   17040             :     case v8::kPromiseResolveAfterResolved: {
   17041           5 :       promise_resolve_after_resolved_counter++;
   17042           5 :       break;
   17043             :     }
   17044             :   }
   17045         140 : }
   17046             : 
   17047             : 
   17048         600 : v8::Local<v8::Promise> GetPromise(const char* name) {
   17049             :   return v8::Local<v8::Promise>::Cast(
   17050        1200 :       CcTest::global()
   17051        2400 :           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   17052         600 :           .ToLocalChecked());
   17053             : }
   17054             : 
   17055             : 
   17056          35 : v8::Local<v8::Value> RejectValue() {
   17057          70 :   return CcTest::global()
   17058         140 :       ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17059          35 :       .ToLocalChecked();
   17060             : }
   17061             : 
   17062             : 
   17063          70 : void ResetPromiseStates() {
   17064          70 :   promise_reject_counter = 0;
   17065          70 :   promise_revoke_counter = 0;
   17066          70 :   promise_reject_after_resolved_counter = 0;
   17067          70 :   promise_resolve_after_resolved_counter = 0;
   17068          70 :   promise_reject_msg_line_number = -1;
   17069          70 :   promise_reject_msg_column_number = -1;
   17070          70 :   promise_reject_line_number = -1;
   17071          70 :   promise_reject_column_number = -1;
   17072          70 :   promise_reject_frame_count = -1;
   17073             : 
   17074          70 :   v8::Local<v8::Object> global = CcTest::global();
   17075          70 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17076         280 :   global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
   17077         280 :   global->Set(context, v8_str("value"), v8_str("")).FromJust();
   17078         280 :   global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
   17079          70 : }
   17080             : 
   17081             : 
   17082       26644 : TEST(PromiseRejectCallback) {
   17083           5 :   LocalContext env;
   17084           5 :   v8::Isolate* isolate = env->GetIsolate();
   17085          10 :   v8::HandleScope scope(isolate);
   17086             : 
   17087           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17088             : 
   17089           5 :   ResetPromiseStates();
   17090             : 
   17091             :   // Create promise p0.
   17092             :   CompileRun(
   17093             :       "var reject;            \n"
   17094             :       "var p0 = new Promise(  \n"
   17095             :       "  function(res, rej) { \n"
   17096             :       "    reject = rej;      \n"
   17097             :       "  }                    \n"
   17098             :       ");                     \n");
   17099          10 :   CHECK(!GetPromise("p0")->HasHandler());
   17100           5 :   CHECK_EQ(0, promise_reject_counter);
   17101           5 :   CHECK_EQ(0, promise_revoke_counter);
   17102             : 
   17103             :   // Add resolve handler (and default reject handler) to p0.
   17104             :   CompileRun("var p1 = p0.then(function(){});");
   17105          10 :   CHECK(GetPromise("p0")->HasHandler());
   17106          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17107           5 :   CHECK_EQ(0, promise_reject_counter);
   17108           5 :   CHECK_EQ(0, promise_revoke_counter);
   17109             : 
   17110             :   // Reject p0.
   17111             :   CompileRun("reject('ppp');");
   17112          10 :   CHECK(GetPromise("p0")->HasHandler());
   17113          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17114           5 :   CHECK_EQ(1, promise_reject_counter);
   17115           5 :   CHECK_EQ(0, promise_revoke_counter);
   17116           5 :   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
   17117          20 :   CHECK(
   17118             :       GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
   17119          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17120             : 
   17121             :   // Reject p0 again. Callback is not triggered again.
   17122             :   CompileRun("reject();");
   17123          10 :   CHECK(GetPromise("p0")->HasHandler());
   17124          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17125           5 :   CHECK_EQ(1, promise_reject_counter);
   17126           5 :   CHECK_EQ(0, promise_revoke_counter);
   17127             : 
   17128             :   // Add resolve handler to p1.
   17129             :   CompileRun("var p2 = p1.then(function(){});");
   17130          10 :   CHECK(GetPromise("p0")->HasHandler());
   17131          10 :   CHECK(GetPromise("p1")->HasHandler());
   17132          10 :   CHECK(!GetPromise("p2")->HasHandler());
   17133           5 :   CHECK_EQ(2, promise_reject_counter);
   17134           5 :   CHECK_EQ(1, promise_revoke_counter);
   17135          20 :   CHECK(
   17136             :       GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
   17137          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17138          20 :   CHECK(
   17139             :       GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
   17140             : 
   17141           5 :   ResetPromiseStates();
   17142             : 
   17143             :   // Create promise q0.
   17144             :   CompileRun(
   17145             :       "var q0 = new Promise(  \n"
   17146             :       "  function(res, rej) { \n"
   17147             :       "    reject = rej;      \n"
   17148             :       "  }                    \n"
   17149             :       ");                     \n");
   17150          10 :   CHECK(!GetPromise("q0")->HasHandler());
   17151           5 :   CHECK_EQ(0, promise_reject_counter);
   17152           5 :   CHECK_EQ(0, promise_revoke_counter);
   17153             : 
   17154             :   // Add reject handler to q0.
   17155             :   CompileRun("var q1 = q0.catch(function() {});");
   17156          10 :   CHECK(GetPromise("q0")->HasHandler());
   17157          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17158           5 :   CHECK_EQ(0, promise_reject_counter);
   17159           5 :   CHECK_EQ(0, promise_revoke_counter);
   17160             : 
   17161             :   // Reject q0.
   17162             :   CompileRun("reject('qq')");
   17163          10 :   CHECK(GetPromise("q0")->HasHandler());
   17164          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17165           5 :   CHECK_EQ(0, promise_reject_counter);
   17166           5 :   CHECK_EQ(0, promise_revoke_counter);
   17167             : 
   17168             :   // Add a new reject handler, which rejects by returning Promise.reject().
   17169             :   // The returned promise q_ triggers a reject callback at first, only to
   17170             :   // revoke it when returning it causes q2 to be rejected.
   17171             :   CompileRun(
   17172             :       "var q_;"
   17173             :       "var q2 = q0.catch(               \n"
   17174             :       "   function() {                  \n"
   17175             :       "     q_ = Promise.reject('qqq'); \n"
   17176             :       "     return q_;                  \n"
   17177             :       "   }                             \n"
   17178             :       ");                               \n");
   17179          10 :   CHECK(GetPromise("q0")->HasHandler());
   17180          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17181          10 :   CHECK(!GetPromise("q2")->HasHandler());
   17182          10 :   CHECK(GetPromise("q_")->HasHandler());
   17183           5 :   CHECK_EQ(2, promise_reject_counter);
   17184           5 :   CHECK_EQ(1, promise_revoke_counter);
   17185          20 :   CHECK(
   17186             :       GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
   17187          20 :   CHECK(
   17188             :       GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
   17189          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
   17190             : 
   17191             :   // Add a reject handler to the resolved q1, which rejects by throwing.
   17192             :   CompileRun(
   17193             :       "var q3 = q1.then(  \n"
   17194             :       "   function() {    \n"
   17195             :       "     throw 'qqqq'; \n"
   17196             :       "   }               \n"
   17197             :       ");                 \n");
   17198          10 :   CHECK(GetPromise("q0")->HasHandler());
   17199          10 :   CHECK(GetPromise("q1")->HasHandler());
   17200          10 :   CHECK(!GetPromise("q2")->HasHandler());
   17201          10 :   CHECK(!GetPromise("q3")->HasHandler());
   17202           5 :   CHECK_EQ(3, promise_reject_counter);
   17203           5 :   CHECK_EQ(1, promise_revoke_counter);
   17204          20 :   CHECK(
   17205             :       GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
   17206          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
   17207             : 
   17208           5 :   ResetPromiseStates();
   17209             : 
   17210             :   // Create promise r0, which has three handlers, two of which handle rejects.
   17211             :   CompileRun(
   17212             :       "var r0 = new Promise(             \n"
   17213             :       "  function(res, rej) {            \n"
   17214             :       "    reject = rej;                 \n"
   17215             :       "  }                               \n"
   17216             :       ");                                \n"
   17217             :       "var r1 = r0.catch(function() {}); \n"
   17218             :       "var r2 = r0.then(function() {});  \n"
   17219             :       "var r3 = r0.then(function() {},   \n"
   17220             :       "                 function() {});  \n");
   17221          10 :   CHECK(GetPromise("r0")->HasHandler());
   17222          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17223          10 :   CHECK(!GetPromise("r2")->HasHandler());
   17224          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17225           5 :   CHECK_EQ(0, promise_reject_counter);
   17226           5 :   CHECK_EQ(0, promise_revoke_counter);
   17227             : 
   17228             :   // Reject r0.
   17229             :   CompileRun("reject('rrr')");
   17230          10 :   CHECK(GetPromise("r0")->HasHandler());
   17231          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17232          10 :   CHECK(!GetPromise("r2")->HasHandler());
   17233          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17234           5 :   CHECK_EQ(1, promise_reject_counter);
   17235           5 :   CHECK_EQ(0, promise_revoke_counter);
   17236          20 :   CHECK(
   17237             :       GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
   17238          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17239             : 
   17240             :   // Add reject handler to r2.
   17241             :   CompileRun("var r4 = r2.catch(function() {});");
   17242          10 :   CHECK(GetPromise("r0")->HasHandler());
   17243          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17244          10 :   CHECK(GetPromise("r2")->HasHandler());
   17245          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17246          10 :   CHECK(!GetPromise("r4")->HasHandler());
   17247           5 :   CHECK_EQ(1, promise_reject_counter);
   17248           5 :   CHECK_EQ(1, promise_revoke_counter);
   17249          20 :   CHECK(
   17250             :       GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
   17251          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17252             : 
   17253             :   // Add reject handlers to r4.
   17254             :   CompileRun("var r5 = r4.then(function() {}, function() {});");
   17255          10 :   CHECK(GetPromise("r0")->HasHandler());
   17256          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17257          10 :   CHECK(GetPromise("r2")->HasHandler());
   17258          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17259          10 :   CHECK(GetPromise("r4")->HasHandler());
   17260          10 :   CHECK(!GetPromise("r5")->HasHandler());
   17261           5 :   CHECK_EQ(1, promise_reject_counter);
   17262           5 :   CHECK_EQ(1, promise_revoke_counter);
   17263             : 
   17264           5 :   ResetPromiseStates();
   17265             : 
   17266             :   // Create promise s0, which has three handlers, none of which handle rejects.
   17267             :   CompileRun(
   17268             :       "var s0 = new Promise(            \n"
   17269             :       "  function(res, rej) {           \n"
   17270             :       "    reject = rej;                \n"
   17271             :       "  }                              \n"
   17272             :       ");                               \n"
   17273             :       "var s1 = s0.then(function() {}); \n"
   17274             :       "var s2 = s0.then(function() {}); \n"
   17275             :       "var s3 = s0.then(function() {}); \n");
   17276          10 :   CHECK(GetPromise("s0")->HasHandler());
   17277          10 :   CHECK(!GetPromise("s1")->HasHandler());
   17278          10 :   CHECK(!GetPromise("s2")->HasHandler());
   17279          10 :   CHECK(!GetPromise("s3")->HasHandler());
   17280           5 :   CHECK_EQ(0, promise_reject_counter);
   17281           5 :   CHECK_EQ(0, promise_revoke_counter);
   17282             : 
   17283             :   // Reject s0.
   17284             :   CompileRun("reject('sss')");
   17285          10 :   CHECK(GetPromise("s0")->HasHandler());
   17286          10 :   CHECK(!GetPromise("s1")->HasHandler());
   17287          10 :   CHECK(!GetPromise("s2")->HasHandler());
   17288          10 :   CHECK(!GetPromise("s3")->HasHandler());
   17289           5 :   CHECK_EQ(3, promise_reject_counter);
   17290           5 :   CHECK_EQ(0, promise_revoke_counter);
   17291          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
   17292             : 
   17293           5 :   ResetPromiseStates();
   17294             : 
   17295             :   // Swallowed exceptions in the Promise constructor.
   17296             :   CompileRun(
   17297             :       "var v0 = new Promise(\n"
   17298             :       "  function(res, rej) {\n"
   17299             :       "    res(1);\n"
   17300             :       "    throw new Error();\n"
   17301             :       "  }\n"
   17302             :       ");\n");
   17303          10 :   CHECK(!GetPromise("v0")->HasHandler());
   17304           5 :   CHECK_EQ(0, promise_reject_counter);
   17305           5 :   CHECK_EQ(0, promise_revoke_counter);
   17306           5 :   CHECK_EQ(1, promise_reject_after_resolved_counter);
   17307           5 :   CHECK_EQ(0, promise_resolve_after_resolved_counter);
   17308             : 
   17309           5 :   ResetPromiseStates();
   17310             : 
   17311             :   // Duplication resolve.
   17312             :   CompileRun(
   17313             :       "var r;\n"
   17314             :       "var y0 = new Promise(\n"
   17315             :       "  function(res, rej) {\n"
   17316             :       "    r = res;\n"
   17317             :       "    throw new Error();\n"
   17318             :       "  }\n"
   17319             :       ");\n"
   17320             :       "r(1);\n");
   17321          10 :   CHECK(!GetPromise("y0")->HasHandler());
   17322           5 :   CHECK_EQ(1, promise_reject_counter);
   17323           5 :   CHECK_EQ(0, promise_revoke_counter);
   17324           5 :   CHECK_EQ(0, promise_reject_after_resolved_counter);
   17325           5 :   CHECK_EQ(1, promise_resolve_after_resolved_counter);
   17326             : 
   17327             :   // Test stack frames.
   17328           5 :   env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
   17329             : 
   17330           5 :   ResetPromiseStates();
   17331             : 
   17332             :   // Create promise t0, which is rejected in the constructor with an error.
   17333             :   CompileRunWithOrigin(
   17334             :       "var t0 = new Promise(  \n"
   17335             :       "  function(res, rej) { \n"
   17336             :       "    reference_error;   \n"
   17337             :       "  }                    \n"
   17338             :       ");                     \n",
   17339           5 :       "pro", 0, 0);
   17340          10 :   CHECK(!GetPromise("t0")->HasHandler());
   17341           5 :   CHECK_EQ(1, promise_reject_counter);
   17342           5 :   CHECK_EQ(0, promise_revoke_counter);
   17343           5 :   CHECK_EQ(2, promise_reject_frame_count);
   17344           5 :   CHECK_EQ(3, promise_reject_line_number);
   17345           5 :   CHECK_EQ(5, promise_reject_column_number);
   17346           5 :   CHECK_EQ(3, promise_reject_msg_line_number);
   17347           5 :   CHECK_EQ(5, promise_reject_msg_column_number);
   17348             : 
   17349           5 :   ResetPromiseStates();
   17350             : 
   17351             :   // Create promise u0 and chain u1 to it, which is rejected via throw.
   17352             :   CompileRunWithOrigin(
   17353             :       "var u0 = Promise.resolve();        \n"
   17354             :       "var u1 = u0.then(                  \n"
   17355             :       "           function() {            \n"
   17356             :       "             (function() {         \n"
   17357             :       "                throw new Error(); \n"
   17358             :       "              })();                \n"
   17359             :       "           }                       \n"
   17360             :       "         );                        \n",
   17361           5 :       "pro", 0, 0);
   17362          10 :   CHECK(GetPromise("u0")->HasHandler());
   17363          10 :   CHECK(!GetPromise("u1")->HasHandler());
   17364           5 :   CHECK_EQ(1, promise_reject_counter);
   17365           5 :   CHECK_EQ(0, promise_revoke_counter);
   17366           5 :   CHECK_EQ(2, promise_reject_frame_count);
   17367           5 :   CHECK_EQ(5, promise_reject_line_number);
   17368           5 :   CHECK_EQ(23, promise_reject_column_number);
   17369           5 :   CHECK_EQ(5, promise_reject_msg_line_number);
   17370           5 :   CHECK_EQ(23, promise_reject_msg_column_number);
   17371             : 
   17372             :   // Throw in u3, which handles u1's rejection.
   17373             :   CompileRunWithOrigin(
   17374             :       "function f() {                \n"
   17375             :       "  return (function() {        \n"
   17376             :       "    return new Error();       \n"
   17377             :       "  })();                       \n"
   17378             :       "}                             \n"
   17379             :       "var u2 = Promise.reject(f()); \n"
   17380             :       "var u3 = u1.catch(            \n"
   17381             :       "           function() {       \n"
   17382             :       "             return u2;       \n"
   17383             :       "           }                  \n"
   17384             :       "         );                   \n",
   17385           5 :       "pro", 0, 0);
   17386          10 :   CHECK(GetPromise("u0")->HasHandler());
   17387          10 :   CHECK(GetPromise("u1")->HasHandler());
   17388          10 :   CHECK(GetPromise("u2")->HasHandler());
   17389          10 :   CHECK(!GetPromise("u3")->HasHandler());
   17390           5 :   CHECK_EQ(3, promise_reject_counter);
   17391           5 :   CHECK_EQ(2, promise_revoke_counter);
   17392           5 :   CHECK_EQ(3, promise_reject_frame_count);
   17393           5 :   CHECK_EQ(3, promise_reject_line_number);
   17394           5 :   CHECK_EQ(12, promise_reject_column_number);
   17395           5 :   CHECK_EQ(3, promise_reject_msg_line_number);
   17396           5 :   CHECK_EQ(12, promise_reject_msg_column_number);
   17397             : 
   17398           5 :   ResetPromiseStates();
   17399             : 
   17400             :   // Create promise rejected promise v0, which is incorrectly handled by v1
   17401             :   // via chaining cycle.
   17402             :   CompileRunWithOrigin(
   17403             :       "var v0 = Promise.reject(); \n"
   17404             :       "var v1 = v0.catch(         \n"
   17405             :       "           function() {    \n"
   17406             :       "             return v1;    \n"
   17407             :       "           }               \n"
   17408             :       "         );                \n",
   17409           5 :       "pro", 0, 0);
   17410          10 :   CHECK(GetPromise("v0")->HasHandler());
   17411          10 :   CHECK(!GetPromise("v1")->HasHandler());
   17412           5 :   CHECK_EQ(2, promise_reject_counter);
   17413           5 :   CHECK_EQ(1, promise_revoke_counter);
   17414           5 :   CHECK_EQ(0, promise_reject_frame_count);
   17415           5 :   CHECK_EQ(-1, promise_reject_line_number);
   17416           5 :   CHECK_EQ(-1, promise_reject_column_number);
   17417             : 
   17418           5 :   ResetPromiseStates();
   17419             : 
   17420             :   // Create promise t1, which rejects by throwing syntax error from eval.
   17421             :   CompileRunWithOrigin(
   17422             :       "var t1 = new Promise(   \n"
   17423             :       "  function(res, rej) {  \n"
   17424             :       "    var content = '\\n\\\n"
   17425             :       "      }';               \n"
   17426             :       "    eval(content);      \n"
   17427             :       "  }                     \n"
   17428             :       ");                      \n",
   17429           5 :       "pro", 0, 0);
   17430          10 :   CHECK(!GetPromise("t1")->HasHandler());
   17431           5 :   CHECK_EQ(1, promise_reject_counter);
   17432           5 :   CHECK_EQ(0, promise_revoke_counter);
   17433           5 :   CHECK_EQ(2, promise_reject_frame_count);
   17434           5 :   CHECK_EQ(5, promise_reject_line_number);
   17435           5 :   CHECK_EQ(10, promise_reject_column_number);
   17436           5 :   CHECK_EQ(2, promise_reject_msg_line_number);
   17437           5 :   CHECK_EQ(7, promise_reject_msg_column_number);
   17438           5 : }
   17439             : 
   17440       26644 : TEST(PromiseRejectIsSharedCrossOrigin) {
   17441           5 :   LocalContext env;
   17442           5 :   v8::Isolate* isolate = env->GetIsolate();
   17443          10 :   v8::HandleScope scope(isolate);
   17444             : 
   17445           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17446             : 
   17447           5 :   ResetPromiseStates();
   17448             : 
   17449             :   // Create promise p0.
   17450             :   CompileRun(
   17451             :       "var reject;            \n"
   17452             :       "var p0 = new Promise(  \n"
   17453             :       "  function(res, rej) { \n"
   17454             :       "    reject = rej;      \n"
   17455             :       "  }                    \n"
   17456             :       ");                     \n");
   17457          10 :   CHECK(!GetPromise("p0")->HasHandler());
   17458           5 :   CHECK_EQ(0, promise_reject_counter);
   17459           5 :   CHECK_EQ(0, promise_revoke_counter);
   17460             :   // Not set because it's not yet rejected.
   17461           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   17462             : 
   17463             :   // Reject p0.
   17464             :   CompileRun("reject('ppp');");
   17465           5 :   CHECK_EQ(1, promise_reject_counter);
   17466           5 :   CHECK_EQ(0, promise_revoke_counter);
   17467             :   // Not set because the ScriptOriginOptions is from the script.
   17468           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   17469             : 
   17470           5 :   ResetPromiseStates();
   17471             : 
   17472             :   // Create promise p1
   17473             :   CompileRun(
   17474             :       "var reject;            \n"
   17475             :       "var p1 = new Promise(  \n"
   17476             :       "  function(res, rej) { \n"
   17477             :       "    reject = rej;      \n"
   17478             :       "  }                    \n"
   17479             :       ");                     \n");
   17480          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17481           5 :   CHECK_EQ(0, promise_reject_counter);
   17482           5 :   CHECK_EQ(0, promise_revoke_counter);
   17483             :   // Not set because it's not yet rejected.
   17484           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   17485             : 
   17486             :   // Add resolve handler (and default reject handler) to p1.
   17487             :   CompileRun("var p2 = p1.then(function(){});");
   17488          10 :   CHECK(GetPromise("p1")->HasHandler());
   17489          10 :   CHECK(!GetPromise("p2")->HasHandler());
   17490           5 :   CHECK_EQ(0, promise_reject_counter);
   17491           5 :   CHECK_EQ(0, promise_revoke_counter);
   17492             : 
   17493             :   // Reject p1.
   17494             :   CompileRun("reject('ppp');");
   17495           5 :   CHECK_EQ(1, promise_reject_counter);
   17496           5 :   CHECK_EQ(0, promise_revoke_counter);
   17497             :   // Set because the event is from an empty script.
   17498           5 :   CHECK(promise_reject_is_shared_cross_origin);
   17499           5 : }
   17500             : 
   17501       26644 : TEST(PromiseRejectMarkAsHandled) {
   17502           5 :   LocalContext env;
   17503           5 :   v8::Isolate* isolate = env->GetIsolate();
   17504          10 :   v8::HandleScope scope(isolate);
   17505             : 
   17506           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17507             : 
   17508           5 :   ResetPromiseStates();
   17509             : 
   17510             :   // Create promise p0.
   17511             :   CompileRun(
   17512             :       "var reject;            \n"
   17513             :       "var p0 = new Promise(  \n"
   17514             :       "  function(res, rej) { \n"
   17515             :       "    reject = rej;      \n"
   17516             :       "  }                    \n"
   17517             :       ");                     \n");
   17518          10 :   CHECK(!GetPromise("p0")->HasHandler());
   17519           5 :   CHECK_EQ(0, promise_reject_counter);
   17520           5 :   CHECK_EQ(0, promise_revoke_counter);
   17521          10 :   GetPromise("p0")->MarkAsHandled();
   17522             : 
   17523             :   // Reject p0. promise_reject_counter shouldn't be incremented because
   17524             :   // it's marked as handled.
   17525             :   CompileRun("reject('ppp');");
   17526           5 :   CHECK_EQ(0, promise_reject_counter);
   17527           5 :   CHECK_EQ(0, promise_revoke_counter);
   17528           5 : }
   17529          30 : void PromiseRejectCallbackConstructError(
   17530             :     v8::PromiseRejectMessage reject_message) {
   17531          30 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17532          30 :   CHECK_EQ(v8::Promise::PromiseState::kRejected,
   17533             :            reject_message.GetPromise()->State());
   17534          60 :   USE(v8::Script::Compile(context, v8_str("new Error('test')"))
   17535             :           .ToLocalChecked()
   17536             :           ->Run(context));
   17537          30 : }
   17538             : 
   17539       26644 : TEST(PromiseRejectCallbackConstructError) {
   17540           5 :   i::FLAG_allow_natives_syntax = true;
   17541           5 :   LocalContext env;
   17542           5 :   v8::Isolate* isolate = env->GetIsolate();
   17543          10 :   v8::HandleScope scope(isolate);
   17544             : 
   17545           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallbackConstructError);
   17546             : 
   17547           5 :   ResetPromiseStates();
   17548             :   CompileRun(
   17549             :       "function f(p) {"
   17550             :       "    p.catch(() => {});"
   17551             :       "}"
   17552             :       "f(Promise.reject());"
   17553             :       "f(Promise.reject());"
   17554             :       "%OptimizeFunctionOnNextCall(f);"
   17555             :       "let p = Promise.reject();"
   17556             :       "f(p);");
   17557           5 : }
   17558             : 
   17559          10 : void AnalyzeStackOfEvalWithSourceURL(
   17560             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17561          20 :   v8::HandleScope scope(args.GetIsolate());
   17562             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17563          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17564          10 :   CHECK_EQ(5, stackTrace->GetFrameCount());
   17565          10 :   v8::Local<v8::String> url = v8_str("eval_url");
   17566          70 :   for (int i = 0; i < 3; i++) {
   17567             :     v8::Local<v8::String> name =
   17568          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   17569          30 :     CHECK(!name.IsEmpty());
   17570          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17571             :   }
   17572          10 : }
   17573             : 
   17574             : 
   17575       26644 : TEST(SourceURLInStackTrace) {
   17576           5 :   v8::Isolate* isolate = CcTest::isolate();
   17577          10 :   v8::HandleScope scope(isolate);
   17578           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17579          15 :   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   17580             :              v8::FunctionTemplate::New(isolate,
   17581           5 :                                        AnalyzeStackOfEvalWithSourceURL));
   17582           5 :   LocalContext context(nullptr, templ);
   17583             : 
   17584             :   const char *source =
   17585             :     "function outer() {\n"
   17586             :     "function bar() {\n"
   17587             :     "  AnalyzeStackOfEvalWithSourceURL();\n"
   17588             :     "}\n"
   17589             :     "function foo() {\n"
   17590             :     "\n"
   17591             :     "  bar();\n"
   17592             :     "}\n"
   17593             :     "foo();\n"
   17594             :     "}\n"
   17595             :     "eval('(' + outer +')()%s');";
   17596             : 
   17597             :   i::ScopedVector<char> code(1024);
   17598           5 :   i::SNPrintF(code, source, "//# sourceURL=eval_url");
   17599           5 :   CHECK(CompileRun(code.start())->IsUndefined());
   17600           5 :   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
   17601           5 :   CHECK(CompileRun(code.start())->IsUndefined());
   17602           5 : }
   17603             : 
   17604             : 
   17605             : static int scriptIdInStack[2];
   17606             : 
   17607           5 : void AnalyzeScriptIdInStack(
   17608             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17609          10 :   v8::HandleScope scope(args.GetIsolate());
   17610             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17611           5 :       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
   17612           5 :   CHECK_EQ(2, stackTrace->GetFrameCount());
   17613          25 :   for (int i = 0; i < 2; i++) {
   17614             :     scriptIdInStack[i] =
   17615          30 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptId();
   17616             :   }
   17617           5 : }
   17618             : 
   17619             : 
   17620       26644 : TEST(ScriptIdInStackTrace) {
   17621           5 :   v8::Isolate* isolate = CcTest::isolate();
   17622          10 :   v8::HandleScope scope(isolate);
   17623           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17624          15 :   templ->Set(v8_str("AnalyzeScriptIdInStack"),
   17625           5 :              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
   17626           5 :   LocalContext context(nullptr, templ);
   17627             : 
   17628             :   v8::Local<v8::String> scriptSource = v8_str(
   17629             :       "function foo() {\n"
   17630             :       "  AnalyzeScriptIdInStack();"
   17631             :       "}\n"
   17632           5 :       "foo();\n");
   17633           5 :   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test", false);
   17634           5 :   script->Run(context.local()).ToLocalChecked();
   17635          25 :   for (int i = 0; i < 2; i++) {
   17636          10 :     CHECK_NE(scriptIdInStack[i], v8::Message::kNoScriptIdInfo);
   17637          20 :     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
   17638             :   }
   17639           5 : }
   17640             : 
   17641             : 
   17642          10 : void AnalyzeStackOfInlineScriptWithSourceURL(
   17643             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17644          20 :   v8::HandleScope scope(args.GetIsolate());
   17645             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17646          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17647          10 :   CHECK_EQ(4, stackTrace->GetFrameCount());
   17648          10 :   v8::Local<v8::String> url = v8_str("source_url");
   17649          70 :   for (int i = 0; i < 3; i++) {
   17650             :     v8::Local<v8::String> name =
   17651          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   17652          30 :     CHECK(!name.IsEmpty());
   17653          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17654             :   }
   17655          10 : }
   17656             : 
   17657             : 
   17658       26644 : TEST(InlineScriptWithSourceURLInStackTrace) {
   17659           5 :   v8::Isolate* isolate = CcTest::isolate();
   17660          10 :   v8::HandleScope scope(isolate);
   17661           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17662          15 :   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   17663             :              v8::FunctionTemplate::New(
   17664           5 :                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
   17665           5 :   LocalContext context(nullptr, templ);
   17666             : 
   17667             :   const char *source =
   17668             :     "function outer() {\n"
   17669             :     "function bar() {\n"
   17670             :     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   17671             :     "}\n"
   17672             :     "function foo() {\n"
   17673             :     "\n"
   17674             :     "  bar();\n"
   17675             :     "}\n"
   17676             :     "foo();\n"
   17677             :     "}\n"
   17678             :     "outer()\n%s";
   17679             : 
   17680             :   i::ScopedVector<char> code(1024);
   17681           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17682          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17683           5 :   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   17684          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17685           5 : }
   17686             : 
   17687         395 : void SetPromise(const char* name, v8::Local<v8::Promise> promise) {
   17688         790 :   CcTest::global()
   17689        1975 :       ->Set(CcTest::isolate()->GetCurrentContext(), v8_str(name), promise)
   17690             :       .FromJust();
   17691         395 : }
   17692             : 
   17693          10 : class PromiseHookData {
   17694             :  public:
   17695             :   int before_hook_count = 0;
   17696             :   int after_hook_count = 0;
   17697             :   int promise_hook_count = 0;
   17698             :   int parent_promise_count = 0;
   17699             :   bool check_value = true;
   17700             :   std::string promise_hook_value;
   17701             : 
   17702             :   void Reset() {
   17703          50 :     before_hook_count = 0;
   17704          50 :     after_hook_count = 0;
   17705          50 :     promise_hook_count = 0;
   17706          50 :     parent_promise_count = 0;
   17707          50 :     check_value = true;
   17708          50 :     promise_hook_value = "";
   17709             :   }
   17710             : };
   17711             : 
   17712             : PromiseHookData* promise_hook_data;
   17713             : 
   17714         350 : void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise,
   17715             :                        v8::Local<v8::Value> parentPromise) {
   17716         350 :   promise_hook_data->promise_hook_count++;
   17717         350 :   switch (type) {
   17718             :     case v8::PromiseHookType::kInit:
   17719         125 :       SetPromise("init", promise);
   17720             : 
   17721         125 :       if (!parentPromise->IsUndefined()) {
   17722          45 :         promise_hook_data->parent_promise_count++;
   17723          45 :         SetPromise("parent", v8::Local<v8::Promise>::Cast(parentPromise));
   17724             :       }
   17725             : 
   17726             :       break;
   17727             :     case v8::PromiseHookType::kResolve:
   17728         125 :       SetPromise("resolve", promise);
   17729         125 :       break;
   17730             :     case v8::PromiseHookType::kBefore:
   17731          50 :       promise_hook_data->before_hook_count++;
   17732          50 :       CHECK(promise_hook_data->before_hook_count >
   17733             :             promise_hook_data->after_hook_count);
   17734         300 :       CHECK(CcTest::global()
   17735             :                 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17736             :                 .ToLocalChecked()
   17737             :                 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str(""))
   17738             :                 .FromJust());
   17739          50 :       SetPromise("before", promise);
   17740          50 :       break;
   17741             :     case v8::PromiseHookType::kAfter:
   17742          50 :       promise_hook_data->after_hook_count++;
   17743          50 :       CHECK(promise_hook_data->after_hook_count <=
   17744             :             promise_hook_data->before_hook_count);
   17745          50 :       if (promise_hook_data->check_value) {
   17746         180 :         CHECK(
   17747             :             CcTest::global()
   17748             :                 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17749             :                 .ToLocalChecked()
   17750             :                 ->Equals(CcTest::isolate()->GetCurrentContext(),
   17751             :                          v8_str(promise_hook_data->promise_hook_value.c_str()))
   17752             :                 .FromJust());
   17753             :       }
   17754          50 :       SetPromise("after", promise);
   17755          50 :       break;
   17756             :   }
   17757         350 : }
   17758             : 
   17759       26644 : TEST(PromiseHook) {
   17760           5 :   LocalContext env;
   17761           5 :   v8::Isolate* isolate = env->GetIsolate();
   17762          10 :   v8::HandleScope scope(isolate);
   17763             : 
   17764           5 :   v8::Local<v8::Object> global = CcTest::global();
   17765           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17766             : 
   17767          10 :   promise_hook_data = new PromiseHookData();
   17768           5 :   isolate->SetPromiseHook(CustomPromiseHook);
   17769             : 
   17770             :   // Test that an initialized promise is passed to init. Other hooks
   17771             :   // can not have un initialized promise.
   17772           5 :   promise_hook_data->check_value = false;
   17773             :   CompileRun("var p = new Promise(() => {});");
   17774             : 
   17775          15 :   auto init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17776          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17777             :   auto init_promise_obj = v8::Local<v8::Promise>::Cast(init_promise);
   17778           5 :   CHECK_EQ(init_promise_obj->State(), v8::Promise::PromiseState::kPending);
   17779           5 :   CHECK(!init_promise_obj->HasHandler());
   17780             : 
   17781           5 :   promise_hook_data->Reset();
   17782           5 :   promise_hook_data->promise_hook_value = "fulfilled";
   17783             :   const char* source =
   17784             :       "var resolve, value = ''; \n"
   17785             :       "var p = new Promise(r => resolve = r); \n";
   17786             : 
   17787             :   CompileRun(source);
   17788          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17789          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17790           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   17791           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17792             : 
   17793             :   CompileRun("var p1 = p.then(() => { value = 'fulfilled'; }); \n");
   17794          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17795          15 :   auto parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   17796          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   17797          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   17798           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17799           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   17800             : 
   17801             :   CompileRun("resolve(); \n");
   17802             :   auto resolve_promise =
   17803          15 :       global->Get(context, v8_str("resolve")).ToLocalChecked();
   17804          15 :   auto before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   17805          15 :   auto after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   17806          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   17807          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   17808          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17809           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   17810             : 
   17811             :   CompileRun("value = ''; var p2 = p1.then(() => { value = 'fulfilled' }); \n");
   17812          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17813          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   17814          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17815          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   17816          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   17817          15 :   CHECK(GetPromise("p2")->Equals(env.local(), init_promise).FromJust());
   17818          15 :   CHECK(GetPromise("p1")->Equals(env.local(), parent_promise).FromJust());
   17819          15 :   CHECK(GetPromise("p2")->Equals(env.local(), before_promise).FromJust());
   17820          15 :   CHECK(GetPromise("p2")->Equals(env.local(), after_promise).FromJust());
   17821          15 :   CHECK(GetPromise("p2")->Equals(env.local(), resolve_promise).FromJust());
   17822           5 :   CHECK_EQ(10, promise_hook_data->promise_hook_count);
   17823             : 
   17824             :   promise_hook_data->Reset();
   17825           5 :   promise_hook_data->promise_hook_value = "rejected";
   17826             :   source =
   17827             :       "var reject, value = ''; \n"
   17828             :       "var p = new Promise((_, r) => reject = r); \n";
   17829             : 
   17830             :   CompileRun(source);
   17831          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17832          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17833           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   17834           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17835             : 
   17836             :   CompileRun("var p1 = p.catch(() => { value = 'rejected'; }); \n");
   17837          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17838          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   17839          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   17840          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   17841           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17842           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   17843             : 
   17844             :   CompileRun("reject(); \n");
   17845          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17846          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   17847          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   17848          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   17849          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   17850          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17851           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   17852             : 
   17853             :   promise_hook_data->Reset();
   17854           5 :   promise_hook_data->promise_hook_value = "Promise.resolve";
   17855             :   source =
   17856             :       "var value = ''; \n"
   17857             :       "var p = Promise.resolve('Promise.resolve'); \n";
   17858             : 
   17859             :   CompileRun(source);
   17860          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17861          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17862             :   // init hook and resolve hook
   17863           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17864           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17865          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17866          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   17867             : 
   17868             :   CompileRun("var p1 = p.then((v) => { value = v; }); \n");
   17869          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17870          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17871          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   17872          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   17873          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   17874          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   17875          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17876          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   17877          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   17878          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   17879           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   17880           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   17881             : 
   17882             :   promise_hook_data->Reset();
   17883             :   source =
   17884             :       "var resolve, value = ''; \n"
   17885             :       "var p = new Promise((_, r) => resolve = r); \n";
   17886             : 
   17887             :   CompileRun(source);
   17888          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17889          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17890           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   17891           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17892             : 
   17893             :   CompileRun("resolve(); \n");
   17894          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17895          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   17896           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17897             : 
   17898             :   promise_hook_data->Reset();
   17899             :   source =
   17900             :       "var reject, value = ''; \n"
   17901             :       "var p = new Promise((_, r) => reject = r); \n";
   17902             : 
   17903             :   CompileRun(source);
   17904          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17905          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17906           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   17907           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17908             : 
   17909             :   CompileRun("reject(); \n");
   17910          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17911          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   17912           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17913             : 
   17914             :   promise_hook_data->Reset();
   17915             :   // This test triggers after callbacks right after each other, so
   17916             :   // lets just check the value at the end.
   17917           5 :   promise_hook_data->check_value = false;
   17918           5 :   promise_hook_data->promise_hook_value = "Promise.all";
   17919             :   source =
   17920             :       "var resolve, value = ''; \n"
   17921             :       "var tempPromise = new Promise(r => resolve = r); \n"
   17922             :       "var p = Promise.all([tempPromise]);\n "
   17923             :       "var p1 = p.then(v => value = v[0]); \n";
   17924             : 
   17925             :   CompileRun(source);
   17926             :   // 1) init hook (tempPromise)
   17927             :   // 2) init hook (p)
   17928             :   // 3) init hook (throwaway Promise in Promise.all, p)
   17929             :   // 4) init hook (p1, p)
   17930           5 :   CHECK_EQ(4, promise_hook_data->promise_hook_count);
   17931           5 :   CHECK_EQ(2, promise_hook_data->parent_promise_count);
   17932             : 
   17933           5 :   promise_hook_data->promise_hook_value = "Promise.all";
   17934             :   CompileRun("resolve('Promise.all'); \n");
   17935          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17936          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17937             :   // 5) resolve hook (tempPromise)
   17938             :   // 6) resolve hook (throwaway Promise in Promise.all)
   17939             :   // 6) before hook (throwaway Promise in Promise.all)
   17940             :   // 7) after hook (throwaway Promise in Promise.all)
   17941             :   // 8) before hook (p)
   17942             :   // 9) after hook (p)
   17943             :   // 10) resolve hook (p1)
   17944             :   // 11) before hook (p1)
   17945             :   // 12) after hook (p1)
   17946           5 :   CHECK_EQ(12, promise_hook_data->promise_hook_count);
   17947          30 :   CHECK(CcTest::global()
   17948             :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17949             :             .ToLocalChecked()
   17950             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
   17951             :                      v8_str(promise_hook_data->promise_hook_value.c_str()))
   17952             :             .FromJust());
   17953             : 
   17954           5 :   promise_hook_data->Reset();
   17955             :   // This test triggers after callbacks right after each other, so
   17956             :   // lets just check the value at the end.
   17957           5 :   promise_hook_data->check_value = false;
   17958           5 :   promise_hook_data->promise_hook_value = "Promise.race";
   17959             :   source =
   17960             :       "var resolve, value = ''; \n"
   17961             :       "var tempPromise = new Promise(r => resolve = r); \n"
   17962             :       "var p = Promise.race([tempPromise]);\n "
   17963             :       "var p1 = p.then(v => value = v); \n";
   17964             : 
   17965             :   CompileRun(source);
   17966             :   // 1) init hook (tempPromise)
   17967             :   // 2) init hook (p)
   17968             :   // 3) init hook (throwaway Promise in Promise.race, p)
   17969             :   // 4) init hook (p1, p)
   17970           5 :   CHECK_EQ(4, promise_hook_data->promise_hook_count);
   17971           5 :   CHECK_EQ(2, promise_hook_data->parent_promise_count);
   17972             : 
   17973           5 :   promise_hook_data->promise_hook_value = "Promise.race";
   17974             :   CompileRun("resolve('Promise.race'); \n");
   17975          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17976          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17977             :   // 5) resolve hook (tempPromise)
   17978             :   // 6) resolve hook (throwaway Promise in Promise.race)
   17979             :   // 6) before hook (throwaway Promise in Promise.race)
   17980             :   // 7) after hook (throwaway Promise in Promise.race)
   17981             :   // 8) before hook (p)
   17982             :   // 9) after hook (p)
   17983             :   // 10) resolve hook (p1)
   17984             :   // 11) before hook (p1)
   17985             :   // 12) after hook (p1)
   17986           5 :   CHECK_EQ(12, promise_hook_data->promise_hook_count);
   17987          30 :   CHECK(CcTest::global()
   17988             :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17989             :             .ToLocalChecked()
   17990             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
   17991             :                      v8_str(promise_hook_data->promise_hook_value.c_str()))
   17992             :             .FromJust());
   17993             : 
   17994           5 :   promise_hook_data->Reset();
   17995           5 :   promise_hook_data->promise_hook_value = "subclass";
   17996             :   source =
   17997             :       "var resolve, value = '';\n"
   17998             :       "class MyPromise extends Promise { \n"
   17999             :       "  then(onFulfilled, onRejected) { \n"
   18000             :       "      return super.then(onFulfilled, onRejected); \n"
   18001             :       "  };\n"
   18002             :       "};\n"
   18003             :       "var p = new MyPromise(r => resolve = r);\n";
   18004             : 
   18005             :   CompileRun(source);
   18006             :   // 1) init hook (p)
   18007           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18008             : 
   18009             :   CompileRun("var p1 = p.then(() => value = 'subclass');\n");
   18010             :   // 2) init hook (p1)
   18011           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18012             : 
   18013             :   CompileRun("resolve();\n");
   18014          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18015          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18016          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18017          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18018          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18019          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18020             :   // 3) resolve hook (p)
   18021             :   // 4) before hook (p)
   18022             :   // 5) after hook (p)
   18023             :   // 6) resolve hook (p1)
   18024           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18025             : 
   18026             :   promise_hook_data->Reset();
   18027             :   source =
   18028             :       "class X extends Promise {\n"
   18029             :       "  static get [Symbol.species]() {\n"
   18030             :       "    return Y;\n"
   18031             :       "  }\n"
   18032             :       "}\n"
   18033             :       "class Y {\n"
   18034             :       "  constructor(executor) {\n"
   18035             :       "    return new Proxy(new Promise(executor), {});\n"
   18036             :       "  }\n"
   18037             :       "}\n"
   18038             :       "var x = X.resolve().then(() => {});\n";
   18039             : 
   18040             :   CompileRun(source);
   18041             : 
   18042           5 :   promise_hook_data->Reset();
   18043             :   source =
   18044             :       "var resolve, value = '';\n"
   18045             :       "var p = new Promise(r => resolve = r);\n";
   18046             : 
   18047             :   CompileRun(source);
   18048          10 :   CHECK_EQ(v8::Promise::kPending, GetPromise("p")->State());
   18049             :   CompileRun("resolve(Promise.resolve(value));\n");
   18050          10 :   CHECK_EQ(v8::Promise::kFulfilled, GetPromise("p")->State());
   18051           5 :   CHECK_EQ(9, promise_hook_data->promise_hook_count);
   18052             : 
   18053          10 :   delete promise_hook_data;
   18054           5 :   isolate->SetPromiseHook(nullptr);
   18055           5 : }
   18056             : 
   18057          10 : void AnalyzeStackOfDynamicScriptWithSourceURL(
   18058             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18059          20 :   v8::HandleScope scope(args.GetIsolate());
   18060             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18061          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   18062          10 :   CHECK_EQ(4, stackTrace->GetFrameCount());
   18063          10 :   v8::Local<v8::String> url = v8_str("source_url");
   18064          70 :   for (int i = 0; i < 3; i++) {
   18065             :     v8::Local<v8::String> name =
   18066          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   18067          30 :     CHECK(!name.IsEmpty());
   18068          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   18069             :   }
   18070          10 : }
   18071             : 
   18072             : 
   18073       26644 : TEST(DynamicWithSourceURLInStackTrace) {
   18074           5 :   v8::Isolate* isolate = CcTest::isolate();
   18075          10 :   v8::HandleScope scope(isolate);
   18076           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18077          15 :   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   18078             :              v8::FunctionTemplate::New(
   18079           5 :                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
   18080           5 :   LocalContext context(nullptr, templ);
   18081             : 
   18082             :   const char *source =
   18083             :     "function outer() {\n"
   18084             :     "function bar() {\n"
   18085             :     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   18086             :     "}\n"
   18087             :     "function foo() {\n"
   18088             :     "\n"
   18089             :     "  bar();\n"
   18090             :     "}\n"
   18091             :     "foo();\n"
   18092             :     "}\n"
   18093             :     "outer()\n%s";
   18094             : 
   18095             :   i::ScopedVector<char> code(1024);
   18096           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18097          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   18098           5 :   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   18099          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   18100           5 : }
   18101             : 
   18102             : 
   18103       26644 : TEST(DynamicWithSourceURLInStackTraceString) {
   18104           5 :   LocalContext context;
   18105          10 :   v8::HandleScope scope(context->GetIsolate());
   18106             : 
   18107             :   const char *source =
   18108             :     "function outer() {\n"
   18109             :     "  function foo() {\n"
   18110             :     "    FAIL.FAIL;\n"
   18111             :     "  }\n"
   18112             :     "  foo();\n"
   18113             :     "}\n"
   18114             :     "outer()\n%s";
   18115             : 
   18116             :   i::ScopedVector<char> code(1024);
   18117           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18118          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18119           5 :   CompileRunWithOrigin(code.start(), "", 0, 0);
   18120           5 :   CHECK(try_catch.HasCaught());
   18121             :   v8::String::Utf8Value stack(
   18122             :       context->GetIsolate(),
   18123          15 :       try_catch.StackTrace(context.local()).ToLocalChecked());
   18124           5 :   CHECK_NOT_NULL(strstr(*stack, "at foo (source_url:3:5)"));
   18125           5 : }
   18126             : 
   18127             : 
   18128       26644 : TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   18129           5 :   LocalContext context;
   18130          10 :   v8::HandleScope scope(context->GetIsolate());
   18131             : 
   18132             :   const char *source =
   18133             :     "function outer() {\n"
   18134             :     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
   18135             :     "  //# sourceURL=source_url\";\n"
   18136             :     "  eval(scriptContents);\n"
   18137             :     "  foo(); }\n"
   18138             :     "outer();\n"
   18139             :     "//# sourceURL=outer_url";
   18140             : 
   18141          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18142             :   CompileRun(source);
   18143           5 :   CHECK(try_catch.HasCaught());
   18144             : 
   18145           5 :   Local<v8::Message> message = try_catch.Message();
   18146          10 :   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   18147           5 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(), sourceURL),
   18148             :                      "source_url"));
   18149           5 : }
   18150             : 
   18151             : 
   18152       26644 : TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   18153           5 :   LocalContext context;
   18154          10 :   v8::HandleScope scope(context->GetIsolate());
   18155             : 
   18156             :   const char *source =
   18157             :     "function outer() {\n"
   18158             :     "  var scriptContents = \"function boo(){ boo(); }\\\n"
   18159             :     "  //# sourceURL=source_url\";\n"
   18160             :     "  eval(scriptContents);\n"
   18161             :     "  boo(); }\n"
   18162             :     "outer();\n"
   18163             :     "//# sourceURL=outer_url";
   18164             : 
   18165          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18166             :   CompileRun(source);
   18167           5 :   CHECK(try_catch.HasCaught());
   18168             : 
   18169           5 :   Local<v8::Message> message = try_catch.Message();
   18170          10 :   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   18171           5 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(), sourceURL),
   18172             :                      "source_url"));
   18173           5 : }
   18174             : 
   18175             : 
   18176           5 : static void CreateGarbageInOldSpace() {
   18177             :   i::Factory* factory = CcTest::i_isolate()->factory();
   18178          10 :   v8::HandleScope scope(CcTest::isolate());
   18179             :   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   18180       10005 :   for (int i = 0; i < 1000; i++) {
   18181        5000 :     factory->NewFixedArray(1000, i::AllocationType::kOld);
   18182             :   }
   18183           5 : }
   18184             : 
   18185             : 
   18186             : // Test that idle notification can be handled and eventually collects garbage.
   18187       26644 : TEST(TestIdleNotification) {
   18188           5 :   if (!i::FLAG_incremental_marking) return;
   18189             :   ManualGCScope manual_gc_scope;
   18190             :   const intptr_t MB = 1024 * 1024;
   18191             :   const double IdlePauseInSeconds = 1.0;
   18192           5 :   LocalContext env;
   18193          10 :   v8::HandleScope scope(env->GetIsolate());
   18194           5 :   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   18195           5 :   CreateGarbageInOldSpace();
   18196           5 :   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   18197           5 :   CHECK_GT(size_with_garbage, initial_size + MB);
   18198             :   bool finished = false;
   18199          75 :   for (int i = 0; i < 200 && !finished; i++) {
   18200          70 :     if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
   18201           5 :       CcTest::heap()->StartIdleIncrementalMarking(
   18202           5 :           i::GarbageCollectionReason::kTesting);
   18203             :     }
   18204          70 :     finished = env->GetIsolate()->IdleNotificationDeadline(
   18205         105 :         (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
   18206             :          static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
   18207          35 :         IdlePauseInSeconds);
   18208          70 :     if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
   18209          10 :       CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
   18210             :     }
   18211             :   }
   18212           5 :   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   18213           5 :   CHECK(finished);
   18214           5 :   CHECK_LT(final_size, initial_size + 1);
   18215             : }
   18216             : 
   18217       26644 : TEST(TestMemorySavingsMode) {
   18218           5 :   LocalContext context;
   18219           5 :   v8::Isolate* isolate = context->GetIsolate();
   18220             :   v8::internal::Isolate* i_isolate =
   18221             :       reinterpret_cast<v8::internal::Isolate*>(isolate);
   18222           5 :   CHECK(!i_isolate->IsMemorySavingsModeActive());
   18223           5 :   isolate->EnableMemorySavingsMode();
   18224           5 :   CHECK(i_isolate->IsMemorySavingsModeActive());
   18225           5 :   isolate->DisableMemorySavingsMode();
   18226           5 :   CHECK(!i_isolate->IsMemorySavingsModeActive());
   18227           5 : }
   18228             : 
   18229       26644 : TEST(Regress2333) {
   18230           5 :   LocalContext env;
   18231          35 :   for (int i = 0; i < 3; i++) {
   18232          15 :     CcTest::CollectGarbage(i::NEW_SPACE);
   18233             :   }
   18234           5 : }
   18235             : 
   18236             : static uint32_t* stack_limit;
   18237             : 
   18238          10 : static void GetStackLimitCallback(
   18239             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18240             :   stack_limit = reinterpret_cast<uint32_t*>(
   18241          10 :       CcTest::i_isolate()->stack_guard()->real_climit());
   18242          10 : }
   18243             : 
   18244             : 
   18245             : // Uses the address of a local variable to determine the stack top now.
   18246             : // Given a size, returns an address that is that far from the current
   18247             : // top of stack.
   18248             : static uint32_t* ComputeStackLimit(uint32_t size) {
   18249             :   uint32_t* answer = &size - (size / sizeof(size));
   18250             :   // If the size is very large and the stack is very near the bottom of
   18251             :   // memory then the calculation above may wrap around and give an address
   18252             :   // that is above the (downwards-growing) stack.  In that case we return
   18253             :   // a very low address.
   18254             :   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   18255             :   return answer;
   18256             : }
   18257             : 
   18258             : 
   18259             : // We need at least 165kB for an x64 debug build with clang and ASAN.
   18260             : static const int stack_breathing_room = 256 * i::KB;
   18261             : 
   18262             : 
   18263       26644 : TEST(SetStackLimit) {
   18264             :   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   18265             : 
   18266             :   // Set stack limit.
   18267           5 :   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   18268             : 
   18269             :   // Execute a script.
   18270           5 :   LocalContext env;
   18271          10 :   v8::HandleScope scope(env->GetIsolate());
   18272             :   Local<v8::FunctionTemplate> fun_templ =
   18273           5 :       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
   18274           5 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   18275          20 :   CHECK(env->Global()
   18276             :             ->Set(env.local(), v8_str("get_stack_limit"), fun)
   18277             :             .FromJust());
   18278             :   CompileRun("get_stack_limit();");
   18279             : 
   18280           5 :   CHECK(stack_limit == set_limit);
   18281           5 : }
   18282             : 
   18283             : 
   18284       26644 : TEST(SetStackLimitInThread) {
   18285             :   uint32_t* set_limit;
   18286             :   {
   18287          10 :     v8::Locker locker(CcTest::isolate());
   18288             :     set_limit = ComputeStackLimit(stack_breathing_room);
   18289             : 
   18290             :     // Set stack limit.
   18291           5 :     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   18292             : 
   18293             :     // Execute a script.
   18294          10 :     v8::HandleScope scope(CcTest::isolate());
   18295           5 :     LocalContext env;
   18296             :     Local<v8::FunctionTemplate> fun_templ =
   18297           5 :         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
   18298           5 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   18299          20 :     CHECK(env->Global()
   18300             :               ->Set(env.local(), v8_str("get_stack_limit"), fun)
   18301             :               .FromJust());
   18302             :     CompileRun("get_stack_limit();");
   18303             : 
   18304           5 :     CHECK(stack_limit == set_limit);
   18305             :   }
   18306             :   {
   18307          10 :     v8::Locker locker(CcTest::isolate());
   18308           5 :     CHECK(stack_limit == set_limit);
   18309             :   }
   18310           5 : }
   18311             : 
   18312       26645 : THREADED_TEST(GetHeapStatistics) {
   18313           6 :   LocalContext c1;
   18314          12 :   v8::HandleScope scope(c1->GetIsolate());
   18315           6 :   v8::HeapStatistics heap_statistics;
   18316           6 :   CHECK_EQ(0u, heap_statistics.total_heap_size());
   18317           6 :   CHECK_EQ(0u, heap_statistics.used_heap_size());
   18318           6 :   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   18319           6 :   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   18320           6 :   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   18321           6 : }
   18322             : 
   18323       26644 : TEST(GetHeapSpaceStatistics) {
   18324           5 :   LocalContext c1;
   18325           5 :   v8::Isolate* isolate = c1->GetIsolate();
   18326          10 :   v8::HandleScope scope(isolate);
   18327           5 :   v8::HeapStatistics heap_statistics;
   18328             : 
   18329             :   // Force allocation in LO_SPACE so that every space has non-zero size.
   18330             :   v8::internal::Isolate* i_isolate =
   18331             :       reinterpret_cast<v8::internal::Isolate*>(isolate);
   18332             :   auto unused = i_isolate->factory()->TryNewFixedArray(512 * 1024,
   18333           5 :                                                        i::AllocationType::kOld);
   18334             :   USE(unused);
   18335             : 
   18336           5 :   isolate->GetHeapStatistics(&heap_statistics);
   18337             : 
   18338             :   // Ensure that the sum of all the spaces matches the totals from
   18339             :   // GetHeapSpaceStatics.
   18340             :   size_t total_size = 0u;
   18341             :   size_t total_used_size = 0u;
   18342             :   size_t total_available_size = 0u;
   18343             :   size_t total_physical_size = 0u;
   18344          85 :   for (size_t i = 0; i < isolate->NumberOfHeapSpaces(); ++i) {
   18345          40 :     v8::HeapSpaceStatistics space_statistics;
   18346          40 :     isolate->GetHeapSpaceStatistics(&space_statistics, i);
   18347          40 :     CHECK_NOT_NULL(space_statistics.space_name());
   18348          40 :     total_size += space_statistics.space_size();
   18349          40 :     total_used_size += space_statistics.space_used_size();
   18350          40 :     total_available_size += space_statistics.space_available_size();
   18351          40 :     total_physical_size += space_statistics.physical_space_size();
   18352             :   }
   18353          10 :   total_available_size += CcTest::heap()->memory_allocator()->Available();
   18354             : 
   18355           5 :   CHECK_EQ(total_size, heap_statistics.total_heap_size());
   18356           5 :   CHECK_EQ(total_used_size, heap_statistics.used_heap_size());
   18357           5 :   CHECK_EQ(total_available_size, heap_statistics.total_available_size());
   18358           5 :   CHECK_EQ(total_physical_size, heap_statistics.total_physical_size());
   18359           5 : }
   18360             : 
   18361       26644 : TEST(NumberOfNativeContexts) {
   18362             :   static const size_t kNumTestContexts = 10;
   18363             :   i::Isolate* isolate = CcTest::i_isolate();
   18364             :   i::HandleScope scope(isolate);
   18365         160 :   v8::Global<v8::Context> context[kNumTestContexts];
   18366           5 :   v8::HeapStatistics heap_statistics;
   18367           5 :   CHECK_EQ(0u, heap_statistics.number_of_native_contexts());
   18368           5 :   CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18369           5 :   CHECK_EQ(0u, heap_statistics.number_of_native_contexts());
   18370          50 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   18371             :     i::HandleScope inner(isolate);
   18372         100 :     context[i].Reset(CcTest::isolate(), v8::Context::New(CcTest::isolate()));
   18373          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18374          50 :     CHECK_EQ(i + 1, heap_statistics.number_of_native_contexts());
   18375             :   }
   18376         105 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   18377             :     context[i].Reset();
   18378          50 :     CcTest::PreciseCollectAllGarbage();
   18379          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18380          50 :     CHECK_EQ(kNumTestContexts - i - 1u,
   18381             :              heap_statistics.number_of_native_contexts());
   18382             :   }
   18383           5 : }
   18384             : 
   18385       26644 : TEST(NumberOfDetachedContexts) {
   18386             :   static const size_t kNumTestContexts = 10;
   18387             :   i::Isolate* isolate = CcTest::i_isolate();
   18388             :   i::HandleScope scope(isolate);
   18389         160 :   v8::Global<v8::Context> context[kNumTestContexts];
   18390           5 :   v8::HeapStatistics heap_statistics;
   18391           5 :   CHECK_EQ(0u, heap_statistics.number_of_detached_contexts());
   18392           5 :   CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18393           5 :   CHECK_EQ(0u, heap_statistics.number_of_detached_contexts());
   18394          50 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   18395             :     i::HandleScope inner(isolate);
   18396          50 :     v8::Local<v8::Context> local = v8::Context::New(CcTest::isolate());
   18397          50 :     context[i].Reset(CcTest::isolate(), local);
   18398          50 :     local->DetachGlobal();
   18399          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18400          50 :     CHECK_EQ(i + 1, heap_statistics.number_of_detached_contexts());
   18401             :   }
   18402         105 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   18403             :     context[i].Reset();
   18404          50 :     CcTest::PreciseCollectAllGarbage();
   18405          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18406          50 :     CHECK_EQ(kNumTestContexts - i - 1u,
   18407             :              heap_statistics.number_of_detached_contexts());
   18408             :   }
   18409           5 : }
   18410             : 
   18411             : class VisitorImpl : public v8::ExternalResourceVisitor {
   18412             :  public:
   18413           5 :   explicit VisitorImpl(TestResource** resource) {
   18414          45 :     for (int i = 0; i < 4; i++) {
   18415          20 :       resource_[i] = resource[i];
   18416          20 :       found_resource_[i] = false;
   18417             :     }
   18418             :   }
   18419          10 :   ~VisitorImpl() override = default;
   18420          25 :   void VisitExternalString(v8::Local<v8::String> string) override {
   18421          25 :     if (!string->IsExternal()) {
   18422           5 :       CHECK(string->IsExternalOneByte());
   18423             :       return;
   18424             :     }
   18425             :     v8::String::ExternalStringResource* resource =
   18426             :         string->GetExternalStringResource();
   18427          20 :     CHECK(resource);
   18428         180 :     for (int i = 0; i < 4; i++) {
   18429          80 :       if (resource_[i] == resource) {
   18430          20 :         CHECK(!found_resource_[i]);
   18431          20 :         found_resource_[i] = true;
   18432             :       }
   18433             :     }
   18434             :   }
   18435           5 :   void CheckVisitedResources() {
   18436          45 :     for (int i = 0; i < 4; i++) {
   18437          20 :       CHECK(found_resource_[i]);
   18438             :     }
   18439           5 :   }
   18440             : 
   18441             :  private:
   18442             :   v8::String::ExternalStringResource* resource_[4];
   18443             :   bool found_resource_[4];
   18444             : };
   18445             : 
   18446             : 
   18447       26644 : TEST(ExternalizeOldSpaceTwoByteCons) {
   18448           5 :   v8::Isolate* isolate = CcTest::isolate();
   18449           5 :   LocalContext env;
   18450          10 :   v8::HandleScope scope(isolate);
   18451             :   v8::Local<v8::String> cons =
   18452             :       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   18453           5 :           ->ToString(env.local())
   18454             :           .ToLocalChecked();
   18455           5 :   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18456           5 :   CcTest::CollectAllAvailableGarbage();
   18457          10 :   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   18458             : 
   18459             :   TestResource* resource = new TestResource(
   18460           5 :       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
   18461           5 :   cons->MakeExternal(resource);
   18462             : 
   18463           5 :   CHECK(cons->IsExternal());
   18464           5 :   CHECK_EQ(resource, cons->GetExternalStringResource());
   18465             :   String::Encoding encoding;
   18466           5 :   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18467           5 :   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
   18468           5 : }
   18469             : 
   18470             : 
   18471       26644 : TEST(ExternalizeOldSpaceOneByteCons) {
   18472           5 :   v8::Isolate* isolate = CcTest::isolate();
   18473           5 :   LocalContext env;
   18474          10 :   v8::HandleScope scope(isolate);
   18475             :   v8::Local<v8::String> cons =
   18476             :       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   18477           5 :           ->ToString(env.local())
   18478             :           .ToLocalChecked();
   18479           5 :   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18480           5 :   CcTest::CollectAllAvailableGarbage();
   18481          10 :   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   18482             : 
   18483             :   TestOneByteResource* resource =
   18484           5 :       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
   18485           5 :   cons->MakeExternal(resource);
   18486             : 
   18487           5 :   CHECK(cons->IsExternalOneByte());
   18488           5 :   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
   18489             :   String::Encoding encoding;
   18490           5 :   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18491           5 :   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
   18492           5 : }
   18493             : 
   18494             : 
   18495       26644 : TEST(VisitExternalStrings) {
   18496           5 :   v8::Isolate* isolate = CcTest::isolate();
   18497           5 :   LocalContext env;
   18498          10 :   v8::HandleScope scope(isolate);
   18499             :   const char* string = "Some string";
   18500           5 :   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   18501             :   TestResource* resource[4];
   18502          10 :   resource[0] = new TestResource(two_byte_string);
   18503             :   v8::Local<v8::String> string0 =
   18504           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
   18505             :           .ToLocalChecked();
   18506          10 :   resource[1] = new TestResource(two_byte_string, nullptr, false);
   18507             :   v8::Local<v8::String> string1 =
   18508           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
   18509             :           .ToLocalChecked();
   18510             : 
   18511             :   // Externalized symbol.
   18512          10 :   resource[2] = new TestResource(two_byte_string, nullptr, false);
   18513             :   v8::Local<v8::String> string2 =
   18514           5 :       v8::String::NewFromUtf8(env->GetIsolate(), string,
   18515           5 :                               v8::NewStringType::kInternalized)
   18516             :           .ToLocalChecked();
   18517           5 :   CHECK(string2->MakeExternal(resource[2]));
   18518             : 
   18519             :   // Symbolized External.
   18520          10 :   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   18521             :   v8::Local<v8::String> string3 =
   18522           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
   18523             :           .ToLocalChecked();
   18524           5 :   CcTest::CollectAllAvailableGarbage();  // Tenure string.
   18525             :   // Turn into a symbol.
   18526             :   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   18527          10 :   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
   18528             :       string3_i).is_null());
   18529          10 :   CHECK(string3_i->IsInternalizedString());
   18530             : 
   18531             :   // We need to add usages for string* to avoid warnings in GCC 4.7
   18532           5 :   CHECK(string0->IsExternal());
   18533           5 :   CHECK(string1->IsExternal());
   18534           5 :   CHECK(string2->IsExternal());
   18535           5 :   CHECK(string3->IsExternal());
   18536             : 
   18537             :   VisitorImpl visitor(resource);
   18538           5 :   isolate->VisitExternalResources(&visitor);
   18539           5 :   visitor.CheckVisitedResources();
   18540           5 : }
   18541             : 
   18542             : 
   18543       26644 : TEST(ExternalStringCollectedAtTearDown) {
   18544           5 :   int destroyed = 0;
   18545             :   v8::Isolate::CreateParams create_params;
   18546           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18547           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18548             :   { v8::Isolate::Scope isolate_scope(isolate);
   18549          10 :     v8::HandleScope handle_scope(isolate);
   18550             :     const char* s = "One string to test them all, one string to find them.";
   18551             :     TestOneByteResource* inscription =
   18552           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18553             :     v8::Local<v8::String> ring =
   18554           5 :         v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
   18555             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18556           5 :     CHECK_EQ(0, destroyed);
   18557             :     USE(ring);
   18558             :   }
   18559             : 
   18560           5 :   isolate->Dispose();
   18561             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18562           5 :   CHECK_EQ(1, destroyed);
   18563           5 : }
   18564             : 
   18565             : 
   18566       26644 : TEST(ExternalInternalizedStringCollectedAtTearDown) {
   18567           5 :   int destroyed = 0;
   18568             :   v8::Isolate::CreateParams create_params;
   18569           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18570           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18571             :   { v8::Isolate::Scope isolate_scope(isolate);
   18572           5 :     LocalContext env(isolate);
   18573          10 :     v8::HandleScope handle_scope(isolate);
   18574             :     CompileRun("var ring = 'One string to test them all';");
   18575             :     const char* s = "One string to test them all";
   18576             :     TestOneByteResource* inscription =
   18577           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18578             :     v8::Local<v8::String> ring =
   18579           5 :         CompileRun("ring")->ToString(env.local()).ToLocalChecked();
   18580           5 :     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18581           5 :     ring->MakeExternal(inscription);
   18582             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18583           5 :     CHECK_EQ(0, destroyed);
   18584             :     USE(ring);
   18585             :   }
   18586             : 
   18587           5 :   isolate->Dispose();
   18588             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18589           5 :   CHECK_EQ(1, destroyed);
   18590           5 : }
   18591             : 
   18592             : 
   18593       26644 : TEST(ExternalInternalizedStringCollectedAtGC) {
   18594           5 :   int destroyed = 0;
   18595           5 :   { LocalContext env;
   18596          10 :     v8::HandleScope handle_scope(env->GetIsolate());
   18597             :     CompileRun("var ring = 'One string to test them all';");
   18598             :     const char* s = "One string to test them all";
   18599             :     TestOneByteResource* inscription =
   18600           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18601             :     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
   18602          10 :     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18603           5 :     ring->MakeExternal(inscription);
   18604             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18605           5 :     CHECK_EQ(0, destroyed);
   18606             :     USE(ring);
   18607             :   }
   18608             : 
   18609             :   // Garbage collector deals swift blows to evil.
   18610           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
   18611           5 :   CcTest::CollectAllAvailableGarbage();
   18612             : 
   18613             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18614           5 :   CHECK_EQ(1, destroyed);
   18615           5 : }
   18616             : 
   18617             : 
   18618             : static double DoubleFromBits(uint64_t value) {
   18619             :   double target;
   18620             :   i::MemCopy(&target, &value, sizeof(target));
   18621             :   return target;
   18622             : }
   18623             : 
   18624             : 
   18625             : static uint64_t DoubleToBits(double value) {
   18626             :   uint64_t target;
   18627             :   i::MemCopy(&target, &value, sizeof(target));
   18628             :   return target;
   18629             : }
   18630             : 
   18631             : 
   18632         120 : static double DoubleToDateTime(double input) {
   18633             :   double date_limit = 864e13;
   18634         120 :   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   18635             :     return std::numeric_limits<double>::quiet_NaN();
   18636             :   }
   18637          60 :   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
   18638             : }
   18639             : 
   18640             : 
   18641             : // We don't have a consistent way to write 64-bit constants syntactically, so we
   18642             : // split them into two 32-bit constants and combine them programmatically.
   18643             : static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   18644             :   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   18645             : }
   18646             : 
   18647             : 
   18648       26645 : THREADED_TEST(QuietSignalingNaNs) {
   18649           6 :   LocalContext context;
   18650           6 :   v8::Isolate* isolate = context->GetIsolate();
   18651          12 :   v8::HandleScope scope(isolate);
   18652          12 :   v8::TryCatch try_catch(isolate);
   18653             : 
   18654             :   // Special double values.
   18655             :   double snan = DoubleFromBits(0x7FF00000, 0x00000001);
   18656             :   double qnan = DoubleFromBits(0x7FF80000, 0x00000000);
   18657             :   double infinity = DoubleFromBits(0x7FF00000, 0x00000000);
   18658             :   double max_normal = DoubleFromBits(0x7FEFFFFF, 0xFFFFFFFFu);
   18659             :   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   18660             :   double max_denormal = DoubleFromBits(0x000FFFFF, 0xFFFFFFFFu);
   18661             :   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   18662             : 
   18663             :   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   18664             :   // on either side of the epoch.
   18665             :   double date_limit = 864e13;
   18666             : 
   18667             :   double test_values[] = {
   18668             :       snan,
   18669             :       qnan,
   18670             :       infinity,
   18671             :       max_normal,
   18672             :       date_limit + 1,
   18673             :       date_limit,
   18674             :       min_normal,
   18675             :       max_denormal,
   18676             :       min_denormal,
   18677             :       0,
   18678             :       -0,
   18679             :       -min_denormal,
   18680             :       -max_denormal,
   18681             :       -min_normal,
   18682             :       -date_limit,
   18683             :       -date_limit - 1,
   18684             :       -max_normal,
   18685             :       -infinity,
   18686             :       -qnan,
   18687             :       -snan
   18688           6 :   };
   18689             :   int num_test_values = 20;
   18690             : 
   18691         246 :   for (int i = 0; i < num_test_values; i++) {
   18692         120 :     double test_value = test_values[i];
   18693             : 
   18694             :     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   18695         120 :     v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
   18696         240 :     double stored_number = number->NumberValue(context.local()).FromJust();
   18697         120 :     if (!std::isnan(test_value)) {
   18698          96 :       CHECK_EQ(test_value, stored_number);
   18699             :     } else {
   18700             :       uint64_t stored_bits = DoubleToBits(stored_number);
   18701             :       // Check if quiet nan (bits 51..62 all set).
   18702             : #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   18703             :     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   18704             :     !defined(USE_SIMULATOR)
   18705             :       // Most significant fraction bit for quiet nan is set to 0
   18706             :       // on MIPS architecture. Allowed by IEEE-754.
   18707             :       CHECK_EQ(0xFFE, static_cast<int>((stored_bits >> 51) & 0xFFF));
   18708             : #else
   18709          24 :       CHECK_EQ(0xFFF, static_cast<int>((stored_bits >> 51) & 0xFFF));
   18710             : #endif
   18711             :     }
   18712             : 
   18713             :     // Check that Date::New preserves non-NaNs in the date range and
   18714             :     // quiets SNaNs.
   18715             :     v8::Local<v8::Value> date =
   18716         120 :         v8::Date::New(context.local(), test_value).ToLocalChecked();
   18717         120 :     double expected_stored_date = DoubleToDateTime(test_value);
   18718         240 :     double stored_date = date->NumberValue(context.local()).FromJust();
   18719         120 :     if (!std::isnan(expected_stored_date)) {
   18720          60 :       CHECK_EQ(expected_stored_date, stored_date);
   18721             :     } else {
   18722             :       uint64_t stored_bits = DoubleToBits(stored_date);
   18723             :       // Check if quiet nan (bits 51..62 all set).
   18724             : #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   18725             :     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   18726             :     !defined(USE_SIMULATOR)
   18727             :       // Most significant fraction bit for quiet nan is set to 0
   18728             :       // on MIPS architecture. Allowed by IEEE-754.
   18729             :       CHECK_EQ(0xFFE, static_cast<int>((stored_bits >> 51) & 0xFFF));
   18730             : #else
   18731          60 :       CHECK_EQ(0xFFF, static_cast<int>((stored_bits >> 51) & 0xFFF));
   18732             : #endif
   18733             :     }
   18734             :   }
   18735           6 : }
   18736             : 
   18737             : 
   18738          66 : static void SpaghettiIncident(
   18739             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18740         132 :   v8::HandleScope scope(args.GetIsolate());
   18741         132 :   v8::TryCatch tc(args.GetIsolate());
   18742             :   v8::MaybeLocal<v8::String> str(
   18743         132 :       args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
   18744             :   USE(str);
   18745          66 :   if (tc.HasCaught())
   18746          66 :     tc.ReThrow();
   18747          66 : }
   18748             : 
   18749             : 
   18750             : // Test that an exception can be propagated down through a spaghetti
   18751             : // stack using ReThrow.
   18752       26645 : THREADED_TEST(SpaghettiStackReThrow) {
   18753           6 :   v8::Isolate* isolate = CcTest::isolate();
   18754          12 :   v8::HandleScope scope(isolate);
   18755           6 :   LocalContext context;
   18756          12 :   context->Global()
   18757          12 :       ->Set(context.local(), v8_str("s"),
   18758          12 :             v8::FunctionTemplate::New(isolate, SpaghettiIncident)
   18759           6 :                 ->GetFunction(context.local())
   18760          12 :                 .ToLocalChecked())
   18761             :       .FromJust();
   18762          12 :   v8::TryCatch try_catch(isolate);
   18763             :   CompileRun(
   18764             :       "var i = 0;"
   18765             :       "var o = {"
   18766             :       "  toString: function () {"
   18767             :       "    if (i == 10) {"
   18768             :       "      throw 'Hey!';"
   18769             :       "    } else {"
   18770             :       "      i++;"
   18771             :       "      return s(o);"
   18772             :       "    }"
   18773             :       "  }"
   18774             :       "};"
   18775             :       "s(o);");
   18776           6 :   CHECK(try_catch.HasCaught());
   18777          12 :   v8::String::Utf8Value value(isolate, try_catch.Exception());
   18778           6 :   CHECK_EQ(0, strcmp(*value, "Hey!"));
   18779           6 : }
   18780             : 
   18781             : 
   18782       26644 : TEST(Regress528) {
   18783             :   ManualGCScope manual_gc_scope;
   18784           5 :   v8::V8::Initialize();
   18785           5 :   v8::Isolate* isolate = CcTest::isolate();
   18786           5 :   i::FLAG_retain_maps_for_n_gc = 0;
   18787          10 :   v8::HandleScope scope(isolate);
   18788             :   v8::Local<Context> other_context;
   18789             :   int gc_count;
   18790             : 
   18791             :   // Create a context used to keep the code from aging in the compilation
   18792             :   // cache.
   18793           5 :   other_context = Context::New(isolate);
   18794             : 
   18795             :   // Context-dependent context data creates reference from the compilation
   18796             :   // cache to the global object.
   18797             :   const char* source_simple = "1";
   18798             :   {
   18799          10 :     v8::HandleScope scope(isolate);
   18800           5 :     v8::Local<Context> context = Context::New(isolate);
   18801             : 
   18802           5 :     context->Enter();
   18803           5 :     Local<v8::String> obj = v8_str("");
   18804           5 :     context->SetEmbedderData(0, obj);
   18805             :     CompileRun(source_simple);
   18806           5 :     context->Exit();
   18807             :   }
   18808           5 :   isolate->ContextDisposedNotification();
   18809           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   18810           5 :     other_context->Enter();
   18811             :     CompileRun(source_simple);
   18812           5 :     other_context->Exit();
   18813           5 :     CcTest::CollectAllGarbage();
   18814           5 :     if (GetGlobalObjectsCount() == 1) break;
   18815             :   }
   18816           5 :   CHECK_GE(2, gc_count);
   18817           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   18818             : 
   18819             :   // Eval in a function creates reference from the compilation cache to the
   18820             :   // global object.
   18821             :   const char* source_eval = "function f(){eval('1')}; f()";
   18822             :   {
   18823          10 :     v8::HandleScope scope(isolate);
   18824           5 :     v8::Local<Context> context = Context::New(isolate);
   18825             : 
   18826           5 :     context->Enter();
   18827             :     CompileRun(source_eval);
   18828           5 :     context->Exit();
   18829             :   }
   18830           5 :   isolate->ContextDisposedNotification();
   18831           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   18832           5 :     other_context->Enter();
   18833             :     CompileRun(source_eval);
   18834           5 :     other_context->Exit();
   18835           5 :     CcTest::CollectAllGarbage();
   18836           5 :     if (GetGlobalObjectsCount() == 1) break;
   18837             :   }
   18838           5 :   CHECK_GE(2, gc_count);
   18839           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   18840             : 
   18841             :   // Looking up the line number for an exception creates reference from the
   18842             :   // compilation cache to the global object.
   18843             :   const char* source_exception = "function f(){throw 1;} f()";
   18844             :   {
   18845          10 :     v8::HandleScope scope(isolate);
   18846           5 :     v8::Local<Context> context = Context::New(isolate);
   18847             : 
   18848           5 :     context->Enter();
   18849          10 :     v8::TryCatch try_catch(isolate);
   18850             :     CompileRun(source_exception);
   18851           5 :     CHECK(try_catch.HasCaught());
   18852           5 :     v8::Local<v8::Message> message = try_catch.Message();
   18853           5 :     CHECK(!message.IsEmpty());
   18854          10 :     CHECK_EQ(1, message->GetLineNumber(context).FromJust());
   18855           5 :     context->Exit();
   18856             :   }
   18857           5 :   isolate->ContextDisposedNotification();
   18858           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   18859           5 :     other_context->Enter();
   18860             :     CompileRun(source_exception);
   18861           5 :     other_context->Exit();
   18862           5 :     CcTest::CollectAllGarbage();
   18863           5 :     if (GetGlobalObjectsCount() == 1) break;
   18864             :   }
   18865           5 :   CHECK_GE(2, gc_count);
   18866           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   18867             : 
   18868           5 :   isolate->ContextDisposedNotification();
   18869           5 : }
   18870             : 
   18871             : 
   18872       26645 : THREADED_TEST(ScriptOrigin) {
   18873           6 :   LocalContext env;
   18874           6 :   v8::Isolate* isolate = env->GetIsolate();
   18875          12 :   v8::HandleScope scope(isolate);
   18876           6 :   Local<v8::PrimitiveArray> array(v8::PrimitiveArray::New(isolate, 1));
   18877           6 :   Local<v8::Symbol> symbol(v8::Symbol::New(isolate));
   18878           6 :   array->Set(isolate, 0, symbol);
   18879             : 
   18880             :   v8::ScriptOrigin origin = v8::ScriptOrigin(
   18881             :       v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
   18882             :       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
   18883             :       v8::Local<v8::Integer>(), v8_str("http://sourceMapUrl"),
   18884             :       v8::True(env->GetIsolate()), v8::False(env->GetIsolate()),
   18885          42 :       v8::False(env->GetIsolate()), array);
   18886           6 :   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   18887           6 :   v8::Script::Compile(env.local(), script, &origin)
   18888             :       .ToLocalChecked()
   18889           6 :       ->Run(env.local())
   18890             :       .ToLocalChecked();
   18891             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18892          24 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18893             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18894          24 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18895             : 
   18896           6 :   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   18897           6 :   CHECK_EQ(0, strcmp("test",
   18898             :                      *v8::String::Utf8Value(env->GetIsolate(),
   18899             :                                             script_origin_f.ResourceName())));
   18900          12 :   CHECK_EQ(
   18901             :       1,
   18902             :       script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   18903           6 :   CHECK(script_origin_f.Options().IsSharedCrossOrigin());
   18904           6 :   CHECK(script_origin_f.Options().IsOpaque());
   18905           6 :   printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
   18906          12 :   CHECK(script_origin_f.HostDefinedOptions()->Get(isolate, 0)->IsSymbol());
   18907             : 
   18908           6 :   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   18909             :                      *v8::String::Utf8Value(env->GetIsolate(),
   18910             :                                             script_origin_f.SourceMapUrl())));
   18911             : 
   18912           6 :   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   18913           6 :   CHECK_EQ(0, strcmp("test",
   18914             :                      *v8::String::Utf8Value(env->GetIsolate(),
   18915             :                                             script_origin_g.ResourceName())));
   18916          12 :   CHECK_EQ(
   18917             :       1,
   18918             :       script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   18919           6 :   CHECK(script_origin_g.Options().IsSharedCrossOrigin());
   18920           6 :   CHECK(script_origin_g.Options().IsOpaque());
   18921           6 :   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   18922             :                      *v8::String::Utf8Value(env->GetIsolate(),
   18923             :                                             script_origin_g.SourceMapUrl())));
   18924          12 :   CHECK(script_origin_g.HostDefinedOptions()->Get(isolate, 0)->IsSymbol());
   18925           6 : }
   18926             : 
   18927             : 
   18928       26645 : THREADED_TEST(FunctionGetInferredName) {
   18929           6 :   LocalContext env;
   18930          12 :   v8::HandleScope scope(env->GetIsolate());
   18931           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18932             :   v8::Local<v8::String> script =
   18933           6 :       v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   18934           6 :   v8::Script::Compile(env.local(), script, &origin)
   18935             :       .ToLocalChecked()
   18936           6 :       ->Run(env.local())
   18937             :       .ToLocalChecked();
   18938             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18939          24 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18940          12 :   CHECK_EQ(0,
   18941             :            strcmp("foo.bar.baz", *v8::String::Utf8Value(env->GetIsolate(),
   18942             :                                                         f->GetInferredName())));
   18943           6 : }
   18944             : 
   18945             : 
   18946       26645 : THREADED_TEST(FunctionGetDebugName) {
   18947           6 :   LocalContext env;
   18948           6 :   v8::Isolate* isolate = env->GetIsolate();
   18949          12 :   v8::HandleScope scope(isolate);
   18950             :   const char* code =
   18951             :       "var error = false;"
   18952             :       "function a() { this.x = 1; };"
   18953             :       "a.displayName = 'display_a';"
   18954             :       "var b = (function() {"
   18955             :       "  var f = function() { this.x = 2; };"
   18956             :       "  f.displayName = 'display_b';"
   18957             :       "  return f;"
   18958             :       "})();"
   18959             :       "var c = function() {};"
   18960             :       "c.__defineGetter__('displayName', function() {"
   18961             :       "  error = true;"
   18962             :       "  throw new Error();"
   18963             :       "});"
   18964             :       "function d() {};"
   18965             :       "d.__defineGetter__('displayName', function() {"
   18966             :       "  error = true;"
   18967             :       "  return 'wrong_display_name';"
   18968             :       "});"
   18969             :       "function e() {};"
   18970             :       "e.displayName = 'wrong_display_name';"
   18971             :       "e.__defineSetter__('displayName', function() {"
   18972             :       "  error = true;"
   18973             :       "  throw new Error();"
   18974             :       "});"
   18975             :       "function f() {};"
   18976             :       "f.displayName = { 'foo': 6, toString: function() {"
   18977             :       "  error = true;"
   18978             :       "  return 'wrong_display_name';"
   18979             :       "}};"
   18980             :       "var g = function() {"
   18981             :       "  arguments.callee.displayName = 'set_in_runtime';"
   18982             :       "}; g();"
   18983             :       "var h = function() {};"
   18984             :       "h.displayName = 'displayName';"
   18985             :       "Object.defineProperty(h, 'name', { value: 'function.name' });"
   18986             :       "var i = function() {};"
   18987             :       "i.displayName = 239;"
   18988             :       "Object.defineProperty(i, 'name', { value: 'function.name' });"
   18989             :       "var j = function() {};"
   18990             :       "Object.defineProperty(j, 'name', { value: 'function.name' });"
   18991             :       "var foo = { bar : { baz : (0, function() {})}}; var k = foo.bar.baz;"
   18992             :       "var foo = { bar : { baz : function() {} }}; var l = foo.bar.baz;";
   18993           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18994          12 :   v8::Script::Compile(env.local(), v8_str(code), &origin)
   18995             :       .ToLocalChecked()
   18996           6 :       ->Run(env.local())
   18997             :       .ToLocalChecked();
   18998             :   v8::Local<v8::Value> error =
   18999          24 :       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   19000           6 :   CHECK(!error->BooleanValue(isolate));
   19001             :   const char* functions[] = {"a", "display_a",
   19002             :                              "b", "display_b",
   19003             :                              "c", "c",
   19004             :                              "d", "d",
   19005             :                              "e", "e",
   19006             :                              "f", "f",
   19007             :                              "g", "set_in_runtime",
   19008             :                              "h", "displayName",
   19009             :                              "i", "function.name",
   19010             :                              "j", "function.name",
   19011             :                              "k", "foo.bar.baz",
   19012           6 :                              "l", "baz"};
   19013         150 :   for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
   19014             :     v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19015         144 :         env->Global()
   19016          72 :             ->Get(env.local(),
   19017         144 :                   v8::String::NewFromUtf8(isolate, functions[i * 2],
   19018          72 :                                           v8::NewStringType::kNormal)
   19019          72 :                       .ToLocalChecked())
   19020             :             .ToLocalChecked());
   19021          72 :     CHECK_EQ(0, strcmp(functions[i * 2 + 1],
   19022             :                        *v8::String::Utf8Value(isolate, f->GetDebugName())));
   19023             :   }
   19024           6 : }
   19025             : 
   19026             : 
   19027       26645 : THREADED_TEST(FunctionGetDisplayName) {
   19028           6 :   LocalContext env;
   19029           6 :   v8::Isolate* isolate = env->GetIsolate();
   19030          12 :   v8::HandleScope scope(isolate);
   19031             :   const char* code = "var error = false;"
   19032             :                      "function a() { this.x = 1; };"
   19033             :                      "a.displayName = 'display_a';"
   19034             :                      "var b = (function() {"
   19035             :                      "  var f = function() { this.x = 2; };"
   19036             :                      "  f.displayName = 'display_b';"
   19037             :                      "  return f;"
   19038             :                      "})();"
   19039             :                      "var c = function() {};"
   19040             :                      "c.__defineGetter__('displayName', function() {"
   19041             :                      "  error = true;"
   19042             :                      "  throw new Error();"
   19043             :                      "});"
   19044             :                      "function d() {};"
   19045             :                      "d.__defineGetter__('displayName', function() {"
   19046             :                      "  error = true;"
   19047             :                      "  return 'wrong_display_name';"
   19048             :                      "});"
   19049             :                      "function e() {};"
   19050             :                      "e.displayName = 'wrong_display_name';"
   19051             :                      "e.__defineSetter__('displayName', function() {"
   19052             :                      "  error = true;"
   19053             :                      "  throw new Error();"
   19054             :                      "});"
   19055             :                      "function f() {};"
   19056             :                      "f.displayName = { 'foo': 6, toString: function() {"
   19057             :                      "  error = true;"
   19058             :                      "  return 'wrong_display_name';"
   19059             :                      "}};"
   19060             :                      "var g = function() {"
   19061             :                      "  arguments.callee.displayName = 'set_in_runtime';"
   19062             :                      "}; g();";
   19063           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19064          12 :   v8::Script::Compile(env.local(), v8_str(code), &origin)
   19065             :       .ToLocalChecked()
   19066           6 :       ->Run(env.local())
   19067             :       .ToLocalChecked();
   19068             :   v8::Local<v8::Value> error =
   19069          24 :       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   19070             :   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
   19071          24 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   19072             :   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
   19073          24 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   19074             :   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
   19075          24 :       env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
   19076             :   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
   19077          24 :       env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
   19078             :   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
   19079          24 :       env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
   19080             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19081          24 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19082             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19083          24 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19084           6 :   CHECK(!error->BooleanValue(isolate));
   19085           6 :   CHECK_EQ(0, strcmp("display_a",
   19086             :                      *v8::String::Utf8Value(isolate, a->GetDisplayName())));
   19087           6 :   CHECK_EQ(0, strcmp("display_b",
   19088             :                      *v8::String::Utf8Value(isolate, b->GetDisplayName())));
   19089          12 :   CHECK(c->GetDisplayName()->IsUndefined());
   19090          12 :   CHECK(d->GetDisplayName()->IsUndefined());
   19091          12 :   CHECK(e->GetDisplayName()->IsUndefined());
   19092          12 :   CHECK(f->GetDisplayName()->IsUndefined());
   19093           6 :   CHECK_EQ(0, strcmp("set_in_runtime",
   19094             :                      *v8::String::Utf8Value(isolate, g->GetDisplayName())));
   19095           6 : }
   19096             : 
   19097             : 
   19098       26645 : THREADED_TEST(ScriptLineNumber) {
   19099           6 :   LocalContext env;
   19100          12 :   v8::HandleScope scope(env->GetIsolate());
   19101           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19102           6 :   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   19103           6 :   v8::Script::Compile(env.local(), script, &origin)
   19104             :       .ToLocalChecked()
   19105           6 :       ->Run(env.local())
   19106             :       .ToLocalChecked();
   19107             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19108          24 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19109             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19110          24 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19111           6 :   CHECK_EQ(0, f->GetScriptLineNumber());
   19112           6 :   CHECK_EQ(2, g->GetScriptLineNumber());
   19113           6 : }
   19114             : 
   19115             : 
   19116       26645 : THREADED_TEST(ScriptColumnNumber) {
   19117           6 :   LocalContext env;
   19118           6 :   v8::Isolate* isolate = env->GetIsolate();
   19119          12 :   v8::HandleScope scope(isolate);
   19120             :   v8::ScriptOrigin origin =
   19121             :       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   19122           6 :                        v8::Integer::New(isolate, 2));
   19123             :   v8::Local<v8::String> script =
   19124           6 :       v8_str("function foo() {}\n\n     function bar() {}");
   19125           6 :   v8::Script::Compile(env.local(), script, &origin)
   19126             :       .ToLocalChecked()
   19127           6 :       ->Run(env.local())
   19128             :       .ToLocalChecked();
   19129             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   19130          24 :       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   19131             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   19132          24 :       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   19133           6 :   CHECK_EQ(14, foo->GetScriptColumnNumber());
   19134           6 :   CHECK_EQ(17, bar->GetScriptColumnNumber());
   19135           6 : }
   19136             : 
   19137             : 
   19138       26645 : THREADED_TEST(FunctionGetScriptId) {
   19139           6 :   LocalContext env;
   19140           6 :   v8::Isolate* isolate = env->GetIsolate();
   19141          12 :   v8::HandleScope scope(isolate);
   19142             :   v8::ScriptOrigin origin =
   19143             :       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   19144           6 :                        v8::Integer::New(isolate, 2));
   19145             :   v8::Local<v8::String> scriptSource =
   19146           6 :       v8_str("function foo() {}\n\n     function bar() {}");
   19147             :   v8::Local<v8::Script> script(
   19148           6 :       v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
   19149           6 :   script->Run(env.local()).ToLocalChecked();
   19150             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   19151          24 :       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   19152             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   19153          24 :       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   19154          12 :   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
   19155          12 :   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
   19156           6 : }
   19157             : 
   19158             : 
   19159       26645 : THREADED_TEST(FunctionGetBoundFunction) {
   19160           6 :   LocalContext env;
   19161          12 :   v8::HandleScope scope(env->GetIsolate());
   19162           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19163             :   v8::Local<v8::String> script = v8_str(
   19164             :       "var a = new Object();\n"
   19165             :       "a.x = 1;\n"
   19166             :       "function f () { return this.x };\n"
   19167             :       "var g = f.bind(a);\n"
   19168           6 :       "var b = g();");
   19169           6 :   v8::Script::Compile(env.local(), script, &origin)
   19170             :       .ToLocalChecked()
   19171           6 :       ->Run(env.local())
   19172             :       .ToLocalChecked();
   19173             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19174          24 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19175             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19176          24 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19177          12 :   CHECK(g->GetBoundFunction()->IsFunction());
   19178             :   Local<v8::Function> original_function = Local<v8::Function>::Cast(
   19179           6 :       g->GetBoundFunction());
   19180          24 :   CHECK(f->GetName()
   19181             :             ->Equals(env.local(), original_function->GetName())
   19182             :             .FromJust());
   19183           6 :   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
   19184           6 :   CHECK_EQ(f->GetScriptColumnNumber(),
   19185             :            original_function->GetScriptColumnNumber());
   19186           6 : }
   19187             : 
   19188             : 
   19189         330 : static void GetterWhichReturns42(
   19190             :     Local<String> name,
   19191             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19192         330 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19193         330 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19194         330 :   info.GetReturnValue().Set(v8_num(42));
   19195         330 : }
   19196             : 
   19197             : 
   19198         270 : static void SetterWhichSetsYOnThisTo23(
   19199             :     Local<String> name,
   19200             :     Local<Value> value,
   19201             :     const v8::PropertyCallbackInfo<void>& info) {
   19202         270 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19203         270 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19204             :   Local<Object>::Cast(info.This())
   19205        1080 :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19206             :       .FromJust();
   19207         270 : }
   19208             : 
   19209             : 
   19210         120 : void FooGetInterceptor(Local<Name> name,
   19211             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   19212         120 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19213         120 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19214         480 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19215             :            .FromJust()) {
   19216             :     return;
   19217             :   }
   19218          96 :   info.GetReturnValue().Set(v8_num(42));
   19219             : }
   19220             : 
   19221             : 
   19222         336 : void FooSetInterceptor(Local<Name> name, Local<Value> value,
   19223             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   19224         336 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19225         336 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19226        1344 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19227             :            .FromJust()) {
   19228             :     return;
   19229             :   }
   19230             :   Local<Object>::Cast(info.This())
   19231         384 :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19232             :       .FromJust();
   19233          96 :   info.GetReturnValue().Set(v8_num(23));
   19234             : }
   19235             : 
   19236             : 
   19237       26644 : TEST(SetterOnConstructorPrototype) {
   19238           5 :   v8::Isolate* isolate = CcTest::isolate();
   19239          10 :   v8::HandleScope scope(isolate);
   19240           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19241          10 :   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   19242           5 :                      SetterWhichSetsYOnThisTo23);
   19243           5 :   LocalContext context;
   19244          25 :   CHECK(context->Global()
   19245             :             ->Set(context.local(), v8_str("P"),
   19246             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19247             :             .FromJust());
   19248             :   CompileRun("function C1() {"
   19249             :              "  this.x = 23;"
   19250             :              "};"
   19251             :              "C1.prototype = P;"
   19252             :              "function C2() {"
   19253             :              "  this.x = 23"
   19254             :              "};"
   19255             :              "C2.prototype = { };"
   19256             :              "C2.prototype.__proto__ = P;");
   19257             : 
   19258             :   v8::Local<v8::Script> script;
   19259             :   script = v8_compile("new C1();");
   19260         105 :   for (int i = 0; i < 10; i++) {
   19261             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19262          50 :         script->Run(context.local()).ToLocalChecked());
   19263         200 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   19264             :                      .ToLocalChecked()
   19265             :                      ->Int32Value(context.local())
   19266             :                      .FromJust());
   19267         200 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   19268             :                      .ToLocalChecked()
   19269             :                      ->Int32Value(context.local())
   19270             :                      .FromJust());
   19271             :   }
   19272             : 
   19273             :   script = v8_compile("new C2();");
   19274         105 :   for (int i = 0; i < 10; i++) {
   19275             :     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   19276          50 :         script->Run(context.local()).ToLocalChecked());
   19277         200 :     CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
   19278             :                      .ToLocalChecked()
   19279             :                      ->Int32Value(context.local())
   19280             :                      .FromJust());
   19281         200 :     CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
   19282             :                      .ToLocalChecked()
   19283             :                      ->Int32Value(context.local())
   19284             :                      .FromJust());
   19285             :   }
   19286           5 : }
   19287             : 
   19288             : 
   19289           0 : static void NamedPropertySetterWhichSetsYOnThisTo23(
   19290             :     Local<Name> name, Local<Value> value,
   19291             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19292           0 :   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
   19293             :           .FromJust()) {
   19294             :     Local<Object>::Cast(info.This())
   19295           0 :         ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19296             :         .FromJust();
   19297             :   }
   19298           0 : }
   19299             : 
   19300             : 
   19301       26645 : THREADED_TEST(InterceptorOnConstructorPrototype) {
   19302           6 :   v8::Isolate* isolate = CcTest::isolate();
   19303          12 :   v8::HandleScope scope(isolate);
   19304           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19305           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   19306             :       NamedPropertyGetterWhichReturns42,
   19307           6 :       NamedPropertySetterWhichSetsYOnThisTo23));
   19308           6 :   LocalContext context;
   19309          30 :   CHECK(context->Global()
   19310             :             ->Set(context.local(), v8_str("P"),
   19311             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19312             :             .FromJust());
   19313             :   CompileRun("function C1() {"
   19314             :              "  this.x = 23;"
   19315             :              "};"
   19316             :              "C1.prototype = P;"
   19317             :              "function C2() {"
   19318             :              "  this.x = 23"
   19319             :              "};"
   19320             :              "C2.prototype = { };"
   19321             :              "C2.prototype.__proto__ = P;");
   19322             : 
   19323             :   v8::Local<v8::Script> script;
   19324             :   script = v8_compile("new C1();");
   19325         126 :   for (int i = 0; i < 10; i++) {
   19326             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19327          60 :         script->Run(context.local()).ToLocalChecked());
   19328         240 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   19329             :                      .ToLocalChecked()
   19330             :                      ->Int32Value(context.local())
   19331             :                      .FromJust());
   19332         240 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   19333             :                      .ToLocalChecked()
   19334             :                      ->Int32Value(context.local())
   19335             :                      .FromJust());
   19336             :   }
   19337             : 
   19338             :   script = v8_compile("new C2();");
   19339         126 :   for (int i = 0; i < 10; i++) {
   19340             :     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   19341          60 :         script->Run(context.local()).ToLocalChecked());
   19342         240 :     CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
   19343             :                      .ToLocalChecked()
   19344             :                      ->Int32Value(context.local())
   19345             :                      .FromJust());
   19346         240 :     CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
   19347             :                      .ToLocalChecked()
   19348             :                      ->Int32Value(context.local())
   19349             :                      .FromJust());
   19350             :   }
   19351           6 : }
   19352             : 
   19353             : 
   19354       26644 : TEST(Regress618) {
   19355             :   const char* source = "function C1() {"
   19356             :                        "  this.x = 23;"
   19357             :                        "};"
   19358             :                        "C1.prototype = P;";
   19359             : 
   19360           5 :   LocalContext context;
   19361           5 :   v8::Isolate* isolate = context->GetIsolate();
   19362          10 :   v8::HandleScope scope(isolate);
   19363             :   v8::Local<v8::Script> script;
   19364             : 
   19365             :   // Use a simple object as prototype.
   19366           5 :   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
   19367          15 :   prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
   19368          20 :   CHECK(context->Global()
   19369             :             ->Set(context.local(), v8_str("P"), prototype)
   19370             :             .FromJust());
   19371             : 
   19372             :   // This compile will add the code to the compilation cache.
   19373             :   CompileRun(source);
   19374             : 
   19375             :   script = v8_compile("new C1();");
   19376             :   // Allow enough iterations for the inobject slack tracking logic
   19377             :   // to finalize instance size and install the fast construct stub.
   19378        2565 :   for (int i = 0; i < 256; i++) {
   19379             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19380        1280 :         script->Run(context.local()).ToLocalChecked());
   19381        5120 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   19382             :                      .ToLocalChecked()
   19383             :                      ->Int32Value(context.local())
   19384             :                      .FromJust());
   19385        5120 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   19386             :                      .ToLocalChecked()
   19387             :                      ->Int32Value(context.local())
   19388             :                      .FromJust());
   19389             :   }
   19390             : 
   19391             :   // Use an API object with accessors as prototype.
   19392           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19393          10 :   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   19394           5 :                      SetterWhichSetsYOnThisTo23);
   19395          25 :   CHECK(context->Global()
   19396             :             ->Set(context.local(), v8_str("P"),
   19397             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19398             :             .FromJust());
   19399             : 
   19400             :   // This compile will get the code from the compilation cache.
   19401             :   CompileRun(source);
   19402             : 
   19403             :   script = v8_compile("new C1();");
   19404         105 :   for (int i = 0; i < 10; i++) {
   19405             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19406          50 :         script->Run(context.local()).ToLocalChecked());
   19407         200 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   19408             :                      .ToLocalChecked()
   19409             :                      ->Int32Value(context.local())
   19410             :                      .FromJust());
   19411         200 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   19412             :                      .ToLocalChecked()
   19413             :                      ->Int32Value(context.local())
   19414             :                      .FromJust());
   19415             :   }
   19416           5 : }
   19417             : 
   19418             : v8::Isolate* gc_callbacks_isolate = nullptr;
   19419             : int prologue_call_count = 0;
   19420             : int epilogue_call_count = 0;
   19421             : int prologue_call_count_second = 0;
   19422             : int epilogue_call_count_second = 0;
   19423             : int prologue_call_count_alloc = 0;
   19424             : int epilogue_call_count_alloc = 0;
   19425             : 
   19426          20 : void PrologueCallback(v8::Isolate* isolate,
   19427             :                       v8::GCType,
   19428             :                       v8::GCCallbackFlags flags) {
   19429          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19430          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19431          20 :   ++prologue_call_count;
   19432          20 : }
   19433             : 
   19434          20 : void EpilogueCallback(v8::Isolate* isolate,
   19435             :                       v8::GCType,
   19436             :                       v8::GCCallbackFlags flags) {
   19437          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19438          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19439          20 :   ++epilogue_call_count;
   19440          20 : }
   19441             : 
   19442             : 
   19443          20 : void PrologueCallbackSecond(v8::Isolate* isolate,
   19444             :                             v8::GCType,
   19445             :                             v8::GCCallbackFlags flags) {
   19446          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19447          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19448          20 :   ++prologue_call_count_second;
   19449          20 : }
   19450             : 
   19451             : 
   19452          20 : void EpilogueCallbackSecond(v8::Isolate* isolate,
   19453             :                             v8::GCType,
   19454             :                             v8::GCCallbackFlags flags) {
   19455          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19456          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19457          20 :   ++epilogue_call_count_second;
   19458          20 : }
   19459             : 
   19460          20 : void PrologueCallbackNew(v8::Isolate* isolate, v8::GCType,
   19461             :                          v8::GCCallbackFlags flags, void* data) {
   19462          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19463          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19464          20 :   ++*static_cast<int*>(data);
   19465          20 : }
   19466             : 
   19467          20 : void EpilogueCallbackNew(v8::Isolate* isolate, v8::GCType,
   19468             :                          v8::GCCallbackFlags flags, void* data) {
   19469          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19470          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19471          20 :   ++*static_cast<int*>(data);
   19472          20 : }
   19473             : 
   19474           5 : void PrologueCallbackAlloc(v8::Isolate* isolate,
   19475             :                            v8::GCType,
   19476             :                            v8::GCCallbackFlags flags) {
   19477          10 :   v8::HandleScope scope(isolate);
   19478             : 
   19479           5 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19480           5 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19481           5 :   ++prologue_call_count_alloc;
   19482             : 
   19483             :   // Simulate full heap to see if we will reenter this callback
   19484           5 :   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   19485             : 
   19486           5 :   Local<Object> obj = Object::New(isolate);
   19487           5 :   CHECK(!obj.IsEmpty());
   19488             : 
   19489           5 :   CcTest::PreciseCollectAllGarbage();
   19490           5 : }
   19491             : 
   19492             : 
   19493           5 : void EpilogueCallbackAlloc(v8::Isolate* isolate,
   19494             :                            v8::GCType,
   19495             :                            v8::GCCallbackFlags flags) {
   19496          10 :   v8::HandleScope scope(isolate);
   19497             : 
   19498           5 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19499           5 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19500           5 :   ++epilogue_call_count_alloc;
   19501             : 
   19502             :   // Simulate full heap to see if we will reenter this callback
   19503           5 :   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   19504             : 
   19505           5 :   Local<Object> obj = Object::New(isolate);
   19506           5 :   CHECK(!obj.IsEmpty());
   19507             : 
   19508           5 :   CcTest::PreciseCollectAllGarbage();
   19509           5 : }
   19510             : 
   19511             : 
   19512       26644 : TEST(GCCallbacksOld) {
   19513           5 :   LocalContext context;
   19514             : 
   19515           5 :   gc_callbacks_isolate = context->GetIsolate();
   19516             : 
   19517           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
   19518           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
   19519           5 :   CHECK_EQ(0, prologue_call_count);
   19520           5 :   CHECK_EQ(0, epilogue_call_count);
   19521           5 :   CcTest::CollectAllGarbage();
   19522           5 :   CHECK_EQ(1, prologue_call_count);
   19523           5 :   CHECK_EQ(1, epilogue_call_count);
   19524           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
   19525           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
   19526           5 :   CcTest::CollectAllGarbage();
   19527           5 :   CHECK_EQ(2, prologue_call_count);
   19528           5 :   CHECK_EQ(2, epilogue_call_count);
   19529           5 :   CHECK_EQ(1, prologue_call_count_second);
   19530           5 :   CHECK_EQ(1, epilogue_call_count_second);
   19531           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
   19532           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
   19533           5 :   CcTest::CollectAllGarbage();
   19534           5 :   CHECK_EQ(2, prologue_call_count);
   19535           5 :   CHECK_EQ(2, epilogue_call_count);
   19536           5 :   CHECK_EQ(2, prologue_call_count_second);
   19537           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19538           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
   19539           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   19540           5 :   CcTest::CollectAllGarbage();
   19541           5 :   CHECK_EQ(2, prologue_call_count);
   19542           5 :   CHECK_EQ(2, epilogue_call_count);
   19543           5 :   CHECK_EQ(2, prologue_call_count_second);
   19544           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19545           5 : }
   19546             : 
   19547       26644 : TEST(GCCallbacksWithData) {
   19548           5 :   LocalContext context;
   19549             : 
   19550           5 :   gc_callbacks_isolate = context->GetIsolate();
   19551           5 :   int prologue1 = 0;
   19552           5 :   int epilogue1 = 0;
   19553           5 :   int prologue2 = 0;
   19554           5 :   int epilogue2 = 0;
   19555             : 
   19556           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue1);
   19557           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue1);
   19558           5 :   CHECK_EQ(0, prologue1);
   19559           5 :   CHECK_EQ(0, epilogue1);
   19560           5 :   CHECK_EQ(0, prologue2);
   19561           5 :   CHECK_EQ(0, epilogue2);
   19562           5 :   CcTest::CollectAllGarbage();
   19563           5 :   CHECK_EQ(1, prologue1);
   19564           5 :   CHECK_EQ(1, epilogue1);
   19565           5 :   CHECK_EQ(0, prologue2);
   19566           5 :   CHECK_EQ(0, epilogue2);
   19567           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue2);
   19568           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue2);
   19569           5 :   CcTest::CollectAllGarbage();
   19570           5 :   CHECK_EQ(2, prologue1);
   19571           5 :   CHECK_EQ(2, epilogue1);
   19572           5 :   CHECK_EQ(1, prologue2);
   19573           5 :   CHECK_EQ(1, epilogue2);
   19574           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew,
   19575           5 :                                                   &prologue1);
   19576           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew,
   19577           5 :                                                   &epilogue1);
   19578           5 :   CcTest::CollectAllGarbage();
   19579           5 :   CHECK_EQ(2, prologue1);
   19580           5 :   CHECK_EQ(2, epilogue1);
   19581           5 :   CHECK_EQ(2, prologue2);
   19582           5 :   CHECK_EQ(2, epilogue2);
   19583           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew,
   19584           5 :                                                   &prologue2);
   19585           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew,
   19586           5 :                                                   &epilogue2);
   19587           5 :   CcTest::CollectAllGarbage();
   19588           5 :   CHECK_EQ(2, prologue1);
   19589           5 :   CHECK_EQ(2, epilogue1);
   19590           5 :   CHECK_EQ(2, prologue2);
   19591           5 :   CHECK_EQ(2, epilogue2);
   19592           5 : }
   19593             : 
   19594       26644 : TEST(GCCallbacks) {
   19595           5 :   LocalContext context;
   19596           5 :   v8::Isolate* isolate = context->GetIsolate();
   19597           5 :   gc_callbacks_isolate = isolate;
   19598           5 :   isolate->AddGCPrologueCallback(PrologueCallback);
   19599           5 :   isolate->AddGCEpilogueCallback(EpilogueCallback);
   19600           5 :   CHECK_EQ(0, prologue_call_count);
   19601           5 :   CHECK_EQ(0, epilogue_call_count);
   19602           5 :   CcTest::CollectAllGarbage();
   19603           5 :   CHECK_EQ(1, prologue_call_count);
   19604           5 :   CHECK_EQ(1, epilogue_call_count);
   19605           5 :   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
   19606           5 :   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
   19607           5 :   CcTest::CollectAllGarbage();
   19608           5 :   CHECK_EQ(2, prologue_call_count);
   19609           5 :   CHECK_EQ(2, epilogue_call_count);
   19610           5 :   CHECK_EQ(1, prologue_call_count_second);
   19611           5 :   CHECK_EQ(1, epilogue_call_count_second);
   19612           5 :   isolate->RemoveGCPrologueCallback(PrologueCallback);
   19613           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
   19614           5 :   CcTest::CollectAllGarbage();
   19615           5 :   CHECK_EQ(2, prologue_call_count);
   19616           5 :   CHECK_EQ(2, epilogue_call_count);
   19617           5 :   CHECK_EQ(2, prologue_call_count_second);
   19618           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19619           5 :   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
   19620           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   19621           5 :   CcTest::CollectAllGarbage();
   19622           5 :   CHECK_EQ(2, prologue_call_count);
   19623           5 :   CHECK_EQ(2, epilogue_call_count);
   19624           5 :   CHECK_EQ(2, prologue_call_count_second);
   19625           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19626             : 
   19627           5 :   CHECK_EQ(0, prologue_call_count_alloc);
   19628           5 :   CHECK_EQ(0, epilogue_call_count_alloc);
   19629           5 :   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
   19630           5 :   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
   19631           5 :   CcTest::PreciseCollectAllGarbage();
   19632           5 :   CHECK_EQ(1, prologue_call_count_alloc);
   19633           5 :   CHECK_EQ(1, epilogue_call_count_alloc);
   19634           5 :   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
   19635           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
   19636           5 : }
   19637             : 
   19638             : 
   19639       26645 : THREADED_TEST(TwoByteStringInOneByteCons) {
   19640             :   // See Chromium issue 47824.
   19641           6 :   LocalContext context;
   19642          12 :   v8::HandleScope scope(context->GetIsolate());
   19643             : 
   19644             :   const char* init_code =
   19645             :       "var str1 = 'abelspendabel';"
   19646             :       "var str2 = str1 + str1 + str1;"
   19647             :       "str2;";
   19648             :   Local<Value> result = CompileRun(init_code);
   19649             : 
   19650           6 :   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   19651           6 :   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   19652             : 
   19653           6 :   CHECK(result->IsString());
   19654             :   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   19655             :   int length = string->length();
   19656           6 :   CHECK(string->IsOneByteRepresentation());
   19657             : 
   19658           6 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
   19659           6 :   i::Handle<i::String> flat_string = i::String::Flatten(i_isolate, string);
   19660             : 
   19661           6 :   CHECK(string->IsOneByteRepresentation());
   19662           6 :   CHECK(flat_string->IsOneByteRepresentation());
   19663             : 
   19664             :   // Create external resource.
   19665           6 :   uint16_t* uc16_buffer = new uint16_t[length + 1];
   19666             : 
   19667           6 :   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   19668           6 :   uc16_buffer[length] = 0;
   19669             : 
   19670           6 :   TestResource resource(uc16_buffer);
   19671             : 
   19672           6 :   flat_string->MakeExternal(&resource);
   19673             : 
   19674           6 :   CHECK(flat_string->IsTwoByteRepresentation());
   19675             : 
   19676             :   // If the cons string has been short-circuited, skip the following checks.
   19677           6 :   if (!string.is_identical_to(flat_string)) {
   19678             :     // At this point, we should have a Cons string which is flat and one-byte,
   19679             :     // with a first half that is a two-byte string (although it only contains
   19680             :     // one-byte characters). This is a valid sequence of steps, and it can
   19681             :     // happen in real pages.
   19682           6 :     CHECK(string->IsOneByteRepresentation());
   19683             :     i::ConsString cons = i::ConsString::cast(*string);
   19684           6 :     CHECK_EQ(0, cons->second()->length());
   19685           6 :     CHECK(cons->first()->IsTwoByteRepresentation());
   19686             :   }
   19687             : 
   19688             :   // Check that some string operations work.
   19689             : 
   19690             :   // Atom RegExp.
   19691             :   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   19692          12 :   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   19693             : 
   19694             :   // Nonatom RegExp.
   19695             :   reresult = CompileRun("str2.match(/abe./g).length;");
   19696          12 :   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   19697             : 
   19698             :   reresult = CompileRun("str2.search(/bel/g);");
   19699          12 :   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   19700             : 
   19701             :   reresult = CompileRun("str2.search(/be./g);");
   19702          12 :   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   19703             : 
   19704             :   ExpectTrue("/bel/g.test(str2);");
   19705             : 
   19706             :   ExpectTrue("/be./g.test(str2);");
   19707             : 
   19708             :   reresult = CompileRun("/bel/g.exec(str2);");
   19709           6 :   CHECK(!reresult->IsNull());
   19710             : 
   19711             :   reresult = CompileRun("/be./g.exec(str2);");
   19712           6 :   CHECK(!reresult->IsNull());
   19713             : 
   19714           6 :   ExpectString("str2.substring(2, 10);", "elspenda");
   19715             : 
   19716           6 :   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   19717             : 
   19718           6 :   ExpectString("str2.charAt(2);", "e");
   19719             : 
   19720           6 :   ExpectObject("str2.indexOf('els');", indexof);
   19721             : 
   19722           6 :   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   19723             : 
   19724             :   reresult = CompileRun("str2.charCodeAt(2);");
   19725          12 :   CHECK_EQ(static_cast<int32_t>('e'),
   19726             :            reresult->Int32Value(context.local()).FromJust());
   19727             :   // This avoids the GC from trying to free stack allocated resources.
   19728             :   i::Handle<i::ExternalTwoByteString>::cast(flat_string)
   19729           6 :       ->SetResource(i_isolate, nullptr);
   19730           6 : }
   19731             : 
   19732             : 
   19733       26644 : TEST(ContainsOnlyOneByte) {
   19734           5 :   v8::V8::Initialize();
   19735           5 :   v8::Isolate* isolate = CcTest::isolate();
   19736          10 :   v8::HandleScope scope(isolate);
   19737             :   // Make a buffer long enough that it won't automatically be converted.
   19738             :   const int length = 512;
   19739             :   // Ensure word aligned assignment.
   19740             :   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   19741           5 :   std::unique_ptr<uintptr_t[]> aligned_contents(new uintptr_t[aligned_length]);
   19742             :   uint16_t* string_contents =
   19743             :       reinterpret_cast<uint16_t*>(aligned_contents.get());
   19744             :   // Set to contain only one byte.
   19745        5115 :   for (int i = 0; i < length-1; i++) {
   19746        2555 :     string_contents[i] = 0x41;
   19747             :   }
   19748           5 :   string_contents[length-1] = 0;
   19749             :   // Simple case.
   19750             :   Local<String> string =
   19751           5 :       String::NewExternalTwoByte(
   19752           5 :           isolate, new TestResource(string_contents, nullptr, false))
   19753             :           .ToLocalChecked();
   19754           5 :   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19755             :   // Counter example.
   19756           5 :   string = String::NewFromTwoByte(isolate, string_contents,
   19757             :                                   v8::NewStringType::kNormal)
   19758             :                .ToLocalChecked();
   19759           5 :   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   19760             :   // Test left right and balanced cons strings.
   19761           5 :   Local<String> base = v8_str("a");
   19762           5 :   Local<String> left = base;
   19763           5 :   Local<String> right = base;
   19764       10005 :   for (int i = 0; i < 1000; i++) {
   19765        5000 :     left = String::Concat(isolate, base, left);
   19766        5000 :     right = String::Concat(isolate, right, base);
   19767             :   }
   19768           5 :   Local<String> balanced = String::Concat(isolate, left, base);
   19769           5 :   balanced = String::Concat(isolate, balanced, right);
   19770           5 :   Local<String> cons_strings[] = {left, balanced, right};
   19771             :   Local<String> two_byte =
   19772           5 :       String::NewExternalTwoByte(
   19773           5 :           isolate, new TestResource(string_contents, nullptr, false))
   19774           5 :           .ToLocalChecked();
   19775             :   USE(two_byte); USE(cons_strings);
   19776          35 :   for (size_t i = 0; i < arraysize(cons_strings); i++) {
   19777             :     // Base assumptions.
   19778          15 :     string = cons_strings[i];
   19779          15 :     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   19780             :     // Test left and right concatentation.
   19781          15 :     string = String::Concat(isolate, two_byte, cons_strings[i]);
   19782          15 :     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19783          15 :     string = String::Concat(isolate, cons_strings[i], two_byte);
   19784          15 :     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19785             :   }
   19786             :   // Set bits in different positions
   19787             :   // for strings of different lengths and alignments.
   19788          75 :   for (int alignment = 0; alignment < 7; alignment++) {
   19789         595 :     for (int size = 2; alignment + size < length; size *= 2) {
   19790             :       int zero_offset = size + alignment;
   19791         280 :       string_contents[zero_offset] = 0;
   19792       35980 :       for (int i = 0; i < size; i++) {
   19793       17850 :         int shift = 8 + (i % 7);
   19794       17850 :         string_contents[alignment + i] = 1 << shift;
   19795       17850 :         string = String::NewExternalTwoByte(
   19796             :                      isolate, new TestResource(string_contents + alignment,
   19797       17850 :                                                nullptr, false))
   19798             :                      .ToLocalChecked();
   19799       17850 :         CHECK_EQ(size, string->Length());
   19800       17850 :         CHECK(!string->ContainsOnlyOneByte());
   19801       17850 :         string_contents[alignment + i] = 0x41;
   19802             :       }
   19803         280 :       string_contents[zero_offset] = 0x41;
   19804             :     }
   19805             :   }
   19806           5 : }
   19807             : 
   19808             : 
   19809             : // Failed access check callback that performs a GC on each invocation.
   19810          75 : void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   19811             :                                  v8::AccessType type,
   19812             :                                  Local<v8::Value> data) {
   19813          75 :   CcTest::CollectAllGarbage();
   19814             :   CcTest::isolate()->ThrowException(
   19815          75 :       v8::Exception::Error(v8_str("cross context")));
   19816          75 : }
   19817             : 
   19818             : 
   19819       26644 : TEST(GCInFailedAccessCheckCallback) {
   19820             :   // Install a failed access check callback that performs a GC on each
   19821             :   // invocation. Then force the callback to be called from va
   19822             : 
   19823           5 :   v8::V8::Initialize();
   19824           5 :   v8::Isolate* isolate = CcTest::isolate();
   19825             : 
   19826           5 :   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   19827             : 
   19828          10 :   v8::HandleScope scope(isolate);
   19829             : 
   19830             :   // Create an ObjectTemplate for global objects and install access
   19831             :   // check callbacks that will block access.
   19832             :   v8::Local<v8::ObjectTemplate> global_template =
   19833           5 :       v8::ObjectTemplate::New(isolate);
   19834           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   19835             : 
   19836             :   // Create a context and set an x property on it's global object.
   19837           5 :   LocalContext context0(nullptr, global_template);
   19838          20 :   CHECK(context0->Global()
   19839             :             ->Set(context0.local(), v8_str("x"), v8_num(42))
   19840             :             .FromJust());
   19841           5 :   v8::Local<v8::Object> global0 = context0->Global();
   19842             : 
   19843             :   // Create a context with a different security token so that the
   19844             :   // failed access check callback will be called on each access.
   19845           5 :   LocalContext context1(nullptr, global_template);
   19846          20 :   CHECK(context1->Global()
   19847             :             ->Set(context1.local(), v8_str("other"), global0)
   19848             :             .FromJust());
   19849             : 
   19850          10 :   v8::TryCatch try_catch(isolate);
   19851             : 
   19852             :   // Get property with failed access check.
   19853           5 :   CHECK(CompileRun("other.x").IsEmpty());
   19854           5 :   CHECK(try_catch.HasCaught());
   19855           5 :   try_catch.Reset();
   19856             : 
   19857             :   // Get element with failed access check.
   19858           5 :   CHECK(CompileRun("other[0]").IsEmpty());
   19859           5 :   CHECK(try_catch.HasCaught());
   19860           5 :   try_catch.Reset();
   19861             : 
   19862             :   // Set property with failed access check.
   19863           5 :   CHECK(CompileRun("other.x = new Object()").IsEmpty());
   19864           5 :   CHECK(try_catch.HasCaught());
   19865           5 :   try_catch.Reset();
   19866             : 
   19867             :   // Set element with failed access check.
   19868           5 :   CHECK(CompileRun("other[0] = new Object()").IsEmpty());
   19869           5 :   CHECK(try_catch.HasCaught());
   19870           5 :   try_catch.Reset();
   19871             : 
   19872             :   // Get property attribute with failed access check.
   19873           5 :   CHECK(CompileRun("\'x\' in other").IsEmpty());
   19874           5 :   CHECK(try_catch.HasCaught());
   19875           5 :   try_catch.Reset();
   19876             : 
   19877             :   // Get property attribute for element with failed access check.
   19878           5 :   CHECK(CompileRun("0 in other").IsEmpty());
   19879           5 :   CHECK(try_catch.HasCaught());
   19880           5 :   try_catch.Reset();
   19881             : 
   19882             :   // Delete property.
   19883           5 :   CHECK(CompileRun("delete other.x").IsEmpty());
   19884           5 :   CHECK(try_catch.HasCaught());
   19885           5 :   try_catch.Reset();
   19886             : 
   19887             :   // Delete element.
   19888          10 :   CHECK(global0->Delete(context1.local(), 0).IsNothing());
   19889           5 :   CHECK(try_catch.HasCaught());
   19890           5 :   try_catch.Reset();
   19891             : 
   19892             :   // DefineAccessor.
   19893          20 :   CHECK(global0
   19894             :             ->SetAccessor(context1.local(), v8_str("x"), GetXValue, nullptr,
   19895             :                           v8_str("x"))
   19896             :             .IsNothing());
   19897           5 :   CHECK(try_catch.HasCaught());
   19898           5 :   try_catch.Reset();
   19899             : 
   19900             :   // Define JavaScript accessor.
   19901           5 :   CHECK(CompileRun(
   19902             :             "Object.prototype.__defineGetter__.call("
   19903             :             "    other, \'x\', function() { return 42; })").IsEmpty());
   19904           5 :   CHECK(try_catch.HasCaught());
   19905           5 :   try_catch.Reset();
   19906             : 
   19907             :   // LookupAccessor.
   19908           5 :   CHECK(CompileRun(
   19909             :             "Object.prototype.__lookupGetter__.call("
   19910             :             "    other, \'x\')").IsEmpty());
   19911           5 :   CHECK(try_catch.HasCaught());
   19912           5 :   try_catch.Reset();
   19913             : 
   19914             :   // HasOwnElement.
   19915           5 :   CHECK(CompileRun(
   19916             :             "Object.prototype.hasOwnProperty.call("
   19917             :             "other, \'0\')").IsEmpty());
   19918           5 :   CHECK(try_catch.HasCaught());
   19919           5 :   try_catch.Reset();
   19920             : 
   19921          10 :   CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
   19922           5 :   CHECK(try_catch.HasCaught());
   19923           5 :   try_catch.Reset();
   19924             : 
   19925          15 :   CHECK(
   19926             :       global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
   19927           5 :   CHECK(try_catch.HasCaught());
   19928           5 :   try_catch.Reset();
   19929             : 
   19930          15 :   CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
   19931             :             .IsNothing());
   19932           5 :   CHECK(try_catch.HasCaught());
   19933           5 :   try_catch.Reset();
   19934             : 
   19935             :   // Reset the failed access check callback so it does not influence
   19936             :   // the other tests.
   19937           5 :   isolate->SetFailedAccessCheckCallbackFunction(nullptr);
   19938           5 : }
   19939             : 
   19940             : 
   19941       26644 : TEST(IsolateNewDispose) {
   19942           5 :   v8::Isolate* current_isolate = CcTest::isolate();
   19943             :   v8::Isolate::CreateParams create_params;
   19944           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19945           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19946           5 :   CHECK_NOT_NULL(isolate);
   19947           5 :   CHECK(current_isolate != isolate);
   19948           5 :   CHECK(current_isolate == CcTest::isolate());
   19949          10 :   CHECK(isolate->GetArrayBufferAllocator() == CcTest::array_buffer_allocator());
   19950             : 
   19951           5 :   isolate->SetFatalErrorHandler(StoringErrorCallback);
   19952           5 :   last_location = last_message = nullptr;
   19953           5 :   isolate->Dispose();
   19954           5 :   CHECK(!last_location);
   19955           5 :   CHECK(!last_message);
   19956           5 : }
   19957             : 
   19958             : 
   19959       26644 : UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   19960             :   v8::Isolate::CreateParams create_params;
   19961           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19962           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19963             :   {
   19964             :     v8::Isolate::Scope i_scope(isolate);
   19965          10 :     v8::HandleScope scope(isolate);
   19966           5 :     LocalContext context(isolate);
   19967             :     // Run something in this isolate.
   19968             :     ExpectTrue("true");
   19969           5 :     isolate->SetFatalErrorHandler(StoringErrorCallback);
   19970           5 :     last_location = last_message = nullptr;
   19971             :     // Still entered, should fail.
   19972           5 :     isolate->Dispose();
   19973           5 :     CHECK(last_location);
   19974           5 :     CHECK(last_message);
   19975             :   }
   19976           5 :   isolate->Dispose();
   19977           5 : }
   19978             : 
   19979             : 
   19980          40 : static void BreakArrayGuarantees(const char* script) {
   19981             :   v8::Isolate::CreateParams create_params;
   19982          40 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19983          40 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   19984          40 :   isolate1->Enter();
   19985             :   v8::Persistent<v8::Context> context1;
   19986             :   {
   19987          80 :     v8::HandleScope scope(isolate1);
   19988          80 :     context1.Reset(isolate1, Context::New(isolate1));
   19989             :   }
   19990             : 
   19991             :   {
   19992          80 :     v8::HandleScope scope(isolate1);
   19993             :     v8::Local<v8::Context> context =
   19994             :         v8::Local<v8::Context>::New(isolate1, context1);
   19995             :     v8::Context::Scope context_scope(context);
   19996             :     v8::internal::Isolate* i_isolate =
   19997             :         reinterpret_cast<v8::internal::Isolate*>(isolate1);
   19998          40 :     CHECK(i_isolate->IsNoElementsProtectorIntact());
   19999             :     // Run something in new isolate.
   20000             :     CompileRun(script);
   20001          40 :     CHECK(!i_isolate->IsNoElementsProtectorIntact());
   20002             :   }
   20003          40 :   isolate1->Exit();
   20004          40 :   isolate1->Dispose();
   20005          40 : }
   20006             : 
   20007             : 
   20008       26644 : TEST(VerifyArrayPrototypeGuarantees) {
   20009             :   // Break fast array hole handling by element changes.
   20010           5 :   BreakArrayGuarantees("[].__proto__[1] = 3;");
   20011           5 :   BreakArrayGuarantees("Object.prototype[3] = 'three';");
   20012           5 :   BreakArrayGuarantees("Array.prototype.push(1);");
   20013           5 :   BreakArrayGuarantees("Array.prototype.unshift(1);");
   20014             :   // Break fast array hole handling by changing length.
   20015           5 :   BreakArrayGuarantees("Array.prototype.length = 30;");
   20016             :   // Break fast array hole handling by prototype structure changes.
   20017           5 :   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
   20018             :   // By sending elements to dictionary mode.
   20019             :   BreakArrayGuarantees(
   20020             :       "Object.defineProperty(Array.prototype, 0, {"
   20021           5 :       "  get: function() { return 3; }});");
   20022             :   BreakArrayGuarantees(
   20023             :       "Object.defineProperty(Object.prototype, 0, {"
   20024           5 :       "  get: function() { return 3; }});");
   20025           5 : }
   20026             : 
   20027             : 
   20028       26644 : TEST(RunTwoIsolatesOnSingleThread) {
   20029             :   // Run isolate 1.
   20030             :   v8::Isolate::CreateParams create_params;
   20031           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20032           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   20033           5 :   isolate1->Enter();
   20034             :   v8::Persistent<v8::Context> context1;
   20035             :   {
   20036          10 :     v8::HandleScope scope(isolate1);
   20037          10 :     context1.Reset(isolate1, Context::New(isolate1));
   20038             :   }
   20039             : 
   20040             :   {
   20041          10 :     v8::HandleScope scope(isolate1);
   20042             :     v8::Local<v8::Context> context =
   20043             :         v8::Local<v8::Context>::New(isolate1, context1);
   20044             :     v8::Context::Scope context_scope(context);
   20045             :     // Run something in new isolate.
   20046             :     CompileRun("var foo = 'isolate 1';");
   20047           5 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20048             :   }
   20049             : 
   20050             :   // Run isolate 2.
   20051           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   20052             :   v8::Persistent<v8::Context> context2;
   20053             : 
   20054             :   {
   20055             :     v8::Isolate::Scope iscope(isolate2);
   20056          10 :     v8::HandleScope scope(isolate2);
   20057          10 :     context2.Reset(isolate2, Context::New(isolate2));
   20058             :     v8::Local<v8::Context> context =
   20059             :         v8::Local<v8::Context>::New(isolate2, context2);
   20060             :     v8::Context::Scope context_scope(context);
   20061             : 
   20062             :     // Run something in new isolate.
   20063             :     CompileRun("var foo = 'isolate 2';");
   20064           5 :     ExpectString("function f() { return foo; }; f()", "isolate 2");
   20065             :   }
   20066             : 
   20067             :   {
   20068          10 :     v8::HandleScope scope(isolate1);
   20069             :     v8::Local<v8::Context> context =
   20070             :         v8::Local<v8::Context>::New(isolate1, context1);
   20071             :     v8::Context::Scope context_scope(context);
   20072             :     // Now again in isolate 1
   20073           5 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20074             :   }
   20075             : 
   20076           5 :   isolate1->Exit();
   20077             : 
   20078             :   // Run some stuff in default isolate.
   20079             :   v8::Persistent<v8::Context> context_default;
   20080             :   {
   20081           5 :     v8::Isolate* isolate = CcTest::isolate();
   20082             :     v8::Isolate::Scope iscope(isolate);
   20083          10 :     v8::HandleScope scope(isolate);
   20084          10 :     context_default.Reset(isolate, Context::New(isolate));
   20085             :   }
   20086             : 
   20087             :   {
   20088          10 :     v8::HandleScope scope(CcTest::isolate());
   20089             :     v8::Local<v8::Context> context =
   20090           5 :         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   20091             :     v8::Context::Scope context_scope(context);
   20092             :     // Variables in other isolates should be not available, verify there
   20093             :     // is an exception.
   20094             :     ExpectTrue("function f() {"
   20095             :                "  try {"
   20096             :                "    foo;"
   20097             :                "    return false;"
   20098             :                "  } catch(e) {"
   20099             :                "    return true;"
   20100             :                "  }"
   20101             :                "};"
   20102             :                "var isDefaultIsolate = true;"
   20103             :                "f()");
   20104             :   }
   20105             : 
   20106           5 :   isolate1->Enter();
   20107             : 
   20108             :   {
   20109             :     v8::Isolate::Scope iscope(isolate2);
   20110          10 :     v8::HandleScope scope(isolate2);
   20111             :     v8::Local<v8::Context> context =
   20112             :         v8::Local<v8::Context>::New(isolate2, context2);
   20113             :     v8::Context::Scope context_scope(context);
   20114           5 :     ExpectString("function f() { return foo; }; f()", "isolate 2");
   20115             :   }
   20116             : 
   20117             :   {
   20118          10 :     v8::HandleScope scope(v8::Isolate::GetCurrent());
   20119             :     v8::Local<v8::Context> context =
   20120           5 :         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   20121             :     v8::Context::Scope context_scope(context);
   20122           5 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20123             :   }
   20124             : 
   20125             :   {
   20126             :     v8::Isolate::Scope iscope(isolate2);
   20127             :     context2.Reset();
   20128             :   }
   20129             : 
   20130             :   context1.Reset();
   20131           5 :   isolate1->Exit();
   20132             : 
   20133           5 :   isolate2->SetFatalErrorHandler(StoringErrorCallback);
   20134           5 :   last_location = last_message = nullptr;
   20135             : 
   20136           5 :   isolate1->Dispose();
   20137           5 :   CHECK(!last_location);
   20138           5 :   CHECK(!last_message);
   20139             : 
   20140           5 :   isolate2->Dispose();
   20141           5 :   CHECK(!last_location);
   20142           5 :   CHECK(!last_message);
   20143             : 
   20144             :   // Check that default isolate still runs.
   20145             :   {
   20146          10 :     v8::HandleScope scope(CcTest::isolate());
   20147             :     v8::Local<v8::Context> context =
   20148           5 :         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   20149             :     v8::Context::Scope context_scope(context);
   20150             :     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   20151             :   }
   20152           5 : }
   20153             : 
   20154             : 
   20155          20 : static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   20156             :   v8::Isolate::Scope isolate_scope(isolate);
   20157          39 :   v8::HandleScope scope(isolate);
   20158          20 :   LocalContext context(isolate);
   20159             :   i::ScopedVector<char> code(1024);
   20160             :   i::SNPrintF(code, "function fib(n) {"
   20161             :                     "  if (n <= 2) return 1;"
   20162             :                     "  return fib(n-1) + fib(n-2);"
   20163             :                     "}"
   20164          20 :                     "fib(%d)", limit);
   20165             :   Local<Value> value = CompileRun(code.start());
   20166          20 :   CHECK(value->IsNumber());
   20167          60 :   return static_cast<int>(value->NumberValue(context.local()).FromJust());
   20168             : }
   20169             : 
   20170           5 : class IsolateThread : public v8::base::Thread {
   20171             :  public:
   20172             :   explicit IsolateThread(int fib_limit)
   20173          10 :       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
   20174             : 
   20175          10 :   void Run() override {
   20176             :     v8::Isolate::CreateParams create_params;
   20177          10 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20178          10 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   20179          10 :     result_ = CalcFibonacci(isolate, fib_limit_);
   20180          10 :     isolate->Dispose();
   20181          10 :   }
   20182             : 
   20183             :   int result() { return result_; }
   20184             : 
   20185             :  private:
   20186             :   int fib_limit_;
   20187             :   int result_;
   20188             : };
   20189             : 
   20190             : 
   20191       26644 : TEST(MultipleIsolatesOnIndividualThreads) {
   20192             :   IsolateThread thread1(21);
   20193             :   IsolateThread thread2(12);
   20194             : 
   20195             :   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   20196           5 :   thread1.Start();
   20197           5 :   thread2.Start();
   20198             : 
   20199           5 :   int result1 = CalcFibonacci(CcTest::isolate(), 21);
   20200           5 :   int result2 = CalcFibonacci(CcTest::isolate(), 12);
   20201             : 
   20202           5 :   thread1.Join();
   20203           5 :   thread2.Join();
   20204             : 
   20205             :   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   20206             :   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   20207           5 :   CHECK_EQ(result1, 10946);
   20208           5 :   CHECK_EQ(result2, 144);
   20209           5 :   CHECK_EQ(result1, thread1.result());
   20210           5 :   CHECK_EQ(result2, thread2.result());
   20211           5 : }
   20212             : 
   20213             : 
   20214       26644 : TEST(IsolateDifferentContexts) {
   20215             :   v8::Isolate::CreateParams create_params;
   20216           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20217           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20218             :   Local<v8::Context> context;
   20219             :   {
   20220             :     v8::Isolate::Scope isolate_scope(isolate);
   20221          10 :     v8::HandleScope handle_scope(isolate);
   20222           5 :     context = v8::Context::New(isolate);
   20223             :     v8::Context::Scope context_scope(context);
   20224             :     Local<Value> v = CompileRun("2");
   20225           5 :     CHECK(v->IsNumber());
   20226          10 :     CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
   20227             :   }
   20228             :   {
   20229             :     v8::Isolate::Scope isolate_scope(isolate);
   20230          10 :     v8::HandleScope handle_scope(isolate);
   20231           5 :     context = v8::Context::New(isolate);
   20232             :     v8::Context::Scope context_scope(context);
   20233             :     Local<Value> v = CompileRun("22");
   20234           5 :     CHECK(v->IsNumber());
   20235          10 :     CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
   20236             :   }
   20237           5 :   isolate->Dispose();
   20238           5 : }
   20239             : 
   20240          20 : class InitDefaultIsolateThread : public v8::base::Thread {
   20241             :  public:
   20242             :   enum TestCase {
   20243             :     SetFatalHandler,
   20244             :     SetCounterFunction,
   20245             :     SetCreateHistogramFunction,
   20246             :     SetAddHistogramSampleFunction
   20247             :   };
   20248             : 
   20249             :   explicit InitDefaultIsolateThread(TestCase testCase)
   20250             :       : Thread(Options("InitDefaultIsolateThread")),
   20251             :         testCase_(testCase),
   20252          20 :         result_(false) {}
   20253             : 
   20254          20 :   void Run() override {
   20255             :     v8::Isolate::CreateParams create_params;
   20256          20 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20257          20 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   20258          20 :     isolate->Enter();
   20259          20 :     switch (testCase_) {
   20260             :       case SetFatalHandler:
   20261           5 :         isolate->SetFatalErrorHandler(nullptr);
   20262           5 :         break;
   20263             : 
   20264             :       case SetCounterFunction:
   20265           5 :         CcTest::isolate()->SetCounterFunction(nullptr);
   20266           5 :         break;
   20267             : 
   20268             :       case SetCreateHistogramFunction:
   20269           5 :         CcTest::isolate()->SetCreateHistogramFunction(nullptr);
   20270           5 :         break;
   20271             : 
   20272             :       case SetAddHistogramSampleFunction:
   20273           5 :         CcTest::isolate()->SetAddHistogramSampleFunction(nullptr);
   20274           5 :         break;
   20275             :     }
   20276          20 :     isolate->Exit();
   20277          20 :     isolate->Dispose();
   20278          20 :     result_ = true;
   20279          20 :   }
   20280             : 
   20281             :   bool result() { return result_; }
   20282             : 
   20283             :  private:
   20284             :   TestCase testCase_;
   20285             :   bool result_;
   20286             : };
   20287             : 
   20288             : 
   20289          20 : static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   20290             :   InitDefaultIsolateThread thread(testCase);
   20291          20 :   thread.Start();
   20292          20 :   thread.Join();
   20293          20 :   CHECK(thread.result());
   20294          20 : }
   20295             : 
   20296       26644 : TEST(InitializeDefaultIsolateOnSecondaryThread_FatalHandler) {
   20297           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   20298           5 : }
   20299             : 
   20300       26644 : TEST(InitializeDefaultIsolateOnSecondaryThread_CounterFunction) {
   20301           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   20302           5 : }
   20303             : 
   20304       26644 : TEST(InitializeDefaultIsolateOnSecondaryThread_CreateHistogramFunction) {
   20305           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   20306           5 : }
   20307             : 
   20308       26644 : TEST(InitializeDefaultIsolateOnSecondaryThread_AddHistogramSampleFunction) {
   20309           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   20310           5 : }
   20311             : 
   20312             : 
   20313       26644 : TEST(StringCheckMultipleContexts) {
   20314             :   const char* code =
   20315             :       "(function() { return \"a\".charAt(0); })()";
   20316             : 
   20317             :   {
   20318             :     // Run the code twice in the first context to initialize the call IC.
   20319           5 :     LocalContext context1;
   20320          10 :     v8::HandleScope scope(context1->GetIsolate());
   20321           5 :     ExpectString(code, "a");
   20322           5 :     ExpectString(code, "a");
   20323             :   }
   20324             : 
   20325             :   {
   20326             :     // Change the String.prototype in the second context and check
   20327             :     // that the right function gets called.
   20328           5 :     LocalContext context2;
   20329          10 :     v8::HandleScope scope(context2->GetIsolate());
   20330             :     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   20331           5 :     ExpectString(code, "not a");
   20332             :   }
   20333           5 : }
   20334             : 
   20335             : 
   20336       26644 : TEST(NumberCheckMultipleContexts) {
   20337             :   const char* code =
   20338             :       "(function() { return (42).toString(); })()";
   20339             : 
   20340             :   {
   20341             :     // Run the code twice in the first context to initialize the call IC.
   20342           5 :     LocalContext context1;
   20343          10 :     v8::HandleScope scope(context1->GetIsolate());
   20344           5 :     ExpectString(code, "42");
   20345           5 :     ExpectString(code, "42");
   20346             :   }
   20347             : 
   20348             :   {
   20349             :     // Change the Number.prototype in the second context and check
   20350             :     // that the right function gets called.
   20351           5 :     LocalContext context2;
   20352          10 :     v8::HandleScope scope(context2->GetIsolate());
   20353             :     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   20354           5 :     ExpectString(code, "not 42");
   20355             :   }
   20356           5 : }
   20357             : 
   20358             : 
   20359       26644 : TEST(BooleanCheckMultipleContexts) {
   20360             :   const char* code =
   20361             :       "(function() { return true.toString(); })()";
   20362             : 
   20363             :   {
   20364             :     // Run the code twice in the first context to initialize the call IC.
   20365           5 :     LocalContext context1;
   20366          10 :     v8::HandleScope scope(context1->GetIsolate());
   20367           5 :     ExpectString(code, "true");
   20368           5 :     ExpectString(code, "true");
   20369             :   }
   20370             : 
   20371             :   {
   20372             :     // Change the Boolean.prototype in the second context and check
   20373             :     // that the right function gets called.
   20374           5 :     LocalContext context2;
   20375          10 :     v8::HandleScope scope(context2->GetIsolate());
   20376             :     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   20377           5 :     ExpectString(code, "");
   20378             :   }
   20379           5 : }
   20380             : 
   20381             : 
   20382       26644 : TEST(DontDeleteCellLoadIC) {
   20383             :   const char* function_code =
   20384             :       "function readCell() { while (true) { return cell; } }";
   20385             : 
   20386             :   {
   20387             :     // Run the code twice in the first context to initialize the load
   20388             :     // IC for a don't delete cell.
   20389           5 :     LocalContext context1;
   20390          10 :     v8::HandleScope scope(context1->GetIsolate());
   20391             :     CompileRun("var cell = \"first\";");
   20392           5 :     ExpectBoolean("delete cell", false);
   20393             :     CompileRun(function_code);
   20394           5 :     ExpectString("readCell()", "first");
   20395           5 :     ExpectString("readCell()", "first");
   20396             :   }
   20397             : 
   20398             :   {
   20399             :     // Use a deletable cell in the second context.
   20400           5 :     LocalContext context2;
   20401          10 :     v8::HandleScope scope(context2->GetIsolate());
   20402             :     CompileRun("cell = \"second\";");
   20403             :     CompileRun(function_code);
   20404           5 :     ExpectString("readCell()", "second");
   20405           5 :     ExpectBoolean("delete cell", true);
   20406             :     ExpectString("(function() {"
   20407             :                  "  try {"
   20408             :                  "    return readCell();"
   20409             :                  "  } catch(e) {"
   20410             :                  "    return e.toString();"
   20411             :                  "  }"
   20412             :                  "})()",
   20413           5 :                  "ReferenceError: cell is not defined");
   20414             :     CompileRun("cell = \"new_second\";");
   20415           5 :     CcTest::CollectAllGarbage();
   20416           5 :     ExpectString("readCell()", "new_second");
   20417           5 :     ExpectString("readCell()", "new_second");
   20418             :   }
   20419           5 : }
   20420             : 
   20421             : 
   20422          10 : class Visitor42 : public v8::PersistentHandleVisitor {
   20423             :  public:
   20424             :   explicit Visitor42(v8::Persistent<v8::Object>* object)
   20425           5 :       : counter_(0), object_(object) { }
   20426             : 
   20427           5 :   void VisitPersistentHandle(Persistent<Value>* value,
   20428             :                              uint16_t class_id) override {
   20429           5 :     if (class_id != 42) return;
   20430           5 :     CHECK_EQ(42, value->WrapperClassId());
   20431           5 :     v8::Isolate* isolate = CcTest::isolate();
   20432          10 :     v8::HandleScope handle_scope(isolate);
   20433             :     v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   20434           5 :     v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
   20435           5 :     CHECK(handle->IsObject());
   20436          10 :     CHECK(Local<Object>::Cast(handle)
   20437             :               ->Equals(isolate->GetCurrentContext(), object)
   20438             :               .FromJust());
   20439           5 :     ++counter_;
   20440             :   }
   20441             : 
   20442             :   int counter_;
   20443             :   v8::Persistent<v8::Object>* object_;
   20444             : };
   20445             : 
   20446             : 
   20447       26644 : TEST(PersistentHandleVisitor) {
   20448           5 :   LocalContext context;
   20449           5 :   v8::Isolate* isolate = context->GetIsolate();
   20450          10 :   v8::HandleScope scope(isolate);
   20451           5 :   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   20452           5 :   CHECK_EQ(0, object.WrapperClassId());
   20453             :   object.SetWrapperClassId(42);
   20454           5 :   CHECK_EQ(42, object.WrapperClassId());
   20455             : 
   20456             :   Visitor42 visitor(&object);
   20457           5 :   isolate->VisitHandlesWithClassIds(&visitor);
   20458           5 :   CHECK_EQ(1, visitor.counter_);
   20459             : 
   20460             :   object.Reset();
   20461           5 : }
   20462             : 
   20463             : 
   20464       26644 : TEST(WrapperClassId) {
   20465           5 :   LocalContext context;
   20466           5 :   v8::Isolate* isolate = context->GetIsolate();
   20467          10 :   v8::HandleScope scope(isolate);
   20468           5 :   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   20469           5 :   CHECK_EQ(0, object.WrapperClassId());
   20470             :   object.SetWrapperClassId(65535);
   20471           5 :   CHECK_EQ(65535, object.WrapperClassId());
   20472             :   object.Reset();
   20473           5 : }
   20474             : 
   20475       26644 : TEST(RegExp) {
   20476           5 :   LocalContext context;
   20477          10 :   v8::HandleScope scope(context->GetIsolate());
   20478             : 
   20479             :   v8::Local<v8::RegExp> re =
   20480          10 :       v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
   20481             :           .ToLocalChecked();
   20482           5 :   CHECK(re->IsRegExp());
   20483          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
   20484           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20485             : 
   20486           5 :   re = v8::RegExp::New(context.local(), v8_str("bar"),
   20487             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20488           5 :                                                       v8::RegExp::kGlobal))
   20489             :            .ToLocalChecked();
   20490           5 :   CHECK(re->IsRegExp());
   20491          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
   20492           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   20493             :            static_cast<int>(re->GetFlags()));
   20494             : 
   20495           5 :   re = v8::RegExp::New(context.local(), v8_str("baz"),
   20496             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20497           5 :                                                       v8::RegExp::kMultiline))
   20498             :            .ToLocalChecked();
   20499           5 :   CHECK(re->IsRegExp());
   20500          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   20501           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   20502             :            static_cast<int>(re->GetFlags()));
   20503             : 
   20504           5 :   re = v8::RegExp::New(context.local(), v8_str("baz"),
   20505             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
   20506           5 :                                                       v8::RegExp::kSticky))
   20507             :            .ToLocalChecked();
   20508           5 :   CHECK(re->IsRegExp());
   20509          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   20510           5 :   CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
   20511             :            static_cast<int>(re->GetFlags()));
   20512             : 
   20513             :   re = CompileRun("/quux/").As<v8::RegExp>();
   20514           5 :   CHECK(re->IsRegExp());
   20515          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   20516           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20517             : 
   20518             :   re = CompileRun("/quux/gm").As<v8::RegExp>();
   20519           5 :   CHECK(re->IsRegExp());
   20520          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   20521           5 :   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   20522             :            static_cast<int>(re->GetFlags()));
   20523             : 
   20524             :   // Override the RegExp constructor and check the API constructor
   20525             :   // still works.
   20526             :   CompileRun("RegExp = function() {}");
   20527             : 
   20528          10 :   re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
   20529             :            .ToLocalChecked();
   20530           5 :   CHECK(re->IsRegExp());
   20531          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
   20532           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20533             : 
   20534           5 :   re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
   20535             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20536           5 :                                                       v8::RegExp::kMultiline))
   20537             :            .ToLocalChecked();
   20538           5 :   CHECK(re->IsRegExp());
   20539          20 :   CHECK(
   20540             :       re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
   20541           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   20542             :            static_cast<int>(re->GetFlags()));
   20543             : 
   20544          20 :   CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
   20545             :   ExpectTrue("re.test('FoobarbaZ')");
   20546             : 
   20547             :   // RegExps are objects on which you can set properties.
   20548          10 :   re->Set(context.local(), v8_str("property"),
   20549          15 :           v8::Integer::New(context->GetIsolate(), 32))
   20550             :       .FromJust();
   20551             :   v8::Local<v8::Value> value(CompileRun("re.property"));
   20552          10 :   CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
   20553             : 
   20554          10 :   v8::TryCatch try_catch(context->GetIsolate());
   20555          15 :   CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
   20556             :             .IsEmpty());
   20557           5 :   CHECK(try_catch.HasCaught());
   20558          20 :   CHECK(context->Global()
   20559             :             ->Set(context.local(), v8_str("ex"), try_catch.Exception())
   20560             :             .FromJust());
   20561             :   ExpectTrue("ex instanceof SyntaxError");
   20562           5 : }
   20563             : 
   20564             : 
   20565       26645 : THREADED_TEST(Equals) {
   20566           6 :   LocalContext localContext;
   20567          12 :   v8::HandleScope handleScope(localContext->GetIsolate());
   20568             : 
   20569           6 :   v8::Local<v8::Object> globalProxy = localContext->Global();
   20570           6 :   v8::Local<Value> global = globalProxy->GetPrototype();
   20571             : 
   20572           6 :   CHECK(global->StrictEquals(global));
   20573           6 :   CHECK(!global->StrictEquals(globalProxy));
   20574           6 :   CHECK(!globalProxy->StrictEquals(global));
   20575           6 :   CHECK(globalProxy->StrictEquals(globalProxy));
   20576             : 
   20577          12 :   CHECK(global->Equals(localContext.local(), global).FromJust());
   20578          12 :   CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
   20579          12 :   CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
   20580          12 :   CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
   20581           6 : }
   20582             : 
   20583             : 
   20584           5 : static void Getter(v8::Local<v8::Name> property,
   20585             :                    const v8::PropertyCallbackInfo<v8::Value>& info) {
   20586           5 :   info.GetReturnValue().Set(v8_str("42!"));
   20587           5 : }
   20588             : 
   20589             : 
   20590           5 : static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   20591           5 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
   20592          10 :   result->Set(info.GetIsolate()->GetCurrentContext(), 0,
   20593          15 :               v8_str("universalAnswer"))
   20594             :       .FromJust();
   20595             :   info.GetReturnValue().Set(result);
   20596           5 : }
   20597             : 
   20598             : 
   20599       26644 : TEST(NamedEnumeratorAndForIn) {
   20600           5 :   LocalContext context;
   20601           5 :   v8::Isolate* isolate = context->GetIsolate();
   20602          10 :   v8::HandleScope handle_scope(isolate);
   20603             :   v8::Context::Scope context_scope(context.local());
   20604             : 
   20605           5 :   v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
   20606           5 :   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20607           5 :       Getter, nullptr, nullptr, nullptr, Enumerator));
   20608          25 :   CHECK(context->Global()
   20609             :             ->Set(context.local(), v8_str("o"),
   20610             :                   tmpl->NewInstance(context.local()).ToLocalChecked())
   20611             :             .FromJust());
   20612             :   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
   20613             :       CompileRun("var result = []; for (var k in o) result.push(k); result"));
   20614           5 :   CHECK_EQ(1u, result->Length());
   20615          20 :   CHECK(v8_str("universalAnswer")
   20616             :             ->Equals(context.local(),
   20617             :                      result->Get(context.local(), 0).ToLocalChecked())
   20618             :             .FromJust());
   20619           5 : }
   20620             : 
   20621             : 
   20622       26644 : TEST(DefinePropertyPostDetach) {
   20623           5 :   LocalContext context;
   20624          10 :   v8::HandleScope scope(context->GetIsolate());
   20625           5 :   v8::Local<v8::Object> proxy = context->Global();
   20626             :   v8::Local<v8::Function> define_property =
   20627             :       CompileRun(
   20628             :           "(function() {"
   20629             :           "  Object.defineProperty("
   20630             :           "    this,"
   20631             :           "    1,"
   20632             :           "    { configurable: true, enumerable: true, value: 3 });"
   20633             :           "})")
   20634             :           .As<Function>();
   20635           5 :   context->DetachGlobal();
   20636          10 :   CHECK(define_property->Call(context.local(), proxy, 0, nullptr).IsEmpty());
   20637           5 : }
   20638             : 
   20639             : 
   20640          36 : static void InstallContextId(v8::Local<Context> context, int id) {
   20641             :   Context::Scope scope(context);
   20642         144 :   CHECK(CompileRun("Object.prototype")
   20643             :             .As<Object>()
   20644             :             ->Set(context, v8_str("context_id"),
   20645             :                   v8::Integer::New(context->GetIsolate(), id))
   20646             :             .FromJust());
   20647          36 : }
   20648             : 
   20649             : 
   20650         126 : static void CheckContextId(v8::Local<Object> object, int expected) {
   20651         126 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   20652         504 :   CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
   20653             :                          .ToLocalChecked()
   20654             :                          ->Int32Value(context)
   20655             :                          .FromJust());
   20656         126 : }
   20657             : 
   20658             : 
   20659       26645 : THREADED_TEST(CreationContext) {
   20660           6 :   v8::Isolate* isolate = CcTest::isolate();
   20661          12 :   HandleScope handle_scope(isolate);
   20662           6 :   Local<Context> context1 = Context::New(isolate);
   20663           6 :   InstallContextId(context1, 1);
   20664           6 :   Local<Context> context2 = Context::New(isolate);
   20665           6 :   InstallContextId(context2, 2);
   20666           6 :   Local<Context> context3 = Context::New(isolate);
   20667           6 :   InstallContextId(context3, 3);
   20668             : 
   20669           6 :   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
   20670             : 
   20671             :   Local<Object> object1;
   20672             :   Local<Function> func1;
   20673             :   {
   20674             :     Context::Scope scope(context1);
   20675           6 :     object1 = Object::New(isolate);
   20676           6 :     func1 = tmpl->GetFunction(context1).ToLocalChecked();
   20677             :   }
   20678             : 
   20679             :   Local<Object> object2;
   20680             :   Local<Function> func2;
   20681             :   {
   20682             :     Context::Scope scope(context2);
   20683           6 :     object2 = Object::New(isolate);
   20684           6 :     func2 = tmpl->GetFunction(context2).ToLocalChecked();
   20685             :   }
   20686             : 
   20687             :   Local<Object> instance1;
   20688             :   Local<Object> instance2;
   20689             : 
   20690             :   {
   20691             :     Context::Scope scope(context3);
   20692             :     instance1 = func1->NewInstance(context3).ToLocalChecked();
   20693             :     instance2 = func2->NewInstance(context3).ToLocalChecked();
   20694             :   }
   20695             : 
   20696             :   {
   20697           6 :     Local<Context> other_context = Context::New(isolate);
   20698             :     Context::Scope scope(other_context);
   20699          12 :     CHECK(object1->CreationContext() == context1);
   20700           6 :     CheckContextId(object1, 1);
   20701          12 :     CHECK(func1->CreationContext() == context1);
   20702           6 :     CheckContextId(func1, 1);
   20703          12 :     CHECK(instance1->CreationContext() == context1);
   20704           6 :     CheckContextId(instance1, 1);
   20705          12 :     CHECK(object2->CreationContext() == context2);
   20706           6 :     CheckContextId(object2, 2);
   20707          12 :     CHECK(func2->CreationContext() == context2);
   20708           6 :     CheckContextId(func2, 2);
   20709          12 :     CHECK(instance2->CreationContext() == context2);
   20710           6 :     CheckContextId(instance2, 2);
   20711             :   }
   20712             : 
   20713             :   {
   20714             :     Context::Scope scope(context1);
   20715          12 :     CHECK(object1->CreationContext() == context1);
   20716           6 :     CheckContextId(object1, 1);
   20717          12 :     CHECK(func1->CreationContext() == context1);
   20718           6 :     CheckContextId(func1, 1);
   20719          12 :     CHECK(instance1->CreationContext() == context1);
   20720           6 :     CheckContextId(instance1, 1);
   20721          12 :     CHECK(object2->CreationContext() == context2);
   20722           6 :     CheckContextId(object2, 2);
   20723          12 :     CHECK(func2->CreationContext() == context2);
   20724           6 :     CheckContextId(func2, 2);
   20725          12 :     CHECK(instance2->CreationContext() == context2);
   20726           6 :     CheckContextId(instance2, 2);
   20727             :   }
   20728             : 
   20729             :   {
   20730             :     Context::Scope scope(context2);
   20731          12 :     CHECK(object1->CreationContext() == context1);
   20732           6 :     CheckContextId(object1, 1);
   20733          12 :     CHECK(func1->CreationContext() == context1);
   20734           6 :     CheckContextId(func1, 1);
   20735          12 :     CHECK(instance1->CreationContext() == context1);
   20736           6 :     CheckContextId(instance1, 1);
   20737          12 :     CHECK(object2->CreationContext() == context2);
   20738           6 :     CheckContextId(object2, 2);
   20739          12 :     CHECK(func2->CreationContext() == context2);
   20740           6 :     CheckContextId(func2, 2);
   20741          12 :     CHECK(instance2->CreationContext() == context2);
   20742           6 :     CheckContextId(instance2, 2);
   20743             :   }
   20744           6 : }
   20745             : 
   20746             : 
   20747       26645 : THREADED_TEST(CreationContextOfJsFunction) {
   20748          12 :   HandleScope handle_scope(CcTest::isolate());
   20749           6 :   Local<Context> context = Context::New(CcTest::isolate());
   20750           6 :   InstallContextId(context, 1);
   20751             : 
   20752             :   Local<Object> function;
   20753             :   {
   20754             :     Context::Scope scope(context);
   20755             :     function = CompileRun("function foo() {}; foo").As<Object>();
   20756             :   }
   20757             : 
   20758           6 :   Local<Context> other_context = Context::New(CcTest::isolate());
   20759             :   Context::Scope scope(other_context);
   20760          12 :   CHECK(function->CreationContext() == context);
   20761           6 :   CheckContextId(function, 1);
   20762           6 : }
   20763             : 
   20764             : 
   20765       26645 : THREADED_TEST(CreationContextOfJsBoundFunction) {
   20766          12 :   HandleScope handle_scope(CcTest::isolate());
   20767           6 :   Local<Context> context1 = Context::New(CcTest::isolate());
   20768           6 :   InstallContextId(context1, 1);
   20769           6 :   Local<Context> context2 = Context::New(CcTest::isolate());
   20770           6 :   InstallContextId(context2, 2);
   20771             : 
   20772             :   Local<Function> target_function;
   20773             :   {
   20774             :     Context::Scope scope(context1);
   20775             :     target_function = CompileRun("function foo() {}; foo").As<Function>();
   20776             :   }
   20777             : 
   20778             :   Local<Function> bound_function1, bound_function2;
   20779             :   {
   20780             :     Context::Scope scope(context2);
   20781          24 :     CHECK(context2->Global()
   20782             :               ->Set(context2, v8_str("foo"), target_function)
   20783             :               .FromJust());
   20784             :     bound_function1 = CompileRun("foo.bind(1)").As<Function>();
   20785             :     bound_function2 =
   20786             :         CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
   20787             :   }
   20788             : 
   20789           6 :   Local<Context> other_context = Context::New(CcTest::isolate());
   20790             :   Context::Scope scope(other_context);
   20791          12 :   CHECK(bound_function1->CreationContext() == context1);
   20792           6 :   CheckContextId(bound_function1, 1);
   20793          12 :   CHECK(bound_function2->CreationContext() == context1);
   20794           6 :   CheckContextId(bound_function2, 1);
   20795           6 : }
   20796             : 
   20797             : 
   20798          20 : void HasOwnPropertyIndexedPropertyGetter(
   20799             :     uint32_t index,
   20800             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20801          20 :   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   20802          20 : }
   20803             : 
   20804             : 
   20805          10 : void HasOwnPropertyNamedPropertyGetter(
   20806             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   20807          40 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   20808             :           .FromJust()) {
   20809           5 :     info.GetReturnValue().Set(v8_str("yes"));
   20810             :   }
   20811          10 : }
   20812             : 
   20813             : 
   20814          50 : void HasOwnPropertyIndexedPropertyQuery(
   20815             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20816          50 :   if (index == 42) info.GetReturnValue().Set(1);
   20817          50 : }
   20818             : 
   20819             : 
   20820          10 : void HasOwnPropertyNamedPropertyQuery(
   20821             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20822          40 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   20823             :           .FromJust()) {
   20824             :     info.GetReturnValue().Set(1);
   20825             :   }
   20826          10 : }
   20827             : 
   20828             : 
   20829          10 : void HasOwnPropertyNamedPropertyQuery2(
   20830             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20831          40 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
   20832             :           .FromJust()) {
   20833             :     info.GetReturnValue().Set(1);
   20834             :   }
   20835          10 : }
   20836             : 
   20837           0 : void HasOwnPropertyAccessorGetter(
   20838             :     Local<String> property,
   20839             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20840           0 :   info.GetReturnValue().Set(v8_str("yes"));
   20841           0 : }
   20842             : 
   20843           5 : void HasOwnPropertyAccessorNameGetter(
   20844             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   20845           5 :   info.GetReturnValue().Set(v8_str("yes"));
   20846           5 : }
   20847             : 
   20848       26644 : TEST(HasOwnProperty) {
   20849           5 :   LocalContext env;
   20850           5 :   v8::Isolate* isolate = env->GetIsolate();
   20851          10 :   v8::HandleScope scope(isolate);
   20852             :   { // Check normal properties and defined getters.
   20853             :     Local<Value> value = CompileRun(
   20854             :         "function Foo() {"
   20855             :         "    this.foo = 11;"
   20856             :         "    this.__defineGetter__('baz', function() { return 1; });"
   20857             :         "};"
   20858             :         "function Bar() { "
   20859             :         "    this.bar = 13;"
   20860             :         "    this.__defineGetter__('bla', function() { return 2; });"
   20861             :         "};"
   20862             :         "Bar.prototype = new Foo();"
   20863             :         "new Bar();");
   20864           5 :     CHECK(value->IsObject());
   20865           5 :     Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
   20866          15 :     CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
   20867          15 :     CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20868          15 :     CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20869          15 :     CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
   20870          15 :     CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
   20871          15 :     CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
   20872             :   }
   20873             :   { // Check named getter interceptors.
   20874           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20875           5 :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20876           5 :         HasOwnPropertyNamedPropertyGetter));
   20877           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20878          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20879          10 :     CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
   20880          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20881          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20882             :   }
   20883             :   { // Check indexed getter interceptors.
   20884           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20885           5 :     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   20886           5 :         HasOwnPropertyIndexedPropertyGetter));
   20887           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20888          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20889          10 :     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   20890          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
   20891          10 :     CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
   20892          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20893             :   }
   20894             :   { // Check named query interceptors.
   20895           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20896           5 :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20897           5 :         nullptr, nullptr, HasOwnPropertyNamedPropertyQuery));
   20898           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20899          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20900          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20901             :   }
   20902             :   { // Check indexed query interceptors.
   20903           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20904           5 :     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   20905           5 :         nullptr, nullptr, HasOwnPropertyIndexedPropertyQuery));
   20906           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20907          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20908          10 :     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   20909          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
   20910          10 :     CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
   20911             :   }
   20912             :   { // Check callbacks.
   20913           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20914           5 :     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   20915           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20916          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20917          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20918             :   }
   20919             :   { // Check that query wins on disagreement.
   20920           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20921           5 :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20922             :         HasOwnPropertyNamedPropertyGetter, nullptr,
   20923           5 :         HasOwnPropertyNamedPropertyQuery2));
   20924           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20925          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20926          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20927             :   }
   20928             :   {  // Check that non-internalized keys are handled correctly.
   20929           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20930           5 :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20931           5 :         HasOwnPropertyAccessorNameGetter));
   20932           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20933          20 :     env->Global()->Set(env.local(), v8_str("obj"), instance).FromJust();
   20934             :     const char* src =
   20935             :         "var dyn_string = 'this string ';"
   20936             :         "dyn_string += 'does not exist elsewhere';"
   20937             :         "({}).hasOwnProperty.call(obj, dyn_string)";
   20938           5 :     CHECK(CompileRun(src)->BooleanValue(isolate));
   20939             :   }
   20940           5 : }
   20941             : 
   20942             : 
   20943       26644 : TEST(IndexedInterceptorWithStringProto) {
   20944           5 :   v8::Isolate* isolate = CcTest::isolate();
   20945          10 :   v8::HandleScope scope(isolate);
   20946           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20947           5 :   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   20948           5 :       nullptr, nullptr, HasOwnPropertyIndexedPropertyQuery));
   20949           5 :   LocalContext context;
   20950          25 :   CHECK(context->Global()
   20951             :             ->Set(context.local(), v8_str("obj"),
   20952             :                   templ->NewInstance(context.local()).ToLocalChecked())
   20953             :             .FromJust());
   20954             :   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   20955             :   // These should be intercepted.
   20956           5 :   CHECK(CompileRun("42 in obj")->BooleanValue(isolate));
   20957           5 :   CHECK(CompileRun("'42' in obj")->BooleanValue(isolate));
   20958             :   // These should fall through to the String prototype.
   20959           5 :   CHECK(CompileRun("0 in obj")->BooleanValue(isolate));
   20960           5 :   CHECK(CompileRun("'0' in obj")->BooleanValue(isolate));
   20961             :   // And these should both fail.
   20962           5 :   CHECK(!CompileRun("32 in obj")->BooleanValue(isolate));
   20963           5 :   CHECK(!CompileRun("'32' in obj")->BooleanValue(isolate));
   20964           5 : }
   20965             : 
   20966             : 
   20967          18 : void CheckCodeGenerationAllowed() {
   20968          18 :   Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   20969             :   Local<Value> result = CompileRun("eval('42')");
   20970          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   20971             :   result = CompileRun("(function(e) { return e('42'); })(eval)");
   20972          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   20973             :   result = CompileRun("var f = new Function('return 42'); f()");
   20974          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   20975          18 : }
   20976             : 
   20977             : 
   20978          12 : void CheckCodeGenerationDisallowed() {
   20979          24 :   TryCatch try_catch(CcTest::isolate());
   20980             : 
   20981             :   Local<Value> result = CompileRun("eval('42')");
   20982          12 :   CHECK(result.IsEmpty());
   20983          12 :   CHECK(try_catch.HasCaught());
   20984          12 :   try_catch.Reset();
   20985             : 
   20986             :   result = CompileRun("(function(e) { return e('42'); })(eval)");
   20987          12 :   CHECK(result.IsEmpty());
   20988          12 :   CHECK(try_catch.HasCaught());
   20989          12 :   try_catch.Reset();
   20990             : 
   20991             :   result = CompileRun("var f = new Function('return 42'); f()");
   20992          12 :   CHECK(result.IsEmpty());
   20993          12 :   CHECK(try_catch.HasCaught());
   20994          12 : }
   20995             : 
   20996             : char first_fourty_bytes[41];
   20997             : 
   20998          23 : bool CodeGenerationAllowed(Local<Context> context, Local<String> source) {
   20999          46 :   String::Utf8Value str(CcTest::isolate(), source);
   21000             :   size_t len = std::min(sizeof(first_fourty_bytes) - 1,
   21001          46 :                         static_cast<size_t>(str.length()));
   21002             :   strncpy(first_fourty_bytes, *str, len);
   21003          23 :   first_fourty_bytes[len] = 0;
   21004          23 :   ApiTestFuzzer::Fuzz();
   21005          23 :   return true;
   21006             : }
   21007             : 
   21008          23 : bool CodeGenerationDisallowed(Local<Context> context, Local<String> source) {
   21009          23 :   ApiTestFuzzer::Fuzz();
   21010          23 :   return false;
   21011             : }
   21012             : 
   21013             : 
   21014       26645 : THREADED_TEST(AllowCodeGenFromStrings) {
   21015           6 :   LocalContext context;
   21016          12 :   v8::HandleScope scope(context->GetIsolate());
   21017             : 
   21018             :   // eval and the Function constructor allowed by default.
   21019           6 :   CHECK(context->IsCodeGenerationFromStringsAllowed());
   21020           6 :   CheckCodeGenerationAllowed();
   21021             : 
   21022             :   // Disallow eval and the Function constructor.
   21023           6 :   context->AllowCodeGenerationFromStrings(false);
   21024           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21025           6 :   CheckCodeGenerationDisallowed();
   21026             : 
   21027             :   // Allow again.
   21028           6 :   context->AllowCodeGenerationFromStrings(true);
   21029           6 :   CheckCodeGenerationAllowed();
   21030             : 
   21031             :   // Disallow but setting a global callback that will allow the calls.
   21032           6 :   context->AllowCodeGenerationFromStrings(false);
   21033           6 :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21034           6 :       &CodeGenerationAllowed);
   21035           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21036           6 :   CheckCodeGenerationAllowed();
   21037             : 
   21038             :   // Set a callback that disallows the code generation.
   21039           6 :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21040           6 :       &CodeGenerationDisallowed);
   21041           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21042           6 :   CheckCodeGenerationDisallowed();
   21043           6 : }
   21044             : 
   21045             : 
   21046       26644 : TEST(SetErrorMessageForCodeGenFromStrings) {
   21047           5 :   LocalContext context;
   21048          10 :   v8::HandleScope scope(context->GetIsolate());
   21049          10 :   TryCatch try_catch(context->GetIsolate());
   21050             : 
   21051           5 :   Local<String> message = v8_str("Message");
   21052           5 :   Local<String> expected_message = v8_str("Uncaught EvalError: Message");
   21053           5 :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21054           5 :       &CodeGenerationDisallowed);
   21055           5 :   context->AllowCodeGenerationFromStrings(false);
   21056           5 :   context->SetErrorMessageForCodeGenerationFromStrings(message);
   21057             :   Local<Value> result = CompileRun("eval('42')");
   21058           5 :   CHECK(result.IsEmpty());
   21059           5 :   CHECK(try_catch.HasCaught());
   21060          10 :   Local<String> actual_message = try_catch.Message()->Get();
   21061          10 :   CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
   21062           5 : }
   21063             : 
   21064       26644 : TEST(CaptureSourceForCodeGenFromStrings) {
   21065           5 :   LocalContext context;
   21066          10 :   v8::HandleScope scope(context->GetIsolate());
   21067          10 :   TryCatch try_catch(context->GetIsolate());
   21068             : 
   21069           5 :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21070           5 :       &CodeGenerationAllowed);
   21071           5 :   context->AllowCodeGenerationFromStrings(false);
   21072             :   CompileRun("eval('42')");
   21073           5 :   CHECK(!strcmp(first_fourty_bytes, "42"));
   21074           5 : }
   21075             : 
   21076           6 : static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21077           6 : }
   21078             : 
   21079             : 
   21080       26645 : THREADED_TEST(CallAPIFunctionOnNonObject) {
   21081           6 :   LocalContext context;
   21082           6 :   v8::Isolate* isolate = context->GetIsolate();
   21083          12 :   v8::HandleScope scope(isolate);
   21084             :   Local<FunctionTemplate> templ =
   21085           6 :       v8::FunctionTemplate::New(isolate, NonObjectThis);
   21086             :   Local<Function> function =
   21087           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   21088          24 :   CHECK(context->Global()
   21089             :             ->Set(context.local(), v8_str("f"), function)
   21090             :             .FromJust());
   21091          12 :   TryCatch try_catch(isolate);
   21092             :   CompileRun("f.call(2)");
   21093           6 : }
   21094             : 
   21095             : 
   21096             : // Regression test for issue 1470.
   21097       26645 : THREADED_TEST(ReadOnlyIndexedProperties) {
   21098           6 :   v8::Isolate* isolate = CcTest::isolate();
   21099          12 :   v8::HandleScope scope(isolate);
   21100           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21101             : 
   21102           6 :   LocalContext context;
   21103           6 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   21104          24 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   21105          12 :   obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
   21106          18 :                          v8::ReadOnly)
   21107             :       .FromJust();
   21108          24 :   obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
   21109          30 :   CHECK(v8_str("DONT_CHANGE")
   21110             :             ->Equals(context.local(),
   21111             :                      obj->Get(context.local(), v8_str("1")).ToLocalChecked())
   21112             :             .FromJust());
   21113          12 :   obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
   21114          18 :                          v8::ReadOnly)
   21115             :       .FromJust();
   21116          24 :   obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
   21117          30 :   CHECK(v8_str("DONT_CHANGE")
   21118             :             ->Equals(context.local(),
   21119             :                      obj->Get(context.local(), v8_num(2)).ToLocalChecked())
   21120             :             .FromJust());
   21121             : 
   21122             :   // Test non-smi case.
   21123          12 :   obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
   21124          18 :                          v8_str("DONT_CHANGE"), v8::ReadOnly)
   21125             :       .FromJust();
   21126          24 :   obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
   21127          30 :   CHECK(v8_str("DONT_CHANGE")
   21128             :             ->Equals(context.local(),
   21129             :                      obj->Get(context.local(), v8_str("2000000000"))
   21130             :                          .ToLocalChecked())
   21131             :             .FromJust());
   21132           6 : }
   21133             : 
   21134          12 : static int CountLiveMapsInMapCache(i::Context context) {
   21135          12 :   i::WeakFixedArray map_cache = i::WeakFixedArray::cast(context->map_cache());
   21136             :   int length = map_cache->length();
   21137             :   int count = 0;
   21138        3084 :   for (int i = 0; i < length; i++) {
   21139        1536 :     if (map_cache->Get(i)->IsWeak()) count++;
   21140             :   }
   21141          12 :   return count;
   21142             : }
   21143             : 
   21144             : 
   21145       26645 : THREADED_TEST(Regress1516) {
   21146           6 :   LocalContext context;
   21147          12 :   v8::HandleScope scope(context->GetIsolate());
   21148             : 
   21149             :   // Object with 20 properties is not a common case, so it should be removed
   21150             :   // from the cache after GC.
   21151          12 :   { v8::HandleScope temp_scope(context->GetIsolate());
   21152             :     CompileRun(
   21153             :         "({"
   21154             :         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
   21155             :         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
   21156             :         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
   21157             :         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
   21158             :         "})");
   21159             :   }
   21160             : 
   21161           6 :   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
   21162           6 :   CHECK_LE(1, elements);
   21163             : 
   21164             :   // We have to abort incremental marking here to abandon black pages.
   21165           6 :   CcTest::PreciseCollectAllGarbage();
   21166             : 
   21167           6 :   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
   21168           6 : }
   21169             : 
   21170             : 
   21171          84 : static void TestReceiver(Local<Value> expected_result,
   21172             :                          Local<Value> expected_receiver,
   21173             :                          const char* code) {
   21174             :   Local<Value> result = CompileRun(code);
   21175          84 :   Local<Context> context = CcTest::isolate()->GetCurrentContext();
   21176          84 :   CHECK(result->IsObject());
   21177         252 :   CHECK(expected_receiver
   21178             :             ->Equals(context,
   21179             :                      result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
   21180             :             .FromJust());
   21181         252 :   CHECK(expected_result
   21182             :             ->Equals(context,
   21183             :                      result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
   21184             :             .FromJust());
   21185          84 : }
   21186             : 
   21187             : 
   21188       26645 : THREADED_TEST(ForeignFunctionReceiver) {
   21189           6 :   v8::Isolate* isolate = CcTest::isolate();
   21190          12 :   HandleScope scope(isolate);
   21191             : 
   21192             :   // Create two contexts with different "id" properties ('i' and 'o').
   21193             :   // Call a function both from its own context and from a the foreign
   21194             :   // context, and see what "this" is bound to (returning both "this"
   21195             :   // and "this.id" for comparison).
   21196             : 
   21197           6 :   Local<Context> foreign_context = v8::Context::New(isolate);
   21198           6 :   foreign_context->Enter();
   21199             :   Local<Value> foreign_function =
   21200             :     CompileRun("function func() { return { 0: this.id, "
   21201             :                "                           1: this, "
   21202             :                "                           toString: function() { "
   21203             :                "                               return this[0];"
   21204             :                "                           }"
   21205             :                "                         };"
   21206             :                "}"
   21207             :                "var id = 'i';"
   21208             :                "func;");
   21209           6 :   CHECK(foreign_function->IsFunction());
   21210           6 :   foreign_context->Exit();
   21211             : 
   21212           6 :   LocalContext context;
   21213             : 
   21214           6 :   Local<String> password = v8_str("Password");
   21215             :   // Don't get hit by security checks when accessing foreign_context's
   21216             :   // global receiver (aka. global proxy).
   21217           6 :   context->SetSecurityToken(password);
   21218           6 :   foreign_context->SetSecurityToken(password);
   21219             : 
   21220           6 :   Local<String> i = v8_str("i");
   21221           6 :   Local<String> o = v8_str("o");
   21222           6 :   Local<String> id = v8_str("id");
   21223             : 
   21224             :   CompileRun("function ownfunc() { return { 0: this.id, "
   21225             :              "                              1: this, "
   21226             :              "                              toString: function() { "
   21227             :              "                                  return this[0];"
   21228             :              "                              }"
   21229             :              "                             };"
   21230             :              "}"
   21231             :              "var id = 'o';"
   21232             :              "ownfunc");
   21233          24 :   CHECK(context->Global()
   21234             :             ->Set(context.local(), v8_str("func"), foreign_function)
   21235             :             .FromJust());
   21236             : 
   21237             :   // Sanity check the contexts.
   21238          24 :   CHECK(
   21239             :       i->Equals(
   21240             :            context.local(),
   21241             :            foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
   21242             :           .FromJust());
   21243          24 :   CHECK(o->Equals(context.local(),
   21244             :                   context->Global()->Get(context.local(), id).ToLocalChecked())
   21245             :             .FromJust());
   21246             : 
   21247             :   // Checking local function's receiver.
   21248             :   // Calling function using its call/apply methods.
   21249          12 :   TestReceiver(o, context->Global(), "ownfunc.call()");
   21250          12 :   TestReceiver(o, context->Global(), "ownfunc.apply()");
   21251             :   // Making calls through built-in functions.
   21252          12 :   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   21253          12 :   CHECK(
   21254             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
   21255             :           .FromJust());
   21256          12 :   CHECK(
   21257             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
   21258             :           .FromJust());
   21259          12 :   CHECK(
   21260             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
   21261             :           .FromJust());
   21262             :   // Calling with environment record as base.
   21263          12 :   TestReceiver(o, context->Global(), "ownfunc()");
   21264             :   // Calling with no base.
   21265          12 :   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   21266             : 
   21267             :   // Checking foreign function return value.
   21268             :   // Calling function using its call/apply methods.
   21269          12 :   TestReceiver(i, foreign_context->Global(), "func.call()");
   21270          12 :   TestReceiver(i, foreign_context->Global(), "func.apply()");
   21271             :   // Calling function using another context's call/apply methods.
   21272          12 :   TestReceiver(i, foreign_context->Global(),
   21273           6 :                "Function.prototype.call.call(func)");
   21274          12 :   TestReceiver(i, foreign_context->Global(),
   21275           6 :                "Function.prototype.call.apply(func)");
   21276          12 :   TestReceiver(i, foreign_context->Global(),
   21277           6 :                "Function.prototype.apply.call(func)");
   21278          12 :   TestReceiver(i, foreign_context->Global(),
   21279           6 :                "Function.prototype.apply.apply(func)");
   21280             :   // Making calls through built-in functions.
   21281          12 :   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   21282             :   // ToString(func()) is func()[0], i.e., the returned this.id.
   21283          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
   21284             :             .FromJust());
   21285          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
   21286             :             .FromJust());
   21287          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
   21288             :             .FromJust());
   21289             : 
   21290             :   // Calling with environment record as base.
   21291          12 :   TestReceiver(i, foreign_context->Global(), "func()");
   21292             :   // Calling with no base.
   21293          12 :   TestReceiver(i, foreign_context->Global(), "(1,func)()");
   21294           6 : }
   21295             : 
   21296             : 
   21297             : uint8_t callback_fired = 0;
   21298             : uint8_t before_call_entered_callback_count1 = 0;
   21299             : uint8_t before_call_entered_callback_count2 = 0;
   21300             : 
   21301             : 
   21302           5 : void CallCompletedCallback1(v8::Isolate*) {
   21303           5 :   v8::base::OS::Print("Firing callback 1.\n");
   21304           5 :   callback_fired ^= 1;  // Toggle first bit.
   21305           5 : }
   21306             : 
   21307             : 
   21308          15 : void CallCompletedCallback2(v8::Isolate*) {
   21309          15 :   v8::base::OS::Print("Firing callback 2.\n");
   21310          15 :   callback_fired ^= 2;  // Toggle second bit.
   21311          15 : }
   21312             : 
   21313             : 
   21314          20 : void BeforeCallEnteredCallback1(v8::Isolate*) {
   21315          20 :   v8::base::OS::Print("Firing before call entered callback 1.\n");
   21316          20 :   before_call_entered_callback_count1++;
   21317          20 : }
   21318             : 
   21319             : 
   21320          60 : void BeforeCallEnteredCallback2(v8::Isolate*) {
   21321          60 :   v8::base::OS::Print("Firing before call entered callback 2.\n");
   21322          60 :   before_call_entered_callback_count2++;
   21323          60 : }
   21324             : 
   21325             : 
   21326          60 : void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21327             :   int32_t level =
   21328         180 :       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   21329          60 :   if (level < 3) {
   21330          45 :     level++;
   21331          45 :     v8::base::OS::Print("Entering recursion level %d.\n", level);
   21332             :     char script[64];
   21333             :     i::Vector<char> script_vector(script, sizeof(script));
   21334          45 :     i::SNPrintF(script_vector, "recursion(%d)", level);
   21335             :     CompileRun(script_vector.start());
   21336          45 :     v8::base::OS::Print("Leaving recursion level %d.\n", level);
   21337          90 :     CHECK_EQ(0, callback_fired);
   21338             :   } else {
   21339          15 :     v8::base::OS::Print("Recursion ends.\n");
   21340          30 :     CHECK_EQ(0, callback_fired);
   21341             :   }
   21342          60 : }
   21343             : 
   21344             : 
   21345       26644 : TEST(CallCompletedCallback) {
   21346           5 :   LocalContext env;
   21347          10 :   v8::HandleScope scope(env->GetIsolate());
   21348             :   v8::Local<v8::FunctionTemplate> recursive_runtime =
   21349           5 :       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
   21350          10 :   env->Global()
   21351          10 :       ->Set(env.local(), v8_str("recursion"),
   21352          15 :             recursive_runtime->GetFunction(env.local()).ToLocalChecked())
   21353             :       .FromJust();
   21354             :   // Adding the same callback a second time has no effect.
   21355           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   21356           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   21357           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
   21358           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   21359           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
   21360           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   21361           5 :   v8::base::OS::Print("--- Script (1) ---\n");
   21362           5 :   callback_fired = 0;
   21363           5 :   before_call_entered_callback_count1 = 0;
   21364           5 :   before_call_entered_callback_count2 = 0;
   21365             :   Local<Script> script =
   21366          10 :       v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
   21367           5 :   script->Run(env.local()).ToLocalChecked();
   21368          10 :   CHECK_EQ(3, callback_fired);
   21369          10 :   CHECK_EQ(4, before_call_entered_callback_count1);
   21370          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21371             : 
   21372           5 :   v8::base::OS::Print("\n--- Script (2) ---\n");
   21373           5 :   callback_fired = 0;
   21374           5 :   before_call_entered_callback_count1 = 0;
   21375           5 :   before_call_entered_callback_count2 = 0;
   21376           5 :   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
   21377           5 :   env->GetIsolate()->RemoveBeforeCallEnteredCallback(
   21378           5 :       BeforeCallEnteredCallback1);
   21379           5 :   script->Run(env.local()).ToLocalChecked();
   21380          10 :   CHECK_EQ(2, callback_fired);
   21381          10 :   CHECK_EQ(0, before_call_entered_callback_count1);
   21382          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21383             : 
   21384           5 :   v8::base::OS::Print("\n--- Function ---\n");
   21385           5 :   callback_fired = 0;
   21386           5 :   before_call_entered_callback_count1 = 0;
   21387           5 :   before_call_entered_callback_count2 = 0;
   21388             :   Local<Function> recursive_function = Local<Function>::Cast(
   21389          20 :       env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
   21390           5 :   v8::Local<Value> args[] = {v8_num(0)};
   21391          15 :   recursive_function->Call(env.local(), env->Global(), 1, args)
   21392             :       .ToLocalChecked();
   21393          10 :   CHECK_EQ(2, callback_fired);
   21394          10 :   CHECK_EQ(0, before_call_entered_callback_count1);
   21395          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21396           5 : }
   21397             : 
   21398             : 
   21399           5 : void CallCompletedCallbackNoException(v8::Isolate*) {
   21400          10 :   v8::HandleScope scope(CcTest::isolate());
   21401             :   CompileRun("1+1;");
   21402           5 : }
   21403             : 
   21404             : 
   21405           5 : void CallCompletedCallbackException(v8::Isolate*) {
   21406          10 :   v8::HandleScope scope(CcTest::isolate());
   21407             :   CompileRun("throw 'second exception';");
   21408           5 : }
   21409             : 
   21410             : 
   21411       26644 : TEST(CallCompletedCallbackOneException) {
   21412           5 :   LocalContext env;
   21413          10 :   v8::HandleScope scope(env->GetIsolate());
   21414           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
   21415             :   CompileRun("throw 'exception';");
   21416           5 : }
   21417             : 
   21418             : 
   21419       26644 : TEST(CallCompletedCallbackTwoExceptions) {
   21420           5 :   LocalContext env;
   21421          10 :   v8::HandleScope scope(env->GetIsolate());
   21422           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
   21423             :   CompileRun("throw 'first exception';");
   21424           5 : }
   21425             : 
   21426             : 
   21427          45 : static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
   21428          45 :   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   21429          90 :   v8::HandleScope scope(info.GetIsolate());
   21430             :   v8::MicrotasksScope microtasks(info.GetIsolate(),
   21431          90 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21432             :   CompileRun("ext1Calls++;");
   21433          45 : }
   21434             : 
   21435             : 
   21436          50 : static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
   21437          50 :   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   21438         100 :   v8::HandleScope scope(info.GetIsolate());
   21439             :   v8::MicrotasksScope microtasks(info.GetIsolate(),
   21440         100 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21441             :   CompileRun("ext2Calls++;");
   21442          50 : }
   21443             : 
   21444             : void* g_passed_to_three = nullptr;
   21445             : 
   21446          10 : static void MicrotaskThree(void* data) {
   21447          10 :   g_passed_to_three = data;
   21448          10 : }
   21449             : 
   21450             : 
   21451       26644 : TEST(EnqueueMicrotask) {
   21452           5 :   LocalContext env;
   21453          10 :   v8::HandleScope scope(env->GetIsolate());
   21454           5 :   CHECK(!v8::MicrotasksScope::IsRunningMicrotasks(env->GetIsolate()));
   21455             :   CompileRun(
   21456             :       "var ext1Calls = 0;"
   21457             :       "var ext2Calls = 0;");
   21458             :   CompileRun("1+1;");
   21459          10 :   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21460          10 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21461             : 
   21462           5 :   env->GetIsolate()->EnqueueMicrotask(
   21463          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21464             :   CompileRun("1+1;");
   21465          10 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21466          10 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21467             : 
   21468           5 :   env->GetIsolate()->EnqueueMicrotask(
   21469          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21470           5 :   env->GetIsolate()->EnqueueMicrotask(
   21471          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21472             :   CompileRun("1+1;");
   21473          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21474          10 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21475             : 
   21476           5 :   env->GetIsolate()->EnqueueMicrotask(
   21477          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21478             :   CompileRun("1+1;");
   21479          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21480          10 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21481             : 
   21482             :   CompileRun("1+1;");
   21483          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21484          10 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21485             : 
   21486           5 :   g_passed_to_three = nullptr;
   21487           5 :   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
   21488             :   CompileRun("1+1;");
   21489           5 :   CHECK(!g_passed_to_three);
   21490          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21491          10 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21492             : 
   21493             :   int dummy;
   21494           5 :   env->GetIsolate()->EnqueueMicrotask(
   21495          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21496           5 :   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
   21497           5 :   env->GetIsolate()->EnqueueMicrotask(
   21498          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21499             :   CompileRun("1+1;");
   21500           5 :   CHECK_EQ(&dummy, g_passed_to_three);
   21501          10 :   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21502          10 :   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21503           5 :   g_passed_to_three = nullptr;
   21504           5 : }
   21505             : 
   21506             : 
   21507           5 : static void MicrotaskExceptionOne(
   21508             :     const v8::FunctionCallbackInfo<Value>& info) {
   21509          10 :   v8::HandleScope scope(info.GetIsolate());
   21510             :   CompileRun("exception1Calls++;");
   21511             :   info.GetIsolate()->ThrowException(
   21512          10 :       v8::Exception::Error(v8_str("first")));
   21513           5 : }
   21514             : 
   21515             : 
   21516           5 : static void MicrotaskExceptionTwo(
   21517             :     const v8::FunctionCallbackInfo<Value>& info) {
   21518          10 :   v8::HandleScope scope(info.GetIsolate());
   21519             :   CompileRun("exception2Calls++;");
   21520             :   info.GetIsolate()->ThrowException(
   21521          10 :       v8::Exception::Error(v8_str("second")));
   21522           5 : }
   21523             : 
   21524             : 
   21525       26644 : TEST(RunMicrotasksIgnoresThrownExceptions) {
   21526           5 :   LocalContext env;
   21527           5 :   v8::Isolate* isolate = env->GetIsolate();
   21528          10 :   v8::HandleScope scope(isolate);
   21529             :   CompileRun(
   21530             :       "var exception1Calls = 0;"
   21531             :       "var exception2Calls = 0;");
   21532             :   isolate->EnqueueMicrotask(
   21533          10 :       Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
   21534             :   isolate->EnqueueMicrotask(
   21535          10 :       Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
   21536          10 :   TryCatch try_catch(isolate);
   21537             :   CompileRun("1+1;");
   21538           5 :   CHECK(!try_catch.HasCaught());
   21539          10 :   CHECK_EQ(1,
   21540             :            CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
   21541          10 :   CHECK_EQ(1,
   21542             :            CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
   21543           5 : }
   21544             : 
   21545           5 : static void ThrowExceptionMicrotask(void* data) {
   21546          10 :   CcTest::isolate()->ThrowException(v8_str("exception"));
   21547           5 : }
   21548             : 
   21549             : int microtask_callback_count = 0;
   21550             : 
   21551           5 : static void IncrementCounterMicrotask(void* data) {
   21552           5 :   microtask_callback_count++;
   21553           5 : }
   21554             : 
   21555       26644 : TEST(RunMicrotasksIgnoresThrownExceptionsFromApi) {
   21556           5 :   LocalContext env;
   21557           5 :   v8::Isolate* isolate = CcTest::isolate();
   21558           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   21559          10 :   v8::HandleScope scope(isolate);
   21560          10 :   v8::TryCatch try_catch(isolate);
   21561             :   {
   21562           5 :     CHECK(!isolate->IsExecutionTerminating());
   21563           5 :     isolate->EnqueueMicrotask(ThrowExceptionMicrotask);
   21564           5 :     isolate->EnqueueMicrotask(IncrementCounterMicrotask);
   21565           5 :     isolate->RunMicrotasks();
   21566           5 :     CHECK_EQ(1, microtask_callback_count);
   21567           5 :     CHECK(!try_catch.HasCaught());
   21568             :   }
   21569           5 : }
   21570             : 
   21571             : uint8_t microtasks_completed_callback_count = 0;
   21572             : 
   21573          25 : static void MicrotasksCompletedCallback(v8::Isolate* isolate, void*) {
   21574          25 :   ++microtasks_completed_callback_count;
   21575          25 : }
   21576             : 
   21577       26644 : TEST(SetAutorunMicrotasks) {
   21578           5 :   LocalContext env;
   21579          10 :   v8::HandleScope scope(env->GetIsolate());
   21580           5 :   env->GetIsolate()->AddMicrotasksCompletedCallback(
   21581           5 :       &MicrotasksCompletedCallback);
   21582             :   CompileRun(
   21583             :       "var ext1Calls = 0;"
   21584             :       "var ext2Calls = 0;");
   21585             :   CompileRun("1+1;");
   21586          10 :   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21587          10 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21588           5 :   CHECK_EQ(0u, microtasks_completed_callback_count);
   21589             : 
   21590           5 :   env->GetIsolate()->EnqueueMicrotask(
   21591          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21592             :   CompileRun("1+1;");
   21593          10 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21594          10 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21595           5 :   CHECK_EQ(1u, microtasks_completed_callback_count);
   21596             : 
   21597           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   21598           5 :   env->GetIsolate()->EnqueueMicrotask(
   21599          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21600           5 :   env->GetIsolate()->EnqueueMicrotask(
   21601          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21602             :   CompileRun("1+1;");
   21603          10 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21604          10 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21605           5 :   CHECK_EQ(1u, microtasks_completed_callback_count);
   21606             : 
   21607           5 :   env->GetIsolate()->RunMicrotasks();
   21608          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21609          10 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21610           5 :   CHECK_EQ(2u, microtasks_completed_callback_count);
   21611             : 
   21612           5 :   env->GetIsolate()->EnqueueMicrotask(
   21613          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21614             :   CompileRun("1+1;");
   21615          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21616          10 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21617           5 :   CHECK_EQ(2u, microtasks_completed_callback_count);
   21618             : 
   21619           5 :   env->GetIsolate()->RunMicrotasks();
   21620          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21621          10 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21622           5 :   CHECK_EQ(3u, microtasks_completed_callback_count);
   21623             : 
   21624           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21625           5 :   env->GetIsolate()->EnqueueMicrotask(
   21626          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21627             :   CompileRun("1+1;");
   21628          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21629          10 :   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21630           5 :   CHECK_EQ(4u, microtasks_completed_callback_count);
   21631             : 
   21632           5 :   env->GetIsolate()->EnqueueMicrotask(
   21633          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21634             :   {
   21635          10 :     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
   21636             :     CompileRun("1+1;");
   21637          10 :     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21638          10 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21639           5 :     CHECK_EQ(4u, microtasks_completed_callback_count);
   21640             :   }
   21641             : 
   21642             :   CompileRun("1+1;");
   21643          10 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21644          10 :   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21645           5 :   CHECK_EQ(5u, microtasks_completed_callback_count);
   21646             : 
   21647           5 :   env->GetIsolate()->RemoveMicrotasksCompletedCallback(
   21648           5 :       &MicrotasksCompletedCallback);
   21649           5 :   env->GetIsolate()->EnqueueMicrotask(
   21650          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21651             :   CompileRun("1+1;");
   21652          10 :   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21653          10 :   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21654           5 :   CHECK_EQ(5u, microtasks_completed_callback_count);
   21655           5 : }
   21656             : 
   21657             : 
   21658       26644 : TEST(RunMicrotasksWithoutEnteringContext) {
   21659           5 :   v8::Isolate* isolate = CcTest::isolate();
   21660          10 :   HandleScope handle_scope(isolate);
   21661           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   21662           5 :   Local<Context> context = Context::New(isolate);
   21663             :   {
   21664             :     Context::Scope context_scope(context);
   21665             :     CompileRun("var ext1Calls = 0;");
   21666             :     isolate->EnqueueMicrotask(
   21667          10 :         Function::New(context, MicrotaskOne).ToLocalChecked());
   21668             :   }
   21669           5 :   isolate->RunMicrotasks();
   21670             :   {
   21671             :     Context::Scope context_scope(context);
   21672          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
   21673             :   }
   21674           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21675           5 : }
   21676             : 
   21677           6 : static void Regress808911_MicrotaskCallback(void* data) {
   21678             :   // So here we expect "current context" to be context1 and
   21679             :   // "entered or microtask context" to be context2.
   21680             :   v8::Isolate* isolate = static_cast<v8::Isolate*>(data);
   21681          12 :   CHECK(isolate->GetCurrentContext() !=
   21682             :         isolate->GetEnteredOrMicrotaskContext());
   21683           6 : }
   21684             : 
   21685           6 : static void Regress808911_CurrentContextWrapper(
   21686             :     const v8::FunctionCallbackInfo<Value>& info) {
   21687             :   // So here we expect "current context" to be context1 and
   21688             :   // "entered or microtask context" to be context2.
   21689             :   v8::Isolate* isolate = info.GetIsolate();
   21690          12 :   CHECK(isolate->GetCurrentContext() !=
   21691             :         isolate->GetEnteredOrMicrotaskContext());
   21692           6 :   isolate->EnqueueMicrotask(Regress808911_MicrotaskCallback, isolate);
   21693           6 :   isolate->RunMicrotasks();
   21694           6 : }
   21695             : 
   21696       26645 : THREADED_TEST(Regress808911) {
   21697           6 :   v8::Isolate* isolate = CcTest::isolate();
   21698          12 :   HandleScope handle_scope(isolate);
   21699           6 :   Local<Context> context1 = Context::New(isolate);
   21700             :   Local<Function> function;
   21701             :   {
   21702             :     Context::Scope context_scope(context1);
   21703          12 :     function = Function::New(context1, Regress808911_CurrentContextWrapper)
   21704             :                    .ToLocalChecked();
   21705             :   }
   21706           6 :   Local<Context> context2 = Context::New(isolate);
   21707             :   Context::Scope context_scope(context2);
   21708          12 :   function->CallAsFunction(context2, v8::Undefined(isolate), 0, nullptr)
   21709             :       .ToLocalChecked();
   21710           6 : }
   21711             : 
   21712       26644 : TEST(ScopedMicrotasks) {
   21713           5 :   LocalContext env;
   21714          10 :   v8::HandleScope handles(env->GetIsolate());
   21715           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
   21716             :   {
   21717             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   21718          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21719           5 :     env->GetIsolate()->EnqueueMicrotask(
   21720          10 :         Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21721             :     CompileRun(
   21722             :         "var ext1Calls = 0;"
   21723             :         "var ext2Calls = 0;");
   21724             :     CompileRun("1+1;");
   21725          10 :     CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21726          10 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21727             :     {
   21728             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   21729          10 :                                  v8::MicrotasksScope::kRunMicrotasks);
   21730             :       CompileRun("1+1;");
   21731          10 :       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21732          10 :       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21733             :       {
   21734             :         v8::MicrotasksScope scope3(env->GetIsolate(),
   21735          10 :                                    v8::MicrotasksScope::kRunMicrotasks);
   21736             :         CompileRun("1+1;");
   21737          10 :         CHECK_EQ(0,
   21738             :                  CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21739          10 :         CHECK_EQ(0,
   21740             :                  CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21741             :       }
   21742          10 :       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21743          10 :       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21744             :     }
   21745          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21746          10 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21747           5 :     env->GetIsolate()->EnqueueMicrotask(
   21748          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21749             :   }
   21750             : 
   21751             :   {
   21752             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21753          10 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21754          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21755          10 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21756             :   }
   21757             : 
   21758             :   {
   21759             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   21760          10 :                                v8::MicrotasksScope::kRunMicrotasks);
   21761             :     CompileRun("1+1;");
   21762          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21763          10 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21764             :     {
   21765             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   21766           5 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21767             :     }
   21768          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21769          10 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21770             :   }
   21771             : 
   21772             :   {
   21773             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21774          10 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21775          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21776          10 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21777           5 :     env->GetIsolate()->EnqueueMicrotask(
   21778          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21779             :   }
   21780             : 
   21781             :   {
   21782          10 :     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   21783             :     {
   21784             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   21785           5 :                                  v8::MicrotasksScope::kRunMicrotasks);
   21786             :     }
   21787             :     v8::MicrotasksScope scope3(env->GetIsolate(),
   21788          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21789          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21790          10 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21791             :   }
   21792             : 
   21793             :   {
   21794             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   21795          10 :                                v8::MicrotasksScope::kRunMicrotasks);
   21796           5 :     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21797          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21798          10 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21799             :   }
   21800             : 
   21801             :   {
   21802             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21803          10 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21804          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21805          10 :     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21806             :   }
   21807             : 
   21808           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21809             : 
   21810             :   {
   21811             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21812          10 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21813          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21814          10 :     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21815           5 :     env->GetIsolate()->EnqueueMicrotask(
   21816          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21817             :   }
   21818             : 
   21819           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21820             : 
   21821             :   {
   21822             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21823          10 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21824          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21825          10 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21826             :   }
   21827             : 
   21828           5 :   env->GetIsolate()->EnqueueMicrotask(
   21829          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21830             :   {
   21831          10 :     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   21832           5 :     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21833             :     v8::MicrotasksScope scope2(env->GetIsolate(),
   21834          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21835          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21836          10 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21837             :   }
   21838             : 
   21839           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21840             : 
   21841             :   {
   21842             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21843          10 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21844          10 :     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21845          10 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21846             :   }
   21847             : 
   21848           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21849           5 : }
   21850             : 
   21851             : namespace {
   21852             : 
   21853          35 : void AssertCowElements(bool expected, const char* source) {
   21854             :   Local<Value> object = CompileRun(source);
   21855             :   i::Handle<i::JSObject> array =
   21856             :       i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*object.As<Object>()));
   21857          35 :   CHECK_EQ(expected, array->elements()->IsCowArray());
   21858          35 : }
   21859             : 
   21860             : }  // namespace
   21861             : 
   21862       26644 : TEST(CheckCOWArraysCreatedRuntimeCounter) {
   21863           5 :   LocalContext env;
   21864          10 :   v8::HandleScope scope(env->GetIsolate());
   21865           5 :   AssertCowElements(true, "[1, 2, 3]");
   21866           5 :   AssertCowElements(false, "[[1], 2, 3]");
   21867           5 :   AssertCowElements(true, "[[1], 2, 3][0]");
   21868           5 :   AssertCowElements(true, "({foo: [4, 5, 6], bar: [3, 0]}.foo)");
   21869           5 :   AssertCowElements(true, "({foo: [4, 5, 6], bar: [3, 0]}.bar)");
   21870           5 :   AssertCowElements(false, "({foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'}.foo)");
   21871           5 :   AssertCowElements(true, "({foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'}.foo[3])");
   21872           5 : }
   21873             : 
   21874             : 
   21875       26644 : TEST(StaticGetters) {
   21876           5 :   LocalContext context;
   21877             :   i::Factory* factory = CcTest::i_isolate()->factory();
   21878           5 :   v8::Isolate* isolate = CcTest::isolate();
   21879          10 :   v8::HandleScope scope(isolate);
   21880             :   i::Handle<i::Object> undefined_value = factory->undefined_value();
   21881           5 :   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   21882             :   i::Handle<i::Object> null_value = factory->null_value();
   21883           5 :   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   21884             :   i::Handle<i::Object> true_value = factory->true_value();
   21885           5 :   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   21886             :   i::Handle<i::Object> false_value = factory->false_value();
   21887           5 :   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   21888           5 : }
   21889             : 
   21890             : 
   21891       26644 : UNINITIALIZED_TEST(IsolateEmbedderData) {
   21892           5 :   CcTest::DisableAutomaticDispose();
   21893             :   v8::Isolate::CreateParams create_params;
   21894           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   21895           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   21896           5 :   isolate->Enter();
   21897             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   21898          45 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21899          20 :     CHECK(!isolate->GetData(slot));
   21900          20 :     CHECK(!i_isolate->GetData(slot));
   21901             :   }
   21902          45 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21903          20 :     void* data = reinterpret_cast<void*>(0xACCE55ED + slot);
   21904             :     isolate->SetData(slot, data);
   21905             :   }
   21906          45 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21907          20 :     void* data = reinterpret_cast<void*>(0xACCE55ED + slot);
   21908          20 :     CHECK_EQ(data, isolate->GetData(slot));
   21909          20 :     CHECK_EQ(data, i_isolate->GetData(slot));
   21910             :   }
   21911          45 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21912          20 :     void* data = reinterpret_cast<void*>(0xDECEA5ED + slot);
   21913             :     isolate->SetData(slot, data);
   21914             :   }
   21915          45 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21916          20 :     void* data = reinterpret_cast<void*>(0xDECEA5ED + slot);
   21917          20 :     CHECK_EQ(data, isolate->GetData(slot));
   21918          20 :     CHECK_EQ(data, i_isolate->GetData(slot));
   21919             :   }
   21920           5 :   isolate->Exit();
   21921           5 :   isolate->Dispose();
   21922           5 : }
   21923             : 
   21924             : 
   21925       26644 : TEST(StringEmpty) {
   21926           5 :   LocalContext context;
   21927             :   i::Factory* factory = CcTest::i_isolate()->factory();
   21928           5 :   v8::Isolate* isolate = CcTest::isolate();
   21929          10 :   v8::HandleScope scope(isolate);
   21930             :   i::Handle<i::Object> empty_string = factory->empty_string();
   21931           5 :   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   21932           5 : }
   21933             : 
   21934             : 
   21935             : static int instance_checked_getter_count = 0;
   21936         120 : static void InstanceCheckedGetter(
   21937             :     Local<String> name,
   21938             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   21939         480 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   21940             :             .FromJust());
   21941         120 :   instance_checked_getter_count++;
   21942         120 :   info.GetReturnValue().Set(v8_num(11));
   21943         120 : }
   21944             : 
   21945             : 
   21946             : static int instance_checked_setter_count = 0;
   21947         120 : static void InstanceCheckedSetter(Local<String> name,
   21948             :                       Local<Value> value,
   21949             :                       const v8::PropertyCallbackInfo<void>& info) {
   21950         480 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   21951             :             .FromJust());
   21952         480 :   CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
   21953             :             .FromJust());
   21954         120 :   instance_checked_setter_count++;
   21955         120 : }
   21956             : 
   21957             : 
   21958         420 : static void CheckInstanceCheckedResult(int getters, int setters,
   21959             :                                        bool expects_callbacks,
   21960             :                                        TryCatch* try_catch) {
   21961         420 :   if (expects_callbacks) {
   21962         240 :     CHECK(!try_catch->HasCaught());
   21963         240 :     CHECK_EQ(getters, instance_checked_getter_count);
   21964         240 :     CHECK_EQ(setters, instance_checked_setter_count);
   21965             :   } else {
   21966         180 :     CHECK(try_catch->HasCaught());
   21967         180 :     CHECK_EQ(0, instance_checked_getter_count);
   21968         180 :     CHECK_EQ(0, instance_checked_setter_count);
   21969             :   }
   21970         420 :   try_catch->Reset();
   21971         420 : }
   21972             : 
   21973             : 
   21974          42 : static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   21975          42 :   instance_checked_getter_count = 0;
   21976          42 :   instance_checked_setter_count = 0;
   21977          84 :   TryCatch try_catch(CcTest::isolate());
   21978             : 
   21979             :   // Test path through generic runtime code.
   21980             :   CompileRun("obj.foo");
   21981          42 :   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   21982             :   CompileRun("obj.foo = 23");
   21983          42 :   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   21984             : 
   21985             :   // Test path through generated LoadIC and StoredIC.
   21986             :   CompileRun("function test_get(o) { o.foo; }"
   21987             :              "test_get(obj);");
   21988          42 :   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   21989             :   CompileRun("test_get(obj);");
   21990          42 :   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   21991             :   CompileRun("test_get(obj);");
   21992          42 :   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   21993             :   CompileRun("function test_set(o) { o.foo = 23; }"
   21994             :              "test_set(obj);");
   21995          42 :   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   21996             :   CompileRun("test_set(obj);");
   21997          42 :   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   21998             :   CompileRun("test_set(obj);");
   21999          42 :   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   22000             : 
   22001             :   // Test path through optimized code.
   22002             :   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   22003             :              "test_get(obj);");
   22004          42 :   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   22005             :   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   22006             :              "test_set(obj);");
   22007          42 :   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   22008             : 
   22009             :   // Cleanup so that closures start out fresh in next check.
   22010             :   CompileRun(
   22011             :       "%DeoptimizeFunction(test_get);"
   22012             :       "%ClearFunctionFeedback(test_get);"
   22013             :       "%DeoptimizeFunction(test_set);"
   22014             :       "%ClearFunctionFeedback(test_set);");
   22015          42 : }
   22016             : 
   22017             : 
   22018       26645 : THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   22019           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22020           6 :   LocalContext context;
   22021          12 :   v8::HandleScope scope(context->GetIsolate());
   22022             : 
   22023           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22024           6 :   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   22025          18 :   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   22026             :                     Local<Value>(), v8::DEFAULT, v8::None,
   22027           6 :                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   22028          30 :   CHECK(context->Global()
   22029             :             ->Set(context.local(), v8_str("f"),
   22030             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22031             :             .FromJust());
   22032             : 
   22033             :   printf("Testing positive ...\n");
   22034             :   CompileRun("var obj = new f();");
   22035          24 :   CHECK(templ->HasInstance(
   22036             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22037           6 :   CheckInstanceCheckedAccessors(true);
   22038             : 
   22039             :   printf("Testing negative ...\n");
   22040             :   CompileRun("var obj = {};"
   22041             :              "obj.__proto__ = new f();");
   22042          24 :   CHECK(!templ->HasInstance(
   22043             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22044           6 :   CheckInstanceCheckedAccessors(false);
   22045           6 : }
   22046             : 
   22047          90 : static void EmptyInterceptorGetter(
   22048          90 :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22049             : 
   22050          30 : static void EmptyInterceptorSetter(
   22051             :     Local<Name> name, Local<Value> value,
   22052          30 :     const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22053             : 
   22054       26645 : THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   22055           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22056           6 :   LocalContext context;
   22057          12 :   v8::HandleScope scope(context->GetIsolate());
   22058             : 
   22059           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22060           6 :   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   22061          12 :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
   22062           6 :       EmptyInterceptorGetter, EmptyInterceptorSetter));
   22063          18 :   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   22064             :                     Local<Value>(), v8::DEFAULT, v8::None,
   22065           6 :                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   22066          30 :   CHECK(context->Global()
   22067             :             ->Set(context.local(), v8_str("f"),
   22068             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22069             :             .FromJust());
   22070             : 
   22071             :   printf("Testing positive ...\n");
   22072             :   CompileRun("var obj = new f();");
   22073          24 :   CHECK(templ->HasInstance(
   22074             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22075           6 :   CheckInstanceCheckedAccessors(true);
   22076             : 
   22077             :   printf("Testing negative ...\n");
   22078             :   CompileRun("var obj = {};"
   22079             :              "obj.__proto__ = new f();");
   22080          24 :   CHECK(!templ->HasInstance(
   22081             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22082           6 :   CheckInstanceCheckedAccessors(false);
   22083           6 : }
   22084             : 
   22085             : 
   22086       26645 : THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   22087           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22088           6 :   LocalContext context;
   22089          12 :   v8::HandleScope scope(context->GetIsolate());
   22090             : 
   22091           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22092           6 :   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   22093          18 :   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
   22094             :                      InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
   22095             :                      v8::None,
   22096           6 :                      v8::AccessorSignature::New(context->GetIsolate(), templ));
   22097          30 :   CHECK(context->Global()
   22098             :             ->Set(context.local(), v8_str("f"),
   22099             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22100             :             .FromJust());
   22101             : 
   22102             :   printf("Testing positive ...\n");
   22103             :   CompileRun("var obj = new f();");
   22104          24 :   CHECK(templ->HasInstance(
   22105             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22106           6 :   CheckInstanceCheckedAccessors(true);
   22107             : 
   22108             :   printf("Testing negative ...\n");
   22109             :   CompileRun("var obj = {};"
   22110             :              "obj.__proto__ = new f();");
   22111          24 :   CHECK(!templ->HasInstance(
   22112             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22113           6 :   CheckInstanceCheckedAccessors(false);
   22114             : 
   22115             :   printf("Testing positive with modified prototype chain ...\n");
   22116             :   CompileRun("var obj = new f();"
   22117             :              "var pro = {};"
   22118             :              "pro.__proto__ = obj.__proto__;"
   22119             :              "obj.__proto__ = pro;");
   22120          24 :   CHECK(templ->HasInstance(
   22121             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22122           6 :   CheckInstanceCheckedAccessors(true);
   22123           6 : }
   22124             : 
   22125             : 
   22126       26644 : TEST(TryFinallyMessage) {
   22127           5 :   LocalContext context;
   22128          10 :   v8::HandleScope scope(context->GetIsolate());
   22129             :   {
   22130             :     // Test that the original error message is not lost if there is a
   22131             :     // recursive call into Javascript is done in the finally block, e.g. to
   22132             :     // initialize an IC. (crbug.com/129171)
   22133          10 :     TryCatch try_catch(context->GetIsolate());
   22134             :     const char* trigger_ic =
   22135             :         "try {                      \n"
   22136             :         "  throw new Error('test'); \n"
   22137             :         "} finally {                \n"
   22138             :         "  var x = 0;               \n"
   22139             :         "  x++;                     \n"  // Trigger an IC initialization here.
   22140             :         "}                          \n";
   22141             :     CompileRun(trigger_ic);
   22142           5 :     CHECK(try_catch.HasCaught());
   22143           5 :     Local<Message> message = try_catch.Message();
   22144           5 :     CHECK(!message.IsEmpty());
   22145          10 :     CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   22146             :   }
   22147             : 
   22148             :   {
   22149             :     // Test that the original exception message is indeed overwritten if
   22150             :     // a new error is thrown in the finally block.
   22151          10 :     TryCatch try_catch(context->GetIsolate());
   22152             :     const char* throw_again =
   22153             :         "try {                       \n"
   22154             :         "  throw new Error('test');  \n"
   22155             :         "} finally {                 \n"
   22156             :         "  var x = 0;                \n"
   22157             :         "  x++;                      \n"
   22158             :         "  throw new Error('again'); \n"  // This is the new uncaught error.
   22159             :         "}                           \n";
   22160             :     CompileRun(throw_again);
   22161           5 :     CHECK(try_catch.HasCaught());
   22162           5 :     Local<Message> message = try_catch.Message();
   22163           5 :     CHECK(!message.IsEmpty());
   22164          10 :     CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
   22165             :   }
   22166           5 : }
   22167             : 
   22168             : 
   22169          96 : static void Helper137002(bool do_store,
   22170             :                          bool polymorphic,
   22171             :                          bool remove_accessor,
   22172             :                          bool interceptor) {
   22173          96 :   LocalContext context;
   22174          96 :   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
   22175          96 :   if (interceptor) {
   22176          48 :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
   22177          48 :                                                             FooSetInterceptor));
   22178             :   } else {
   22179          96 :     templ->SetAccessor(v8_str("foo"),
   22180             :                        GetterWhichReturns42,
   22181          48 :                        SetterWhichSetsYOnThisTo23);
   22182             :   }
   22183         480 :   CHECK(context->Global()
   22184             :             ->Set(context.local(), v8_str("obj"),
   22185             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22186             :             .FromJust());
   22187             : 
   22188             :   // Turn monomorphic on slow object with native accessor, then turn
   22189             :   // polymorphic, finally optimize to create negative lookup and fail.
   22190             :   CompileRun(do_store ?
   22191             :              "function f(x) { x.foo = void 0; }" :
   22192          96 :              "function f(x) { return x.foo; }");
   22193             :   CompileRun("obj.y = void 0;");
   22194          96 :   if (!interceptor) {
   22195             :     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   22196             :   }
   22197             :   CompileRun("obj.__proto__ = null;"
   22198             :              "f(obj); f(obj); f(obj);");
   22199          96 :   if (polymorphic) {
   22200             :     CompileRun("f({});");
   22201             :   }
   22202             :   CompileRun("obj.y = void 0;"
   22203             :              "%OptimizeFunctionOnNextCall(f);");
   22204          96 :   if (remove_accessor) {
   22205             :     CompileRun("delete obj.foo;");
   22206             :   }
   22207             :   CompileRun("var result = f(obj);");
   22208          96 :   if (do_store) {
   22209             :     CompileRun("result = obj.y;");
   22210             :   }
   22211          96 :   if (remove_accessor && !interceptor) {
   22212          96 :     CHECK(context->Global()
   22213             :               ->Get(context.local(), v8_str("result"))
   22214             :               .ToLocalChecked()
   22215             :               ->IsUndefined());
   22216             :   } else {
   22217         360 :     CHECK_EQ(do_store ? 23 : 42, context->Global()
   22218             :                                      ->Get(context.local(), v8_str("result"))
   22219             :                                      .ToLocalChecked()
   22220             :                                      ->Int32Value(context.local())
   22221             :                                      .FromJust());
   22222             :   }
   22223          96 : }
   22224             : 
   22225             : 
   22226       26645 : THREADED_TEST(Regress137002a) {
   22227           6 :   i::FLAG_allow_natives_syntax = true;
   22228           6 :   i::FLAG_compilation_cache = false;
   22229          12 :   v8::HandleScope scope(CcTest::isolate());
   22230         198 :   for (int i = 0; i < 16; i++) {
   22231          96 :     Helper137002(i & 8, i & 4, i & 2, i & 1);
   22232             :   }
   22233           6 : }
   22234             : 
   22235             : 
   22236       26645 : THREADED_TEST(Regress137002b) {
   22237           6 :   i::FLAG_allow_natives_syntax = true;
   22238           6 :   LocalContext context;
   22239           6 :   v8::Isolate* isolate = context->GetIsolate();
   22240          12 :   v8::HandleScope scope(isolate);
   22241           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22242          12 :   templ->SetAccessor(v8_str("foo"),
   22243             :                      GetterWhichReturns42,
   22244           6 :                      SetterWhichSetsYOnThisTo23);
   22245          30 :   CHECK(context->Global()
   22246             :             ->Set(context.local(), v8_str("obj"),
   22247             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22248             :             .FromJust());
   22249             : 
   22250             :   // Turn monomorphic on slow object with native accessor, then just
   22251             :   // delete the property and fail.
   22252             :   CompileRun("function load(x) { return x.foo; }"
   22253             :              "function store(x) { x.foo = void 0; }"
   22254             :              "function keyed_load(x, key) { return x[key]; }"
   22255             :              // Second version of function has a different source (add void 0)
   22256             :              // so that it does not share code with the first version.  This
   22257             :              // ensures that the ICs are monomorphic.
   22258             :              "function load2(x) { void 0; return x.foo; }"
   22259             :              "function store2(x) { void 0; x.foo = void 0; }"
   22260             :              "function keyed_load2(x, key) { void 0; return x[key]; }"
   22261             : 
   22262             :              "obj.y = void 0;"
   22263             :              "obj.__proto__ = null;"
   22264             :              "var subobj = {};"
   22265             :              "subobj.y = void 0;"
   22266             :              "subobj.__proto__ = obj;"
   22267             :              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   22268             : 
   22269             :              // Make the ICs monomorphic.
   22270             :              "load(obj); load(obj);"
   22271             :              "load2(subobj); load2(subobj);"
   22272             :              "store(obj); store(obj);"
   22273             :              "store2(subobj); store2(subobj);"
   22274             :              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   22275             :              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   22276             : 
   22277             :              // Actually test the shiny new ICs and better not crash. This
   22278             :              // serves as a regression test for issue 142088 as well.
   22279             :              "load(obj);"
   22280             :              "load2(subobj);"
   22281             :              "store(obj);"
   22282             :              "store2(subobj);"
   22283             :              "keyed_load(obj, 'foo');"
   22284             :              "keyed_load2(subobj, 'foo');"
   22285             : 
   22286             :              // Delete the accessor.  It better not be called any more now.
   22287             :              "delete obj.foo;"
   22288             :              "obj.y = void 0;"
   22289             :              "subobj.y = void 0;"
   22290             : 
   22291             :              "var load_result = load(obj);"
   22292             :              "var load_result2 = load2(subobj);"
   22293             :              "var keyed_load_result = keyed_load(obj, 'foo');"
   22294             :              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   22295             :              "store(obj);"
   22296             :              "store2(subobj);"
   22297             :              "var y_from_obj = obj.y;"
   22298             :              "var y_from_subobj = subobj.y;");
   22299          24 :   CHECK(context->Global()
   22300             :             ->Get(context.local(), v8_str("load_result"))
   22301             :             .ToLocalChecked()
   22302             :             ->IsUndefined());
   22303          24 :   CHECK(context->Global()
   22304             :             ->Get(context.local(), v8_str("load_result2"))
   22305             :             .ToLocalChecked()
   22306             :             ->IsUndefined());
   22307          24 :   CHECK(context->Global()
   22308             :             ->Get(context.local(), v8_str("keyed_load_result"))
   22309             :             .ToLocalChecked()
   22310             :             ->IsUndefined());
   22311          24 :   CHECK(context->Global()
   22312             :             ->Get(context.local(), v8_str("keyed_load_result2"))
   22313             :             .ToLocalChecked()
   22314             :             ->IsUndefined());
   22315          24 :   CHECK(context->Global()
   22316             :             ->Get(context.local(), v8_str("y_from_obj"))
   22317             :             .ToLocalChecked()
   22318             :             ->IsUndefined());
   22319          24 :   CHECK(context->Global()
   22320             :             ->Get(context.local(), v8_str("y_from_subobj"))
   22321             :             .ToLocalChecked()
   22322             :             ->IsUndefined());
   22323           6 : }
   22324             : 
   22325             : 
   22326       26645 : THREADED_TEST(Regress142088) {
   22327           6 :   i::FLAG_allow_natives_syntax = true;
   22328           6 :   LocalContext context;
   22329           6 :   v8::Isolate* isolate = context->GetIsolate();
   22330          12 :   v8::HandleScope scope(isolate);
   22331           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22332          12 :   templ->SetAccessor(v8_str("foo"),
   22333             :                      GetterWhichReturns42,
   22334           6 :                      SetterWhichSetsYOnThisTo23);
   22335          30 :   CHECK(context->Global()
   22336             :             ->Set(context.local(), v8_str("obj"),
   22337             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22338             :             .FromJust());
   22339             : 
   22340             :   CompileRun("function load(x) { return x.foo; }"
   22341             :              "var o = Object.create(obj);"
   22342             :              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   22343             :              "load(o); load(o); load(o); load(o);");
   22344           6 : }
   22345             : 
   22346             : 
   22347       26645 : THREADED_TEST(Regress137496) {
   22348           6 :   i::FLAG_expose_gc = true;
   22349           6 :   LocalContext context;
   22350          12 :   v8::HandleScope scope(context->GetIsolate());
   22351             : 
   22352             :   // Compile a try-finally clause where the finally block causes a GC
   22353             :   // while there still is a message pending for external reporting.
   22354          12 :   TryCatch try_catch(context->GetIsolate());
   22355           6 :   try_catch.SetVerbose(true);
   22356             :   CompileRun("try { throw new Error(); } finally { gc(); }");
   22357           6 :   CHECK(try_catch.HasCaught());
   22358           6 : }
   22359             : 
   22360             : 
   22361       26645 : THREADED_TEST(Regress157124) {
   22362           6 :   LocalContext context;
   22363           6 :   v8::Isolate* isolate = context->GetIsolate();
   22364          12 :   v8::HandleScope scope(isolate);
   22365           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22366           6 :   Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   22367           6 :   obj->GetIdentityHash();
   22368          12 :   obj->DeletePrivate(context.local(),
   22369           6 :                      v8::Private::ForApi(isolate, v8_str("Bug")))
   22370             :       .FromJust();
   22371           6 : }
   22372             : 
   22373             : 
   22374       26645 : THREADED_TEST(Regress2535) {
   22375           6 :   LocalContext context;
   22376          12 :   v8::HandleScope scope(context->GetIsolate());
   22377             :   Local<Value> set_value = CompileRun("new Set();");
   22378             :   Local<Object> set_object(Local<Object>::Cast(set_value));
   22379           6 :   CHECK_EQ(0, set_object->InternalFieldCount());
   22380             :   Local<Value> map_value = CompileRun("new Map();");
   22381             :   Local<Object> map_object(Local<Object>::Cast(map_value));
   22382           6 :   CHECK_EQ(0, map_object->InternalFieldCount());
   22383           6 : }
   22384             : 
   22385             : 
   22386       26645 : THREADED_TEST(Regress2746) {
   22387           6 :   LocalContext context;
   22388           6 :   v8::Isolate* isolate = context->GetIsolate();
   22389          12 :   v8::HandleScope scope(isolate);
   22390           6 :   Local<Object> obj = Object::New(isolate);
   22391           6 :   Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
   22392          12 :   CHECK(
   22393             :       obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
   22394           6 :   Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
   22395           6 :   CHECK(!value.IsEmpty());
   22396           6 :   CHECK(value->IsUndefined());
   22397           6 : }
   22398             : 
   22399             : 
   22400       26645 : THREADED_TEST(Regress260106) {
   22401           6 :   LocalContext context;
   22402           6 :   v8::Isolate* isolate = context->GetIsolate();
   22403          12 :   v8::HandleScope scope(isolate);
   22404             :   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
   22405           6 :                                                         DummyCallHandler);
   22406             :   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   22407             :   Local<Function> function =
   22408           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   22409           6 :   CHECK(!function.IsEmpty());
   22410           6 :   CHECK(function->IsFunction());
   22411           6 : }
   22412             : 
   22413       26645 : THREADED_TEST(JSONParseObject) {
   22414           6 :   LocalContext context;
   22415          12 :   HandleScope scope(context->GetIsolate());
   22416             :   Local<Value> obj =
   22417          18 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22418           6 :   Local<Object> global = context->Global();
   22419          18 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22420           6 :   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   22421           6 : }
   22422             : 
   22423       26645 : THREADED_TEST(JSONParseNumber) {
   22424           6 :   LocalContext context;
   22425          12 :   HandleScope scope(context->GetIsolate());
   22426             :   Local<Value> obj =
   22427          18 :       v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
   22428           6 :   Local<Object> global = context->Global();
   22429          18 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22430           6 :   ExpectString("JSON.stringify(obj)", "42");
   22431           6 : }
   22432             : 
   22433             : namespace {
   22434          42 : void TestJSONParseArray(Local<Context> context, const char* input_str,
   22435             :                         const char* expected_output_str,
   22436             :                         i::ElementsKind expected_elements_kind) {
   22437             :   Local<Value> obj =
   22438          42 :       v8::JSON::Parse(context, v8_str(input_str)).ToLocalChecked();
   22439             : 
   22440             :   i::Handle<i::JSArray> a =
   22441             :       i::Handle<i::JSArray>::cast(v8::Utils::OpenHandle(*obj));
   22442          42 :   CHECK_EQ(expected_elements_kind, a->GetElementsKind());
   22443             : 
   22444          42 :   Local<Object> global = context->Global();
   22445         126 :   global->Set(context, v8_str("obj"), obj).FromJust();
   22446          42 :   ExpectString("JSON.stringify(obj)", expected_output_str);
   22447          42 : }
   22448             : }  // namespace
   22449             : 
   22450       26645 : THREADED_TEST(JSONParseArray) {
   22451           6 :   LocalContext context;
   22452          12 :   HandleScope scope(context->GetIsolate());
   22453             : 
   22454             :   TestJSONParseArray(context.local(), "[0, 1, 2]", "[0,1,2]",
   22455           6 :                      i::PACKED_SMI_ELEMENTS);
   22456             :   TestJSONParseArray(context.local(), "[0, 1.2, 2]", "[0,1.2,2]",
   22457           6 :                      i::PACKED_DOUBLE_ELEMENTS);
   22458             :   TestJSONParseArray(context.local(), "[0.2, 1, 2]", "[0.2,1,2]",
   22459           6 :                      i::PACKED_DOUBLE_ELEMENTS);
   22460             :   TestJSONParseArray(context.local(), "[0, \"a\", 2]", "[0,\"a\",2]",
   22461           6 :                      i::PACKED_ELEMENTS);
   22462             :   TestJSONParseArray(context.local(), "[\"a\", 1, 2]", "[\"a\",1,2]",
   22463           6 :                      i::PACKED_ELEMENTS);
   22464             :   TestJSONParseArray(context.local(), "[\"a\", 1.2, 2]", "[\"a\",1.2,2]",
   22465           6 :                      i::PACKED_ELEMENTS);
   22466             :   TestJSONParseArray(context.local(), "[0, 1.2, \"a\"]", "[0,1.2,\"a\"]",
   22467           6 :                      i::PACKED_ELEMENTS);
   22468           6 : }
   22469             : 
   22470       26645 : THREADED_TEST(JSONStringifyObject) {
   22471           6 :   LocalContext context;
   22472          12 :   HandleScope scope(context->GetIsolate());
   22473             :   Local<Value> value =
   22474          12 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22475           6 :   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   22476           6 :   Local<Object> global = context->Global();
   22477          18 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22478             :   Local<String> json =
   22479          12 :       v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
   22480          12 :   v8::String::Utf8Value utf8(context->GetIsolate(), json);
   22481           6 :   ExpectString("JSON.stringify(obj)", *utf8);
   22482           6 : }
   22483             : 
   22484       26645 : THREADED_TEST(JSONStringifyObjectWithGap) {
   22485           6 :   LocalContext context;
   22486          12 :   HandleScope scope(context->GetIsolate());
   22487             :   Local<Value> value =
   22488          12 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22489           6 :   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   22490           6 :   Local<Object> global = context->Global();
   22491          18 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22492             :   Local<String> json =
   22493          18 :       v8::JSON::Stringify(context.local(), obj, v8_str("*")).ToLocalChecked();
   22494          12 :   v8::String::Utf8Value utf8(context->GetIsolate(), json);
   22495           6 :   ExpectString("JSON.stringify(obj, null,  '*')", *utf8);
   22496           6 : }
   22497             : 
   22498             : #if V8_OS_POSIX
   22499             : class ThreadInterruptTest {
   22500             :  public:
   22501           6 :   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
   22502           6 :   ~ThreadInterruptTest() = default;
   22503             : 
   22504           6 :   void RunTest() {
   22505             :     InterruptThread i_thread(this);
   22506           6 :     i_thread.Start();
   22507             : 
   22508           6 :     sem_.Wait();
   22509           6 :     CHECK_EQ(kExpectedValue, sem_value_);
   22510           6 :   }
   22511             : 
   22512             :  private:
   22513             :   static const int kExpectedValue = 1;
   22514             : 
   22515           6 :   class InterruptThread : public v8::base::Thread {
   22516             :    public:
   22517             :     explicit InterruptThread(ThreadInterruptTest* test)
   22518           6 :         : Thread(Options("InterruptThread")), test_(test) {}
   22519             : 
   22520           6 :     void Run() override {
   22521             :       struct sigaction action;
   22522             : 
   22523             :       // Ensure that we'll enter waiting condition
   22524           6 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   22525             : 
   22526             :       // Setup signal handler
   22527             :       memset(&action, 0, sizeof(action));
   22528           6 :       action.sa_handler = SignalHandler;
   22529           6 :       sigaction(SIGCHLD, &action, nullptr);
   22530             : 
   22531             :       // Send signal
   22532           6 :       kill(getpid(), SIGCHLD);
   22533             : 
   22534             :       // Ensure that if wait has returned because of error
   22535           6 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   22536             : 
   22537             :       // Set value and signal semaphore
   22538           6 :       test_->sem_value_ = 1;
   22539           6 :       test_->sem_.Signal();
   22540           6 :     }
   22541             : 
   22542           6 :     static void SignalHandler(int signal) {
   22543           6 :     }
   22544             : 
   22545             :    private:
   22546             :      ThreadInterruptTest* test_;
   22547             :   };
   22548             : 
   22549             :   v8::base::Semaphore sem_;
   22550             :   volatile int sem_value_;
   22551             : };
   22552             : 
   22553             : 
   22554       26645 : THREADED_TEST(SemaphoreInterruption) {
   22555          12 :   ThreadInterruptTest().RunTest();
   22556           6 : }
   22557             : 
   22558             : 
   22559             : #endif  // V8_OS_POSIX
   22560             : 
   22561             : 
   22562           0 : void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22563           0 :   UNREACHABLE();
   22564             : }
   22565             : 
   22566             : 
   22567       26644 : TEST(JSONStringifyAccessCheck) {
   22568           5 :   v8::V8::Initialize();
   22569           5 :   v8::Isolate* isolate = CcTest::isolate();
   22570          10 :   v8::HandleScope scope(isolate);
   22571             : 
   22572             :   // Create an ObjectTemplate for global objects and install access
   22573             :   // check callbacks that will block access.
   22574             :   v8::Local<v8::ObjectTemplate> global_template =
   22575           5 :       v8::ObjectTemplate::New(isolate);
   22576           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   22577             : 
   22578             :   // Create a context and set an x property on it's global object.
   22579           5 :   LocalContext context0(nullptr, global_template);
   22580           5 :   v8::Local<v8::Object> global0 = context0->Global();
   22581          15 :   global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
   22582           5 :   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   22583             : 
   22584          25 :   for (int i = 0; i < 2; i++) {
   22585          10 :     if (i == 1) {
   22586             :       // Install a toJSON function on the second run.
   22587             :       v8::Local<v8::FunctionTemplate> toJSON =
   22588           5 :           v8::FunctionTemplate::New(isolate, UnreachableCallback);
   22589             : 
   22590          10 :       global0->Set(context0.local(), v8_str("toJSON"),
   22591          15 :                    toJSON->GetFunction(context0.local()).ToLocalChecked())
   22592             :           .FromJust();
   22593             :     }
   22594             :     // Create a context with a different security token so that the
   22595             :     // failed access check callback will be called on each access.
   22596          10 :     LocalContext context1(nullptr, global_template);
   22597          40 :     CHECK(context1->Global()
   22598             :               ->Set(context1.local(), v8_str("other"), global0)
   22599             :               .FromJust());
   22600             : 
   22601          10 :     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
   22602          10 :     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
   22603          10 :     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
   22604             :   }
   22605           5 : }
   22606             : 
   22607             : 
   22608             : bool access_check_fail_thrown = false;
   22609             : bool catch_callback_called = false;
   22610             : 
   22611             : 
   22612             : // Failed access check callback that performs a GC on each invocation.
   22613          80 : void FailedAccessCheckThrows(Local<v8::Object> target,
   22614             :                              v8::AccessType type,
   22615             :                              Local<v8::Value> data) {
   22616          80 :   access_check_fail_thrown = true;
   22617          80 :   i::PrintF("Access check failed. Error thrown.\n");
   22618             :   CcTest::isolate()->ThrowException(
   22619          80 :       v8::Exception::Error(v8_str("cross context")));
   22620          80 : }
   22621             : 
   22622             : 
   22623          75 : void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22624         225 :   for (int i = 0; i < args.Length(); i++) {
   22625          75 :     i::PrintF("%s\n", *String::Utf8Value(args.GetIsolate(), args[i]));
   22626             :   }
   22627          75 :   catch_callback_called = true;
   22628          75 : }
   22629             : 
   22630             : 
   22631           5 : void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22632           5 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   22633          20 :   CHECK(
   22634             :       args[0]
   22635             :           ->ToObject(context)
   22636             :           .ToLocalChecked()
   22637             :           ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
   22638             :           .IsNothing());
   22639           5 : }
   22640             : 
   22641             : 
   22642          75 : void CheckCorrectThrow(const char* script) {
   22643             :   // Test that the script, when wrapped into a try-catch, triggers the catch
   22644             :   // clause due to failed access check throwing an exception.
   22645             :   // The subsequent try-catch should run without any exception.
   22646          75 :   access_check_fail_thrown = false;
   22647          75 :   catch_callback_called = false;
   22648             :   i::ScopedVector<char> source(1024);
   22649          75 :   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   22650             :   CompileRun(source.start());
   22651          75 :   CHECK(access_check_fail_thrown);
   22652          75 :   CHECK(catch_callback_called);
   22653             : 
   22654          75 :   access_check_fail_thrown = false;
   22655          75 :   catch_callback_called = false;
   22656             :   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   22657          75 :   CHECK(!access_check_fail_thrown);
   22658          75 :   CHECK(!catch_callback_called);
   22659          75 : }
   22660             : 
   22661             : 
   22662       26644 : TEST(AccessCheckThrows) {
   22663           5 :   i::FLAG_allow_natives_syntax = true;
   22664           5 :   v8::V8::Initialize();
   22665           5 :   v8::Isolate* isolate = CcTest::isolate();
   22666           5 :   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   22667          10 :   v8::HandleScope scope(isolate);
   22668             : 
   22669             :   // Create an ObjectTemplate for global objects and install access
   22670             :   // check callbacks that will block access.
   22671             :   v8::Local<v8::ObjectTemplate> global_template =
   22672           5 :       v8::ObjectTemplate::New(isolate);
   22673           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   22674             : 
   22675             :   // Create a context and set an x property on it's global object.
   22676           5 :   LocalContext context0(nullptr, global_template);
   22677           5 :   v8::Local<v8::Object> global0 = context0->Global();
   22678          15 :   CHECK(global0->Set(context0.local(), v8_str("x"), global0).FromJust());
   22679             : 
   22680             :   // Create a context with a different security token so that the
   22681             :   // failed access check callback will be called on each access.
   22682           5 :   LocalContext context1(nullptr, global_template);
   22683          20 :   CHECK(context1->Global()
   22684             :             ->Set(context1.local(), v8_str("other"), global0)
   22685             :             .FromJust());
   22686             : 
   22687             :   v8::Local<v8::FunctionTemplate> catcher_fun =
   22688           5 :       v8::FunctionTemplate::New(isolate, CatcherCallback);
   22689          25 :   CHECK(context1->Global()
   22690             :             ->Set(context1.local(), v8_str("catcher"),
   22691             :                   catcher_fun->GetFunction(context1.local()).ToLocalChecked())
   22692             :             .FromJust());
   22693             : 
   22694             :   v8::Local<v8::FunctionTemplate> has_own_property_fun =
   22695           5 :       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
   22696          25 :   CHECK(context1->Global()
   22697             :             ->Set(context1.local(), v8_str("has_own_property"),
   22698             :                   has_own_property_fun->GetFunction(context1.local())
   22699             :                       .ToLocalChecked())
   22700             :             .FromJust());
   22701             : 
   22702             :   {
   22703          10 :     v8::TryCatch try_catch(isolate);
   22704           5 :     access_check_fail_thrown = false;
   22705             :     CompileRun("other.x;");
   22706           5 :     CHECK(access_check_fail_thrown);
   22707           5 :     CHECK(try_catch.HasCaught());
   22708             :   }
   22709             : 
   22710           5 :   CheckCorrectThrow("other.x");
   22711           5 :   CheckCorrectThrow("other[1]");
   22712           5 :   CheckCorrectThrow("JSON.stringify(other)");
   22713           5 :   CheckCorrectThrow("has_own_property(other, 'x')");
   22714           5 :   CheckCorrectThrow("%GetProperty(other, 'x')");
   22715           5 :   CheckCorrectThrow("%SetKeyedProperty(other, 'x', 'foo')");
   22716           5 :   CheckCorrectThrow("%SetNamedProperty(other, 'y', 'foo')");
   22717             :   STATIC_ASSERT(static_cast<int>(i::LanguageMode::kSloppy) == 0);
   22718             :   STATIC_ASSERT(static_cast<int>(i::LanguageMode::kStrict) == 1);
   22719           5 :   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");  // 0 == SLOPPY
   22720           5 :   CheckCorrectThrow("%DeleteProperty(other, 'x', 1)");  // 1 == STRICT
   22721           5 :   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
   22722           5 :   CheckCorrectThrow("%DeleteProperty(other, '1', 1)");
   22723           5 :   CheckCorrectThrow("Object.prototype.hasOwnProperty.call(other, 'x')");
   22724           5 :   CheckCorrectThrow("%HasProperty(other, 'x')");
   22725           5 :   CheckCorrectThrow("Object.prototype.propertyIsEnumerable(other, 'x')");
   22726             :   // PROPERTY_ATTRIBUTES_NONE = 0
   22727             :   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
   22728           5 :                         "other, 'x', null, null, 1)");
   22729             : 
   22730             :   // Reset the failed access check callback so it does not influence
   22731             :   // the other tests.
   22732           5 :   isolate->SetFailedAccessCheckCallbackFunction(nullptr);
   22733           5 : }
   22734             : 
   22735             : namespace {
   22736             : 
   22737             : const char kOneByteSubjectString[] = {
   22738             :     'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
   22739             :     'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
   22740             :     'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', '\0'};
   22741             : const uint16_t kTwoByteSubjectString[] = {
   22742             :     'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
   22743             :     'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
   22744             :     'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', '\0'};
   22745             : 
   22746             : const int kSubjectStringLength = arraysize(kOneByteSubjectString) - 1;
   22747             : STATIC_ASSERT(arraysize(kOneByteSubjectString) ==
   22748             :               arraysize(kTwoByteSubjectString));
   22749             : 
   22750       26639 : OneByteVectorResource one_byte_string_resource(
   22751             :     i::Vector<const char>(&kOneByteSubjectString[0], kSubjectStringLength));
   22752       26639 : UC16VectorResource two_byte_string_resource(
   22753             :     i::Vector<const i::uc16>(&kTwoByteSubjectString[0], kSubjectStringLength));
   22754             : 
   22755          45 : class RegExpInterruptTest {
   22756             :  public:
   22757          15 :   RegExpInterruptTest()
   22758             :       : i_thread(this),
   22759             :         env_(),
   22760          15 :         isolate_(env_->GetIsolate()),
   22761             :         sem_(0),
   22762             :         ran_test_body_(false),
   22763          45 :         ran_to_completion_(false) {}
   22764             : 
   22765          15 :   void RunTest(v8::InterruptCallback test_body_fn) {
   22766          30 :     v8::HandleScope handle_scope(isolate_);
   22767             : 
   22768             :     i_thread.SetTestBody(test_body_fn);
   22769          15 :     i_thread.Start();
   22770             : 
   22771          15 :     TestBody();
   22772             : 
   22773          15 :     i_thread.Join();
   22774          15 :   }
   22775             : 
   22776           5 :   static void CollectAllGarbage(v8::Isolate* isolate, void* data) {
   22777             :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   22778             :     i_isolate->heap()->PreciseCollectAllGarbage(
   22779           5 :         i::Heap::kNoGCFlags, i::GarbageCollectionReason::kRuntime);
   22780           5 :   }
   22781             : 
   22782           5 :   static void MakeSubjectOneByteExternal(v8::Isolate* isolate, void* data) {
   22783             :     auto instance = reinterpret_cast<RegExpInterruptTest*>(data);
   22784             : 
   22785          10 :     v8::HandleScope scope(isolate);
   22786             :     v8::Local<v8::String> string =
   22787             :         v8::Local<v8::String>::New(isolate, instance->string_handle_);
   22788           5 :     CHECK(string->CanMakeExternal());
   22789           5 :     string->MakeExternal(&one_byte_string_resource);
   22790           5 :   }
   22791             : 
   22792           5 :   static void MakeSubjectTwoByteExternal(v8::Isolate* isolate, void* data) {
   22793             :     auto instance = reinterpret_cast<RegExpInterruptTest*>(data);
   22794             : 
   22795          10 :     v8::HandleScope scope(isolate);
   22796             :     v8::Local<v8::String> string =
   22797             :         v8::Local<v8::String>::New(isolate, instance->string_handle_);
   22798           5 :     CHECK(string->CanMakeExternal());
   22799           5 :     string->MakeExternal(&two_byte_string_resource);
   22800           5 :   }
   22801             : 
   22802             :  private:
   22803          30 :   static void SignalSemaphore(v8::Isolate* isolate, void* data) {
   22804          30 :     reinterpret_cast<RegExpInterruptTest*>(data)->sem_.Signal();
   22805          30 :   }
   22806             : 
   22807          15 :   void CreateTestStrings() {
   22808          15 :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
   22809             : 
   22810             :     // The string must be in old space to support externalization.
   22811             :     i::Handle<i::String> i_string =
   22812             :         i_isolate->factory()->NewStringFromAsciiChecked(
   22813          15 :             &kOneByteSubjectString[0], i::AllocationType::kOld);
   22814             :     v8::Local<v8::String> string = v8::Utils::ToLocal(i_string);
   22815             : 
   22816          60 :     env_->Global()->Set(env_.local(), v8_str("a"), string).FromJust();
   22817             : 
   22818          15 :     string_handle_.Reset(env_->GetIsolate(), string);
   22819          15 :   }
   22820             : 
   22821          15 :   void TestBody() {
   22822          15 :     CHECK(!ran_test_body_.load());
   22823          15 :     CHECK(!ran_to_completion_.load());
   22824             : 
   22825          15 :     CreateTestStrings();
   22826             : 
   22827          30 :     v8::TryCatch try_catch(env_->GetIsolate());
   22828             : 
   22829          15 :     isolate_->RequestInterrupt(&SignalSemaphore, this);
   22830             :     CompileRun("/((a*)*)*b/.exec(a)");
   22831             : 
   22832          15 :     CHECK(try_catch.HasTerminated());
   22833          15 :     CHECK(ran_test_body_.load());
   22834          15 :     CHECK(ran_to_completion_.load());
   22835          15 :   }
   22836             : 
   22837          15 :   class InterruptThread : public v8::base::Thread {
   22838             :    public:
   22839             :     explicit InterruptThread(RegExpInterruptTest* test)
   22840          15 :         : Thread(Options("RegExpInterruptTest")), test_(test) {}
   22841             : 
   22842          15 :     void Run() override {
   22843          15 :       CHECK_NOT_NULL(test_body_fn_);
   22844             : 
   22845             :       // Wait for JS execution to start.
   22846          15 :       test_->sem_.Wait();
   22847             : 
   22848             :       // Sleep for a bit to allow irregexp execution to start up, then run the
   22849             :       // test body.
   22850          15 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   22851          15 :       test_->isolate_->RequestInterrupt(&RunTestBody, test_);
   22852          15 :       test_->isolate_->RequestInterrupt(&SignalSemaphore, test_);
   22853             : 
   22854             :       // Wait for the scheduled interrupt to signal.
   22855          15 :       test_->sem_.Wait();
   22856             : 
   22857             :       // Sleep again to resume irregexp execution, then terminate.
   22858          15 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   22859          15 :       test_->ran_to_completion_.store(true);
   22860          15 :       test_->isolate_->TerminateExecution();
   22861          15 :     }
   22862             : 
   22863          15 :     static void RunTestBody(v8::Isolate* isolate, void* data) {
   22864             :       auto instance = reinterpret_cast<RegExpInterruptTest*>(data);
   22865          15 :       instance->i_thread.test_body_fn_(isolate, data);
   22866             :       instance->ran_test_body_.store(true);
   22867          15 :     }
   22868             : 
   22869             :     void SetTestBody(v8::InterruptCallback callback) {
   22870          15 :       test_body_fn_ = callback;
   22871             :     }
   22872             : 
   22873             :    private:
   22874             :     v8::InterruptCallback test_body_fn_;
   22875             :     RegExpInterruptTest* test_;
   22876             :   };
   22877             : 
   22878             :   InterruptThread i_thread;
   22879             : 
   22880             :   LocalContext env_;
   22881             :   v8::Isolate* isolate_;
   22882             :   v8::base::Semaphore sem_;  // Coordinates between main and interrupt threads.
   22883             : 
   22884             :   v8::Persistent<v8::String> string_handle_;
   22885             : 
   22886             :   std::atomic<bool> ran_test_body_;
   22887             :   std::atomic<bool> ran_to_completion_;
   22888             : };
   22889             : 
   22890             : }  // namespace
   22891             : 
   22892       26644 : TEST(RegExpInterruptAndCollectAllGarbage) {
   22893           5 :   i::FLAG_always_compact = true;  // Move all movable objects on GC.
   22894          10 :   RegExpInterruptTest test;
   22895           5 :   test.RunTest(RegExpInterruptTest::CollectAllGarbage);
   22896           5 : }
   22897             : 
   22898       26644 : TEST(RegExpInterruptAndMakeSubjectOneByteExternal) {
   22899          10 :   RegExpInterruptTest test;
   22900           5 :   test.RunTest(RegExpInterruptTest::MakeSubjectOneByteExternal);
   22901           5 : }
   22902             : 
   22903       26644 : TEST(RegExpInterruptAndMakeSubjectTwoByteExternal) {
   22904          10 :   RegExpInterruptTest test;
   22905           5 :   test.RunTest(RegExpInterruptTest::MakeSubjectTwoByteExternal);
   22906           5 : }
   22907             : 
   22908             : class RequestInterruptTestBase {
   22909             :  public:
   22910          35 :   RequestInterruptTestBase()
   22911             :       : env_(),
   22912          35 :         isolate_(env_->GetIsolate()),
   22913             :         sem_(0),
   22914             :         warmup_(20000),
   22915          70 :         should_continue_(true) {
   22916          35 :   }
   22917             : 
   22918          35 :   virtual ~RequestInterruptTestBase() = default;
   22919             : 
   22920             :   virtual void StartInterruptThread() = 0;
   22921             : 
   22922             :   virtual void TestBody() = 0;
   22923             : 
   22924          35 :   void RunTest() {
   22925          35 :     StartInterruptThread();
   22926             : 
   22927          70 :     v8::HandleScope handle_scope(isolate_);
   22928             : 
   22929          35 :     TestBody();
   22930             : 
   22931             :     // Verify we arrived here because interruptor was called
   22932             :     // not due to a bug causing us to exit the loop too early.
   22933          35 :     CHECK(!should_continue());
   22934          35 :   }
   22935             : 
   22936             :   void WakeUpInterruptor() {
   22937          35 :     sem_.Signal();
   22938             :   }
   22939             : 
   22940             :   bool should_continue() const { return should_continue_; }
   22941             : 
   22942             :   bool ShouldContinue() {
   22943      810398 :     if (warmup_ > 0) {
   22944      600000 :       if (--warmup_ == 0) {
   22945             :         WakeUpInterruptor();
   22946             :       }
   22947             :     }
   22948             : 
   22949      810398 :     return should_continue_;
   22950             :   }
   22951             : 
   22952      702611 :   static void ShouldContinueCallback(
   22953             :       const v8::FunctionCallbackInfo<Value>& info) {
   22954             :     RequestInterruptTestBase* test =
   22955             :         reinterpret_cast<RequestInterruptTestBase*>(
   22956      702611 :             info.Data().As<v8::External>()->Value());
   22957             :     info.GetReturnValue().Set(test->ShouldContinue());
   22958      702611 :   }
   22959             : 
   22960             :   LocalContext env_;
   22961             :   v8::Isolate* isolate_;
   22962             :   v8::base::Semaphore sem_;
   22963             :   int warmup_;
   22964             :   bool should_continue_;
   22965             : };
   22966             : 
   22967             : 
   22968          60 : class RequestInterruptTestBaseWithSimpleInterrupt
   22969             :     : public RequestInterruptTestBase {
   22970             :  public:
   22971          60 :   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
   22972             : 
   22973          30 :   void StartInterruptThread() override { i_thread.Start(); }
   22974             : 
   22975             :  private:
   22976          30 :   class InterruptThread : public v8::base::Thread {
   22977             :    public:
   22978             :     explicit InterruptThread(RequestInterruptTestBase* test)
   22979          30 :         : Thread(Options("RequestInterruptTest")), test_(test) {}
   22980             : 
   22981          30 :     void Run() override {
   22982          30 :       test_->sem_.Wait();
   22983          30 :       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   22984          30 :     }
   22985             : 
   22986          30 :     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   22987             :       reinterpret_cast<RequestInterruptTestBase*>(data)->
   22988          30 :           should_continue_ = false;
   22989          30 :     }
   22990             : 
   22991             :    private:
   22992             :      RequestInterruptTestBase* test_;
   22993             :   };
   22994             : 
   22995             :   InterruptThread i_thread;
   22996             : };
   22997             : 
   22998             : 
   22999          10 : class RequestInterruptTestWithFunctionCall
   23000             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23001             :  public:
   23002           5 :   void TestBody() override {
   23003           5 :     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   23004          10 :                                          v8::External::New(isolate_, this))
   23005             :                                .ToLocalChecked();
   23006          20 :     CHECK(env_->Global()
   23007             :               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   23008             :               .FromJust());
   23009             : 
   23010             :     CompileRun("while (ShouldContinue()) { }");
   23011           5 :   }
   23012             : };
   23013             : 
   23014             : 
   23015          10 : class RequestInterruptTestWithMethodCall
   23016             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23017             :  public:
   23018           5 :   void TestBody() override {
   23019           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23020           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23021          20 :     proto->Set(v8_str("shouldContinue"),
   23022             :                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   23023           5 :                                      v8::External::New(isolate_, this)));
   23024          25 :     CHECK(env_->Global()
   23025             :               ->Set(env_.local(), v8_str("Klass"),
   23026             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23027             :               .FromJust());
   23028             : 
   23029             :     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   23030           5 :   }
   23031             : };
   23032             : 
   23033             : 
   23034          10 : class RequestInterruptTestWithAccessor
   23035             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23036             :  public:
   23037           5 :   void TestBody() override {
   23038           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23039           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23040          15 :     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
   23041           5 :         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   23042          25 :     CHECK(env_->Global()
   23043             :               ->Set(env_.local(), v8_str("Klass"),
   23044             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23045             :               .FromJust());
   23046             : 
   23047             :     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   23048           5 :   }
   23049             : };
   23050             : 
   23051             : 
   23052          10 : class RequestInterruptTestWithNativeAccessor
   23053             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23054             :  public:
   23055           5 :   void TestBody() override {
   23056           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23057          15 :     t->InstanceTemplate()->SetNativeDataProperty(
   23058             :         v8_str("shouldContinue"), &ShouldContinueNativeGetter, nullptr,
   23059           5 :         v8::External::New(isolate_, this));
   23060          25 :     CHECK(env_->Global()
   23061             :               ->Set(env_.local(), v8_str("Klass"),
   23062             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23063             :               .FromJust());
   23064             : 
   23065             :     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   23066           5 :   }
   23067             : 
   23068             :  private:
   23069      107787 :   static void ShouldContinueNativeGetter(
   23070             :       Local<String> property,
   23071             :       const v8::PropertyCallbackInfo<v8::Value>& info) {
   23072             :     RequestInterruptTestBase* test =
   23073             :         reinterpret_cast<RequestInterruptTestBase*>(
   23074      107787 :             info.Data().As<v8::External>()->Value());
   23075             :     info.GetReturnValue().Set(test->ShouldContinue());
   23076      107787 :   }
   23077             : };
   23078             : 
   23079             : 
   23080          10 : class RequestInterruptTestWithMethodCallAndInterceptor
   23081             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23082             :  public:
   23083           5 :   void TestBody() override {
   23084           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23085           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23086          20 :     proto->Set(v8_str("shouldContinue"),
   23087             :                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   23088           5 :                                      v8::External::New(isolate_, this)));
   23089           5 :     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
   23090           5 :     instance_template->SetHandler(
   23091           5 :         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
   23092             : 
   23093          25 :     CHECK(env_->Global()
   23094             :               ->Set(env_.local(), v8_str("Klass"),
   23095             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23096             :               .FromJust());
   23097             : 
   23098             :     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   23099           5 :   }
   23100             : 
   23101             :  private:
   23102      121078 :   static void EmptyInterceptor(
   23103      121078 :       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   23104             : };
   23105             : 
   23106             : 
   23107          10 : class RequestInterruptTestWithMathAbs
   23108             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23109             :  public:
   23110           5 :   void TestBody() override {
   23111          10 :     env_->Global()
   23112          10 :         ->Set(env_.local(), v8_str("WakeUpInterruptor"),
   23113           5 :               Function::New(env_.local(), WakeUpInterruptorCallback,
   23114          10 :                             v8::External::New(isolate_, this))
   23115          10 :                   .ToLocalChecked())
   23116             :         .FromJust();
   23117             : 
   23118          10 :     env_->Global()
   23119          10 :         ->Set(env_.local(), v8_str("ShouldContinue"),
   23120           5 :               Function::New(env_.local(), ShouldContinueCallback,
   23121          10 :                             v8::External::New(isolate_, this))
   23122          10 :                   .ToLocalChecked())
   23123             :         .FromJust();
   23124             : 
   23125           5 :     i::FLAG_allow_natives_syntax = true;
   23126             :     CompileRun("function loopish(o) {"
   23127             :                "  var pre = 10;"
   23128             :                "  while (o.abs(1) > 0) {"
   23129             :                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
   23130             :                "    if (pre > 0) {"
   23131             :                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
   23132             :                "    }"
   23133             :                "  }"
   23134             :                "}"
   23135             :                "var i = 50;"
   23136             :                "var obj = {abs: function () { return i-- }, x: null};"
   23137             :                "delete obj.x;"
   23138             :                "loopish(obj);"
   23139             :                "%OptimizeFunctionOnNextCall(loopish);"
   23140             :                "loopish(Math);");
   23141             : 
   23142           5 :     i::FLAG_allow_natives_syntax = false;
   23143           5 :   }
   23144             : 
   23145             :  private:
   23146          10 :   static void WakeUpInterruptorCallback(
   23147             :       const v8::FunctionCallbackInfo<Value>& info) {
   23148          10 :     if (!info[0]->BooleanValue(info.GetIsolate())) {
   23149             :       return;
   23150             :     }
   23151             : 
   23152             :     RequestInterruptTestBase* test =
   23153             :         reinterpret_cast<RequestInterruptTestBase*>(
   23154           5 :             info.Data().As<v8::External>()->Value());
   23155             :     test->WakeUpInterruptor();
   23156             :   }
   23157             : 
   23158        7538 :   static void ShouldContinueCallback(
   23159             :       const v8::FunctionCallbackInfo<Value>& info) {
   23160             :     RequestInterruptTestBase* test =
   23161             :         reinterpret_cast<RequestInterruptTestBase*>(
   23162        7538 :             info.Data().As<v8::External>()->Value());
   23163             :     info.GetReturnValue().Set(test->should_continue());
   23164        7538 :   }
   23165             : };
   23166             : 
   23167             : 
   23168       26644 : TEST(RequestInterruptTestWithFunctionCall) {
   23169          15 :   RequestInterruptTestWithFunctionCall().RunTest();
   23170           5 : }
   23171             : 
   23172             : 
   23173       26644 : TEST(RequestInterruptTestWithMethodCall) {
   23174          15 :   RequestInterruptTestWithMethodCall().RunTest();
   23175           5 : }
   23176             : 
   23177             : 
   23178       26644 : TEST(RequestInterruptTestWithAccessor) {
   23179          15 :   RequestInterruptTestWithAccessor().RunTest();
   23180           5 : }
   23181             : 
   23182             : 
   23183       26644 : TEST(RequestInterruptTestWithNativeAccessor) {
   23184          15 :   RequestInterruptTestWithNativeAccessor().RunTest();
   23185           5 : }
   23186             : 
   23187             : 
   23188       26644 : TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
   23189          15 :   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
   23190           5 : }
   23191             : 
   23192             : 
   23193       26644 : TEST(RequestInterruptTestWithMathAbs) {
   23194          15 :   RequestInterruptTestWithMathAbs().RunTest();
   23195           5 : }
   23196             : 
   23197             : 
   23198          10 : class RequestMultipleInterrupts : public RequestInterruptTestBase {
   23199             :  public:
   23200          10 :   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
   23201             : 
   23202           5 :   void StartInterruptThread() override { i_thread.Start(); }
   23203             : 
   23204           5 :   void TestBody() override {
   23205           5 :     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   23206          10 :                                          v8::External::New(isolate_, this))
   23207             :                                .ToLocalChecked();
   23208          20 :     CHECK(env_->Global()
   23209             :               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   23210             :               .FromJust());
   23211             : 
   23212             :     CompileRun("while (ShouldContinue()) { }");
   23213           5 :   }
   23214             : 
   23215             :  private:
   23216           5 :   class InterruptThread : public v8::base::Thread {
   23217             :    public:
   23218             :     enum { NUM_INTERRUPTS = 10 };
   23219             :     explicit InterruptThread(RequestMultipleInterrupts* test)
   23220           5 :         : Thread(Options("RequestInterruptTest")), test_(test) {}
   23221             : 
   23222           5 :     void Run() override {
   23223           5 :       test_->sem_.Wait();
   23224         105 :       for (int i = 0; i < NUM_INTERRUPTS; i++) {
   23225          50 :         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   23226             :       }
   23227           5 :     }
   23228             : 
   23229          50 :     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   23230             :       RequestMultipleInterrupts* test =
   23231             :           reinterpret_cast<RequestMultipleInterrupts*>(data);
   23232          50 :       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
   23233          50 :     }
   23234             : 
   23235             :    private:
   23236             :     RequestMultipleInterrupts* test_;
   23237             :   };
   23238             : 
   23239             :   InterruptThread i_thread;
   23240             :   int counter_;
   23241             : };
   23242             : 
   23243             : 
   23244       26644 : TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
   23245             : 
   23246             : 
   23247             : static bool interrupt_was_called = false;
   23248             : 
   23249             : 
   23250           5 : void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
   23251           5 :   interrupt_was_called = true;
   23252           5 : }
   23253             : 
   23254             : 
   23255       26644 : TEST(RequestInterruptSmallScripts) {
   23256           5 :   LocalContext env;
   23257           5 :   v8::Isolate* isolate = CcTest::isolate();
   23258          10 :   v8::HandleScope scope(isolate);
   23259             : 
   23260           5 :   interrupt_was_called = false;
   23261           5 :   isolate->RequestInterrupt(&SmallScriptsInterruptCallback, nullptr);
   23262             :   CompileRun("(function(x){return x;})(1);");
   23263           5 :   CHECK(interrupt_was_called);
   23264           5 : }
   23265             : 
   23266             : 
   23267             : static Local<Value> function_new_expected_env;
   23268          12 : static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
   23269          36 :   CHECK(
   23270             :       function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
   23271             :                                         info.Data())
   23272             :           .FromJust());
   23273             :   info.GetReturnValue().Set(17);
   23274          12 : }
   23275             : 
   23276             : 
   23277       26645 : THREADED_TEST(FunctionNew) {
   23278           6 :   LocalContext env;
   23279           6 :   v8::Isolate* isolate = env->GetIsolate();
   23280          12 :   v8::HandleScope scope(isolate);
   23281           6 :   Local<Object> data = v8::Object::New(isolate);
   23282           6 :   function_new_expected_env = data;
   23283             :   Local<Function> func =
   23284          12 :       Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
   23285          24 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   23286           6 :   Local<Value> result = CompileRun("func();");
   23287          18 :   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
   23288             :   // Serial number should be invalid => should not be cached.
   23289             :   auto serial_number =
   23290             :       i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
   23291             :                        ->shared()
   23292             :                        ->get_api_func_data()
   23293             :                        ->serial_number())
   23294             :           ->value();
   23295           6 :   CHECK_EQ(i::FunctionTemplateInfo::kInvalidSerialNumber, serial_number);
   23296             : 
   23297             :   // Verify that each Function::New creates a new function instance
   23298           6 :   Local<Object> data2 = v8::Object::New(isolate);
   23299           6 :   function_new_expected_env = data2;
   23300             :   Local<Function> func2 =
   23301          12 :       Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
   23302           6 :   CHECK(!func2->IsNull());
   23303          12 :   CHECK(!func->Equals(env.local(), func2).FromJust());
   23304          24 :   CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   23305           6 :   Local<Value> result2 = CompileRun("func2();");
   23306          18 :   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
   23307           6 : }
   23308             : 
   23309             : namespace {
   23310             : 
   23311             : void Verify(v8::Isolate* isolate, Local<v8::Object> obj) {
   23312             : #if VERIFY_HEAP
   23313             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   23314             :   i::Handle<i::JSReceiver> i_obj = v8::Utils::OpenHandle(*obj);
   23315             :   i_obj->ObjectVerify(i_isolate);
   23316             : #endif
   23317             : }
   23318             : 
   23319             : }  // namespace
   23320             : 
   23321       26645 : THREADED_TEST(ObjectNew) {
   23322           6 :   LocalContext env;
   23323           6 :   v8::Isolate* isolate = env->GetIsolate();
   23324          12 :   v8::HandleScope scope(isolate);
   23325             :   {
   23326             :     // Verify that Object::New(null) produces an object with a null
   23327             :     // [[Prototype]].
   23328             :     Local<v8::Object> obj =
   23329           6 :         v8::Object::New(isolate, v8::Null(isolate), nullptr, nullptr, 0);
   23330          12 :     CHECK(obj->GetPrototype()->IsNull());
   23331             :     Verify(isolate, obj);
   23332           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23333           6 :     CHECK_EQ(0, keys->Length());
   23334             :   }
   23335             :   {
   23336             :     // Verify that Object::New(proto) produces an object with
   23337             :     // proto as it's [[Prototype]].
   23338           6 :     Local<v8::Object> proto = v8::Object::New(isolate);
   23339             :     Local<v8::Object> obj =
   23340           6 :         v8::Object::New(isolate, proto, nullptr, nullptr, 0);
   23341             :     Verify(isolate, obj);
   23342          12 :     CHECK(obj->GetPrototype()->SameValue(proto));
   23343             :   }
   23344             :   {
   23345             :     // Verify that the properties are installed correctly.
   23346          18 :     Local<v8::Name> names[3] = {v8_str("a"), v8_str("b"), v8_str("c")};
   23347           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23348             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23349           6 :                                             values, arraysize(values));
   23350             :     Verify(isolate, obj);
   23351           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23352           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23353          42 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23354          36 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23355          36 :       CHECK(values[i]->SameValue(
   23356             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   23357             :     }
   23358             :   }
   23359             :   {
   23360             :     // Same as above, but with non-null prototype.
   23361           6 :     Local<v8::Object> proto = v8::Object::New(isolate);
   23362          18 :     Local<v8::Name> names[3] = {v8_str("x"), v8_str("y"), v8_str("z")};
   23363           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23364             :     Local<v8::Object> obj =
   23365           6 :         v8::Object::New(isolate, proto, names, values, arraysize(values));
   23366          12 :     CHECK(obj->GetPrototype()->SameValue(proto));
   23367             :     Verify(isolate, obj);
   23368           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23369           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23370          42 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23371          36 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23372          36 :       CHECK(values[i]->SameValue(
   23373             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   23374             :     }
   23375             :   }
   23376             :   {
   23377             :     // This has to work with duplicate names too.
   23378          18 :     Local<v8::Name> names[3] = {v8_str("a"), v8_str("a"), v8_str("a")};
   23379           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23380             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23381           6 :                                             values, arraysize(values));
   23382             :     Verify(isolate, obj);
   23383           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23384           6 :     CHECK_EQ(1, keys->Length());
   23385          18 :     CHECK(v8_str("a")->SameValue(keys->Get(env.local(), 0).ToLocalChecked()));
   23386          24 :     CHECK(v8_num(3)->SameValue(
   23387             :         obj->Get(env.local(), v8_str("a")).ToLocalChecked()));
   23388             :   }
   23389             :   {
   23390             :     // This has to work with array indices too.
   23391          12 :     Local<v8::Name> names[2] = {v8_str("0"), v8_str("1")};
   23392           6 :     Local<v8::Value> values[2] = {v8_num(0), v8_num(1)};
   23393             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23394           6 :                                             values, arraysize(values));
   23395             :     Verify(isolate, obj);
   23396           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23397           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23398          30 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23399          36 :       CHECK(v8::Number::New(isolate, i)
   23400             :                 ->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23401          24 :       CHECK(values[i]->SameValue(obj->Get(env.local(), i).ToLocalChecked()));
   23402             :     }
   23403             :   }
   23404             :   {
   23405             :     // This has to work with mixed array indices / property names too.
   23406          12 :     Local<v8::Name> names[2] = {v8_str("0"), v8_str("x")};
   23407           6 :     Local<v8::Value> values[2] = {v8_num(42), v8_num(24)};
   23408             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23409           6 :                                             values, arraysize(values));
   23410             :     Verify(isolate, obj);
   23411           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23412           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23413             :     // 0 -> 42
   23414          18 :     CHECK(v8_num(0)->SameValue(keys->Get(env.local(), 0).ToLocalChecked()));
   23415          12 :     CHECK(
   23416             :         values[0]->SameValue(obj->Get(env.local(), names[0]).ToLocalChecked()));
   23417             :     // "x" -> 24
   23418          18 :     CHECK(v8_str("x")->SameValue(keys->Get(env.local(), 1).ToLocalChecked()));
   23419          12 :     CHECK(
   23420             :         values[1]->SameValue(obj->Get(env.local(), names[1]).ToLocalChecked()));
   23421             :   }
   23422             :   {
   23423             :     // Verify that this also works for a couple thousand properties.
   23424             :     size_t const kLength = 10 * 1024;
   23425      122886 :     Local<v8::Name> names[kLength];
   23426      122886 :     Local<v8::Value> values[kLength];
   23427      122886 :     for (size_t i = 0; i < arraysize(names); ++i) {
   23428      122880 :       std::ostringstream ost;
   23429             :       ost << "a" << i;
   23430      122880 :       names[i] = v8_str(ost.str().c_str());
   23431       61440 :       values[i] = v8_num(static_cast<double>(i));
   23432             :     }
   23433             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23434           6 :                                             values, arraysize(names));
   23435             :     Verify(isolate, obj);
   23436           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23437           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23438      122886 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23439      122880 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23440      122880 :       CHECK(values[i]->SameValue(
   23441             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   23442             :     }
   23443             :   }
   23444           6 : }
   23445             : 
   23446       26644 : TEST(EscapableHandleScope) {
   23447          10 :   HandleScope outer_scope(CcTest::isolate());
   23448           5 :   LocalContext context;
   23449             :   const int runs = 10;
   23450         105 :   Local<String> values[runs];
   23451         105 :   for (int i = 0; i < runs; i++) {
   23452          50 :     v8::EscapableHandleScope inner_scope(CcTest::isolate());
   23453             :     Local<String> value;
   23454          50 :     if (i != 0) value = v8_str("escape value");
   23455          50 :     if (i < runs / 2) {
   23456          25 :       values[i] = inner_scope.Escape(value);
   23457             :     } else {
   23458             :       values[i] = inner_scope.EscapeMaybe(v8::MaybeLocal<String>(value))
   23459          25 :                       .ToLocalChecked();
   23460             :     }
   23461             :   }
   23462         105 :   for (int i = 0; i < runs; i++) {
   23463             :     Local<String> expected;
   23464          50 :     if (i != 0) {
   23465         135 :       CHECK(v8_str("escape value")
   23466             :                 ->Equals(context.local(), values[i])
   23467             :                 .FromJust());
   23468             :     } else {
   23469           5 :       CHECK(values[i].IsEmpty());
   23470             :     }
   23471             :   }
   23472           5 : }
   23473             : 
   23474             : 
   23475          20 : static void SetterWhichExpectsThisAndHolderToDiffer(
   23476             :     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
   23477          20 :   CHECK(info.Holder() != info.This());
   23478          20 : }
   23479             : 
   23480             : 
   23481       26644 : TEST(Regress239669) {
   23482           5 :   LocalContext context;
   23483           5 :   v8::Isolate* isolate = context->GetIsolate();
   23484          10 :   v8::HandleScope scope(isolate);
   23485           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   23486          10 :   templ->SetAccessor(v8_str("x"), nullptr,
   23487           5 :                      SetterWhichExpectsThisAndHolderToDiffer);
   23488          25 :   CHECK(context->Global()
   23489             :             ->Set(context.local(), v8_str("P"),
   23490             :                   templ->NewInstance(context.local()).ToLocalChecked())
   23491             :             .FromJust());
   23492             :   CompileRun(
   23493             :       "function C1() {"
   23494             :       "  this.x = 23;"
   23495             :       "};"
   23496             :       "C1.prototype = P;"
   23497             :       "for (var i = 0; i < 4; i++ ) {"
   23498             :       "  new C1();"
   23499             :       "}");
   23500           5 : }
   23501             : 
   23502             : 
   23503             : class ApiCallOptimizationChecker {
   23504             :  private:
   23505             :   static Local<Object> data;
   23506             :   static Local<Object> receiver;
   23507             :   static Local<Object> holder;
   23508             :   static Local<Object> callee;
   23509             :   static int count;
   23510             : 
   23511         270 :   static void OptimizationCallback(
   23512             :       const v8::FunctionCallbackInfo<v8::Value>& info) {
   23513         270 :     CHECK(data == info.Data());
   23514         270 :     CHECK(receiver == info.This());
   23515         270 :     if (info.Length() == 1) {
   23516         270 :       CHECK(v8_num(1)
   23517             :                 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
   23518             :                 .FromJust());
   23519             :     }
   23520         270 :     CHECK(holder == info.Holder());
   23521         270 :     count++;
   23522         270 :     info.GetReturnValue().Set(v8_str("returned"));
   23523         270 :   }
   23524             : 
   23525             :  public:
   23526             :   enum SignatureType {
   23527             :     kNoSignature,
   23528             :     kSignatureOnReceiver,
   23529             :     kSignatureOnPrototype
   23530             :   };
   23531             : 
   23532           5 :   void RunAll() {
   23533             :     SignatureType signature_types[] =
   23534           5 :       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
   23535          35 :     for (unsigned i = 0; i < arraysize(signature_types); i++) {
   23536          15 :       SignatureType signature_type = signature_types[i];
   23537          75 :       for (int j = 0; j < 2; j++) {
   23538          30 :         bool global = j == 0;
   23539             :         int key = signature_type +
   23540          30 :             arraysize(signature_types) * (global ? 1 : 0);
   23541          30 :         Run(signature_type, global, key);
   23542             :       }
   23543             :     }
   23544           5 :   }
   23545             : 
   23546          30 :   void Run(SignatureType signature_type, bool global, int key) {
   23547          30 :     v8::Isolate* isolate = CcTest::isolate();
   23548          60 :     v8::HandleScope scope(isolate);
   23549             :     // Build a template for signature checks.
   23550             :     Local<v8::ObjectTemplate> signature_template;
   23551             :     Local<v8::Signature> signature;
   23552             :     {
   23553             :       Local<v8::FunctionTemplate> parent_template =
   23554          30 :         FunctionTemplate::New(isolate);
   23555             :       Local<v8::FunctionTemplate> function_template
   23556          30 :           = FunctionTemplate::New(isolate);
   23557          30 :       function_template->Inherit(parent_template);
   23558          30 :       switch (signature_type) {
   23559             :         case kNoSignature:
   23560             :           break;
   23561             :         case kSignatureOnReceiver:
   23562          10 :           signature = v8::Signature::New(isolate, function_template);
   23563          10 :           break;
   23564             :         case kSignatureOnPrototype:
   23565          10 :           signature = v8::Signature::New(isolate, parent_template);
   23566          10 :           break;
   23567             :       }
   23568          30 :       signature_template = function_template->InstanceTemplate();
   23569             :     }
   23570             :     // Global object must pass checks.
   23571             :     Local<v8::Context> context =
   23572          30 :         v8::Context::New(isolate, nullptr, signature_template);
   23573             :     v8::Context::Scope context_scope(context);
   23574             :     // Install regular object that can pass signature checks.
   23575             :     Local<Object> function_receiver =
   23576          30 :         signature_template->NewInstance(context).ToLocalChecked();
   23577         120 :     CHECK(context->Global()
   23578             :               ->Set(context, v8_str("function_receiver"), function_receiver)
   23579             :               .FromJust());
   23580             :     // Get the holder objects.
   23581             :     Local<Object> inner_global =
   23582          60 :         Local<Object>::Cast(context->Global()->GetPrototype());
   23583          30 :     data = Object::New(isolate);
   23584             :     Local<FunctionTemplate> function_template = FunctionTemplate::New(
   23585          30 :         isolate, OptimizationCallback, data, signature);
   23586             :     Local<Function> function =
   23587          30 :         function_template->GetFunction(context).ToLocalChecked();
   23588             :     Local<Object> global_holder = inner_global;
   23589             :     Local<Object> function_holder = function_receiver;
   23590          30 :     if (signature_type == kSignatureOnPrototype) {
   23591          10 :       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
   23592          10 :       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
   23593             :     }
   23594          90 :     global_holder->Set(context, v8_str("g_f"), function).FromJust();
   23595          60 :     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
   23596          90 :     function_holder->Set(context, v8_str("f"), function).FromJust();
   23597          60 :     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
   23598             :     // Initialize expected values.
   23599          30 :     callee = function;
   23600          30 :     count = 0;
   23601          30 :     if (global) {
   23602          15 :       receiver = context->Global();
   23603          15 :       holder = inner_global;
   23604             :     } else {
   23605          15 :       holder = function_receiver;
   23606             :       // If not using a signature, add something else to the prototype chain
   23607             :       // to test the case that holder != receiver
   23608          15 :       if (signature_type == kNoSignature) {
   23609             :         receiver = Local<Object>::Cast(CompileRun(
   23610             :             "var receiver_subclass = {};\n"
   23611             :             "receiver_subclass.__proto__ = function_receiver;\n"
   23612           5 :             "receiver_subclass"));
   23613             :       } else {
   23614             :         receiver = Local<Object>::Cast(CompileRun(
   23615             :           "var receiver_subclass = function_receiver;\n"
   23616          10 :           "receiver_subclass"));
   23617             :       }
   23618             :     }
   23619             :     // With no signature, the holder is not set.
   23620          30 :     if (signature_type == kNoSignature) holder = receiver;
   23621             :     // build wrap_function
   23622             :     i::ScopedVector<char> wrap_function(200);
   23623          30 :     if (global) {
   23624             :       i::SNPrintF(
   23625             :           wrap_function,
   23626             :           "function wrap_f_%d() { var f = g_f; return f(); }\n"
   23627             :           "function wrap_get_%d() { return this.g_acc; }\n"
   23628             :           "function wrap_set_%d() { return this.g_acc = 1; }\n",
   23629          15 :           key, key, key);
   23630             :     } else {
   23631             :       i::SNPrintF(
   23632             :           wrap_function,
   23633             :           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
   23634             :           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
   23635             :           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
   23636          15 :           key, key, key);
   23637             :     }
   23638             :     // build source string
   23639             :     i::ScopedVector<char> source(1000);
   23640             :     i::SNPrintF(
   23641             :         source,
   23642             :         "%s\n"  // wrap functions
   23643             :         "function wrap_f() { return wrap_f_%d(); }\n"
   23644             :         "function wrap_get() { return wrap_get_%d(); }\n"
   23645             :         "function wrap_set() { return wrap_set_%d(); }\n"
   23646             :         "check = function(returned) {\n"
   23647             :         "  if (returned !== 'returned') { throw returned; }\n"
   23648             :         "}\n"
   23649             :         "\n"
   23650             :         "check(wrap_f());\n"
   23651             :         "check(wrap_f());\n"
   23652             :         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
   23653             :         "check(wrap_f());\n"
   23654             :         "\n"
   23655             :         "check(wrap_get());\n"
   23656             :         "check(wrap_get());\n"
   23657             :         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
   23658             :         "check(wrap_get());\n"
   23659             :         "\n"
   23660             :         "check = function(returned) {\n"
   23661             :         "  if (returned !== 1) { throw returned; }\n"
   23662             :         "}\n"
   23663             :         "check(wrap_set());\n"
   23664             :         "check(wrap_set());\n"
   23665             :         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
   23666             :         "check(wrap_set());\n",
   23667          30 :         wrap_function.start(), key, key, key, key, key, key);
   23668          60 :     v8::TryCatch try_catch(isolate);
   23669             :     CompileRun(source.start());
   23670          30 :     CHECK(!try_catch.HasCaught());
   23671          30 :     CHECK_EQ(9, count);
   23672          30 :   }
   23673             : };
   23674             : 
   23675             : 
   23676             : Local<Object> ApiCallOptimizationChecker::data;
   23677             : Local<Object> ApiCallOptimizationChecker::receiver;
   23678             : Local<Object> ApiCallOptimizationChecker::holder;
   23679             : Local<Object> ApiCallOptimizationChecker::callee;
   23680             : int ApiCallOptimizationChecker::count = 0;
   23681             : 
   23682             : 
   23683       26644 : TEST(FunctionCallOptimization) {
   23684           5 :   i::FLAG_allow_natives_syntax = true;
   23685             :   ApiCallOptimizationChecker checker;
   23686           5 :   checker.RunAll();
   23687           5 : }
   23688             : 
   23689             : 
   23690       26644 : TEST(FunctionCallOptimizationMultipleArgs) {
   23691           5 :   i::FLAG_allow_natives_syntax = true;
   23692           5 :   LocalContext context;
   23693           5 :   v8::Isolate* isolate = context->GetIsolate();
   23694          10 :   v8::HandleScope scope(isolate);
   23695           5 :   Local<Object> global = context->Global();
   23696             :   Local<v8::Function> function =
   23697          10 :       Function::New(context.local(), Returns42).ToLocalChecked();
   23698          15 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   23699             :   CompileRun(
   23700             :       "function x_wrap() {\n"
   23701             :       "  for (var i = 0; i < 5; i++) {\n"
   23702             :       "    x(1,2,3);\n"
   23703             :       "  }\n"
   23704             :       "}\n"
   23705             :       "x_wrap();\n"
   23706             :       "%OptimizeFunctionOnNextCall(x_wrap);"
   23707             :       "x_wrap();\n");
   23708           5 : }
   23709             : 
   23710             : 
   23711          50 : static void ReturnsSymbolCallback(
   23712             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   23713         100 :   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
   23714          50 : }
   23715             : 
   23716             : 
   23717       26644 : TEST(ApiCallbackCanReturnSymbols) {
   23718           5 :   i::FLAG_allow_natives_syntax = true;
   23719           5 :   LocalContext context;
   23720           5 :   v8::Isolate* isolate = context->GetIsolate();
   23721          10 :   v8::HandleScope scope(isolate);
   23722           5 :   Local<Object> global = context->Global();
   23723             :   Local<v8::Function> function =
   23724          10 :       Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
   23725          15 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   23726             :   CompileRun(
   23727             :       "function x_wrap() {\n"
   23728             :       "  for (var i = 0; i < 5; i++) {\n"
   23729             :       "    x();\n"
   23730             :       "  }\n"
   23731             :       "}\n"
   23732             :       "x_wrap();\n"
   23733             :       "%OptimizeFunctionOnNextCall(x_wrap);"
   23734             :       "x_wrap();\n");
   23735           5 : }
   23736             : 
   23737             : 
   23738       26644 : TEST(EmptyApiCallback) {
   23739           5 :   LocalContext context;
   23740           5 :   auto isolate = context->GetIsolate();
   23741          10 :   v8::HandleScope scope(isolate);
   23742           5 :   auto global = context->Global();
   23743          10 :   auto function = FunctionTemplate::New(isolate)
   23744           5 :                       ->GetFunction(context.local())
   23745             :                       .ToLocalChecked();
   23746          15 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   23747             : 
   23748             :   auto result = CompileRun("x()");
   23749           5 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23750             : 
   23751             :   result = CompileRun("x(1,2,3)");
   23752           5 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23753             : 
   23754             :   result = CompileRun("x.call(undefined)");
   23755           5 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23756             : 
   23757             :   result = CompileRun("x.call(null)");
   23758           5 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23759             : 
   23760             :   result = CompileRun("7 + x.call(3) + 11");
   23761           5 :   CHECK(result->IsInt32());
   23762          10 :   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   23763             : 
   23764             :   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
   23765           5 :   CHECK(result->IsInt32());
   23766          10 :   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   23767             : 
   23768             :   result = CompileRun("var y = []; x.call(y)");
   23769           5 :   CHECK(result->IsArray());
   23770             : 
   23771             :   result = CompileRun("x.call(y, 1, 2, 3, 4)");
   23772           5 :   CHECK(result->IsArray());
   23773           5 : }
   23774             : 
   23775             : 
   23776       26644 : TEST(SimpleSignatureCheck) {
   23777           5 :   LocalContext context;
   23778           5 :   auto isolate = context->GetIsolate();
   23779          10 :   v8::HandleScope scope(isolate);
   23780           5 :   auto global = context->Global();
   23781           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   23782           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   23783           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   23784          10 :   global->Set(context.local(), v8_str("sig_obj"),
   23785          15 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   23786             :       .FromJust();
   23787          10 :   global->Set(context.local(), v8_str("x"),
   23788          15 :               x->GetFunction(context.local()).ToLocalChecked())
   23789             :       .FromJust();
   23790             :   CompileRun("var s = new sig_obj();");
   23791             :   {
   23792          10 :     TryCatch try_catch(isolate);
   23793             :     CompileRun("x()");
   23794           5 :     CHECK(try_catch.HasCaught());
   23795             :   }
   23796             :   {
   23797          10 :     TryCatch try_catch(isolate);
   23798             :     CompileRun("x.call(1)");
   23799           5 :     CHECK(try_catch.HasCaught());
   23800             :   }
   23801             :   {
   23802          10 :     TryCatch try_catch(isolate);
   23803             :     auto result = CompileRun("s.x = x; s.x()");
   23804           5 :     CHECK(!try_catch.HasCaught());
   23805          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23806             :   }
   23807             :   {
   23808          10 :     TryCatch try_catch(isolate);
   23809             :     auto result = CompileRun("x.call(s)");
   23810           5 :     CHECK(!try_catch.HasCaught());
   23811          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23812             :   }
   23813           5 : }
   23814             : 
   23815             : 
   23816       26644 : TEST(ChainSignatureCheck) {
   23817           5 :   LocalContext context;
   23818           5 :   auto isolate = context->GetIsolate();
   23819          10 :   v8::HandleScope scope(isolate);
   23820           5 :   auto global = context->Global();
   23821           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   23822           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   23823          45 :   for (int i = 0; i < 4; ++i) {
   23824          20 :     auto temp = FunctionTemplate::New(isolate);
   23825          20 :     temp->Inherit(sig_obj);
   23826             :     sig_obj = temp;
   23827             :   }
   23828           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   23829          10 :   global->Set(context.local(), v8_str("sig_obj"),
   23830          15 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   23831             :       .FromJust();
   23832          10 :   global->Set(context.local(), v8_str("x"),
   23833          15 :               x->GetFunction(context.local()).ToLocalChecked())
   23834             :       .FromJust();
   23835             :   CompileRun("var s = new sig_obj();");
   23836             :   {
   23837          10 :     TryCatch try_catch(isolate);
   23838             :     CompileRun("x()");
   23839           5 :     CHECK(try_catch.HasCaught());
   23840             :   }
   23841             :   {
   23842          10 :     TryCatch try_catch(isolate);
   23843             :     CompileRun("x.call(1)");
   23844           5 :     CHECK(try_catch.HasCaught());
   23845             :   }
   23846             :   {
   23847          10 :     TryCatch try_catch(isolate);
   23848             :     auto result = CompileRun("s.x = x; s.x()");
   23849           5 :     CHECK(!try_catch.HasCaught());
   23850          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23851             :   }
   23852             :   {
   23853          10 :     TryCatch try_catch(isolate);
   23854             :     auto result = CompileRun("x.call(s)");
   23855           5 :     CHECK(!try_catch.HasCaught());
   23856          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23857             :   }
   23858           5 : }
   23859             : 
   23860             : 
   23861             : static const char* last_event_message;
   23862             : static int last_event_status;
   23863          10 : void StoringEventLoggerCallback(const char* message, int status) {
   23864          10 :     last_event_message = message;
   23865          10 :     last_event_status = status;
   23866          10 : }
   23867             : 
   23868             : 
   23869       26644 : TEST(EventLogging) {
   23870           5 :   v8::Isolate* isolate = CcTest::isolate();
   23871           5 :   isolate->SetEventLogger(StoringEventLoggerCallback);
   23872             :   v8::internal::HistogramTimer histogramTimer(
   23873             :       "V8.Test", 0, 10000, v8::internal::HistogramTimerResolution::MILLISECOND,
   23874             :       50, reinterpret_cast<v8::internal::Isolate*>(isolate)->counters());
   23875             :   histogramTimer.Start();
   23876           5 :   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   23877           5 :   CHECK_EQ(0, last_event_status);
   23878             :   histogramTimer.Stop();
   23879           5 :   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   23880           5 :   CHECK_EQ(1, last_event_status);
   23881           5 : }
   23882             : 
   23883       26644 : TEST(PropertyDescriptor) {
   23884           5 :   LocalContext context;
   23885           5 :   v8::Isolate* isolate = context->GetIsolate();
   23886          10 :   v8::HandleScope scope(isolate);
   23887             : 
   23888             :   {  // empty descriptor
   23889          10 :     v8::PropertyDescriptor desc;
   23890           5 :     CHECK(!desc.has_value());
   23891           5 :     CHECK(!desc.has_set());
   23892           5 :     CHECK(!desc.has_get());
   23893           5 :     CHECK(!desc.has_enumerable());
   23894           5 :     CHECK(!desc.has_configurable());
   23895           5 :     CHECK(!desc.has_writable());
   23896             :   }
   23897             :   {
   23898             :     // data descriptor
   23899          10 :     v8::PropertyDescriptor desc(v8_num(42));
   23900           5 :     desc.set_enumerable(false);
   23901          10 :     CHECK(desc.value() == v8_num(42));
   23902           5 :     CHECK(desc.has_value());
   23903           5 :     CHECK(!desc.has_set());
   23904           5 :     CHECK(!desc.has_get());
   23905           5 :     CHECK(desc.has_enumerable());
   23906           5 :     CHECK(!desc.enumerable());
   23907           5 :     CHECK(!desc.has_configurable());
   23908           5 :     CHECK(!desc.has_writable());
   23909             :   }
   23910             :   {
   23911             :     // data descriptor
   23912          10 :     v8::PropertyDescriptor desc(v8_num(42));
   23913           5 :     desc.set_configurable(true);
   23914          10 :     CHECK(desc.value() == v8_num(42));
   23915           5 :     CHECK(desc.has_value());
   23916           5 :     CHECK(!desc.has_set());
   23917           5 :     CHECK(!desc.has_get());
   23918           5 :     CHECK(desc.has_configurable());
   23919           5 :     CHECK(desc.configurable());
   23920           5 :     CHECK(!desc.has_enumerable());
   23921           5 :     CHECK(!desc.has_writable());
   23922             :   }
   23923             :   {
   23924             :     // data descriptor
   23925          10 :     v8::PropertyDescriptor desc(v8_num(42));
   23926           5 :     desc.set_configurable(false);
   23927          10 :     CHECK(desc.value() == v8_num(42));
   23928           5 :     CHECK(desc.has_value());
   23929           5 :     CHECK(!desc.has_set());
   23930           5 :     CHECK(!desc.has_get());
   23931           5 :     CHECK(desc.has_configurable());
   23932           5 :     CHECK(!desc.configurable());
   23933           5 :     CHECK(!desc.has_enumerable());
   23934           5 :     CHECK(!desc.has_writable());
   23935             :   }
   23936             :   {
   23937             :     // data descriptor
   23938          10 :     v8::PropertyDescriptor desc(v8_num(42), false);
   23939          10 :     CHECK(desc.value() == v8_num(42));
   23940           5 :     CHECK(desc.has_value());
   23941           5 :     CHECK(!desc.has_set());
   23942           5 :     CHECK(!desc.has_get());
   23943           5 :     CHECK(!desc.has_enumerable());
   23944           5 :     CHECK(!desc.has_configurable());
   23945           5 :     CHECK(desc.has_writable());
   23946           5 :     CHECK(!desc.writable());
   23947             :   }
   23948             :   {
   23949             :     // data descriptor
   23950          10 :     v8::PropertyDescriptor desc(v8::Local<v8::Value>(), true);
   23951           5 :     CHECK(!desc.has_value());
   23952           5 :     CHECK(!desc.has_set());
   23953           5 :     CHECK(!desc.has_get());
   23954           5 :     CHECK(!desc.has_enumerable());
   23955           5 :     CHECK(!desc.has_configurable());
   23956           5 :     CHECK(desc.has_writable());
   23957           5 :     CHECK(desc.writable());
   23958             :   }
   23959             :   {
   23960             :     // accessor descriptor
   23961             :     CompileRun("var set = function() {return 43;};");
   23962             : 
   23963             :     v8::Local<v8::Function> set =
   23964          10 :         v8::Local<v8::Function>::Cast(context->Global()
   23965          15 :                                           ->Get(context.local(), v8_str("set"))
   23966             :                                           .ToLocalChecked());
   23967          10 :     v8::PropertyDescriptor desc(v8::Undefined(isolate), set);
   23968           5 :     desc.set_configurable(false);
   23969           5 :     CHECK(!desc.has_value());
   23970           5 :     CHECK(desc.has_get());
   23971          10 :     CHECK(desc.get() == v8::Undefined(isolate));
   23972           5 :     CHECK(desc.has_set());
   23973          10 :     CHECK(desc.set() == set);
   23974           5 :     CHECK(!desc.has_enumerable());
   23975           5 :     CHECK(desc.has_configurable());
   23976           5 :     CHECK(!desc.configurable());
   23977           5 :     CHECK(!desc.has_writable());
   23978             :   }
   23979             :   {
   23980             :     // accessor descriptor with Proxy
   23981             :     CompileRun(
   23982             :         "var set = new Proxy(function() {}, {});"
   23983             :         "var get = undefined;");
   23984             : 
   23985             :     v8::Local<v8::Value> get =
   23986          10 :         v8::Local<v8::Value>::Cast(context->Global()
   23987          15 :                                        ->Get(context.local(), v8_str("get"))
   23988           5 :                                        .ToLocalChecked());
   23989             :     v8::Local<v8::Function> set =
   23990          10 :         v8::Local<v8::Function>::Cast(context->Global()
   23991          15 :                                           ->Get(context.local(), v8_str("set"))
   23992             :                                           .ToLocalChecked());
   23993          10 :     v8::PropertyDescriptor desc(get, set);
   23994           5 :     desc.set_configurable(false);
   23995           5 :     CHECK(!desc.has_value());
   23996          10 :     CHECK(desc.get() == v8::Undefined(isolate));
   23997           5 :     CHECK(desc.has_get());
   23998          10 :     CHECK(desc.set() == set);
   23999           5 :     CHECK(desc.has_set());
   24000           5 :     CHECK(!desc.has_enumerable());
   24001           5 :     CHECK(desc.has_configurable());
   24002           5 :     CHECK(!desc.configurable());
   24003           5 :     CHECK(!desc.has_writable());
   24004             :   }
   24005             :   {
   24006             :     // accessor descriptor with empty function handle
   24007             :     v8::Local<v8::Function> get = v8::Local<v8::Function>();
   24008          10 :     v8::PropertyDescriptor desc(get, get);
   24009           5 :     CHECK(!desc.has_value());
   24010           5 :     CHECK(!desc.has_get());
   24011           5 :     CHECK(!desc.has_set());
   24012           5 :     CHECK(!desc.has_enumerable());
   24013           5 :     CHECK(!desc.has_configurable());
   24014           5 :     CHECK(!desc.has_writable());
   24015             :   }
   24016           5 : }
   24017             : 
   24018       26644 : TEST(Promises) {
   24019           5 :   LocalContext context;
   24020           5 :   v8::Isolate* isolate = context->GetIsolate();
   24021          10 :   v8::HandleScope scope(isolate);
   24022             : 
   24023             :   // Creation.
   24024             :   Local<v8::Promise::Resolver> pr =
   24025           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24026             :   Local<v8::Promise::Resolver> rr =
   24027           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24028           5 :   Local<v8::Promise> p = pr->GetPromise();
   24029           5 :   Local<v8::Promise> r = rr->GetPromise();
   24030             : 
   24031             :   // IsPromise predicate.
   24032           5 :   CHECK(p->IsPromise());
   24033           5 :   CHECK(r->IsPromise());
   24034           5 :   Local<Value> o = v8::Object::New(isolate);
   24035           5 :   CHECK(!o->IsPromise());
   24036             : 
   24037             :   // Resolution and rejection.
   24038          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24039           5 :   CHECK(p->IsPromise());
   24040          15 :   rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
   24041           5 :   CHECK(r->IsPromise());
   24042           5 : }
   24043             : 
   24044             : // Promise.Then(on_fulfilled)
   24045       26644 : TEST(PromiseThen) {
   24046           5 :   LocalContext context;
   24047           5 :   v8::Isolate* isolate = context->GetIsolate();
   24048           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   24049          10 :   v8::HandleScope scope(isolate);
   24050           5 :   Local<Object> global = context->Global();
   24051             : 
   24052             :   // Creation.
   24053             :   Local<v8::Promise::Resolver> pr =
   24054           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24055             :   Local<v8::Promise::Resolver> qr =
   24056           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24057           5 :   Local<v8::Promise> p = pr->GetPromise();
   24058           5 :   Local<v8::Promise> q = qr->GetPromise();
   24059             : 
   24060           5 :   CHECK(p->IsPromise());
   24061           5 :   CHECK(q->IsPromise());
   24062             : 
   24063          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24064          10 :   qr->Resolve(context.local(), p).FromJust();
   24065             : 
   24066             :   // Chaining non-pending promises.
   24067             :   CompileRun(
   24068             :       "var x1 = 0;\n"
   24069             :       "var x2 = 0;\n"
   24070             :       "function f1(x) { x1 = x; return x+1 };\n"
   24071             :       "function f2(x) { x2 = x; return x+1 };\n");
   24072             :   Local<Function> f1 = Local<Function>::Cast(
   24073          15 :       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   24074             :   Local<Function> f2 = Local<Function>::Cast(
   24075          15 :       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   24076             : 
   24077             :   // Then
   24078             :   CompileRun("x1 = x2 = 0;");
   24079           5 :   q->Then(context.local(), f1).ToLocalChecked();
   24080          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24081             :                   .ToLocalChecked()
   24082             :                   ->Int32Value(context.local())
   24083             :                   .FromJust());
   24084           5 :   isolate->RunMicrotasks();
   24085          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24086             :                   .ToLocalChecked()
   24087             :                   ->Int32Value(context.local())
   24088             :                   .FromJust());
   24089             : 
   24090             :   // Then
   24091             :   CompileRun("x1 = x2 = 0;");
   24092           5 :   pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24093           5 :   qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24094             : 
   24095          10 :   qr->Resolve(context.local(), pr).FromJust();
   24096          10 :   qr->GetPromise()
   24097           5 :       ->Then(context.local(), f1)
   24098             :       .ToLocalChecked()
   24099           5 :       ->Then(context.local(), f2)
   24100             :       .ToLocalChecked();
   24101             : 
   24102          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24103             :                   .ToLocalChecked()
   24104             :                   ->Int32Value(context.local())
   24105             :                   .FromJust());
   24106          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24107             :                   .ToLocalChecked()
   24108             :                   ->Int32Value(context.local())
   24109             :                   .FromJust());
   24110           5 :   isolate->RunMicrotasks();
   24111          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24112             :                   .ToLocalChecked()
   24113             :                   ->Int32Value(context.local())
   24114             :                   .FromJust());
   24115          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24116             :                   .ToLocalChecked()
   24117             :                   ->Int32Value(context.local())
   24118             :                   .FromJust());
   24119             : 
   24120          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
   24121             : 
   24122          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24123             :                   .ToLocalChecked()
   24124             :                   ->Int32Value(context.local())
   24125             :                   .FromJust());
   24126          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24127             :                   .ToLocalChecked()
   24128             :                   ->Int32Value(context.local())
   24129             :                   .FromJust());
   24130           5 :   isolate->RunMicrotasks();
   24131          20 :   CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
   24132             :                   .ToLocalChecked()
   24133             :                   ->Int32Value(context.local())
   24134             :                   .FromJust());
   24135          20 :   CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
   24136             :                   .ToLocalChecked()
   24137             :                   ->Int32Value(context.local())
   24138             :                   .FromJust());
   24139           5 : }
   24140             : 
   24141             : // Promise.Then(on_fulfilled, on_rejected)
   24142       26644 : TEST(PromiseThen2) {
   24143           5 :   LocalContext context;
   24144           5 :   v8::Isolate* isolate = context->GetIsolate();
   24145           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   24146          10 :   v8::HandleScope scope(isolate);
   24147           5 :   Local<Object> global = context->Global();
   24148             : 
   24149             :   // Creation.
   24150             :   Local<v8::Promise::Resolver> pr =
   24151           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24152           5 :   Local<v8::Promise> p = pr->GetPromise();
   24153             : 
   24154           5 :   CHECK(p->IsPromise());
   24155             : 
   24156          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24157             : 
   24158             :   // Chaining non-pending promises.
   24159             :   CompileRun(
   24160             :       "var x1 = 0;\n"
   24161             :       "var x2 = 0;\n"
   24162             :       "function f1(x) { x1 = x; return x+1 };\n"
   24163             :       "function f2(x) { x2 = x; return x+1 };\n"
   24164             :       "function f3(x) { throw x + 100 };\n");
   24165             :   Local<Function> f1 = Local<Function>::Cast(
   24166          15 :       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   24167             :   Local<Function> f2 = Local<Function>::Cast(
   24168          15 :       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   24169             :   Local<Function> f3 = Local<Function>::Cast(
   24170          15 :       global->Get(context.local(), v8_str("f3")).ToLocalChecked());
   24171             : 
   24172             :   // Then
   24173             :   CompileRun("x1 = x2 = 0;");
   24174           5 :   Local<v8::Promise> a = p->Then(context.local(), f1, f2).ToLocalChecked();
   24175          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24176             :                   .ToLocalChecked()
   24177             :                   ->Int32Value(context.local())
   24178             :                   .FromJust());
   24179           5 :   isolate->RunMicrotasks();
   24180          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24181             :                   .ToLocalChecked()
   24182             :                   ->Int32Value(context.local())
   24183             :                   .FromJust());
   24184          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24185             :                   .ToLocalChecked()
   24186             :                   ->Int32Value(context.local())
   24187             :                   .FromJust());
   24188             : 
   24189           5 :   Local<v8::Promise> b = a->Then(context.local(), f3, f2).ToLocalChecked();
   24190           5 :   isolate->RunMicrotasks();
   24191          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24192             :                   .ToLocalChecked()
   24193             :                   ->Int32Value(context.local())
   24194             :                   .FromJust());
   24195          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24196             :                   .ToLocalChecked()
   24197             :                   ->Int32Value(context.local())
   24198             :                   .FromJust());
   24199             : 
   24200           5 :   Local<v8::Promise> c = b->Then(context.local(), f1, f2).ToLocalChecked();
   24201           5 :   isolate->RunMicrotasks();
   24202          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24203             :                   .ToLocalChecked()
   24204             :                   ->Int32Value(context.local())
   24205             :                   .FromJust());
   24206          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24207             :                     .ToLocalChecked()
   24208             :                     ->Int32Value(context.local())
   24209             :                     .FromJust());
   24210             : 
   24211           5 :   v8::Local<v8::Promise> d = c->Then(context.local(), f1, f2).ToLocalChecked();
   24212           5 :   isolate->RunMicrotasks();
   24213          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24214             :                     .ToLocalChecked()
   24215             :                     ->Int32Value(context.local())
   24216             :                     .FromJust());
   24217          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24218             :                     .ToLocalChecked()
   24219             :                     ->Int32Value(context.local())
   24220             :                     .FromJust());
   24221             : 
   24222           5 :   v8::Local<v8::Promise> e = d->Then(context.local(), f3, f2).ToLocalChecked();
   24223           5 :   isolate->RunMicrotasks();
   24224          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24225             :                     .ToLocalChecked()
   24226             :                     ->Int32Value(context.local())
   24227             :                     .FromJust());
   24228          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24229             :                     .ToLocalChecked()
   24230             :                     ->Int32Value(context.local())
   24231             :                     .FromJust());
   24232             : 
   24233           5 :   v8::Local<v8::Promise> f = e->Then(context.local(), f1, f3).ToLocalChecked();
   24234           5 :   isolate->RunMicrotasks();
   24235          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24236             :                     .ToLocalChecked()
   24237             :                     ->Int32Value(context.local())
   24238             :                     .FromJust());
   24239          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24240             :                     .ToLocalChecked()
   24241             :                     ->Int32Value(context.local())
   24242             :                     .FromJust());
   24243             : 
   24244           5 :   f->Then(context.local(), f1, f2).ToLocalChecked();
   24245           5 :   isolate->RunMicrotasks();
   24246          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24247             :                     .ToLocalChecked()
   24248             :                     ->Int32Value(context.local())
   24249             :                     .FromJust());
   24250          20 :   CHECK_EQ(304, global->Get(context.local(), v8_str("x2"))
   24251             :                     .ToLocalChecked()
   24252             :                     ->Int32Value(context.local())
   24253             :                     .FromJust());
   24254           5 : }
   24255             : 
   24256       26644 : TEST(PromiseStateAndValue) {
   24257           5 :   LocalContext context;
   24258           5 :   v8::Isolate* isolate = context->GetIsolate();
   24259          10 :   v8::HandleScope scope(isolate);
   24260             :   v8::Local<v8::Value> result = CompileRun(
   24261             :       "var resolver;"
   24262             :       "new Promise((res, rej) => { resolver = res; })");
   24263             :   v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(result);
   24264           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24265             : 
   24266             :   CompileRun("resolver('fulfilled')");
   24267           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24268          10 :   CHECK(v8_str("fulfilled")->SameValue(promise->Result()));
   24269             : 
   24270             :   result = CompileRun("Promise.reject('rejected')");
   24271             :   promise = v8::Local<v8::Promise>::Cast(result);
   24272           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24273          10 :   CHECK(v8_str("rejected")->SameValue(promise->Result()));
   24274           5 : }
   24275             : 
   24276       26644 : TEST(ResolvedPromiseReFulfill) {
   24277           5 :   LocalContext context;
   24278           5 :   v8::Isolate* isolate = context->GetIsolate();
   24279          10 :   v8::HandleScope scope(isolate);
   24280             :   v8::Local<v8::String> value1 =
   24281           5 :       v8::String::NewFromUtf8(isolate, "foo", v8::NewStringType::kNormal)
   24282             :           .ToLocalChecked();
   24283             :   v8::Local<v8::String> value2 =
   24284           5 :       v8::String::NewFromUtf8(isolate, "bar", v8::NewStringType::kNormal)
   24285             :           .ToLocalChecked();
   24286             : 
   24287             :   v8::Local<v8::Promise::Resolver> resolver =
   24288           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24289           5 :   v8::Local<v8::Promise> promise = resolver->GetPromise();
   24290           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24291             : 
   24292          10 :   resolver->Resolve(context.local(), value1).ToChecked();
   24293           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24294          10 :   CHECK_EQ(promise->Result(), value1);
   24295             : 
   24296             :   // This should be a no-op.
   24297          10 :   resolver->Resolve(context.local(), value2).ToChecked();
   24298           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24299          10 :   CHECK_EQ(promise->Result(), value1);
   24300             : 
   24301             :   // This should be a no-op.
   24302          10 :   resolver->Reject(context.local(), value2).ToChecked();
   24303           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24304          10 :   CHECK_EQ(promise->Result(), value1);
   24305           5 : }
   24306             : 
   24307       26644 : TEST(RejectedPromiseReFulfill) {
   24308           5 :   LocalContext context;
   24309           5 :   v8::Isolate* isolate = context->GetIsolate();
   24310          10 :   v8::HandleScope scope(isolate);
   24311             :   v8::Local<v8::String> value1 =
   24312           5 :       v8::String::NewFromUtf8(isolate, "foo", v8::NewStringType::kNormal)
   24313             :           .ToLocalChecked();
   24314             :   v8::Local<v8::String> value2 =
   24315           5 :       v8::String::NewFromUtf8(isolate, "bar", v8::NewStringType::kNormal)
   24316             :           .ToLocalChecked();
   24317             : 
   24318             :   v8::Local<v8::Promise::Resolver> resolver =
   24319           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24320           5 :   v8::Local<v8::Promise> promise = resolver->GetPromise();
   24321           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24322             : 
   24323          10 :   resolver->Reject(context.local(), value1).ToChecked();
   24324           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24325          10 :   CHECK_EQ(promise->Result(), value1);
   24326             : 
   24327             :   // This should be a no-op.
   24328          10 :   resolver->Reject(context.local(), value2).ToChecked();
   24329           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24330          10 :   CHECK_EQ(promise->Result(), value1);
   24331             : 
   24332             :   // This should be a no-op.
   24333          10 :   resolver->Resolve(context.local(), value2).ToChecked();
   24334           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24335          10 :   CHECK_EQ(promise->Result(), value1);
   24336           5 : }
   24337             : 
   24338       26639 : TEST(DisallowJavascriptExecutionScope) {
   24339           0 :   LocalContext context;
   24340           0 :   v8::Isolate* isolate = context->GetIsolate();
   24341           0 :   v8::HandleScope scope(isolate);
   24342             :   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   24343           0 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   24344             :   CompileRun("2+2");
   24345           0 : }
   24346             : 
   24347       26644 : TEST(AllowJavascriptExecutionScope) {
   24348           5 :   LocalContext context;
   24349           5 :   v8::Isolate* isolate = context->GetIsolate();
   24350          10 :   v8::HandleScope scope(isolate);
   24351             :   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   24352          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   24353             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   24354          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   24355          10 :   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
   24356             :     CompileRun("1+1");
   24357             :   }
   24358           5 : }
   24359             : 
   24360       26644 : TEST(ThrowOnJavascriptExecution) {
   24361           5 :   LocalContext context;
   24362           5 :   v8::Isolate* isolate = context->GetIsolate();
   24363          10 :   v8::HandleScope scope(isolate);
   24364          10 :   v8::TryCatch try_catch(isolate);
   24365             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   24366          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   24367             :   CompileRun("1+1");
   24368           5 :   CHECK(try_catch.HasCaught());
   24369           5 : }
   24370             : 
   24371             : namespace {
   24372             : 
   24373             : class MockPlatform : public TestPlatform {
   24374             :  public:
   24375          10 :   MockPlatform() : old_platform_(i::V8::GetCurrentPlatform()) {
   24376             :     // Now that it's completely constructed, make this the current platform.
   24377           5 :     i::V8::SetPlatformForTesting(this);
   24378           5 :   }
   24379          10 :   ~MockPlatform() override { i::V8::SetPlatformForTesting(old_platform_); }
   24380             : 
   24381             :   bool dump_without_crashing_called() const {
   24382             :     return dump_without_crashing_called_;
   24383             :   }
   24384             : 
   24385           5 :   void DumpWithoutCrashing() override { dump_without_crashing_called_ = true; }
   24386             : 
   24387             :  private:
   24388             :   v8::Platform* old_platform_;
   24389             :   bool dump_without_crashing_called_ = false;
   24390             : };
   24391             : 
   24392             : }  // namespace
   24393             : 
   24394       26644 : TEST(DumpOnJavascriptExecution) {
   24395          10 :   MockPlatform platform;
   24396             : 
   24397           5 :   LocalContext context;
   24398           5 :   v8::Isolate* isolate = context->GetIsolate();
   24399          10 :   v8::HandleScope scope(isolate);
   24400             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   24401          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::DUMP_ON_FAILURE);
   24402           5 :   CHECK(!platform.dump_without_crashing_called());
   24403             :   CompileRun("1+1");
   24404           5 :   CHECK(platform.dump_without_crashing_called());
   24405           5 : }
   24406             : 
   24407       26644 : TEST(Regress354123) {
   24408           5 :   LocalContext current;
   24409           5 :   v8::Isolate* isolate = current->GetIsolate();
   24410          10 :   v8::HandleScope scope(isolate);
   24411             : 
   24412           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   24413           5 :   templ->SetAccessCheckCallback(AccessCounter);
   24414          25 :   CHECK(current->Global()
   24415             :             ->Set(current.local(), v8_str("friend"),
   24416             :                   templ->NewInstance(current.local()).ToLocalChecked())
   24417             :             .FromJust());
   24418             : 
   24419             :   // Test access using __proto__ from the prototype chain.
   24420           5 :   access_count = 0;
   24421             :   CompileRun("friend.__proto__ = {};");
   24422           5 :   CHECK_EQ(2, access_count);
   24423             :   CompileRun("friend.__proto__;");
   24424           5 :   CHECK_EQ(4, access_count);
   24425             : 
   24426             :   // Test access using __proto__ as a hijacked function (A).
   24427           5 :   access_count = 0;
   24428             :   CompileRun("var p = Object.prototype;"
   24429             :              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
   24430             :              "f.call(friend, {});");
   24431           5 :   CHECK_EQ(1, access_count);
   24432             :   CompileRun("var p = Object.prototype;"
   24433             :              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
   24434             :              "f.call(friend);");
   24435           5 :   CHECK_EQ(2, access_count);
   24436             : 
   24437             :   // Test access using __proto__ as a hijacked function (B).
   24438           5 :   access_count = 0;
   24439             :   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
   24440             :              "f.call(friend, {});");
   24441           5 :   CHECK_EQ(1, access_count);
   24442             :   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
   24443             :              "f.call(friend);");
   24444           5 :   CHECK_EQ(2, access_count);
   24445             : 
   24446             :   // Test access using Object.setPrototypeOf reflective method.
   24447           5 :   access_count = 0;
   24448             :   CompileRun("Object.setPrototypeOf(friend, {});");
   24449           5 :   CHECK_EQ(1, access_count);
   24450             :   CompileRun("Object.getPrototypeOf(friend);");
   24451           5 :   CHECK_EQ(2, access_count);
   24452           5 : }
   24453             : 
   24454             : 
   24455       26644 : TEST(CaptureStackTraceForStackOverflow) {
   24456           5 :   v8::internal::FLAG_stack_size = 150;
   24457           5 :   LocalContext current;
   24458           5 :   v8::Isolate* isolate = current->GetIsolate();
   24459          10 :   v8::HandleScope scope(isolate);
   24460             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
   24461           5 :                                                      v8::StackTrace::kDetailed);
   24462          10 :   v8::TryCatch try_catch(isolate);
   24463             :   CompileRun("(function f(x) { f(x+1); })(0)");
   24464           5 :   CHECK(try_catch.HasCaught());
   24465           5 : }
   24466             : 
   24467             : namespace {
   24468           5 : bool ValueEqualsString(v8::Isolate* isolate, Local<Value> lhs,
   24469             :                        const char* rhs) {
   24470           5 :   CHECK(!lhs.IsEmpty());
   24471           5 :   CHECK(lhs->IsString());
   24472          10 :   String::Utf8Value utf8_lhs(isolate, lhs);
   24473          10 :   return strcmp(rhs, *utf8_lhs) == 0;
   24474             : }
   24475             : }  // namespace
   24476             : 
   24477       26644 : TEST(ScriptNameAndLineNumber) {
   24478           5 :   LocalContext env;
   24479           5 :   v8::Isolate* isolate = env->GetIsolate();
   24480          10 :   v8::HandleScope scope(isolate);
   24481             :   const char* url = "http://www.foo.com/foo.js";
   24482           5 :   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   24483           5 :   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
   24484             : 
   24485             :   Local<Script> script =
   24486           5 :       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   24487          10 :   CHECK(ValueEqualsString(isolate, script->GetUnboundScript()->GetScriptName(),
   24488             :                           url));
   24489             : 
   24490          10 :   int line_number = script->GetUnboundScript()->GetLineNumber(0);
   24491           5 :   CHECK_EQ(13, line_number);
   24492           5 : }
   24493             : 
   24494       26644 : TEST(ScriptPositionInfo) {
   24495           5 :   LocalContext env;
   24496           5 :   v8::Isolate* isolate = env->GetIsolate();
   24497             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   24498          10 :   v8::HandleScope scope(isolate);
   24499             :   const char* url = "http://www.foo.com/foo.js";
   24500           5 :   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   24501             :   v8::ScriptCompiler::Source script_source(v8_str("var foo;\n"
   24502             :                                                   "var bar;\n"
   24503             :                                                   "var fisk = foo + bar;\n"),
   24504           5 :                                            origin);
   24505             :   Local<Script> script =
   24506           5 :       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   24507             : 
   24508             :   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   24509          10 :       v8::Utils::OpenHandle(*script->GetUnboundScript()));
   24510          10 :   CHECK(obj->script()->IsScript());
   24511             : 
   24512          10 :   i::Handle<i::Script> script1(i::Script::cast(obj->script()), i_isolate);
   24513             : 
   24514             :   v8::internal::Script::PositionInfo info;
   24515             : 
   24516          25 :   for (int i = 0; i < 2; ++i) {
   24517             :     // With offset.
   24518             : 
   24519             :     // Behave as if 0 was passed if position is negative.
   24520          10 :     CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
   24521          10 :     CHECK_EQ(13, info.line);
   24522          10 :     CHECK_EQ(0, info.column);
   24523          10 :     CHECK_EQ(0, info.line_start);
   24524          10 :     CHECK_EQ(8, info.line_end);
   24525             : 
   24526          10 :     CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
   24527          10 :     CHECK_EQ(13, info.line);
   24528          10 :     CHECK_EQ(0, info.column);
   24529          10 :     CHECK_EQ(0, info.line_start);
   24530          10 :     CHECK_EQ(8, info.line_end);
   24531             : 
   24532          10 :     CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
   24533          10 :     CHECK_EQ(13, info.line);
   24534          10 :     CHECK_EQ(8, info.column);
   24535          10 :     CHECK_EQ(0, info.line_start);
   24536          10 :     CHECK_EQ(8, info.line_end);
   24537             : 
   24538          10 :     CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
   24539          10 :     CHECK_EQ(14, info.line);
   24540          10 :     CHECK_EQ(0, info.column);
   24541          10 :     CHECK_EQ(9, info.line_start);
   24542          10 :     CHECK_EQ(17, info.line_end);
   24543             : 
   24544             :     // Fail when position is larger than script size.
   24545          10 :     CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
   24546             : 
   24547             :     // Without offset.
   24548             : 
   24549             :     // Behave as if 0 was passed if position is negative.
   24550          10 :     CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
   24551          10 :     CHECK_EQ(0, info.line);
   24552          10 :     CHECK_EQ(0, info.column);
   24553          10 :     CHECK_EQ(0, info.line_start);
   24554          10 :     CHECK_EQ(8, info.line_end);
   24555             : 
   24556          10 :     CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
   24557          10 :     CHECK_EQ(0, info.line);
   24558          10 :     CHECK_EQ(0, info.column);
   24559          10 :     CHECK_EQ(0, info.line_start);
   24560          10 :     CHECK_EQ(8, info.line_end);
   24561             : 
   24562          10 :     CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
   24563          10 :     CHECK_EQ(0, info.line);
   24564          10 :     CHECK_EQ(8, info.column);
   24565          10 :     CHECK_EQ(0, info.line_start);
   24566          10 :     CHECK_EQ(8, info.line_end);
   24567             : 
   24568          10 :     CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
   24569          10 :     CHECK_EQ(1, info.line);
   24570          10 :     CHECK_EQ(0, info.column);
   24571          10 :     CHECK_EQ(9, info.line_start);
   24572          10 :     CHECK_EQ(17, info.line_end);
   24573             : 
   24574             :     // Fail when position is larger than script size.
   24575          10 :     CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
   24576             : 
   24577          10 :     i::Script::InitLineEnds(script1);
   24578             :   }
   24579           5 : }
   24580             : 
   24581         155 : void CheckMagicComments(v8::Isolate* isolate, Local<Script> script,
   24582             :                         const char* expected_source_url,
   24583             :                         const char* expected_source_mapping_url) {
   24584         155 :   if (expected_source_url != nullptr) {
   24585             :     v8::String::Utf8Value url(isolate,
   24586         105 :                               script->GetUnboundScript()->GetSourceURL());
   24587          35 :     CHECK_EQ(0, strcmp(expected_source_url, *url));
   24588             :   } else {
   24589         360 :     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
   24590             :   }
   24591         155 :   if (expected_source_mapping_url != nullptr) {
   24592             :     v8::String::Utf8Value url(
   24593          90 :         isolate, script->GetUnboundScript()->GetSourceMappingURL());
   24594          30 :     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
   24595             :   } else {
   24596         375 :     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
   24597             :   }
   24598         155 : }
   24599             : 
   24600          70 : void SourceURLHelper(v8::Isolate* isolate, const char* source,
   24601             :                      const char* expected_source_url,
   24602             :                      const char* expected_source_mapping_url) {
   24603          70 :   Local<Script> script = v8_compile(source);
   24604             :   CheckMagicComments(isolate, script, expected_source_url,
   24605          70 :                      expected_source_mapping_url);
   24606          70 : }
   24607             : 
   24608             : 
   24609       26644 : TEST(ScriptSourceURLAndSourceMappingURL) {
   24610           5 :   LocalContext env;
   24611           5 :   v8::Isolate* isolate = env->GetIsolate();
   24612          10 :   v8::HandleScope scope(isolate);
   24613             :   SourceURLHelper(isolate,
   24614             :                   "function foo() {}\n"
   24615             :                   "//# sourceURL=bar1.js\n",
   24616           5 :                   "bar1.js", nullptr);
   24617             :   SourceURLHelper(isolate,
   24618             :                   "function foo() {}\n"
   24619             :                   "//# sourceMappingURL=bar2.js\n",
   24620           5 :                   nullptr, "bar2.js");
   24621             : 
   24622             :   // Both sourceURL and sourceMappingURL.
   24623             :   SourceURLHelper(isolate,
   24624             :                   "function foo() {}\n"
   24625             :                   "//# sourceURL=bar3.js\n"
   24626             :                   "//# sourceMappingURL=bar4.js\n",
   24627           5 :                   "bar3.js", "bar4.js");
   24628             : 
   24629             :   // Two source URLs; the first one is ignored.
   24630             :   SourceURLHelper(isolate,
   24631             :                   "function foo() {}\n"
   24632             :                   "//# sourceURL=ignoreme.js\n"
   24633             :                   "//# sourceURL=bar5.js\n",
   24634           5 :                   "bar5.js", nullptr);
   24635             :   SourceURLHelper(isolate,
   24636             :                   "function foo() {}\n"
   24637             :                   "//# sourceMappingURL=ignoreme.js\n"
   24638             :                   "//# sourceMappingURL=bar6.js\n",
   24639           5 :                   nullptr, "bar6.js");
   24640             : 
   24641             :   // SourceURL or sourceMappingURL in the middle of the script.
   24642             :   SourceURLHelper(isolate,
   24643             :                   "function foo() {}\n"
   24644             :                   "//# sourceURL=bar7.js\n"
   24645             :                   "function baz() {}\n",
   24646           5 :                   "bar7.js", nullptr);
   24647             :   SourceURLHelper(isolate,
   24648             :                   "function foo() {}\n"
   24649             :                   "//# sourceMappingURL=bar8.js\n"
   24650             :                   "function baz() {}\n",
   24651           5 :                   nullptr, "bar8.js");
   24652             : 
   24653             :   // Too much whitespace.
   24654             :   SourceURLHelper(isolate,
   24655             :                   "function foo() {}\n"
   24656             :                   "//#  sourceURL=bar9.js\n"
   24657             :                   "//#  sourceMappingURL=bar10.js\n",
   24658           5 :                   nullptr, nullptr);
   24659             :   SourceURLHelper(isolate,
   24660             :                   "function foo() {}\n"
   24661             :                   "//# sourceURL =bar11.js\n"
   24662             :                   "//# sourceMappingURL =bar12.js\n",
   24663           5 :                   nullptr, nullptr);
   24664             : 
   24665             :   // Disallowed characters in value.
   24666             :   SourceURLHelper(isolate,
   24667             :                   "function foo() {}\n"
   24668             :                   "//# sourceURL=bar13 .js   \n"
   24669             :                   "//# sourceMappingURL=bar14 .js \n",
   24670           5 :                   nullptr, nullptr);
   24671             :   SourceURLHelper(isolate,
   24672             :                   "function foo() {}\n"
   24673             :                   "//# sourceURL=bar15\t.js   \n"
   24674             :                   "//# sourceMappingURL=bar16\t.js \n",
   24675           5 :                   nullptr, nullptr);
   24676             :   SourceURLHelper(isolate,
   24677             :                   "function foo() {}\n"
   24678             :                   "//# sourceURL=bar17'.js   \n"
   24679             :                   "//# sourceMappingURL=bar18'.js \n",
   24680           5 :                   nullptr, nullptr);
   24681             :   SourceURLHelper(isolate,
   24682             :                   "function foo() {}\n"
   24683             :                   "//# sourceURL=bar19\".js   \n"
   24684             :                   "//# sourceMappingURL=bar20\".js \n",
   24685           5 :                   nullptr, nullptr);
   24686             : 
   24687             :   // Not too much whitespace.
   24688             :   SourceURLHelper(isolate,
   24689             :                   "function foo() {}\n"
   24690             :                   "//# sourceURL=  bar21.js   \n"
   24691             :                   "//# sourceMappingURL=  bar22.js \n",
   24692           5 :                   "bar21.js", "bar22.js");
   24693           5 : }
   24694             : 
   24695             : 
   24696       26644 : TEST(GetOwnPropertyDescriptor) {
   24697           5 :   LocalContext env;
   24698           5 :   v8::Isolate* isolate = env->GetIsolate();
   24699          10 :   v8::HandleScope scope(isolate);
   24700             :   CompileRun(
   24701             :       "var x = { value : 13};"
   24702             :       "Object.defineProperty(x, 'p0', {value : 12});"
   24703             :       "Object.defineProperty(x, Symbol.toStringTag, {value: 'foo'});"
   24704             :       "Object.defineProperty(x, 'p1', {"
   24705             :       "  set : function(value) { this.value = value; },"
   24706             :       "  get : function() { return this.value; },"
   24707             :       "});");
   24708             :   Local<Object> x = Local<Object>::Cast(
   24709          20 :       env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
   24710             :   Local<Value> desc =
   24711          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
   24712             :           .ToLocalChecked();
   24713           5 :   CHECK(desc->IsUndefined());
   24714             :   desc =
   24715          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
   24716          25 :   CHECK(v8_num(12)
   24717             :             ->Equals(env.local(), Local<Object>::Cast(desc)
   24718             :                                       ->Get(env.local(), v8_str("value"))
   24719             :                                       .ToLocalChecked())
   24720             :             .FromJust());
   24721             :   desc =
   24722          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
   24723             :   Local<Function> set =
   24724             :       Local<Function>::Cast(Local<Object>::Cast(desc)
   24725          15 :                                 ->Get(env.local(), v8_str("set"))
   24726             :                                 .ToLocalChecked());
   24727             :   Local<Function> get =
   24728             :       Local<Function>::Cast(Local<Object>::Cast(desc)
   24729          15 :                                 ->Get(env.local(), v8_str("get"))
   24730             :                                 .ToLocalChecked());
   24731          20 :   CHECK(v8_num(13)
   24732             :             ->Equals(env.local(),
   24733             :                      get->Call(env.local(), x, 0, nullptr).ToLocalChecked())
   24734             :             .FromJust());
   24735           5 :   Local<Value> args[] = {v8_num(14)};
   24736          10 :   set->Call(env.local(), x, 1, args).ToLocalChecked();
   24737          20 :   CHECK(v8_num(14)
   24738             :             ->Equals(env.local(),
   24739             :                      get->Call(env.local(), x, 0, nullptr).ToLocalChecked())
   24740             :             .FromJust());
   24741             :   desc =
   24742          15 :       x->GetOwnPropertyDescriptor(env.local(), Symbol::GetToStringTag(isolate))
   24743             :           .ToLocalChecked();
   24744          25 :   CHECK(v8_str("foo")
   24745             :             ->Equals(env.local(), Local<Object>::Cast(desc)
   24746             :                                       ->Get(env.local(), v8_str("value"))
   24747             :                                       .ToLocalChecked())
   24748             :             .FromJust());
   24749           5 : }
   24750             : 
   24751             : 
   24752       26644 : TEST(Regress411877) {
   24753           5 :   v8::Isolate* isolate = CcTest::isolate();
   24754          10 :   v8::HandleScope handle_scope(isolate);
   24755             :   v8::Local<v8::ObjectTemplate> object_template =
   24756           5 :       v8::ObjectTemplate::New(isolate);
   24757           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24758             : 
   24759           5 :   v8::Local<Context> context = Context::New(isolate);
   24760             :   v8::Context::Scope context_scope(context);
   24761             : 
   24762          25 :   CHECK(context->Global()
   24763             :             ->Set(context, v8_str("o"),
   24764             :                   object_template->NewInstance(context).ToLocalChecked())
   24765             :             .FromJust());
   24766             :   CompileRun("Object.getOwnPropertyNames(o)");
   24767           5 : }
   24768             : 
   24769             : 
   24770       26644 : TEST(GetHiddenPropertyTableAfterAccessCheck) {
   24771           5 :   v8::Isolate* isolate = CcTest::isolate();
   24772          10 :   v8::HandleScope handle_scope(isolate);
   24773             :   v8::Local<v8::ObjectTemplate> object_template =
   24774           5 :       v8::ObjectTemplate::New(isolate);
   24775           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24776             : 
   24777           5 :   v8::Local<Context> context = Context::New(isolate);
   24778             :   v8::Context::Scope context_scope(context);
   24779             : 
   24780             :   v8::Local<v8::Object> obj =
   24781           5 :       object_template->NewInstance(context).ToLocalChecked();
   24782          20 :   obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
   24783          15 :   obj->Delete(context, v8_str("key")).FromJust();
   24784             : 
   24785          10 :   obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
   24786          15 :                   v8_str("hidden value 2"))
   24787             :       .FromJust();
   24788           5 : }
   24789             : 
   24790             : 
   24791       26644 : TEST(Regress411793) {
   24792           5 :   v8::Isolate* isolate = CcTest::isolate();
   24793          10 :   v8::HandleScope handle_scope(isolate);
   24794             :   v8::Local<v8::ObjectTemplate> object_template =
   24795           5 :       v8::ObjectTemplate::New(isolate);
   24796           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24797             : 
   24798           5 :   v8::Local<Context> context = Context::New(isolate);
   24799             :   v8::Context::Scope context_scope(context);
   24800             : 
   24801          25 :   CHECK(context->Global()
   24802             :             ->Set(context, v8_str("o"),
   24803             :                   object_template->NewInstance(context).ToLocalChecked())
   24804             :             .FromJust());
   24805             :   CompileRun(
   24806             :       "Object.defineProperty(o, 'key', "
   24807             :       "    { get: function() {}, set: function() {} });");
   24808           5 : }
   24809             : 
   24810         210 : class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
   24811             :  public:
   24812         105 :   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
   24813             : 
   24814         405 :   size_t GetMoreData(const uint8_t** src) override {
   24815             :     // Unlike in real use cases, this function will never block.
   24816         405 :     if (chunks_[index_] == nullptr) {
   24817             :       return 0;
   24818             :     }
   24819             :     // Copy the data, since the caller takes ownership of it.
   24820         310 :     size_t len = strlen(chunks_[index_]);
   24821             :     // We don't need to zero-terminate since we return the length.
   24822         310 :     uint8_t* copy = new uint8_t[len];
   24823         310 :     memcpy(copy, chunks_[index_], len);
   24824         310 :     *src = copy;
   24825         310 :     ++index_;
   24826         310 :     return len;
   24827             :   }
   24828             : 
   24829             :   // Helper for constructing a string from chunks (the compilation needs it
   24830             :   // too).
   24831         105 :   static char* FullSourceString(const char** chunks) {
   24832             :     size_t total_len = 0;
   24833         765 :     for (size_t i = 0; chunks[i] != nullptr; ++i) {
   24834         330 :       total_len += strlen(chunks[i]);
   24835             :     }
   24836         105 :     char* full_string = new char[total_len + 1];
   24837             :     size_t offset = 0;
   24838         765 :     for (size_t i = 0; chunks[i] != nullptr; ++i) {
   24839         330 :       size_t len = strlen(chunks[i]);
   24840         330 :       memcpy(full_string + offset, chunks[i], len);
   24841         330 :       offset += len;
   24842             :     }
   24843         105 :     full_string[total_len] = 0;
   24844         105 :     return full_string;
   24845             :   }
   24846             : 
   24847             :  private:
   24848             :   const char** chunks_;
   24849             :   unsigned index_;
   24850             : };
   24851             : 
   24852             : 
   24853             : // Helper function for running streaming tests.
   24854          95 : void RunStreamingTest(const char** chunks,
   24855             :                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
   24856             :                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   24857             :                       bool expected_success = true,
   24858             :                       const char* expected_source_url = nullptr,
   24859             :                       const char* expected_source_mapping_url = nullptr) {
   24860          95 :   LocalContext env;
   24861          95 :   v8::Isolate* isolate = env->GetIsolate();
   24862         190 :   v8::HandleScope scope(isolate);
   24863         190 :   v8::TryCatch try_catch(isolate);
   24864             : 
   24865             :   v8::ScriptCompiler::StreamedSource source(
   24866         285 :       v8::base::make_unique<TestSourceStream>(chunks), encoding);
   24867             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   24868          95 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   24869             : 
   24870             :   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   24871             :   // task here in the main thread.
   24872          95 :   task->Run();
   24873          95 :   delete task;
   24874             : 
   24875             :   // Possible errors are only produced while compiling.
   24876          95 :   CHECK(!try_catch.HasCaught());
   24877             : 
   24878          95 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   24879          95 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   24880             :   v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
   24881         190 :       env.local(), &source, v8_str(full_source), origin);
   24882          95 :   if (expected_success) {
   24883          85 :     CHECK(!script.IsEmpty());
   24884             :     v8::Local<Value> result(
   24885          85 :         script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
   24886             :     // All scripts are supposed to return the fixed value 13 when ran.
   24887         170 :     CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
   24888             :     CheckMagicComments(isolate, script.ToLocalChecked(), expected_source_url,
   24889          85 :                        expected_source_mapping_url);
   24890             :   } else {
   24891          10 :     CHECK(script.IsEmpty());
   24892          10 :     CHECK(try_catch.HasCaught());
   24893             :   }
   24894          95 :   delete[] full_source;
   24895          95 : }
   24896             : 
   24897       26644 : TEST(StreamingSimpleScript) {
   24898             :   // This script is unrealistically small, since no one chunk is enough to fill
   24899             :   // the backing buffer of Scanner, let alone overflow it.
   24900             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   24901           5 :                           nullptr};
   24902           5 :   RunStreamingTest(chunks);
   24903           5 : }
   24904             : 
   24905       26644 : TEST(StreamingScriptConstantArray) {
   24906             :   // When run with Ignition, tests that the streaming parser canonicalizes
   24907             :   // handles so that they are only added to the constant pool array once.
   24908             :   const char* chunks[] = {
   24909             :       "var a = {};",        "var b = {};", "var c = 'testing';",
   24910           5 :       "var d = 'testing';", "13;",         nullptr};
   24911           5 :   RunStreamingTest(chunks);
   24912           5 : }
   24913             : 
   24914       26644 : TEST(StreamingScriptEvalShadowing) {
   24915             :   // When run with Ignition, tests that the streaming parser canonicalizes
   24916             :   // handles so the Variable::is_possibly_eval() is correct.
   24917             :   const char* chunk1 =
   24918             :       "(function() {\n"
   24919             :       "  var y = 2;\n"
   24920             :       "  return (function() {\n"
   24921             :       "    eval('var y = 13;');\n"
   24922             :       "    function g() {\n"
   24923             :       "      return y\n"
   24924             :       "    }\n"
   24925             :       "    return g();\n"
   24926             :       "  })()\n"
   24927             :       "})()\n";
   24928           5 :   const char* chunks[] = {chunk1, nullptr};
   24929           5 :   RunStreamingTest(chunks);
   24930           5 : }
   24931             : 
   24932       26644 : TEST(StreamingBiggerScript) {
   24933             :   const char* chunk1 =
   24934             :       "function foo() {\n"
   24935             :       "  // Make this chunk sufficiently long so that it will overflow the\n"
   24936             :       "  // backing buffer of the Scanner.\n"
   24937             :       "  var i = 0;\n"
   24938             :       "  var result = 0;\n"
   24939             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   24940             :       "  result = 0;\n"
   24941             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   24942             :       "  result = 0;\n"
   24943             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   24944             :       "  result = 0;\n"
   24945             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   24946             :       "  return result;\n"
   24947             :       "}\n";
   24948           5 :   const char* chunks[] = {chunk1, "foo(); ", nullptr};
   24949           5 :   RunStreamingTest(chunks);
   24950           5 : }
   24951             : 
   24952             : 
   24953       26644 : TEST(StreamingScriptWithParseError) {
   24954             :   // Test that parse errors from streamed scripts are propagated correctly.
   24955             :   {
   24956             :     char chunk1[] =
   24957             :         "  // This will result in a parse error.\n"
   24958           5 :         "  var if else then foo";
   24959           5 :     char chunk2[] = "  13\n";
   24960           5 :     const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   24961             : 
   24962             :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   24963           5 :                      false);
   24964             :   }
   24965             :   // Test that the next script succeeds normally.
   24966             :   {
   24967             :     char chunk1[] =
   24968             :         "  // This will be parsed successfully.\n"
   24969           5 :         "  function foo() { return ";
   24970           5 :     char chunk2[] = "  13; }\n";
   24971           5 :     const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   24972             : 
   24973           5 :     RunStreamingTest(chunks);
   24974             :   }
   24975           5 : }
   24976             : 
   24977             : 
   24978       26644 : TEST(StreamingUtf8Script) {
   24979             :   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
   24980             :   // don't like it.
   24981             :   const char* chunk1 =
   24982             :       "function foo() {\n"
   24983             :       "  // This function will contain an UTF-8 character which is not in\n"
   24984             :       "  // ASCII.\n"
   24985             :       "  var foob\xec\x92\x81r = 13;\n"
   24986             :       "  return foob\xec\x92\x81r;\n"
   24987             :       "}\n";
   24988           5 :   const char* chunks[] = {chunk1, "foo(); ", nullptr};
   24989           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24990           5 : }
   24991             : 
   24992             : 
   24993       26644 : TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
   24994             :   // A sanity check to prove that the approach of splitting UTF-8
   24995             :   // characters is correct. Here is an UTF-8 character which will take three
   24996             :   // bytes.
   24997             :   const char* reference = "\xec\x92\x81";
   24998             :   CHECK_EQ(3, strlen(reference));
   24999             : 
   25000             :   char chunk1[] =
   25001             :       "function foo() {\n"
   25002             :       "  // This function will contain an UTF-8 character which is not in\n"
   25003             :       "  // ASCII.\n"
   25004           5 :       "  var foob";
   25005             :   char chunk2[] =
   25006             :       "XXXr = 13;\n"
   25007             :       "  return foob\xec\x92\x81r;\n"
   25008           5 :       "}\n";
   25009          35 :   for (int i = 0; i < 3; ++i) {
   25010          15 :     chunk2[i] = reference[i];
   25011             :   }
   25012           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25013           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25014           5 : }
   25015             : 
   25016             : 
   25017       26644 : TEST(StreamingUtf8ScriptWithSplitCharacters) {
   25018             :   // Stream data where a multi-byte UTF-8 character is split between two data
   25019             :   // chunks.
   25020             :   const char* reference = "\xec\x92\x81";
   25021             :   char chunk1[] =
   25022             :       "function foo() {\n"
   25023             :       "  // This function will contain an UTF-8 character which is not in\n"
   25024             :       "  // ASCII.\n"
   25025           5 :       "  var foobX";
   25026             :   char chunk2[] =
   25027             :       "XXr = 13;\n"
   25028             :       "  return foob\xec\x92\x81r;\n"
   25029           5 :       "}\n";
   25030           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25031           5 :   chunk2[0] = reference[1];
   25032           5 :   chunk2[1] = reference[2];
   25033           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25034           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25035           5 : }
   25036             : 
   25037             : 
   25038       26644 : TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
   25039             :   // Tests edge cases which should still be decoded correctly.
   25040             : 
   25041             :   // Case 1: a chunk contains only bytes for a split character (and no other
   25042             :   // data). This kind of a chunk would be exceptionally small, but we should
   25043             :   // still decode it correctly.
   25044             :   const char* reference = "\xec\x92\x81";
   25045             :   // The small chunk is at the beginning of the split character
   25046             :   {
   25047             :     char chunk1[] =
   25048             :         "function foo() {\n"
   25049             :         "  // This function will contain an UTF-8 character which is not in\n"
   25050             :         "  // ASCII.\n"
   25051           5 :         "  var foob";
   25052           5 :     char chunk2[] = "XX";
   25053             :     char chunk3[] =
   25054             :         "Xr = 13;\n"
   25055             :         "  return foob\xec\x92\x81r;\n"
   25056           5 :         "}\n";
   25057           5 :     chunk2[0] = reference[0];
   25058           5 :     chunk2[1] = reference[1];
   25059           5 :     chunk3[0] = reference[2];
   25060           5 :     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25061           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25062             :   }
   25063             :   // The small chunk is at the end of a character
   25064             :   {
   25065             :     char chunk1[] =
   25066             :         "function foo() {\n"
   25067             :         "  // This function will contain an UTF-8 character which is not in\n"
   25068             :         "  // ASCII.\n"
   25069           5 :         "  var foobX";
   25070           5 :     char chunk2[] = "XX";
   25071             :     char chunk3[] =
   25072             :         "r = 13;\n"
   25073             :         "  return foob\xec\x92\x81r;\n"
   25074           5 :         "}\n";
   25075           5 :     chunk1[strlen(chunk1) - 1] = reference[0];
   25076           5 :     chunk2[0] = reference[1];
   25077           5 :     chunk2[1] = reference[2];
   25078           5 :     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25079           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25080             :   }
   25081             :   // Case 2: the script ends with a multi-byte character. Make sure that it's
   25082             :   // decoded correctly and not just ignored.
   25083             :   {
   25084             :     char chunk1[] =
   25085             :         "var foob\xec\x92\x81 = 13;\n"
   25086           5 :         "foob\xec\x92\x81";
   25087           5 :     const char* chunks[] = {chunk1, nullptr};
   25088           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25089             :   }
   25090           5 : }
   25091             : 
   25092             : 
   25093       26644 : TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
   25094             :   // Test cases where a UTF-8 character is split over several chunks. Those
   25095             :   // cases are not supported (the embedder should give the data in big enough
   25096             :   // chunks), but we shouldn't crash and parse this just fine.
   25097             :   const char* reference = "\xec\x92\x81";
   25098             :   char chunk1[] =
   25099             :       "function foo() {\n"
   25100             :       "  // This function will contain an UTF-8 character which is not in\n"
   25101             :       "  // ASCII.\n"
   25102           5 :       "  var foobX";
   25103           5 :   char chunk2[] = "X";
   25104             :   char chunk3[] =
   25105             :       "Xr = 13;\n"
   25106             :       "  return foob\xec\x92\x81r;\n"
   25107           5 :       "}\n";
   25108           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25109           5 :   chunk2[0] = reference[1];
   25110           5 :   chunk3[0] = reference[2];
   25111           5 :   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25112             : 
   25113           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25114           5 : }
   25115             : 
   25116             : 
   25117             : 
   25118       26644 : TEST(StreamingWithDebuggingEnabledLate) {
   25119             :   // The streaming parser can only parse lazily, i.e. inner functions are not
   25120             :   // fully parsed. However, we may compile inner functions eagerly when
   25121             :   // debugging. Make sure that we can deal with this when turning on debugging
   25122             :   // after streaming parser has already finished parsing.
   25123             :   const char* chunks[] = {"with({x:1}) {",
   25124             :                           "  var foo = function foo(y) {",
   25125             :                           "    return x + y;",
   25126             :                           "  };",
   25127             :                           "  foo(2);",
   25128             :                           "}",
   25129           5 :                           nullptr};
   25130             : 
   25131           5 :   LocalContext env;
   25132           5 :   v8::Isolate* isolate = env->GetIsolate();
   25133          10 :   v8::HandleScope scope(isolate);
   25134          10 :   v8::TryCatch try_catch(isolate);
   25135             : 
   25136             :   v8::ScriptCompiler::StreamedSource source(
   25137             :       v8::base::make_unique<TestSourceStream>(chunks),
   25138          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25139             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25140           5 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25141             : 
   25142           5 :   task->Run();
   25143           5 :   delete task;
   25144             : 
   25145           5 :   CHECK(!try_catch.HasCaught());
   25146             : 
   25147           5 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25148           5 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25149             : 
   25150             :   EnableDebugger(isolate);
   25151             : 
   25152             :   v8::Local<Script> script =
   25153           5 :       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   25154           5 :                                   origin)
   25155             :           .ToLocalChecked();
   25156             : 
   25157             :   Maybe<uint32_t> result =
   25158          10 :       script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
   25159           5 :   CHECK_EQ(3U, result.FromMaybe(0));
   25160             : 
   25161           5 :   delete[] full_source;
   25162             : 
   25163             :   DisableDebugger(isolate);
   25164           5 : }
   25165             : 
   25166             : 
   25167       26644 : TEST(StreamingScriptWithInvalidUtf8) {
   25168             :   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
   25169             :   // chunk don't produce a crash.
   25170             :   const char* reference = "\xec\x92\x81\x80\x80";
   25171             :   char chunk1[] =
   25172             :       "function foo() {\n"
   25173             :       "  // This function will contain an UTF-8 character which is not in\n"
   25174             :       "  // ASCII.\n"
   25175           5 :       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
   25176             :   char chunk2[] =
   25177             :       "r = 13;\n"
   25178             :       "  return foob\xec\x92\x81\x80\x80r;\n"
   25179           5 :       "}\n";
   25180          30 :   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
   25181             : 
   25182           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25183           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   25184           5 : }
   25185             : 
   25186             : 
   25187       26644 : TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
   25188             :   // Regression test: Stream data where there are several multi-byte UTF-8
   25189             :   // characters in a sequence and one of them is split between two data chunks.
   25190             :   const char* reference = "\xec\x92\x81";
   25191             :   char chunk1[] =
   25192             :       "function foo() {\n"
   25193             :       "  // This function will contain an UTF-8 character which is not in\n"
   25194             :       "  // ASCII.\n"
   25195           5 :       "  var foob\xec\x92\x81X";
   25196             :   char chunk2[] =
   25197             :       "XXr = 13;\n"
   25198             :       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   25199           5 :       "}\n";
   25200           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25201           5 :   chunk2[0] = reference[1];
   25202           5 :   chunk2[1] = reference[2];
   25203           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25204           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25205           5 : }
   25206             : 
   25207             : 
   25208       26644 : TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
   25209             :   // Another regression test, similar to the previous one. The difference is
   25210             :   // that the split character is not the last one in the sequence.
   25211             :   const char* reference = "\xec\x92\x81";
   25212             :   char chunk1[] =
   25213             :       "function foo() {\n"
   25214             :       "  // This function will contain an UTF-8 character which is not in\n"
   25215             :       "  // ASCII.\n"
   25216           5 :       "  var foobX";
   25217             :   char chunk2[] =
   25218             :       "XX\xec\x92\x81r = 13;\n"
   25219             :       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   25220           5 :       "}\n";
   25221           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25222           5 :   chunk2[0] = reference[1];
   25223           5 :   chunk2[1] = reference[2];
   25224           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25225           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25226           5 : }
   25227             : 
   25228             : 
   25229       26644 : TEST(StreamingWithHarmonyScopes) {
   25230             :   // Don't use RunStreamingTest here so that both scripts get to use the same
   25231             :   // LocalContext and HandleScope.
   25232           5 :   LocalContext env;
   25233           5 :   v8::Isolate* isolate = env->GetIsolate();
   25234          10 :   v8::HandleScope scope(isolate);
   25235             : 
   25236             :   // First, run a script with a let variable.
   25237             :   CompileRun("\"use strict\"; let x = 1;");
   25238             : 
   25239             :   // Then stream a script which (erroneously) tries to introduce the same
   25240             :   // variable again.
   25241           5 :   const char* chunks[] = {"\"use strict\"; let x = 2;", nullptr};
   25242             : 
   25243          10 :   v8::TryCatch try_catch(isolate);
   25244             :   v8::ScriptCompiler::StreamedSource source(
   25245             :       v8::base::make_unique<TestSourceStream>(chunks),
   25246          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25247             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25248           5 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25249           5 :   task->Run();
   25250           5 :   delete task;
   25251             : 
   25252             :   // Parsing should succeed (the script will be parsed and compiled in a context
   25253             :   // independent way, so the error is not detected).
   25254           5 :   CHECK(!try_catch.HasCaught());
   25255             : 
   25256           5 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25257           5 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25258             :   v8::Local<Script> script =
   25259           5 :       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   25260           5 :                                   origin)
   25261             :           .ToLocalChecked();
   25262           5 :   CHECK(!script.IsEmpty());
   25263           5 :   CHECK(!try_catch.HasCaught());
   25264             : 
   25265             :   // Running the script exposes the error.
   25266          10 :   CHECK(script->Run(env.local()).IsEmpty());
   25267           5 :   CHECK(try_catch.HasCaught());
   25268           5 :   delete[] full_source;
   25269           5 : }
   25270             : 
   25271             : 
   25272       26644 : TEST(CodeCache) {
   25273             :   v8::Isolate::CreateParams create_params;
   25274           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25275             : 
   25276             :   const char* source = "Math.sqrt(4)";
   25277             :   const char* origin = "code cache test";
   25278             :   v8::ScriptCompiler::CachedData* cache;
   25279             : 
   25280           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   25281             :   {
   25282             :     v8::Isolate::Scope iscope(isolate1);
   25283          10 :     v8::HandleScope scope(isolate1);
   25284           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
   25285             :     v8::Context::Scope cscope(context);
   25286           5 :     v8::Local<v8::String> source_string = v8_str(source);
   25287           5 :     v8::ScriptOrigin script_origin(v8_str(origin));
   25288             :     v8::ScriptCompiler::Source source(source_string, script_origin);
   25289             :     v8::ScriptCompiler::CompileOptions option =
   25290             :         v8::ScriptCompiler::kNoCompileOptions;
   25291             :     v8::Local<v8::Script> script =
   25292           5 :         v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   25293           5 :     cache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
   25294             :   }
   25295           5 :   isolate1->Dispose();
   25296             : 
   25297           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   25298             :   {
   25299             :     v8::Isolate::Scope iscope(isolate2);
   25300          10 :     v8::HandleScope scope(isolate2);
   25301           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   25302             :     v8::Context::Scope cscope(context);
   25303           5 :     v8::Local<v8::String> source_string = v8_str(source);
   25304           5 :     v8::ScriptOrigin script_origin(v8_str(origin));
   25305             :     v8::ScriptCompiler::Source source(source_string, script_origin, cache);
   25306             :     v8::ScriptCompiler::CompileOptions option =
   25307             :         v8::ScriptCompiler::kConsumeCodeCache;
   25308             :     v8::Local<v8::Script> script;
   25309             :     {
   25310             :       i::DisallowCompilation no_compile(
   25311             :           reinterpret_cast<i::Isolate*>(isolate2));
   25312           5 :       script = v8::ScriptCompiler::Compile(context, &source, option)
   25313             :                    .ToLocalChecked();
   25314             :     }
   25315          20 :     CHECK_EQ(2, script->Run(context)
   25316             :                     .ToLocalChecked()
   25317             :                     ->ToInt32(context)
   25318             :                     .ToLocalChecked()
   25319             :                     ->Int32Value(context)
   25320             :                     .FromJust());
   25321             :   }
   25322           5 :   isolate2->Dispose();
   25323           5 : }
   25324             : 
   25325           0 : v8::MaybeLocal<Module> UnexpectedModuleResolveCallback(Local<Context> context,
   25326             :                                                        Local<String> specifier,
   25327             :                                                        Local<Module> referrer) {
   25328           0 :   CHECK_WITH_MSG(false, "Unexpected call to resolve callback");
   25329             : }
   25330             : 
   25331             : namespace {
   25332             : 
   25333          10 : Local<Module> CompileAndInstantiateModule(v8::Isolate* isolate,
   25334             :                                           Local<Context> context,
   25335             :                                           const char* resource_name,
   25336             :                                           const char* source) {
   25337          10 :   Local<String> source_string = v8_str(source);
   25338             :   v8::ScriptOrigin script_origin(
   25339             :       v8_str(resource_name), Local<v8::Integer>(), Local<v8::Integer>(),
   25340             :       Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   25341          10 :       Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   25342             :   v8::ScriptCompiler::Source script_compiler_source(source_string,
   25343             :                                                     script_origin);
   25344             :   Local<Module> module =
   25345          10 :       v8::ScriptCompiler::CompileModule(isolate, &script_compiler_source)
   25346             :           .ToLocalChecked();
   25347          20 :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   25348             :       .ToChecked();
   25349             : 
   25350          20 :   return module;
   25351             : }
   25352             : 
   25353           5 : Local<Module> CompileAndInstantiateModuleFromCache(
   25354             :     v8::Isolate* isolate, Local<Context> context, const char* resource_name,
   25355             :     const char* source, v8::ScriptCompiler::CachedData* cache) {
   25356           5 :   Local<String> source_string = v8_str(source);
   25357             :   v8::ScriptOrigin script_origin(
   25358             :       v8_str(resource_name), Local<v8::Integer>(), Local<v8::Integer>(),
   25359             :       Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   25360           5 :       Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   25361             :   v8::ScriptCompiler::Source script_compiler_source(source_string,
   25362             :                                                     script_origin, cache);
   25363             : 
   25364             :   Local<Module> module =
   25365           5 :       v8::ScriptCompiler::CompileModule(isolate, &script_compiler_source,
   25366             :                                         v8::ScriptCompiler::kConsumeCodeCache)
   25367             :           .ToLocalChecked();
   25368          10 :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   25369             :       .ToChecked();
   25370             : 
   25371          10 :   return module;
   25372             : }
   25373             : 
   25374             : }  // namespace
   25375             : 
   25376       26644 : TEST(ModuleCodeCache) {
   25377             :   v8::Isolate::CreateParams create_params;
   25378           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25379             : 
   25380             :   const char* origin = "code cache test";
   25381             :   const char* source =
   25382             :       "export default 5; export const a = 10; function f() { return 42; } "
   25383             :       "(function() { return f(); })();";
   25384             : 
   25385             :   v8::ScriptCompiler::CachedData* cache;
   25386             :   {
   25387           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25388             :     {
   25389             :       v8::Isolate::Scope iscope(isolate);
   25390          10 :       v8::HandleScope scope(isolate);
   25391           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25392             :       v8::Context::Scope cscope(context);
   25393             : 
   25394             :       Local<Module> module =
   25395           5 :           CompileAndInstantiateModule(isolate, context, origin, source);
   25396             : 
   25397             :       // Fetch the shared function info before evaluation.
   25398             :       Local<v8::UnboundModuleScript> unbound_module_script =
   25399           5 :           module->GetUnboundModuleScript();
   25400             : 
   25401             :       // Evaluate for possible lazy compilation.
   25402             :       Local<Value> completion_value =
   25403           5 :           module->Evaluate(context).ToLocalChecked();
   25404          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   25405             : 
   25406             :       // Now create the cache. Note that it is freed, obscurely, when
   25407             :       // ScriptCompiler::Source goes out of scope below.
   25408           5 :       cache = v8::ScriptCompiler::CreateCodeCache(unbound_module_script);
   25409             :     }
   25410           5 :     isolate->Dispose();
   25411             :   }
   25412             : 
   25413             :   // Test that the cache is consumed and execution still works.
   25414             :   {
   25415             :     // Disable --always_opt, otherwise we try to optimize during module
   25416             :     // instantiation, violating the DisallowCompilation scope.
   25417           5 :     i::FLAG_always_opt = false;
   25418           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25419             :     {
   25420             :       v8::Isolate::Scope iscope(isolate);
   25421          10 :       v8::HandleScope scope(isolate);
   25422           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25423             :       v8::Context::Scope cscope(context);
   25424             : 
   25425             :       Local<Module> module;
   25426             :       {
   25427             :         i::DisallowCompilation no_compile(
   25428             :             reinterpret_cast<i::Isolate*>(isolate));
   25429             :         module = CompileAndInstantiateModuleFromCache(isolate, context, origin,
   25430           5 :                                                       source, cache);
   25431             :       }
   25432             : 
   25433             :       Local<Value> completion_value =
   25434           5 :           module->Evaluate(context).ToLocalChecked();
   25435          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   25436             :     }
   25437           5 :     isolate->Dispose();
   25438             :   }
   25439           5 : }
   25440             : 
   25441             : // Tests that the code cache does not confuse the same source code compiled as a
   25442             : // script and as a module.
   25443       26644 : TEST(CodeCacheModuleScriptMismatch) {
   25444             :   v8::Isolate::CreateParams create_params;
   25445           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25446             : 
   25447             :   const char* origin = "code cache test";
   25448             :   const char* source = "42";
   25449             : 
   25450             :   v8::ScriptCompiler::CachedData* cache;
   25451             :   {
   25452           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25453             :     {
   25454             :       v8::Isolate::Scope iscope(isolate);
   25455          10 :       v8::HandleScope scope(isolate);
   25456           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25457             :       v8::Context::Scope cscope(context);
   25458             : 
   25459             :       Local<Module> module =
   25460           5 :           CompileAndInstantiateModule(isolate, context, origin, source);
   25461             : 
   25462             :       // Fetch the shared function info before evaluation.
   25463             :       Local<v8::UnboundModuleScript> unbound_module_script =
   25464           5 :           module->GetUnboundModuleScript();
   25465             : 
   25466             :       // Evaluate for possible lazy compilation.
   25467             :       Local<Value> completion_value =
   25468           5 :           module->Evaluate(context).ToLocalChecked();
   25469          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   25470             : 
   25471             :       // Now create the cache. Note that it is freed, obscurely, when
   25472             :       // ScriptCompiler::Source goes out of scope below.
   25473           5 :       cache = v8::ScriptCompiler::CreateCodeCache(unbound_module_script);
   25474             :     }
   25475           5 :     isolate->Dispose();
   25476             :   }
   25477             : 
   25478             :   // Test that the cache is not consumed when source is compiled as a script.
   25479             :   {
   25480           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25481             :     {
   25482             :       v8::Isolate::Scope iscope(isolate);
   25483          10 :       v8::HandleScope scope(isolate);
   25484           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25485             :       v8::Context::Scope cscope(context);
   25486             : 
   25487           5 :       v8::ScriptOrigin script_origin(v8_str(origin));
   25488             :       v8::ScriptCompiler::Source script_compiler_source(v8_str(source),
   25489           5 :                                                         script_origin, cache);
   25490             : 
   25491             :       v8::Local<v8::Script> script =
   25492           5 :           v8::ScriptCompiler::Compile(context, &script_compiler_source,
   25493             :                                       v8::ScriptCompiler::kConsumeCodeCache)
   25494             :               .ToLocalChecked();
   25495             : 
   25496           5 :       CHECK(cache->rejected);
   25497             : 
   25498          20 :       CHECK_EQ(42, script->Run(context)
   25499             :                        .ToLocalChecked()
   25500             :                        ->ToInt32(context)
   25501             :                        .ToLocalChecked()
   25502             :                        ->Int32Value(context)
   25503             :                        .FromJust());
   25504             :     }
   25505           5 :     isolate->Dispose();
   25506             :   }
   25507           5 : }
   25508             : 
   25509             : // Same as above but other way around.
   25510       26644 : TEST(CodeCacheScriptModuleMismatch) {
   25511             :   v8::Isolate::CreateParams create_params;
   25512           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25513             : 
   25514             :   const char* origin = "code cache test";
   25515             :   const char* source = "42";
   25516             : 
   25517             :   v8::ScriptCompiler::CachedData* cache;
   25518             :   {
   25519           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25520             :     {
   25521             :       v8::Isolate::Scope iscope(isolate);
   25522          10 :       v8::HandleScope scope(isolate);
   25523           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25524             :       v8::Context::Scope cscope(context);
   25525           5 :       v8::Local<v8::String> source_string = v8_str(source);
   25526           5 :       v8::ScriptOrigin script_origin(v8_str(origin));
   25527             :       v8::ScriptCompiler::Source source(source_string, script_origin);
   25528             :       v8::ScriptCompiler::CompileOptions option =
   25529             :           v8::ScriptCompiler::kNoCompileOptions;
   25530             :       v8::Local<v8::Script> script =
   25531           5 :           v8::ScriptCompiler::Compile(context, &source, option)
   25532             :               .ToLocalChecked();
   25533           5 :       cache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
   25534             :     }
   25535           5 :     isolate->Dispose();
   25536             :   }
   25537             : 
   25538             :   // Test that the cache is not consumed when source is compiled as a module.
   25539             :   {
   25540           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25541             :     {
   25542             :       v8::Isolate::Scope iscope(isolate);
   25543          10 :       v8::HandleScope scope(isolate);
   25544           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25545             :       v8::Context::Scope cscope(context);
   25546             : 
   25547             :       v8::ScriptOrigin script_origin(
   25548             :           v8_str(origin), Local<v8::Integer>(), Local<v8::Integer>(),
   25549             :           Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   25550           5 :           Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   25551             :       v8::ScriptCompiler::Source script_compiler_source(v8_str(source),
   25552           5 :                                                         script_origin, cache);
   25553             : 
   25554           5 :       Local<Module> module = v8::ScriptCompiler::CompileModule(
   25555             :                                  isolate, &script_compiler_source,
   25556             :                                  v8::ScriptCompiler::kConsumeCodeCache)
   25557             :                                  .ToLocalChecked();
   25558          10 :       module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   25559             :           .ToChecked();
   25560             : 
   25561           5 :       CHECK(cache->rejected);
   25562             : 
   25563             :       Local<Value> completion_value =
   25564           5 :           module->Evaluate(context).ToLocalChecked();
   25565          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   25566             :     }
   25567           5 :     isolate->Dispose();
   25568             :   }
   25569           5 : }
   25570             : 
   25571             : // Tests that compilation can handle a garbled cache.
   25572       26644 : TEST(InvalidCodeCacheDataInCompileModule) {
   25573           5 :   v8::V8::Initialize();
   25574           5 :   v8::Isolate* isolate = CcTest::isolate();
   25575          10 :   v8::HandleScope scope(isolate);
   25576           5 :   LocalContext local_context;
   25577             : 
   25578             :   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   25579             :   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   25580           5 :   Local<String> origin = v8_str("origin");
   25581             :   int length = 16;
   25582             :   v8::ScriptCompiler::CachedData* cached_data =
   25583           5 :       new v8::ScriptCompiler::CachedData(data, length);
   25584           5 :   CHECK(!cached_data->rejected);
   25585             : 
   25586             :   v8::ScriptOrigin script_origin(
   25587             :       origin, Local<v8::Integer>(), Local<v8::Integer>(), Local<v8::Boolean>(),
   25588             :       Local<v8::Integer>(), Local<v8::Value>(), Local<v8::Boolean>(),
   25589             :       Local<v8::Boolean>(), True(isolate));
   25590           5 :   v8::ScriptCompiler::Source source(v8_str("42"), script_origin, cached_data);
   25591           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   25592             : 
   25593             :   Local<Module> module =
   25594           5 :       v8::ScriptCompiler::CompileModule(isolate, &source,
   25595             :                                         v8::ScriptCompiler::kConsumeCodeCache)
   25596             :           .ToLocalChecked();
   25597          10 :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   25598             :       .ToChecked();
   25599             : 
   25600           5 :   CHECK(cached_data->rejected);
   25601          15 :   CHECK_EQ(42, module->Evaluate(context)
   25602             :                    .ToLocalChecked()
   25603             :                    ->Int32Value(context)
   25604             :                    .FromJust());
   25605           5 : }
   25606             : 
   25607           5 : void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
   25608             :   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   25609             :   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   25610             :   int length = 16;
   25611             :   v8::ScriptCompiler::CachedData* cached_data =
   25612           5 :       new v8::ScriptCompiler::CachedData(data, length);
   25613           5 :   CHECK(!cached_data->rejected);
   25614           5 :   v8::ScriptOrigin origin(v8_str("origin"));
   25615           5 :   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
   25616           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   25617             :   v8::Local<v8::Script> script =
   25618           5 :       v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   25619           5 :   CHECK(cached_data->rejected);
   25620          15 :   CHECK_EQ(
   25621             :       42,
   25622             :       script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
   25623           5 : }
   25624             : 
   25625             : 
   25626       26644 : TEST(InvalidCodeCacheData) {
   25627           5 :   v8::V8::Initialize();
   25628          10 :   v8::HandleScope scope(CcTest::isolate());
   25629           5 :   LocalContext context;
   25630           5 :   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
   25631           5 : }
   25632             : 
   25633             : 
   25634       26644 : TEST(StringConcatOverflow) {
   25635           5 :   v8::V8::Initialize();
   25636           5 :   v8::Isolate* isolate = CcTest::isolate();
   25637          10 :   v8::HandleScope scope(isolate);
   25638             :   RandomLengthOneByteResource* r =
   25639           5 :       new RandomLengthOneByteResource(i::String::kMaxLength);
   25640             :   v8::Local<v8::String> str =
   25641           5 :       v8::String::NewExternalOneByte(isolate, r).ToLocalChecked();
   25642           5 :   CHECK(!str.IsEmpty());
   25643          10 :   v8::TryCatch try_catch(isolate);
   25644           5 :   v8::Local<v8::String> result = v8::String::Concat(isolate, str, str);
   25645           5 :   v8::String::Concat(CcTest::isolate(), str, str);
   25646           5 :   CHECK(result.IsEmpty());
   25647           5 :   CHECK(!try_catch.HasCaught());
   25648           5 : }
   25649             : 
   25650       26643 : TEST(TurboAsmDisablesDetach) {
   25651             : #ifndef V8_LITE_MODE
   25652           4 :   i::FLAG_opt = true;
   25653           4 :   i::FLAG_allow_natives_syntax = true;
   25654           4 :   v8::V8::Initialize();
   25655           8 :   v8::HandleScope scope(CcTest::isolate());
   25656           4 :   LocalContext context;
   25657             :   const char* load =
   25658             :       "function Module(stdlib, foreign, heap) {"
   25659             :       "  'use asm';"
   25660             :       "  var MEM32 = new stdlib.Int32Array(heap);"
   25661             :       "  function load() { return MEM32[0] | 0; }"
   25662             :       "  return { load: load };"
   25663             :       "}"
   25664             :       "var buffer = new ArrayBuffer(4096);"
   25665             :       "var module = Module(this, {}, buffer);"
   25666             :       "%OptimizeFunctionOnNextCall(module.load);"
   25667             :       "module.load();"
   25668             :       "buffer";
   25669             : 
   25670             :   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
   25671           4 :   CHECK(!result->IsDetachable());
   25672             : 
   25673             :   const char* store =
   25674             :       "function Module(stdlib, foreign, heap) {"
   25675             :       "  'use asm';"
   25676             :       "  var MEM32 = new stdlib.Int32Array(heap);"
   25677             :       "  function store() { MEM32[0] = 0; }"
   25678             :       "  return { store: store };"
   25679             :       "}"
   25680             :       "var buffer = new ArrayBuffer(4096);"
   25681             :       "var module = Module(this, {}, buffer);"
   25682             :       "%OptimizeFunctionOnNextCall(module.store);"
   25683             :       "module.store();"
   25684             :       "buffer";
   25685             : 
   25686             :   result = CompileRun(store).As<v8::ArrayBuffer>();
   25687           4 :   CHECK(!result->IsDetachable());
   25688             : #endif  // V8_LITE_MODE
   25689           4 : }
   25690             : 
   25691       26644 : TEST(ClassPrototypeCreationContext) {
   25692           5 :   v8::Isolate* isolate = CcTest::isolate();
   25693          10 :   v8::HandleScope handle_scope(isolate);
   25694           5 :   LocalContext env;
   25695             : 
   25696             :   Local<Object> result = Local<Object>::Cast(
   25697             :       CompileRun("'use strict'; class Example { }; Example.prototype"));
   25698          10 :   CHECK(env.local() == result->CreationContext());
   25699           5 : }
   25700             : 
   25701             : 
   25702       26644 : TEST(SimpleStreamingScriptWithSourceURL) {
   25703             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
   25704           5 :                           "//# sourceURL=bar2.js\n", nullptr};
   25705             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25706           5 :                    "bar2.js");
   25707           5 : }
   25708             : 
   25709             : 
   25710       26644 : TEST(StreamingScriptWithSplitSourceURL) {
   25711             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
   25712           5 :                           "oo();\n//# sourceURL=b", "ar2.js\n", nullptr};
   25713             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25714           5 :                    "bar2.js");
   25715           5 : }
   25716             : 
   25717             : 
   25718       26644 : TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
   25719             :   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
   25720           5 :                           " sourceMappingURL=bar2.js\n", "foo();", nullptr};
   25721             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25722           5 :                    nullptr, "bar2.js");
   25723           5 : }
   25724             : 
   25725             : 
   25726       26644 : TEST(NewStringRangeError) {
   25727             :   // This test uses a lot of memory and fails with flaky OOM when run
   25728             :   // with --stress-incremental-marking on TSAN.
   25729           5 :   i::FLAG_stress_incremental_marking = false;
   25730           5 :   v8::Isolate* isolate = CcTest::isolate();
   25731          10 :   v8::HandleScope handle_scope(isolate);
   25732             :   const int length = i::String::kMaxLength + 1;
   25733             :   const int buffer_size = length * sizeof(uint16_t);
   25734           5 :   void* buffer = malloc(buffer_size);
   25735           5 :   if (buffer == nullptr) return;
   25736             :   memset(buffer, 'A', buffer_size);
   25737             :   {
   25738          10 :     v8::TryCatch try_catch(isolate);
   25739             :     char* data = reinterpret_cast<char*>(buffer);
   25740          10 :     CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
   25741             :                                   length)
   25742             :               .IsEmpty());
   25743           5 :     CHECK(!try_catch.HasCaught());
   25744             :   }
   25745             :   {
   25746          10 :     v8::TryCatch try_catch(isolate);
   25747             :     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
   25748          10 :     CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
   25749             :                                      length)
   25750             :               .IsEmpty());
   25751           5 :     CHECK(!try_catch.HasCaught());
   25752             :   }
   25753             :   {
   25754          10 :     v8::TryCatch try_catch(isolate);
   25755             :     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
   25756          10 :     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
   25757             :                                      length)
   25758             :               .IsEmpty());
   25759           5 :     CHECK(!try_catch.HasCaught());
   25760             :   }
   25761           5 :   free(buffer);
   25762             : }
   25763             : 
   25764             : 
   25765       26639 : TEST(SealHandleScope) {
   25766           0 :   v8::Isolate* isolate = CcTest::isolate();
   25767           0 :   v8::HandleScope handle_scope(isolate);
   25768           0 :   LocalContext env;
   25769             : 
   25770           0 :   v8::SealHandleScope seal(isolate);
   25771             : 
   25772             :   // Should fail
   25773           0 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   25774             : 
   25775             :   USE(obj);
   25776           0 : }
   25777             : 
   25778             : 
   25779       26644 : TEST(SealHandleScopeNested) {
   25780           5 :   v8::Isolate* isolate = CcTest::isolate();
   25781          10 :   v8::HandleScope handle_scope(isolate);
   25782           5 :   LocalContext env;
   25783             : 
   25784          10 :   v8::SealHandleScope seal(isolate);
   25785             : 
   25786             :   {
   25787          10 :     v8::HandleScope handle_scope(isolate);
   25788             : 
   25789             :     // Should work
   25790           5 :     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   25791             : 
   25792             :     USE(obj);
   25793             :   }
   25794           5 : }
   25795             : 
   25796             : 
   25797           5 : static void ExtrasBindingTestRuntimeFunction(
   25798             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   25799          15 :   CHECK_EQ(
   25800             :       3,
   25801             :       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
   25802           5 :   args.GetReturnValue().Set(v8_num(7));
   25803           5 : }
   25804             : 
   25805       26644 : TEST(ExtrasFunctionSource) {
   25806           5 :   v8::Isolate* isolate = CcTest::isolate();
   25807          10 :   v8::HandleScope handle_scope(isolate);
   25808           5 :   LocalContext env;
   25809             : 
   25810           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25811             : 
   25812             :   // Functions defined in extras do not expose source code.
   25813          15 :   auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
   25814             :                   .ToLocalChecked()
   25815             :                   .As<v8::Function>();
   25816             :   auto undefined = v8::Undefined(isolate);
   25817          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25818             :                     .ToLocalChecked()
   25819             :                     .As<v8::String>();
   25820          10 :   CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
   25821             : 
   25822             :   // Functions defined in extras do not show up in the stack trace.
   25823          15 :   auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
   25824             :                      .ToLocalChecked()
   25825             :                      .As<v8::Function>();
   25826          20 :   CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
   25827             :   ExpectString(
   25828             :       "function f(x) { return wrapper(x) }"
   25829             :       "function g() { return new Error().stack; }"
   25830             :       "f(g)",
   25831             :       "Error\n"
   25832             :       "    at g (<anonymous>:1:58)\n"
   25833             :       "    at f (<anonymous>:1:24)\n"
   25834           5 :       "    at <anonymous>:1:78");
   25835           5 : }
   25836             : 
   25837       26644 : TEST(ExtrasBindingObject) {
   25838           5 :   v8::Isolate* isolate = CcTest::isolate();
   25839          10 :   v8::HandleScope handle_scope(isolate);
   25840           5 :   LocalContext env;
   25841             : 
   25842             :   // standalone.gypi ensures we include the test-extra.js file, which should
   25843             :   // export the tested functions.
   25844           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25845             : 
   25846          15 :   auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
   25847             :                   .ToLocalChecked()
   25848             :                   .As<v8::Function>();
   25849             :   auto undefined = v8::Undefined(isolate);
   25850          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25851             :                     .ToLocalChecked()
   25852             :                     .As<v8::Number>();
   25853          10 :   CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
   25854             : 
   25855             :   v8::Local<v8::FunctionTemplate> runtimeFunction =
   25856           5 :       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   25857          10 :   binding->Set(env.local(), v8_str("runtime"),
   25858          15 :                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   25859             :       .FromJust();
   25860          15 :   func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
   25861             :              .ToLocalChecked()
   25862             :              .As<v8::Function>();
   25863          10 :   result = func->Call(env.local(), undefined, 0, {})
   25864             :                .ToLocalChecked()
   25865             :                .As<v8::Number>();
   25866          10 :   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   25867           5 : }
   25868             : 
   25869             : 
   25870       26644 : TEST(ExtrasCreatePromise) {
   25871           5 :   i::FLAG_allow_natives_syntax = true;
   25872           5 :   LocalContext context;
   25873           5 :   v8::Isolate* isolate = context->GetIsolate();
   25874          10 :   v8::HandleScope handle_scope(isolate);
   25875             : 
   25876           5 :   LocalContext env;
   25877           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25878             : 
   25879          15 :   auto func = binding->Get(env.local(), v8_str("testCreatePromise"))
   25880             :                   .ToLocalChecked()
   25881             :                   .As<v8::Function>();
   25882          20 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   25883             : 
   25884             :   auto promise = CompileRun(
   25885             :                      "func();\n"
   25886             :                      "func();\n"
   25887             :                      "%OptimizeFunctionOnNextCall(func);\n"
   25888             :                      "func()\n")
   25889             :                      .As<v8::Promise>();
   25890           5 :   CHECK_EQ(v8::Promise::kPending, promise->State());
   25891           5 : }
   25892             : 
   25893       26644 : TEST(ExtrasCreatePromiseWithParent) {
   25894           5 :   i::FLAG_allow_natives_syntax = true;
   25895           5 :   LocalContext context;
   25896           5 :   v8::Isolate* isolate = context->GetIsolate();
   25897          10 :   v8::HandleScope handle_scope(isolate);
   25898             : 
   25899           5 :   LocalContext env;
   25900           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25901             : 
   25902          15 :   auto func = binding->Get(env.local(), v8_str("testCreatePromiseWithParent"))
   25903             :                   .ToLocalChecked()
   25904             :                   .As<v8::Function>();
   25905          20 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   25906             : 
   25907             :   auto promise = CompileRun(
   25908             :                      "var parent = new Promise((a, b) => {});\n"
   25909             :                      "func(parent);\n"
   25910             :                      "func(parent);\n"
   25911             :                      "%OptimizeFunctionOnNextCall(func);\n"
   25912             :                      "func(parent)\n")
   25913             :                      .As<v8::Promise>();
   25914           5 :   CHECK_EQ(v8::Promise::kPending, promise->State());
   25915           5 : }
   25916             : 
   25917       26644 : TEST(ExtrasRejectPromise) {
   25918           5 :   i::FLAG_allow_natives_syntax = true;
   25919           5 :   LocalContext context;
   25920           5 :   v8::Isolate* isolate = context->GetIsolate();
   25921          10 :   v8::HandleScope handle_scope(isolate);
   25922             : 
   25923           5 :   LocalContext env;
   25924           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25925             : 
   25926          15 :   auto func = binding->Get(env.local(), v8_str("testRejectPromise"))
   25927             :                   .ToLocalChecked()
   25928             :                   .As<v8::Function>();
   25929          20 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   25930             : 
   25931             :   auto rejected_promise = CompileRun(
   25932             :                               "function newPromise() {\n"
   25933             :                               "  return new Promise((a, b) => {});\n"
   25934             :                               "}\n"
   25935             :                               "func(newPromise(), 1);\n"
   25936             :                               "func(newPromise(), 1);\n"
   25937             :                               "%OptimizeFunctionOnNextCall(func);\n"
   25938             :                               "var promise = newPromise();\n"
   25939             :                               "func(promise, 1);\n"
   25940             :                               "promise;\n")
   25941             :                               .As<v8::Promise>();
   25942           5 :   CHECK_EQ(v8::Promise::kRejected, rejected_promise->State());
   25943          15 :   CHECK_EQ(1, rejected_promise->Result()->Int32Value(env.local()).FromJust());
   25944           5 : }
   25945             : 
   25946       26644 : TEST(ExtrasResolvePromise) {
   25947           5 :   i::FLAG_allow_natives_syntax = true;
   25948           5 :   LocalContext context;
   25949           5 :   v8::Isolate* isolate = context->GetIsolate();
   25950          10 :   v8::HandleScope handle_scope(isolate);
   25951             : 
   25952           5 :   LocalContext env;
   25953           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25954             : 
   25955          15 :   auto func = binding->Get(env.local(), v8_str("testResolvePromise"))
   25956             :                   .ToLocalChecked()
   25957             :                   .As<v8::Function>();
   25958          20 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   25959             : 
   25960             :   auto pending_promise = CompileRun(
   25961             :                              "function newPromise() {\n"
   25962             :                              "  return new Promise((a, b) => {});\n"
   25963             :                              "}\n"
   25964             :                              "func(newPromise(), newPromise());\n"
   25965             :                              "func(newPromise(), newPromise());\n"
   25966             :                              "%OptimizeFunctionOnNextCall(func);\n"
   25967             :                              "var promise = newPromise();\n"
   25968             :                              "func(promise, newPromise());\n"
   25969             :                              "promise;\n")
   25970             :                              .As<v8::Promise>();
   25971           5 :   CHECK_EQ(v8::Promise::kPending, pending_promise->State());
   25972             : 
   25973             :   auto fulfilled_promise = CompileRun(
   25974             :                                "function newPromise() {\n"
   25975             :                                "  return new Promise((a, b) => {});\n"
   25976             :                                "}\n"
   25977             :                                "func(newPromise(), 1);\n"
   25978             :                                "func(newPromise(), 1);\n"
   25979             :                                "%OptimizeFunctionOnNextCall(func);\n"
   25980             :                                "var promise = newPromise();\n"
   25981             :                                "func(promise, 1);\n"
   25982             :                                "promise;\n")
   25983             :                                .As<v8::Promise>();
   25984           5 :   CHECK_EQ(v8::Promise::kFulfilled, fulfilled_promise->State());
   25985          15 :   CHECK_EQ(1, fulfilled_promise->Result()->Int32Value(env.local()).FromJust());
   25986           5 : }
   25987             : 
   25988       26644 : TEST(ExtrasUtilsObject) {
   25989           5 :   LocalContext context;
   25990           5 :   v8::Isolate* isolate = context->GetIsolate();
   25991          10 :   v8::HandleScope handle_scope(isolate);
   25992             : 
   25993           5 :   LocalContext env;
   25994           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25995             : 
   25996          15 :   auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
   25997             :                   .ToLocalChecked()
   25998             :                   .As<v8::Function>();
   25999             :   auto undefined = v8::Undefined(isolate);
   26000          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   26001             :                     .ToLocalChecked()
   26002             :                     .As<v8::Object>();
   26003             : 
   26004          15 :   auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
   26005             :                             .ToLocalChecked()
   26006             :                             .As<v8::Symbol>();
   26007             :   i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
   26008           5 :   CHECK(ips->IsPrivate());
   26009             : 
   26010             :   CompileRun("var result = 0; function store(x) { result = x; }");
   26011           5 :   auto store = CompileRun("store").As<v8::Function>();
   26012             : 
   26013          15 :   auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
   26014             :                                .ToLocalChecked()
   26015             :                                .As<v8::Promise>();
   26016           5 :   fulfilled_promise->Then(env.local(), store).ToLocalChecked();
   26017           5 :   isolate->RunMicrotasks();
   26018          10 :   CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
   26019             : 
   26020             :   auto fulfilled_promise_2 =
   26021          15 :       result->Get(env.local(), v8_str("fulfilledPromise2"))
   26022             :           .ToLocalChecked()
   26023             :           .As<v8::Promise>();
   26024           5 :   fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
   26025           5 :   isolate->RunMicrotasks();
   26026          10 :   CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
   26027             : 
   26028          15 :   auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
   26029             :                               .ToLocalChecked()
   26030             :                               .As<v8::Promise>();
   26031           5 :   rejected_promise->Catch(env.local(), store).ToLocalChecked();
   26032           5 :   isolate->RunMicrotasks();
   26033          10 :   CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
   26034             : 
   26035             :   auto rejected_but_handled_promise =
   26036          15 :       result->Get(env.local(), v8_str("rejectedButHandledPromise"))
   26037             :           .ToLocalChecked()
   26038             :           .As<v8::Promise>();
   26039           5 :   CHECK(rejected_but_handled_promise->HasHandler());
   26040             : 
   26041          15 :   auto promise_states = result->Get(env.local(), v8_str("promiseStates"))
   26042             :                             .ToLocalChecked()
   26043             :                             .As<v8::String>();
   26044          10 :   String::Utf8Value promise_states_string(isolate, promise_states);
   26045           5 :   CHECK_EQ(0, strcmp(*promise_states_string, "pending fulfilled rejected"));
   26046             : 
   26047          15 :   auto promise_is_promise = result->Get(env.local(), v8_str("promiseIsPromise"))
   26048             :                                 .ToLocalChecked()
   26049             :                                 .As<v8::Boolean>();
   26050           5 :   CHECK_EQ(true, promise_is_promise->Value());
   26051             : 
   26052             :   auto thenable_is_promise =
   26053          15 :       result->Get(env.local(), v8_str("thenableIsPromise"))
   26054             :           .ToLocalChecked()
   26055             :           .As<v8::Boolean>();
   26056           5 :   CHECK_EQ(false, thenable_is_promise->Value());
   26057             : 
   26058          15 :   auto uncurry_this = result->Get(env.local(), v8_str("uncurryThis"))
   26059             :                           .ToLocalChecked()
   26060             :                           .As<v8::Boolean>();
   26061           5 :   CHECK_EQ(true, uncurry_this->Value());
   26062           5 : }
   26063             : 
   26064             : 
   26065       26644 : TEST(Map) {
   26066           5 :   v8::Isolate* isolate = CcTest::isolate();
   26067          10 :   v8::HandleScope handle_scope(isolate);
   26068           5 :   LocalContext env;
   26069             : 
   26070           5 :   v8::Local<v8::Map> map = v8::Map::New(isolate);
   26071           5 :   CHECK(map->IsObject());
   26072           5 :   CHECK(map->IsMap());
   26073          10 :   CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
   26074           5 :   CHECK_EQ(0U, map->Size());
   26075             : 
   26076             :   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
   26077           5 :   CHECK(val->IsMap());
   26078             :   map = v8::Local<v8::Map>::Cast(val);
   26079           5 :   CHECK_EQ(2U, map->Size());
   26080             : 
   26081           5 :   v8::Local<v8::Array> contents = map->AsArray();
   26082           5 :   CHECK_EQ(4U, contents->Length());
   26083          10 :   CHECK_EQ(
   26084             :       1,
   26085             :       contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   26086          10 :   CHECK_EQ(
   26087             :       2,
   26088             :       contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   26089          10 :   CHECK_EQ(
   26090             :       3,
   26091             :       contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
   26092          10 :   CHECK_EQ(
   26093             :       4,
   26094             :       contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
   26095             : 
   26096           5 :   CHECK_EQ(2U, map->Size());
   26097             : 
   26098          15 :   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   26099          15 :   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   26100             : 
   26101          15 :   CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   26102          10 :   CHECK(!map->Has(env.local(), map).FromJust());
   26103             : 
   26104          20 :   CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
   26105             :                   .ToLocalChecked()
   26106             :                   ->Int32Value(env.local())
   26107             :                   .FromJust());
   26108          20 :   CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
   26109             :                   .ToLocalChecked()
   26110             :                   ->Int32Value(env.local())
   26111             :                   .FromJust());
   26112             : 
   26113          15 :   CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
   26114             :             .ToLocalChecked()
   26115             :             ->IsUndefined());
   26116             : 
   26117          10 :   CHECK(!map->Set(env.local(), map, map).IsEmpty());
   26118           5 :   CHECK_EQ(3U, map->Size());
   26119          10 :   CHECK(map->Has(env.local(), map).FromJust());
   26120             : 
   26121          10 :   CHECK(map->Delete(env.local(), map).FromJust());
   26122           5 :   CHECK_EQ(2U, map->Size());
   26123          10 :   CHECK(!map->Has(env.local(), map).FromJust());
   26124          10 :   CHECK(!map->Delete(env.local(), map).FromJust());
   26125             : 
   26126           5 :   map->Clear();
   26127           5 :   CHECK_EQ(0U, map->Size());
   26128           5 : }
   26129             : 
   26130             : 
   26131       26644 : TEST(Set) {
   26132           5 :   v8::Isolate* isolate = CcTest::isolate();
   26133          10 :   v8::HandleScope handle_scope(isolate);
   26134           5 :   LocalContext env;
   26135             : 
   26136           5 :   v8::Local<v8::Set> set = v8::Set::New(isolate);
   26137           5 :   CHECK(set->IsObject());
   26138           5 :   CHECK(set->IsSet());
   26139          10 :   CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
   26140           5 :   CHECK_EQ(0U, set->Size());
   26141             : 
   26142             :   v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
   26143           5 :   CHECK(val->IsSet());
   26144             :   set = v8::Local<v8::Set>::Cast(val);
   26145           5 :   CHECK_EQ(2U, set->Size());
   26146             : 
   26147           5 :   v8::Local<v8::Array> keys = set->AsArray();
   26148           5 :   CHECK_EQ(2U, keys->Length());
   26149          10 :   CHECK_EQ(1,
   26150             :            keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   26151          10 :   CHECK_EQ(2,
   26152             :            keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   26153             : 
   26154           5 :   CHECK_EQ(2U, set->Size());
   26155             : 
   26156          15 :   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   26157          15 :   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   26158             : 
   26159          15 :   CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   26160          10 :   CHECK(!set->Has(env.local(), set).FromJust());
   26161             : 
   26162          10 :   CHECK(!set->Add(env.local(), set).IsEmpty());
   26163           5 :   CHECK_EQ(3U, set->Size());
   26164          10 :   CHECK(set->Has(env.local(), set).FromJust());
   26165             : 
   26166          10 :   CHECK(set->Delete(env.local(), set).FromJust());
   26167           5 :   CHECK_EQ(2U, set->Size());
   26168          10 :   CHECK(!set->Has(env.local(), set).FromJust());
   26169          10 :   CHECK(!set->Delete(env.local(), set).FromJust());
   26170             : 
   26171           5 :   set->Clear();
   26172           5 :   CHECK_EQ(0U, set->Size());
   26173           5 : }
   26174             : 
   26175       26644 : TEST(SetDeleteThenAsArray) {
   26176             :   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   26177           5 :   v8::Isolate* isolate = CcTest::isolate();
   26178          10 :   v8::HandleScope handle_scope(isolate);
   26179           5 :   LocalContext env;
   26180             : 
   26181             :   // make a Set
   26182             :   v8::Local<v8::Value> val = CompileRun("new Set([1, 2, 3])");
   26183             :   v8::Local<v8::Set> set = v8::Local<v8::Set>::Cast(val);
   26184           5 :   CHECK_EQ(3U, set->Size());
   26185             : 
   26186             :   // delete the "middle" element (using AsArray to
   26187             :   // determine which element is the "middle" element)
   26188           5 :   v8::Local<v8::Array> array1 = set->AsArray();
   26189           5 :   CHECK_EQ(3U, array1->Length());
   26190          15 :   CHECK(set->Delete(env.local(), array1->Get(env.local(), 1).ToLocalChecked())
   26191             :             .FromJust());
   26192             : 
   26193             :   // make sure there are no undefined values when we convert to an array again.
   26194           5 :   v8::Local<v8::Array> array2 = set->AsArray();
   26195           5 :   uint32_t length = array2->Length();
   26196           5 :   CHECK_EQ(2U, length);
   26197          25 :   for (uint32_t i = 0; i < length; i++) {
   26198          20 :     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   26199             :   }
   26200           5 : }
   26201             : 
   26202       26644 : TEST(MapDeleteThenAsArray) {
   26203             :   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   26204           5 :   v8::Isolate* isolate = CcTest::isolate();
   26205          10 :   v8::HandleScope handle_scope(isolate);
   26206           5 :   LocalContext env;
   26207             : 
   26208             :   // make a Map
   26209             :   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4], [5, 6]])");
   26210             :   v8::Local<v8::Map> map = v8::Local<v8::Map>::Cast(val);
   26211           5 :   CHECK_EQ(3U, map->Size());
   26212             : 
   26213             :   // delete the "middle" element (using AsArray to
   26214             :   // determine which element is the "middle" element)
   26215           5 :   v8::Local<v8::Array> array1 = map->AsArray();
   26216           5 :   CHECK_EQ(6U, array1->Length());
   26217             :   // Map::AsArray returns a flat array, so the second key is at index 2.
   26218          10 :   v8::Local<v8::Value> key = array1->Get(env.local(), 2).ToLocalChecked();
   26219          10 :   CHECK(map->Delete(env.local(), key).FromJust());
   26220             : 
   26221             :   // make sure there are no undefined values when we convert to an array again.
   26222           5 :   v8::Local<v8::Array> array2 = map->AsArray();
   26223           5 :   uint32_t length = array2->Length();
   26224           5 :   CHECK_EQ(4U, length);
   26225          45 :   for (uint32_t i = 0; i < length; i++) {
   26226          40 :     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   26227             :   }
   26228           5 : }
   26229             : 
   26230       26644 : TEST(CompatibleReceiverCheckOnCachedICHandler) {
   26231           5 :   v8::Isolate* isolate = CcTest::isolate();
   26232          10 :   v8::HandleScope scope(isolate);
   26233           5 :   v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
   26234           5 :   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
   26235             :   auto returns_42 =
   26236           5 :       v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
   26237          15 :   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
   26238           5 :   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
   26239           5 :   child->Inherit(parent);
   26240           5 :   LocalContext env;
   26241          25 :   CHECK(env->Global()
   26242             :             ->Set(env.local(), v8_str("Child"),
   26243             :                   child->GetFunction(env.local()).ToLocalChecked())
   26244             :             .FromJust());
   26245             : 
   26246             :   // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
   26247             :   CompileRun(
   26248             :       "var real = new Child();\n"
   26249             :       "for (var i = 0; i < 3; ++i) {\n"
   26250             :       "  real.age;\n"
   26251             :       "}\n");
   26252             : 
   26253             :   // Check that the cached stub is never used.
   26254             :   ExpectInt32(
   26255             :       "var fake = Object.create(Child.prototype);\n"
   26256             :       "var result = 0;\n"
   26257             :       "function test(d) {\n"
   26258             :       "  if (d == 3) return;\n"
   26259             :       "  try {\n"
   26260             :       "    fake.age;\n"
   26261             :       "    result = 1;\n"
   26262             :       "  } catch (e) {\n"
   26263             :       "  }\n"
   26264             :       "  test(d+1);\n"
   26265             :       "}\n"
   26266             :       "test(0);\n"
   26267             :       "result;\n",
   26268           5 :       0);
   26269           5 : }
   26270             : 
   26271       26645 : THREADED_TEST(ReceiverConversionForAccessors) {
   26272           6 :   LocalContext env;
   26273           6 :   v8::Isolate* isolate = CcTest::isolate();
   26274          12 :   v8::HandleScope scope(isolate);
   26275             :   Local<v8::FunctionTemplate> acc =
   26276           6 :       v8::FunctionTemplate::New(isolate, Returns42);
   26277          30 :   CHECK(env->Global()
   26278             :             ->Set(env.local(), v8_str("acc"),
   26279             :                   acc->GetFunction(env.local()).ToLocalChecked())
   26280             :             .FromJust());
   26281             : 
   26282           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   26283          12 :   templ->SetAccessorProperty(v8_str("acc"), acc, acc);
   26284           6 :   Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   26285             : 
   26286          24 :   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
   26287           6 :   CHECK(CompileRun("(p.acc == 42)")->BooleanValue(isolate));
   26288           6 :   CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(isolate));
   26289             : 
   26290           6 :   CHECK(!CompileRun("Number.prototype.__proto__ = p;"
   26291             :                     "var a = 1;")
   26292             :              .IsEmpty());
   26293           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26294           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26295             : 
   26296           6 :   CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
   26297             :                     "var a = true;")
   26298             :              .IsEmpty());
   26299           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26300           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26301             : 
   26302           6 :   CHECK(!CompileRun("String.prototype.__proto__ = p;"
   26303             :                     "var a = 'foo';")
   26304             :              .IsEmpty());
   26305           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26306           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26307             : 
   26308           6 :   CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(isolate));
   26309           6 :   CHECK(CompileRun("acc.call(true)==42")->BooleanValue(isolate));
   26310           6 :   CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(isolate));
   26311           6 :   CHECK(CompileRun("acc.call(null) == 42")->BooleanValue(isolate));
   26312           6 :   CHECK(CompileRun("acc.call(undefined) == 42")->BooleanValue(isolate));
   26313           6 : }
   26314             : 
   26315           5 : class FutexInterruptionThread : public v8::base::Thread {
   26316             :  public:
   26317             :   explicit FutexInterruptionThread(v8::Isolate* isolate)
   26318           5 :       : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
   26319             : 
   26320           5 :   void Run() override {
   26321             :     // Wait a bit before terminating.
   26322           5 :     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   26323           5 :     isolate_->TerminateExecution();
   26324           5 :   }
   26325             : 
   26326             :  private:
   26327             :   v8::Isolate* isolate_;
   26328             : };
   26329             : 
   26330             : 
   26331       26644 : TEST(FutexInterruption) {
   26332           5 :   i::FLAG_harmony_sharedarraybuffer = true;
   26333           5 :   v8::Isolate* isolate = CcTest::isolate();
   26334          10 :   v8::HandleScope scope(isolate);
   26335           5 :   LocalContext env;
   26336             : 
   26337             :   FutexInterruptionThread timeout_thread(isolate);
   26338             : 
   26339          10 :   v8::TryCatch try_catch(CcTest::isolate());
   26340           5 :   timeout_thread.Start();
   26341             : 
   26342             :   CompileRun(
   26343             :       "var ab = new SharedArrayBuffer(4);"
   26344             :       "var i32a = new Int32Array(ab);"
   26345             :       "Atomics.wait(i32a, 0, 0);");
   26346           5 :   CHECK(try_catch.HasTerminated());
   26347           5 :   timeout_thread.Join();
   26348           5 : }
   26349             : 
   26350       26645 : THREADED_TEST(SharedArrayBuffer_AllocationInformation) {
   26351           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   26352           6 :   LocalContext env;
   26353           6 :   v8::Isolate* isolate = env->GetIsolate();
   26354          12 :   v8::HandleScope handle_scope(isolate);
   26355             : 
   26356             :   const size_t ab_size = 1024;
   26357             :   Local<v8::SharedArrayBuffer> ab =
   26358           6 :       v8::SharedArrayBuffer::New(isolate, ab_size);
   26359          12 :   ScopedSharedArrayBufferContents contents(ab->Externalize());
   26360             : 
   26361             :   // Array buffers should have normal allocation mode.
   26362           6 :   CHECK_EQ(contents.AllocationMode(),
   26363             :            v8::ArrayBuffer::Allocator::AllocationMode::kNormal);
   26364             :   // The allocation must contain the buffer (normally they will be equal, but
   26365             :   // this is not required by the contract).
   26366           6 :   CHECK_NOT_NULL(contents.AllocationBase());
   26367             :   const uintptr_t alloc =
   26368           6 :       reinterpret_cast<uintptr_t>(contents.AllocationBase());
   26369           6 :   const uintptr_t data = reinterpret_cast<uintptr_t>(contents.Data());
   26370           6 :   CHECK_LE(alloc, data);
   26371           6 :   CHECK_LE(data + contents.ByteLength(), alloc + contents.AllocationLength());
   26372           6 : }
   26373             : 
   26374             : static int nb_uncaught_exception_callback_calls = 0;
   26375             : 
   26376             : 
   26377           5 : bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
   26378           5 :   ++nb_uncaught_exception_callback_calls;
   26379           5 :   return false;
   26380             : }
   26381             : 
   26382             : 
   26383       26644 : TEST(AbortOnUncaughtExceptionNoAbort) {
   26384           5 :   v8::Isolate* isolate = CcTest::isolate();
   26385          10 :   v8::HandleScope handle_scope(isolate);
   26386             :   v8::Local<v8::ObjectTemplate> global_template =
   26387           5 :       v8::ObjectTemplate::New(isolate);
   26388           5 :   LocalContext env(nullptr, global_template);
   26389             : 
   26390           5 :   i::FLAG_abort_on_uncaught_exception = true;
   26391           5 :   isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
   26392             : 
   26393             :   CompileRun("function boom() { throw new Error(\"boom\") }");
   26394             : 
   26395           5 :   v8::Local<v8::Object> global_object = env->Global();
   26396             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   26397          15 :       global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
   26398             : 
   26399          10 :   CHECK(foo->Call(env.local(), global_object, 0, nullptr).IsEmpty());
   26400             : 
   26401           5 :   CHECK_EQ(1, nb_uncaught_exception_callback_calls);
   26402           5 : }
   26403             : 
   26404             : 
   26405       26644 : TEST(AccessCheckedIsConcatSpreadable) {
   26406           5 :   v8::Isolate* isolate = CcTest::isolate();
   26407          10 :   HandleScope scope(isolate);
   26408           5 :   LocalContext env;
   26409             : 
   26410             :   // Object with access check
   26411           5 :   Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
   26412           5 :   spreadable_template->SetAccessCheckCallback(AccessBlocker);
   26413          10 :   spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
   26414           5 :                            v8::Boolean::New(isolate, true));
   26415             :   Local<Object> object =
   26416           5 :       spreadable_template->NewInstance(env.local()).ToLocalChecked();
   26417             : 
   26418           5 :   allowed_access = true;
   26419          20 :   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   26420          15 :   object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
   26421          15 :   object->Set(env.local(), 0U, v8_str("a")).FromJust();
   26422          15 :   object->Set(env.local(), 1U, v8_str("b")).FromJust();
   26423             : 
   26424             :   // Access check is allowed, and the object is spread
   26425             :   CompileRun("var result = [].concat(object)");
   26426             :   ExpectTrue("Array.isArray(result)");
   26427           5 :   ExpectString("result[0]", "a");
   26428           5 :   ExpectString("result[1]", "b");
   26429             :   ExpectTrue("result.length === 2");
   26430             :   ExpectTrue("object[Symbol.isConcatSpreadable]");
   26431             : 
   26432             :   // If access check fails, the value of @@isConcatSpreadable is ignored
   26433           5 :   allowed_access = false;
   26434             :   CompileRun("var result = [].concat(object)");
   26435             :   ExpectTrue("Array.isArray(result)");
   26436             :   ExpectTrue("result[0] === object");
   26437             :   ExpectTrue("result.length === 1");
   26438             :   ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
   26439           5 : }
   26440             : 
   26441             : 
   26442       26644 : TEST(AccessCheckedToStringTag) {
   26443           5 :   v8::Isolate* isolate = CcTest::isolate();
   26444          10 :   HandleScope scope(isolate);
   26445           5 :   LocalContext env;
   26446             : 
   26447             :   // Object with access check
   26448           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26449           5 :   object_template->SetAccessCheckCallback(AccessBlocker);
   26450             :   Local<Object> object =
   26451           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26452             : 
   26453           5 :   allowed_access = true;
   26454          20 :   env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
   26455          20 :   object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
   26456             :       .FromJust();
   26457             : 
   26458             :   // Access check is allowed, and the toStringTag is read
   26459             :   CompileRun("var result = Object.prototype.toString.call(object)");
   26460           5 :   ExpectString("result", "[object hello]");
   26461           5 :   ExpectString("object[Symbol.toStringTag]", "hello");
   26462             : 
   26463             :   // ToString through the API should succeed too.
   26464             :   String::Utf8Value result_allowed(
   26465          15 :       isolate, object->ObjectProtoToString(env.local()).ToLocalChecked());
   26466           5 :   CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
   26467             : 
   26468             :   // If access check fails, the value of @@toStringTag is ignored
   26469           5 :   allowed_access = false;
   26470             :   CompileRun("var result = Object.prototype.toString.call(object)");
   26471           5 :   ExpectString("result", "[object Object]");
   26472             :   ExpectTrue("object[Symbol.toStringTag] === undefined");
   26473             : 
   26474             :   // ToString through the API should also fail.
   26475             :   String::Utf8Value result_denied(
   26476          15 :       isolate, object->ObjectProtoToString(env.local()).ToLocalChecked());
   26477           5 :   CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
   26478           5 : }
   26479             : 
   26480       26644 : TEST(TemplateIteratorPrototypeIntrinsics) {
   26481           5 :   v8::Isolate* isolate = CcTest::isolate();
   26482          10 :   v8::HandleScope scope(isolate);
   26483           5 :   LocalContext env;
   26484             : 
   26485             :   // Object templates.
   26486             :   {
   26487           5 :     Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26488          10 :     object_template->SetIntrinsicDataProperty(v8_str("iter_proto"),
   26489           5 :                                               v8::kIteratorPrototype);
   26490             :     Local<Object> object =
   26491           5 :         object_template->NewInstance(env.local()).ToLocalChecked();
   26492          20 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust());
   26493             :     ExpectTrue("obj.iter_proto === [][Symbol.iterator]().__proto__.__proto__");
   26494             :   }
   26495             :   // Setting %IteratorProto% on the function object's prototype template.
   26496             :   {
   26497           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26498          15 :     func_template->PrototypeTemplate()->SetIntrinsicDataProperty(
   26499           5 :         v8_str("iter_proto"), v8::kIteratorPrototype);
   26500             :     Local<Function> func1 =
   26501           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26502          20 :     CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust());
   26503             :     Local<Function> func2 =
   26504           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26505          20 :     CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   26506             :     ExpectTrue(
   26507             :         "func1.prototype.iter_proto === "
   26508             :         "[][Symbol.iterator]().__proto__.__proto__");
   26509             :     ExpectTrue(
   26510             :         "func2.prototype.iter_proto === "
   26511             :         "[][Symbol.iterator]().__proto__.__proto__");
   26512             :     ExpectTrue("func1.prototype.iter_proto === func2.prototype.iter_proto");
   26513             : 
   26514             :     Local<Object> instance1 = func1->NewInstance(env.local()).ToLocalChecked();
   26515          20 :     CHECK(env->Global()
   26516             :               ->Set(env.local(), v8_str("instance1"), instance1)
   26517             :               .FromJust());
   26518             :     ExpectFalse("instance1.hasOwnProperty('iter_proto')");
   26519             :     ExpectTrue("'iter_proto' in instance1.__proto__");
   26520             :     ExpectTrue(
   26521             :         "instance1.iter_proto === [][Symbol.iterator]().__proto__.__proto__");
   26522             :   }
   26523             :   // Put %IteratorProto% in a function object's inheritance chain.
   26524             :   {
   26525             :     Local<FunctionTemplate> parent_template =
   26526           5 :         v8::FunctionTemplate::New(isolate);
   26527           5 :     parent_template->RemovePrototype();  // Remove so there is no name clash.
   26528          10 :     parent_template->SetIntrinsicDataProperty(v8_str("prototype"),
   26529           5 :                                               v8::kIteratorPrototype);
   26530           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26531           5 :     func_template->Inherit(parent_template);
   26532             : 
   26533             :     Local<Function> func =
   26534           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26535          20 :     CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26536             :     ExpectTrue(
   26537             :         "func.prototype.__proto__ === "
   26538             :         "[][Symbol.iterator]().__proto__.__proto__");
   26539             : 
   26540             :     Local<Object> func_instance =
   26541             :         func->NewInstance(env.local()).ToLocalChecked();
   26542          20 :     CHECK(env->Global()
   26543             :               ->Set(env.local(), v8_str("instance"), func_instance)
   26544             :               .FromJust());
   26545             :     ExpectTrue(
   26546             :         "instance.__proto__.__proto__ === "
   26547             :         "[][Symbol.iterator]().__proto__.__proto__");
   26548             :     ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype");
   26549             :   }
   26550           5 : }
   26551             : 
   26552       26644 : TEST(TemplateErrorPrototypeIntrinsics) {
   26553           5 :   v8::Isolate* isolate = CcTest::isolate();
   26554          10 :   v8::HandleScope scope(isolate);
   26555           5 :   LocalContext env;
   26556             : 
   26557             :   // Object templates.
   26558             :   {
   26559           5 :     Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26560          10 :     object_template->SetIntrinsicDataProperty(v8_str("error_proto"),
   26561           5 :                                               v8::kErrorPrototype);
   26562             :     Local<Object> object =
   26563           5 :         object_template->NewInstance(env.local()).ToLocalChecked();
   26564          20 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust());
   26565             :     ExpectTrue("obj.error_proto === Error.prototype");
   26566           5 :     Local<Value> error = v8::Exception::Error(v8_str("error message"));
   26567          20 :     CHECK(env->Global()->Set(env.local(), v8_str("err"), error).FromJust());
   26568             :     ExpectTrue("obj.error_proto === Object.getPrototypeOf(err)");
   26569             :   }
   26570             :   // Setting %ErrorPrototype% on the function object's prototype template.
   26571             :   {
   26572           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26573          15 :     func_template->PrototypeTemplate()->SetIntrinsicDataProperty(
   26574           5 :         v8_str("error_proto"), v8::kErrorPrototype);
   26575             :     Local<Function> func1 =
   26576           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26577          20 :     CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust());
   26578             :     Local<Function> func2 =
   26579           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26580          20 :     CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   26581             :     ExpectTrue("func1.prototype.error_proto === Error.prototype");
   26582             :     ExpectTrue("func2.prototype.error_proto === Error.prototype");
   26583             :     ExpectTrue("func1.prototype.error_proto === func2.prototype.error_proto");
   26584             : 
   26585             :     Local<Object> instance1 = func1->NewInstance(env.local()).ToLocalChecked();
   26586          20 :     CHECK(env->Global()
   26587             :               ->Set(env.local(), v8_str("instance1"), instance1)
   26588             :               .FromJust());
   26589             :     ExpectFalse("instance1.hasOwnProperty('error_proto')");
   26590             :     ExpectTrue("'error_proto' in instance1.__proto__");
   26591             :     ExpectTrue("instance1.error_proto === Error.prototype");
   26592             :   }
   26593             :   // Put %ErrorPrototype% in a function object's inheritance chain.
   26594             :   {
   26595             :     Local<FunctionTemplate> parent_template =
   26596           5 :         v8::FunctionTemplate::New(isolate);
   26597           5 :     parent_template->RemovePrototype();  // Remove so there is no name clash.
   26598          10 :     parent_template->SetIntrinsicDataProperty(v8_str("prototype"),
   26599           5 :                                               v8::kErrorPrototype);
   26600           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26601           5 :     func_template->Inherit(parent_template);
   26602             : 
   26603             :     Local<Function> func =
   26604           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26605          20 :     CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26606             :     ExpectTrue("func.prototype.__proto__ === Error.prototype");
   26607             : 
   26608             :     Local<Object> func_instance =
   26609             :         func->NewInstance(env.local()).ToLocalChecked();
   26610          20 :     CHECK(env->Global()
   26611             :               ->Set(env.local(), v8_str("instance"), func_instance)
   26612             :               .FromJust());
   26613             :     ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype");
   26614             :     // Now let's check if %ErrorPrototype% properties are in the instance.
   26615             :     ExpectTrue("'constructor' in instance");
   26616             :     ExpectTrue("'message' in instance");
   26617             :     ExpectTrue("'name' in instance");
   26618             :     ExpectTrue("'toString' in instance");
   26619             :   }
   26620           5 : }
   26621             : 
   26622       26644 : TEST(ObjectTemplateArrayProtoIntrinsics) {
   26623           5 :   v8::Isolate* isolate = CcTest::isolate();
   26624          10 :   v8::HandleScope scope(isolate);
   26625           5 :   LocalContext env;
   26626             : 
   26627           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26628          10 :   object_template->SetIntrinsicDataProperty(v8_str("prop_entries"),
   26629           5 :                                             v8::kArrayProto_entries);
   26630          10 :   object_template->SetIntrinsicDataProperty(v8_str("prop_forEach"),
   26631           5 :                                             v8::kArrayProto_forEach);
   26632          10 :   object_template->SetIntrinsicDataProperty(v8_str("prop_keys"),
   26633           5 :                                             v8::kArrayProto_keys);
   26634          10 :   object_template->SetIntrinsicDataProperty(v8_str("prop_values"),
   26635           5 :                                             v8::kArrayProto_values);
   26636             :   Local<Object> object =
   26637           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26638          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   26639             : 
   26640             :   const struct {
   26641             :     const char* const object_property_name;
   26642             :     const char* const array_property_name;
   26643             :   } intrinsics_comparisons[] = {
   26644             :       {"prop_entries", "Array.prototype.entries"},
   26645             :       {"prop_forEach", "Array.prototype.forEach"},
   26646             :       {"prop_keys", "Array.prototype.keys"},
   26647             :       {"prop_values", "Array.prototype[Symbol.iterator]"},
   26648           5 :   };
   26649             : 
   26650          45 :   for (unsigned i = 0; i < arraysize(intrinsics_comparisons); i++) {
   26651             :     i::ScopedVector<char> test_string(64);
   26652             : 
   26653             :     i::SNPrintF(test_string, "typeof obj1.%s",
   26654          20 :                 intrinsics_comparisons[i].object_property_name);
   26655          20 :     ExpectString(test_string.start(), "function");
   26656             : 
   26657             :     i::SNPrintF(test_string, "obj1.%s === %s",
   26658             :                 intrinsics_comparisons[i].object_property_name,
   26659          20 :                 intrinsics_comparisons[i].array_property_name);
   26660             :     ExpectTrue(test_string.start());
   26661             : 
   26662             :     i::SNPrintF(test_string, "obj1.%s = 42",
   26663          20 :                 intrinsics_comparisons[i].object_property_name);
   26664             :     CompileRun(test_string.start());
   26665             : 
   26666             :     i::SNPrintF(test_string, "obj1.%s === %s",
   26667             :                 intrinsics_comparisons[i].object_property_name,
   26668          20 :                 intrinsics_comparisons[i].array_property_name);
   26669             :     ExpectFalse(test_string.start());
   26670             : 
   26671             :     i::SNPrintF(test_string, "typeof obj1.%s",
   26672          20 :                 intrinsics_comparisons[i].object_property_name);
   26673          20 :     ExpectString(test_string.start(), "number");
   26674             :   }
   26675           5 : }
   26676             : 
   26677       26644 : TEST(ObjectTemplatePerContextIntrinsics) {
   26678           5 :   v8::Isolate* isolate = CcTest::isolate();
   26679          10 :   v8::HandleScope scope(isolate);
   26680           5 :   LocalContext env;
   26681             : 
   26682           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26683          10 :   object_template->SetIntrinsicDataProperty(v8_str("values"),
   26684           5 :                                             v8::kArrayProto_values);
   26685             :   Local<Object> object =
   26686           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26687             : 
   26688          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   26689           5 :   ExpectString("typeof obj1.values", "function");
   26690             : 
   26691             :   auto values = Local<Function>::Cast(
   26692          15 :       object->Get(env.local(), v8_str("values")).ToLocalChecked());
   26693             :   auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
   26694             :   auto ctx = v8::Utils::OpenHandle(*env.local());
   26695          10 :   CHECK_EQ(*fn->GetCreationContext(), *ctx);
   26696             : 
   26697             :   {
   26698           5 :     LocalContext env2;
   26699             :     Local<Object> object2 =
   26700           5 :         object_template->NewInstance(env2.local()).ToLocalChecked();
   26701          20 :     CHECK(
   26702             :         env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
   26703           5 :     ExpectString("typeof obj2.values", "function");
   26704          25 :     CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
   26705             :              *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   26706             : 
   26707             :     auto values2 = Local<Function>::Cast(
   26708          15 :         object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   26709             :     auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
   26710             :     auto ctx2 = v8::Utils::OpenHandle(*env2.local());
   26711          10 :     CHECK_EQ(*fn2->GetCreationContext(), *ctx2);
   26712             :   }
   26713           5 : }
   26714             : 
   26715             : 
   26716       26644 : TEST(Proxy) {
   26717           5 :   LocalContext context;
   26718           5 :   v8::Isolate* isolate = CcTest::isolate();
   26719          10 :   v8::HandleScope scope(isolate);
   26720             :   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
   26721             :   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
   26722             : 
   26723             :   v8::Local<v8::Proxy> proxy =
   26724           5 :       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   26725           5 :   CHECK(proxy->IsProxy());
   26726           5 :   CHECK(!target->IsProxy());
   26727           5 :   CHECK(!proxy->IsRevoked());
   26728          10 :   CHECK(proxy->GetTarget()->SameValue(target));
   26729          10 :   CHECK(proxy->GetHandler()->SameValue(handler));
   26730             : 
   26731           5 :   proxy->Revoke();
   26732           5 :   CHECK(proxy->IsProxy());
   26733           5 :   CHECK(!target->IsProxy());
   26734           5 :   CHECK(proxy->IsRevoked());
   26735          10 :   CHECK(proxy->GetTarget()->IsNull());
   26736          10 :   CHECK(proxy->GetHandler()->IsNull());
   26737           5 : }
   26738             : 
   26739          10 : WeakCallCounterAndPersistent<Value>* CreateGarbageWithWeakCallCounter(
   26740             :     v8::Isolate* isolate, WeakCallCounter* counter) {
   26741          10 :   v8::Locker locker(isolate);
   26742          10 :   LocalContext env;
   26743          20 :   HandleScope scope(isolate);
   26744             :   WeakCallCounterAndPersistent<Value>* val =
   26745          10 :       new WeakCallCounterAndPersistent<Value>(counter);
   26746          20 :   val->handle.Reset(isolate, Object::New(isolate));
   26747             :   val->handle.SetWeak(val, &WeakPointerCallback,
   26748             :                       v8::WeakCallbackType::kParameter);
   26749          10 :   return val;
   26750             : }
   26751             : 
   26752           5 : class MemoryPressureThread : public v8::base::Thread {
   26753             :  public:
   26754             :   explicit MemoryPressureThread(v8::Isolate* isolate,
   26755             :                                 v8::MemoryPressureLevel level)
   26756             :       : Thread(Options("MemoryPressureThread")),
   26757             :         isolate_(isolate),
   26758           5 :         level_(level) {}
   26759             : 
   26760           5 :   void Run() override { isolate_->MemoryPressureNotification(level_); }
   26761             : 
   26762             :  private:
   26763             :   v8::Isolate* isolate_;
   26764             :   v8::MemoryPressureLevel level_;
   26765             : };
   26766             : 
   26767       26644 : TEST(MemoryPressure) {
   26768           5 :   if (v8::internal::FLAG_optimize_for_size) return;
   26769           5 :   v8::Isolate* isolate = CcTest::isolate();
   26770             :   WeakCallCounter counter(1234);
   26771             : 
   26772             :   // Check that critical memory pressure notification sets GC interrupt.
   26773           5 :   auto garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   26774           5 :   CHECK(!v8::Locker::IsLocked(isolate));
   26775             :   {
   26776           5 :     v8::Locker locker(isolate);
   26777          10 :     v8::HandleScope scope(isolate);
   26778           5 :     LocalContext env;
   26779             :     MemoryPressureThread memory_pressure_thread(
   26780             :         isolate, v8::MemoryPressureLevel::kCritical);
   26781           5 :     memory_pressure_thread.Start();
   26782           5 :     memory_pressure_thread.Join();
   26783             :     // This should trigger GC.
   26784           5 :     CHECK_EQ(0, counter.NumberOfWeakCalls());
   26785             :     CompileRun("(function noop() { return 0; })()");
   26786           5 :     CHECK_EQ(1, counter.NumberOfWeakCalls());
   26787             :   }
   26788          10 :   delete garbage;
   26789             :   // Check that critical memory pressure notification triggers GC.
   26790           5 :   garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   26791             :   {
   26792           5 :     v8::Locker locker(isolate);
   26793             :     // If isolate is locked, memory pressure notification should trigger GC.
   26794           5 :     CHECK_EQ(1, counter.NumberOfWeakCalls());
   26795           5 :     isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical);
   26796           5 :     CHECK_EQ(2, counter.NumberOfWeakCalls());
   26797             :   }
   26798          10 :   delete garbage;
   26799             :   // Check that moderate memory pressure notification sets GC into memory
   26800             :   // optimizing mode.
   26801           5 :   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
   26802           5 :   CHECK(CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   26803             :   // Check that disabling memory pressure returns GC into normal mode.
   26804           5 :   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kNone);
   26805           5 :   CHECK(!CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   26806             : }
   26807             : 
   26808       26644 : TEST(SetIntegrityLevel) {
   26809           5 :   LocalContext context;
   26810           5 :   v8::Isolate* isolate = CcTest::isolate();
   26811          10 :   v8::HandleScope scope(isolate);
   26812             : 
   26813           5 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   26814          20 :   CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
   26815             : 
   26816             :   v8::Local<v8::Value> is_frozen = CompileRun("Object.isFrozen(o)");
   26817           5 :   CHECK(!is_frozen->BooleanValue(isolate));
   26818             : 
   26819          10 :   CHECK(obj->SetIntegrityLevel(context.local(), v8::IntegrityLevel::kFrozen)
   26820             :             .FromJust());
   26821             : 
   26822             :   is_frozen = CompileRun("Object.isFrozen(o)");
   26823           5 :   CHECK(is_frozen->BooleanValue(isolate));
   26824           5 : }
   26825             : 
   26826       26644 : TEST(PrivateForApiIsNumber) {
   26827           5 :   LocalContext context;
   26828           5 :   v8::Isolate* isolate = CcTest::isolate();
   26829          10 :   v8::HandleScope scope(isolate);
   26830             : 
   26831             :   // Shouldn't crash.
   26832           5 :   v8::Private::ForApi(isolate, v8_str("42"));
   26833           5 : }
   26834             : 
   26835       26645 : THREADED_TEST(ImmutableProto) {
   26836           6 :   LocalContext context;
   26837           6 :   v8::Isolate* isolate = context->GetIsolate();
   26838          12 :   v8::HandleScope handle_scope(isolate);
   26839             : 
   26840           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   26841          12 :   templ->InstanceTemplate()->SetImmutableProto();
   26842             : 
   26843           6 :   Local<v8::Object> object = templ->GetFunction(context.local())
   26844             :                                  .ToLocalChecked()
   26845             :                                  ->NewInstance(context.local())
   26846             :                                  .ToLocalChecked();
   26847             : 
   26848             :   // Look up the prototype
   26849             :   Local<v8::Value> original_proto =
   26850          18 :       object->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26851             : 
   26852             :   // Setting the prototype (e.g., to null) throws
   26853          12 :   CHECK(object->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
   26854             : 
   26855             :   // The original prototype is still there
   26856             :   Local<Value> new_proto =
   26857          18 :       object->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26858           6 :   CHECK(new_proto->IsObject());
   26859          12 :   CHECK(new_proto.As<v8::Object>()
   26860             :             ->Equals(context.local(), original_proto)
   26861             :             .FromJust());
   26862           6 : }
   26863             : 
   26864             : Local<v8::Context> call_eval_context;
   26865             : Local<v8::Function> call_eval_bound_function;
   26866             : 
   26867           5 : static void CallEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
   26868             :   v8::Context::Scope scope(call_eval_context);
   26869             :   args.GetReturnValue().Set(
   26870             :       call_eval_bound_function
   26871          15 :           ->Call(call_eval_context, call_eval_context->Global(), 0, nullptr)
   26872             :           .ToLocalChecked());
   26873           5 : }
   26874             : 
   26875       26644 : TEST(CrossActivationEval) {
   26876           5 :   LocalContext env;
   26877           5 :   v8::Isolate* isolate = env->GetIsolate();
   26878          10 :   v8::HandleScope scope(isolate);
   26879             :   {
   26880           5 :     call_eval_context = v8::Context::New(isolate);
   26881             :     v8::Context::Scope scope(call_eval_context);
   26882             :     call_eval_bound_function =
   26883           5 :         Local<Function>::Cast(CompileRun("eval.bind(this, '1')"));
   26884             :   }
   26885          10 :   env->Global()
   26886          10 :       ->Set(env.local(), v8_str("CallEval"),
   26887          10 :             v8::FunctionTemplate::New(isolate, CallEval)
   26888           5 :                 ->GetFunction(env.local())
   26889          10 :                 .ToLocalChecked())
   26890             :       .FromJust();
   26891             :   Local<Value> result = CompileRun("CallEval();");
   26892           5 :   CHECK(result->IsInt32());
   26893          10 :   CHECK_EQ(1, result->Int32Value(env.local()).FromJust());
   26894           5 : }
   26895             : 
   26896       26644 : TEST(EvalInAccessCheckedContext) {
   26897           5 :   v8::Isolate* isolate = CcTest::isolate();
   26898          10 :   v8::HandleScope scope(isolate);
   26899             : 
   26900           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   26901             : 
   26902           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysAllowed);
   26903             : 
   26904           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, obj_template);
   26905           5 :   v8::Local<Context> context1 = Context::New(isolate, nullptr, obj_template);
   26906             : 
   26907           5 :   Local<Value> foo = v8_str("foo");
   26908           5 :   Local<Value> bar = v8_str("bar");
   26909             : 
   26910             :   // Set to different domains.
   26911           5 :   context0->SetSecurityToken(foo);
   26912           5 :   context1->SetSecurityToken(bar);
   26913             : 
   26914             :   // Set up function in context0 that uses eval from context0.
   26915           5 :   context0->Enter();
   26916             :   v8::Local<v8::Value> fun = CompileRun(
   26917             :       "var x = 42;"
   26918             :       "(function() {"
   26919             :       "  var e = eval;"
   26920             :       "  return function(s) { return e(s); }"
   26921           5 :       "})()");
   26922           5 :   context0->Exit();
   26923             : 
   26924             :   // Put the function into context1 and call it. Since the access check
   26925             :   // callback always returns true, the call succeeds even though the tokens
   26926             :   // are different.
   26927           5 :   context1->Enter();
   26928          20 :   context1->Global()->Set(context1, v8_str("fun"), fun).FromJust();
   26929             :   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   26930          10 :   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   26931           5 :   context1->Exit();
   26932           5 : }
   26933             : 
   26934       26645 : THREADED_TEST(ImmutableProtoWithParent) {
   26935           6 :   LocalContext context;
   26936           6 :   v8::Isolate* isolate = context->GetIsolate();
   26937          12 :   v8::HandleScope handle_scope(isolate);
   26938             : 
   26939           6 :   Local<v8::FunctionTemplate> parent = v8::FunctionTemplate::New(isolate);
   26940             : 
   26941           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   26942           6 :   templ->Inherit(parent);
   26943          12 :   templ->PrototypeTemplate()->SetImmutableProto();
   26944             : 
   26945             :   Local<v8::Function> function =
   26946           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   26947             :   Local<v8::Object> instance =
   26948             :       function->NewInstance(context.local()).ToLocalChecked();
   26949             :   Local<v8::Object> prototype =
   26950          18 :       instance->Get(context.local(), v8_str("__proto__"))
   26951             :           .ToLocalChecked()
   26952           6 :           ->ToObject(context.local())
   26953             :           .ToLocalChecked();
   26954             : 
   26955             :   // Look up the prototype
   26956             :   Local<v8::Value> original_proto =
   26957          18 :       prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26958             : 
   26959             :   // Setting the prototype (e.g., to null) throws
   26960          12 :   CHECK(
   26961             :       prototype->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
   26962             : 
   26963             :   // The original prototype is still there
   26964             :   Local<Value> new_proto =
   26965          18 :       prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26966           6 :   CHECK(new_proto->IsObject());
   26967          12 :   CHECK(new_proto.As<v8::Object>()
   26968             :             ->Equals(context.local(), original_proto)
   26969             :             .FromJust());
   26970           6 : }
   26971             : 
   26972       26644 : TEST(InternalFieldsOnGlobalProxy) {
   26973           5 :   v8::Isolate* isolate = CcTest::isolate();
   26974          10 :   v8::HandleScope scope(isolate);
   26975             : 
   26976           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   26977           5 :   obj_template->SetInternalFieldCount(1);
   26978             : 
   26979           5 :   v8::Local<v8::Context> context = Context::New(isolate, nullptr, obj_template);
   26980           5 :   v8::Local<v8::Object> global = context->Global();
   26981           5 :   CHECK_EQ(1, global->InternalFieldCount());
   26982           5 : }
   26983             : 
   26984       26645 : THREADED_TEST(ImmutableProtoGlobal) {
   26985           6 :   v8::Isolate* isolate = CcTest::isolate();
   26986          12 :   v8::HandleScope handle_scope(isolate);
   26987           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   26988           6 :   global_template->SetImmutableProto();
   26989           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
   26990             :   Context::Scope context_scope(context);
   26991             :   v8::Local<Value> result = CompileRun(
   26992             :       "global = this;"
   26993             :       "(function() {"
   26994             :       "  try {"
   26995             :       "    global.__proto__ = {};"
   26996             :       "    return 0;"
   26997             :       "  } catch (e) {"
   26998             :       "    return 1;"
   26999             :       "  }"
   27000             :       "})()");
   27001          18 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 1))
   27002             :             .FromJust());
   27003           6 : }
   27004             : 
   27005       26645 : THREADED_TEST(MutableProtoGlobal) {
   27006           6 :   v8::Isolate* isolate = CcTest::isolate();
   27007          12 :   v8::HandleScope handle_scope(isolate);
   27008           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   27009           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
   27010             :   Context::Scope context_scope(context);
   27011             :   v8::Local<Value> result = CompileRun(
   27012             :       "global = this;"
   27013             :       "(function() {"
   27014             :       "  try {"
   27015             :       "    global.__proto__ = {};"
   27016             :       "    return 0;"
   27017             :       "  } catch (e) {"
   27018             :       "    return 1;"
   27019             :       "  }"
   27020             :       "})()");
   27021          18 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 0))
   27022             :             .FromJust());
   27023           6 : }
   27024             : 
   27025       26644 : TEST(InternalFieldsOnTypedArray) {
   27026           5 :   LocalContext env;
   27027           5 :   v8::Isolate* isolate = env->GetIsolate();
   27028          10 :   v8::HandleScope scope(isolate);
   27029             :   v8::Local<v8::Context> context = env.local();
   27030             :   Context::Scope context_scope(context);
   27031           5 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1);
   27032           5 :   v8::Local<v8::Uint8Array> array = v8::Uint8Array::New(buffer, 0, 1);
   27033          25 :   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
   27034          10 :     CHECK_EQ(static_cast<void*>(nullptr),
   27035             :              array->GetAlignedPointerFromInternalField(i));
   27036             :   }
   27037           5 : }
   27038             : 
   27039       26644 : TEST(InternalFieldsOnDataView) {
   27040           5 :   LocalContext env;
   27041           5 :   v8::Isolate* isolate = env->GetIsolate();
   27042          10 :   v8::HandleScope scope(isolate);
   27043             :   v8::Local<v8::Context> context = env.local();
   27044             :   Context::Scope context_scope(context);
   27045           5 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1);
   27046           5 :   v8::Local<v8::DataView> array = v8::DataView::New(buffer, 0, 1);
   27047          25 :   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
   27048          10 :     CHECK_EQ(static_cast<void*>(nullptr),
   27049             :              array->GetAlignedPointerFromInternalField(i));
   27050             :   }
   27051           5 : }
   27052             : 
   27053       26644 : TEST(SetPrototypeTemplate) {
   27054           5 :   LocalContext env;
   27055           5 :   v8::Isolate* isolate = env->GetIsolate();
   27056          10 :   v8::HandleScope scope(isolate);
   27057             : 
   27058           5 :   Local<FunctionTemplate> HTMLElementTemplate = FunctionTemplate::New(isolate);
   27059             :   Local<FunctionTemplate> HTMLImageElementTemplate =
   27060           5 :       FunctionTemplate::New(isolate);
   27061           5 :   HTMLImageElementTemplate->Inherit(HTMLElementTemplate);
   27062             : 
   27063           5 :   Local<FunctionTemplate> ImageTemplate = FunctionTemplate::New(isolate);
   27064           5 :   ImageTemplate->SetPrototypeProviderTemplate(HTMLImageElementTemplate);
   27065             : 
   27066             :   Local<Function> HTMLImageElement =
   27067           5 :       HTMLImageElementTemplate->GetFunction(env.local()).ToLocalChecked();
   27068             :   Local<Function> Image =
   27069           5 :       ImageTemplate->GetFunction(env.local()).ToLocalChecked();
   27070             : 
   27071          20 :   CHECK(env->Global()
   27072             :             ->Set(env.local(), v8_str("HTMLImageElement"), HTMLImageElement)
   27073             :             .FromJust());
   27074          20 :   CHECK(env->Global()->Set(env.local(), v8_str("Image"), Image).FromJust());
   27075             : 
   27076             :   ExpectTrue("Image.prototype === HTMLImageElement.prototype");
   27077           5 : }
   27078             : 
   27079         120 : void ensure_receiver_is_global_proxy(
   27080             :     v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
   27081         120 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSGlobalProxy());
   27082         120 : }
   27083             : 
   27084       26645 : THREADED_TEST(GlobalAccessorInfo) {
   27085           6 :   v8::Isolate* isolate = CcTest::isolate();
   27086          12 :   v8::HandleScope scope(isolate);
   27087           6 :   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   27088           6 :   global_template->SetAccessor(
   27089           6 :       v8::String::NewFromUtf8(isolate, "prop", v8::NewStringType::kInternalized)
   27090             :           .ToLocalChecked(),
   27091           6 :       &ensure_receiver_is_global_proxy);
   27092           6 :   LocalContext env(nullptr, global_template);
   27093             :   CompileRun("for (var i = 0; i < 10; i++) this.prop");
   27094             :   CompileRun("for (var i = 0; i < 10; i++) prop");
   27095           6 : }
   27096             : 
   27097       26644 : TEST(DeterministicRandomNumberGeneration) {
   27098          10 :   v8::HandleScope scope(CcTest::isolate());
   27099             : 
   27100           5 :   int previous_seed = v8::internal::FLAG_random_seed;
   27101           5 :   v8::internal::FLAG_random_seed = 1234;
   27102             : 
   27103             :   double first_value;
   27104             :   double second_value;
   27105             :   {
   27106           5 :     v8::Local<Context> context = Context::New(CcTest::isolate());
   27107             :     Context::Scope context_scope(context);
   27108             :     v8::Local<Value> result = CompileRun("Math.random();");
   27109          10 :     first_value = result->ToNumber(context).ToLocalChecked()->Value();
   27110             :   }
   27111             :   {
   27112           5 :     v8::Local<Context> context = Context::New(CcTest::isolate());
   27113             :     Context::Scope context_scope(context);
   27114             :     v8::Local<Value> result = CompileRun("Math.random();");
   27115          10 :     second_value = result->ToNumber(context).ToLocalChecked()->Value();
   27116             :   }
   27117           5 :   CHECK_EQ(first_value, second_value);
   27118             : 
   27119           5 :   v8::internal::FLAG_random_seed = previous_seed;
   27120           5 : }
   27121             : 
   27122       26644 : UNINITIALIZED_TEST(AllowAtomicsWait) {
   27123             :   v8::Isolate::CreateParams create_params;
   27124           5 :   create_params.allow_atomics_wait = false;
   27125           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   27126           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   27127             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27128             :   {
   27129           5 :     CHECK_EQ(false, i_isolate->allow_atomics_wait());
   27130           5 :     isolate->SetAllowAtomicsWait(true);
   27131           5 :     CHECK_EQ(true, i_isolate->allow_atomics_wait());
   27132             :   }
   27133           5 :   isolate->Dispose();
   27134           5 : }
   27135             : 
   27136             : enum ContextId { EnteredContext, CurrentContext };
   27137             : 
   27138          20 : void CheckContexts(v8::Isolate* isolate) {
   27139          60 :   CHECK_EQ(CurrentContext, isolate->GetCurrentContext()
   27140             :                                ->GetEmbedderData(1)
   27141             :                                .As<v8::Integer>()
   27142             :                                ->Value());
   27143          60 :   CHECK_EQ(EnteredContext, isolate->GetEnteredOrMicrotaskContext()
   27144             :                                ->GetEmbedderData(1)
   27145             :                                .As<v8::Integer>()
   27146             :                                ->Value());
   27147          20 : }
   27148             : 
   27149           5 : void ContextCheckGetter(Local<String> name,
   27150             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   27151           5 :   CheckContexts(info.GetIsolate());
   27152             :   info.GetReturnValue().Set(true);
   27153           5 : }
   27154             : 
   27155           5 : void ContextCheckSetter(Local<String> name, Local<Value>,
   27156             :                         const v8::PropertyCallbackInfo<void>& info) {
   27157           5 :   CheckContexts(info.GetIsolate());
   27158           5 : }
   27159             : 
   27160          10 : void ContextCheckToString(const v8::FunctionCallbackInfo<v8::Value>& info) {
   27161          10 :   CheckContexts(info.GetIsolate());
   27162          10 :   info.GetReturnValue().Set(v8_str("foo"));
   27163          10 : }
   27164             : 
   27165       26644 : TEST(CorrectEnteredContext) {
   27166          10 :   v8::HandleScope scope(CcTest::isolate());
   27167             : 
   27168           5 :   LocalContext currentContext;
   27169          10 :   currentContext->SetEmbedderData(
   27170           5 :       1, v8::Integer::New(currentContext->GetIsolate(), CurrentContext));
   27171           5 :   LocalContext enteredContext;
   27172          10 :   enteredContext->SetEmbedderData(
   27173           5 :       1, v8::Integer::New(enteredContext->GetIsolate(), EnteredContext));
   27174             : 
   27175             :   v8::Context::Scope contextScope(enteredContext.local());
   27176             : 
   27177             :   v8::Local<v8::ObjectTemplate> object_template =
   27178           5 :       ObjectTemplate::New(currentContext->GetIsolate());
   27179          10 :   object_template->SetAccessor(v8_str("p"), &ContextCheckGetter,
   27180           5 :                                &ContextCheckSetter);
   27181             : 
   27182             :   v8::Local<v8::Object> object =
   27183           5 :       object_template->NewInstance(currentContext.local()).ToLocalChecked();
   27184             : 
   27185          15 :   object->Get(currentContext.local(), v8_str("p")).ToLocalChecked();
   27186          15 :   object->Set(currentContext.local(), v8_str("p"), v8_int(0)).FromJust();
   27187             : 
   27188             :   v8::Local<v8::Function> to_string =
   27189          10 :       v8::Function::New(currentContext.local(), ContextCheckToString)
   27190             :           .ToLocalChecked();
   27191             : 
   27192          10 :   to_string->Call(currentContext.local(), object, 0, nullptr).ToLocalChecked();
   27193             : 
   27194             :   object
   27195          10 :       ->CreateDataProperty(currentContext.local(), v8_str("toString"),
   27196          10 :                            to_string)
   27197             :       .FromJust();
   27198             : 
   27199           5 :   object->ToString(currentContext.local()).ToLocalChecked();
   27200           5 : }
   27201             : 
   27202           5 : v8::MaybeLocal<v8::Promise> HostImportModuleDynamicallyCallbackResolve(
   27203             :     Local<Context> context, Local<v8::ScriptOrModule> referrer,
   27204             :     Local<String> specifier) {
   27205           5 :   CHECK(!referrer.IsEmpty());
   27206             :   String::Utf8Value referrer_utf8(
   27207          15 :       context->GetIsolate(), Local<String>::Cast(referrer->GetResourceName()));
   27208           5 :   CHECK_EQ(0, strcmp("www.google.com", *referrer_utf8));
   27209          15 :   CHECK(referrer->GetHostDefinedOptions()
   27210             :             ->Get(context->GetIsolate(), 0)
   27211             :             ->IsSymbol());
   27212             : 
   27213           5 :   CHECK(!specifier.IsEmpty());
   27214          10 :   String::Utf8Value specifier_utf8(context->GetIsolate(), specifier);
   27215           5 :   CHECK_EQ(0, strcmp("index.js", *specifier_utf8));
   27216             : 
   27217             :   Local<v8::Promise::Resolver> resolver =
   27218           5 :       v8::Promise::Resolver::New(context).ToLocalChecked();
   27219           5 :   auto result = v8_str("hello world");
   27220          10 :   resolver->Resolve(context, result).ToChecked();
   27221          10 :   return resolver->GetPromise();
   27222             : }
   27223             : 
   27224       26644 : TEST(DynamicImport) {
   27225           5 :   i::FLAG_harmony_dynamic_import = true;
   27226           5 :   LocalContext context;
   27227           5 :   v8::Isolate* isolate = context->GetIsolate();
   27228          10 :   v8::HandleScope scope(isolate);
   27229             : 
   27230             :   isolate->SetHostImportModuleDynamicallyCallback(
   27231           5 :       HostImportModuleDynamicallyCallbackResolve);
   27232             : 
   27233          10 :   i::Handle<i::String> url(v8::Utils::OpenHandle(*v8_str("www.google.com")));
   27234          10 :   i::Handle<i::Object> specifier(v8::Utils::OpenHandle(*v8_str("index.js")));
   27235          10 :   i::Handle<i::String> result(v8::Utils::OpenHandle(*v8_str("hello world")));
   27236          10 :   i::Handle<i::String> source(v8::Utils::OpenHandle(*v8_str("foo")));
   27237             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27238           5 :   i::Handle<i::FixedArray> options = i_isolate->factory()->NewFixedArray(1);
   27239           5 :   i::Handle<i::Symbol> symbol = i_isolate->factory()->NewSymbol();
   27240          10 :   options->set(0, *symbol);
   27241           5 :   i::Handle<i::Script> referrer = i_isolate->factory()->NewScript(source);
   27242          10 :   referrer->set_name(*url);
   27243           5 :   referrer->set_host_defined_options(*options);
   27244             :   i::MaybeHandle<i::JSPromise> maybe_promise =
   27245           5 :       i_isolate->RunHostImportModuleDynamicallyCallback(referrer, specifier);
   27246             :   i::Handle<i::JSPromise> promise = maybe_promise.ToHandleChecked();
   27247           5 :   isolate->RunMicrotasks();
   27248           5 :   CHECK(result->Equals(i::String::cast(promise->result())));
   27249           5 : }
   27250             : 
   27251           5 : void HostInitializeImportMetaObjectCallbackStatic(Local<Context> context,
   27252             :                                                   Local<Module> module,
   27253             :                                                   Local<Object> meta) {
   27254           5 :   CHECK(!module.IsEmpty());
   27255             : 
   27256          20 :   meta->CreateDataProperty(context, v8_str("foo"), v8_str("bar")).ToChecked();
   27257           5 : }
   27258             : 
   27259       26644 : TEST(ImportMeta) {
   27260           5 :   i::FLAG_harmony_dynamic_import = true;
   27261           5 :   i::FLAG_harmony_import_meta = true;
   27262           5 :   LocalContext context;
   27263           5 :   v8::Isolate* isolate = context->GetIsolate();
   27264          10 :   v8::HandleScope scope(isolate);
   27265             : 
   27266             :   isolate->SetHostInitializeImportMetaObjectCallback(
   27267           5 :       HostInitializeImportMetaObjectCallbackStatic);
   27268             : 
   27269             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27270           5 :   Local<String> url = v8_str("www.google.com");
   27271           5 :   Local<String> source_text = v8_str("import.meta;");
   27272             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27273             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27274             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27275             :                           Local<v8::Boolean>(), True(isolate));
   27276             :   v8::ScriptCompiler::Source source(source_text, origin);
   27277             :   Local<Module> module =
   27278           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27279             :   i::Handle<i::Object> meta =
   27280             :       i_isolate->RunHostInitializeImportMetaObjectCallback(
   27281           5 :           v8::Utils::OpenHandle(*module));
   27282           5 :   CHECK(meta->IsJSObject());
   27283             :   Local<Object> meta_obj = Local<Object>::Cast(v8::Utils::ToLocal(meta));
   27284          15 :   CHECK(meta_obj->Get(context.local(), v8_str("foo"))
   27285             :             .ToLocalChecked()
   27286             :             ->IsString());
   27287          15 :   CHECK(meta_obj->Get(context.local(), v8_str("zapp"))
   27288             :             .ToLocalChecked()
   27289             :             ->IsUndefined());
   27290             : 
   27291          10 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27292             :       .ToChecked();
   27293           5 :   Local<Value> result = module->Evaluate(context.local()).ToLocalChecked();
   27294           5 :   CHECK(result->StrictEquals(Local<v8::Value>::Cast(v8::Utils::ToLocal(meta))));
   27295           5 : }
   27296             : 
   27297       26644 : TEST(GetModuleNamespace) {
   27298           5 :   LocalContext context;
   27299           5 :   v8::Isolate* isolate = context->GetIsolate();
   27300          10 :   v8::HandleScope scope(isolate);
   27301             : 
   27302           5 :   Local<String> url = v8_str("www.google.com");
   27303           5 :   Local<String> source_text = v8_str("export default 5; export const a = 10;");
   27304             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27305             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27306             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27307             :                           Local<v8::Boolean>(), True(isolate));
   27308             :   v8::ScriptCompiler::Source source(source_text, origin);
   27309             :   Local<Module> module =
   27310           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27311          10 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27312             :       .ToChecked();
   27313           5 :   module->Evaluate(context.local()).ToLocalChecked();
   27314             : 
   27315           5 :   Local<Value> ns_val = module->GetModuleNamespace();
   27316           5 :   CHECK(ns_val->IsModuleNamespaceObject());
   27317             :   Local<Object> ns = ns_val.As<Object>();
   27318          20 :   CHECK(ns->Get(context.local(), v8_str("default"))
   27319             :             .ToLocalChecked()
   27320             :             ->StrictEquals(v8::Number::New(isolate, 5)));
   27321          20 :   CHECK(ns->Get(context.local(), v8_str("a"))
   27322             :             .ToLocalChecked()
   27323             :             ->StrictEquals(v8::Number::New(isolate, 10)));
   27324           5 : }
   27325             : 
   27326       26644 : TEST(ModuleGetUnboundModuleScript) {
   27327           5 :   LocalContext context;
   27328           5 :   v8::Isolate* isolate = context->GetIsolate();
   27329          10 :   v8::HandleScope scope(isolate);
   27330             : 
   27331           5 :   Local<String> url = v8_str("www.google.com");
   27332           5 :   Local<String> source_text = v8_str("export default 5; export const a = 10;");
   27333             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27334             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27335             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27336             :                           Local<v8::Boolean>(), True(isolate));
   27337             :   v8::ScriptCompiler::Source source(source_text, origin);
   27338             :   Local<Module> module =
   27339           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27340             :   Local<v8::UnboundModuleScript> sfi_before_instantiation =
   27341           5 :       module->GetUnboundModuleScript();
   27342          10 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27343             :       .ToChecked();
   27344             :   Local<v8::UnboundModuleScript> sfi_after_instantiation =
   27345           5 :       module->GetUnboundModuleScript();
   27346             : 
   27347             :   // Check object identity.
   27348             :   {
   27349             :     i::Handle<i::Object> s1 = v8::Utils::OpenHandle(*sfi_before_instantiation);
   27350             :     i::Handle<i::Object> s2 = v8::Utils::OpenHandle(*sfi_after_instantiation);
   27351           5 :     CHECK_EQ(*s1, *s2);
   27352             :   }
   27353           5 : }
   27354             : 
   27355       26644 : TEST(GlobalTemplateWithDoubleProperty) {
   27356           5 :   v8::Isolate* isolate = CcTest::isolate();
   27357          10 :   v8::HandleScope handle_scope(isolate);
   27358             : 
   27359           5 :   v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
   27360          15 :   global->Set(v8_str("double"), v8_num(3.14));
   27361             : 
   27362           5 :   v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
   27363             : 
   27364             :   v8::Context::Scope context_scope(context);
   27365             : 
   27366             :   Local<Value> result = CompileRun("double");
   27367           5 :   CHECK(result->IsNumber());
   27368          10 :   CheckDoubleEquals(3.14, result->NumberValue(context).ToChecked());
   27369           5 : }
   27370             : 
   27371       26644 : TEST(PrimitiveArray) {
   27372           5 :   v8::Isolate* isolate = CcTest::isolate();
   27373          10 :   v8::HandleScope scope(isolate);
   27374           5 :   LocalContext env;
   27375             : 
   27376             :   int length = 5;
   27377           5 :   Local<v8::PrimitiveArray> array(v8::PrimitiveArray::New(isolate, 5));
   27378           5 :   CHECK_EQ(length, array->Length());
   27379             : 
   27380          55 :   for (int i = 0; i < length; i++) {
   27381          25 :     Local<v8::Primitive> item = array->Get(isolate, i);
   27382          25 :     CHECK(item->IsUndefined());
   27383             :   }
   27384             : 
   27385           5 :   Local<v8::Symbol> symbol(v8::Symbol::New(isolate));
   27386           5 :   array->Set(isolate, 0, symbol);
   27387          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27388             : 
   27389             :   Local<v8::String> string =
   27390           5 :       v8::String::NewFromUtf8(isolate, "test", v8::NewStringType::kInternalized)
   27391             :           .ToLocalChecked();
   27392           5 :   array->Set(isolate, 1, string);
   27393          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27394          10 :   CHECK(array->Get(isolate, 1)->IsString());
   27395             : 
   27396           5 :   Local<v8::Number> num = v8::Number::New(env->GetIsolate(), 3.1415926);
   27397           5 :   array->Set(isolate, 2, num);
   27398          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27399          10 :   CHECK(array->Get(isolate, 1)->IsString());
   27400          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   27401             : 
   27402             :   v8::Local<v8::Boolean> f = v8::False(isolate);
   27403           5 :   array->Set(isolate, 3, f);
   27404          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27405          10 :   CHECK(array->Get(isolate, 1)->IsString());
   27406          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   27407          10 :   CHECK(array->Get(isolate, 3)->IsBoolean());
   27408             : 
   27409           5 :   v8::Local<v8::Primitive> n = v8::Null(isolate);
   27410           5 :   array->Set(isolate, 4, n);
   27411          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27412          10 :   CHECK(array->Get(isolate, 1)->IsString());
   27413          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   27414          10 :   CHECK(array->Get(isolate, 3)->IsBoolean());
   27415          10 :   CHECK(array->Get(isolate, 4)->IsNull());
   27416           5 : }
   27417             : 
   27418       26644 : TEST(PersistentValueMap) {
   27419           5 :   v8::Isolate* isolate = CcTest::isolate();
   27420          10 :   v8::HandleScope scope(isolate);
   27421           5 :   LocalContext env;
   27422             : 
   27423             :   v8::PersistentValueMap<
   27424             :       std::string, v8::Value,
   27425             :       v8::DefaultPersistentValueMapTraits<std::string, v8::Value>>
   27426             :       map(isolate);
   27427             :   v8::Local<v8::Value> value =
   27428           5 :       v8::String::NewFromUtf8(isolate, "value",
   27429             :                               v8::NewStringType::kInternalized)
   27430             :           .ToLocalChecked();
   27431          15 :   map.Set("key", value);
   27432           5 : }
   27433             : 
   27434             : namespace {
   27435             : 
   27436             : bool wasm_streaming_callback_got_called = false;
   27437             : bool wasm_streaming_data_got_collected = false;
   27438             : 
   27439           4 : void WasmStreamingTestFinalizer(const v8::WeakCallbackInfo<void>& data) {
   27440           4 :   CHECK(!wasm_streaming_data_got_collected);
   27441           4 :   wasm_streaming_data_got_collected = true;
   27442           4 :   i::GlobalHandles::Destroy(reinterpret_cast<i::Address*>(data.GetParameter()));
   27443           4 : }
   27444             : 
   27445           4 : void WasmStreamingCallbackTestCallbackIsCalled(
   27446             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27447           4 :   CHECK(!wasm_streaming_callback_got_called);
   27448           4 :   wasm_streaming_callback_got_called = true;
   27449             : 
   27450             :   i::Handle<i::Object> global_handle =
   27451             :       reinterpret_cast<i::Isolate*>(args.GetIsolate())
   27452             :           ->global_handles()
   27453           4 :           ->Create(*v8::Utils::OpenHandle(*args.Data()));
   27454             :   i::GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
   27455             :                              WasmStreamingTestFinalizer,
   27456           4 :                              v8::WeakCallbackType::kParameter);
   27457           4 : }
   27458             : 
   27459           4 : void WasmStreamingCallbackTestOnBytesReceived(
   27460             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27461             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27462           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27463             : 
   27464             :   // The first bytes of the WebAssembly magic word.
   27465           4 :   const uint8_t bytes[]{0x00, 0x61, 0x73};
   27466           4 :   streaming->OnBytesReceived(bytes, arraysize(bytes));
   27467           4 : }
   27468             : 
   27469           4 : void WasmStreamingCallbackTestFinishWithSuccess(
   27470             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27471             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27472           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27473             :   // The bytes of a minimal WebAssembly module.
   27474           4 :   const uint8_t bytes[]{0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00};
   27475           4 :   streaming->OnBytesReceived(bytes, arraysize(bytes));
   27476           4 :   streaming->Finish();
   27477           4 : }
   27478             : 
   27479           4 : void WasmStreamingCallbackTestFinishWithFailure(
   27480             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27481             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27482           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27483           4 :   streaming->Finish();
   27484           4 : }
   27485             : 
   27486           4 : void WasmStreamingCallbackTestAbortWithReject(
   27487             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27488             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27489           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27490           8 :   streaming->Abort(v8::Object::New(args.GetIsolate()));
   27491           4 : }
   27492             : 
   27493           4 : void WasmStreamingCallbackTestAbortNoReject(
   27494             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27495             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27496           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27497           4 :   streaming->Abort({});
   27498           4 : }
   27499             : 
   27500          24 : void TestWasmStreaming(v8::WasmStreamingCallback callback,
   27501             :                        v8::Promise::PromiseState expected_state) {
   27502          24 :   CcTest::isolate()->SetWasmStreamingCallback(callback);
   27503          24 :   LocalContext env;
   27504          24 :   v8::Isolate* isolate = env->GetIsolate();
   27505          48 :   v8::HandleScope scope(isolate);
   27506             : 
   27507             :   // Call {WebAssembly.compileStreaming} with {null} as parameter. The parameter
   27508             :   // is only really processed by the embedder, so for this test the value is
   27509             :   // irrelevant.
   27510             :   v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(
   27511             :       CompileRun("WebAssembly.compileStreaming(null)"));
   27512             : 
   27513          24 :   EmptyMessageQueues(isolate);
   27514          24 :   CHECK_EQ(expected_state, promise->State());
   27515          24 : }
   27516             : 
   27517             : }  // namespace
   27518             : 
   27519       26643 : TEST(WasmStreamingCallback) {
   27520             :   TestWasmStreaming(WasmStreamingCallbackTestCallbackIsCalled,
   27521           4 :                     v8::Promise::kPending);
   27522           4 :   CHECK(wasm_streaming_callback_got_called);
   27523           4 :   CcTest::CollectAllAvailableGarbage();
   27524           4 :   CHECK(wasm_streaming_data_got_collected);
   27525           4 : }
   27526             : 
   27527       26643 : TEST(WasmStreamingOnBytesReceived) {
   27528             :   TestWasmStreaming(WasmStreamingCallbackTestOnBytesReceived,
   27529           4 :                     v8::Promise::kPending);
   27530           4 : }
   27531             : 
   27532       26643 : TEST(WasmStreamingFinishWithSuccess) {
   27533             :   TestWasmStreaming(WasmStreamingCallbackTestFinishWithSuccess,
   27534           4 :                     v8::Promise::kFulfilled);
   27535           4 : }
   27536             : 
   27537       26643 : TEST(WasmStreamingFinishWithFailure) {
   27538             :   TestWasmStreaming(WasmStreamingCallbackTestFinishWithFailure,
   27539           4 :                     v8::Promise::kRejected);
   27540           4 : }
   27541             : 
   27542       26643 : TEST(WasmStreamingAbortWithReject) {
   27543             :   TestWasmStreaming(WasmStreamingCallbackTestAbortWithReject,
   27544           4 :                     v8::Promise::kRejected);
   27545           4 : }
   27546             : 
   27547       26643 : TEST(WasmStreamingAbortWithoutReject) {
   27548             :   TestWasmStreaming(WasmStreamingCallbackTestAbortNoReject,
   27549           4 :                     v8::Promise::kPending);
   27550           4 : }
   27551             : 
   27552             : enum class AtomicsWaitCallbackAction {
   27553             :   Interrupt,
   27554             :   StopAndThrowInFirstCall,
   27555             :   StopAndThrowInSecondCall,
   27556             :   StopFromThreadAndThrow,
   27557             :   KeepWaiting
   27558             : };
   27559             : 
   27560             : class StopAtomicsWaitThread;
   27561             : 
   27562          26 : struct AtomicsWaitCallbackInfo {
   27563             :   v8::Isolate* isolate;
   27564             :   v8::Isolate::AtomicsWaitWakeHandle* wake_handle;
   27565             :   std::unique_ptr<StopAtomicsWaitThread> stop_thread;
   27566             :   AtomicsWaitCallbackAction action;
   27567             : 
   27568             :   Local<v8::SharedArrayBuffer> expected_sab;
   27569             :   v8::Isolate::AtomicsWaitEvent expected_event;
   27570             :   double expected_timeout;
   27571             :   int64_t expected_value;
   27572             :   size_t expected_offset;
   27573             : 
   27574             :   size_t ncalls = 0;
   27575             : };
   27576             : 
   27577          13 : class StopAtomicsWaitThread : public v8::base::Thread {
   27578             :  public:
   27579             :   explicit StopAtomicsWaitThread(AtomicsWaitCallbackInfo* info)
   27580          13 :       : Thread(Options("StopAtomicsWaitThread")), info_(info) {}
   27581             : 
   27582          13 :   void Run() override {
   27583          13 :     CHECK_NOT_NULL(info_->wake_handle);
   27584          13 :     info_->wake_handle->Wake();
   27585          13 :   }
   27586             : 
   27587             :  private:
   27588             :   AtomicsWaitCallbackInfo* info_;
   27589             : };
   27590             : 
   27591         169 : void AtomicsWaitCallbackForTesting(
   27592             :     v8::Isolate::AtomicsWaitEvent event, Local<v8::SharedArrayBuffer> sab,
   27593             :     size_t offset_in_bytes, int64_t value, double timeout_in_ms,
   27594             :     v8::Isolate::AtomicsWaitWakeHandle* wake_handle, void* data) {
   27595         169 :   AtomicsWaitCallbackInfo* info = static_cast<AtomicsWaitCallbackInfo*>(data);
   27596         169 :   info->ncalls++;
   27597         169 :   info->wake_handle = wake_handle;
   27598         169 :   CHECK(sab->StrictEquals(info->expected_sab));
   27599         169 :   CHECK_EQ(timeout_in_ms, info->expected_timeout);
   27600         169 :   CHECK_EQ(value, info->expected_value);
   27601         169 :   CHECK_EQ(offset_in_bytes, info->expected_offset);
   27602             : 
   27603          52 :   auto ThrowSomething = [&]() {
   27604         104 :     info->isolate->ThrowException(v8::Integer::New(info->isolate, 42));
   27605         221 :   };
   27606             : 
   27607         169 :   if (event == v8::Isolate::AtomicsWaitEvent::kStartWait) {
   27608          91 :     CHECK_NOT_NULL(wake_handle);
   27609          91 :     switch (info->action) {
   27610             :       case AtomicsWaitCallbackAction::Interrupt:
   27611          13 :         info->isolate->TerminateExecution();
   27612          13 :         break;
   27613             :       case AtomicsWaitCallbackAction::StopAndThrowInFirstCall:
   27614          13 :         ThrowSomething();
   27615             :         V8_FALLTHROUGH;
   27616             :       case AtomicsWaitCallbackAction::StopAndThrowInSecondCall:
   27617          39 :         wake_handle->Wake();
   27618          39 :         break;
   27619             :       case AtomicsWaitCallbackAction::StopFromThreadAndThrow:
   27620          26 :         info->stop_thread = v8::base::make_unique<StopAtomicsWaitThread>(info);
   27621          26 :         info->stop_thread->Start();
   27622          13 :         break;
   27623             :       case AtomicsWaitCallbackAction::KeepWaiting:
   27624             :         break;
   27625             :     }
   27626             :   } else {
   27627          78 :     CHECK_EQ(event, info->expected_event);
   27628          78 :     CHECK_NULL(wake_handle);
   27629             : 
   27630          78 :     if (info->stop_thread) {
   27631          13 :       info->stop_thread->Join();
   27632          13 :       info->stop_thread.reset();
   27633             :     }
   27634             : 
   27635          78 :     if (info->action == AtomicsWaitCallbackAction::StopAndThrowInSecondCall ||
   27636             :         info->action == AtomicsWaitCallbackAction::StopFromThreadAndThrow) {
   27637          39 :       ThrowSomething();
   27638             :     }
   27639             :   }
   27640         169 : }
   27641             : 
   27642             : // Must be called from within HandleScope
   27643          13 : void AtomicsWaitCallbackCommon(v8::Isolate* isolate, Local<Value> sab,
   27644             :                                size_t initial_offset,
   27645             :                                size_t offset_multiplier) {
   27646          13 :   CHECK(sab->IsSharedArrayBuffer());
   27647             : 
   27648             :   AtomicsWaitCallbackInfo info;
   27649          13 :   info.isolate = isolate;
   27650          13 :   info.expected_sab = sab.As<v8::SharedArrayBuffer>();
   27651          13 :   isolate->SetAtomicsWaitCallback(AtomicsWaitCallbackForTesting, &info);
   27652             : 
   27653             :   {
   27654          26 :     v8::TryCatch try_catch(isolate);
   27655          13 :     info.expected_offset = initial_offset;
   27656          13 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27657          13 :     info.expected_value = 0;
   27658          13 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kTerminatedExecution;
   27659          13 :     info.action = AtomicsWaitCallbackAction::Interrupt;
   27660          13 :     info.ncalls = 0;
   27661             :     CompileRun("wait(0, 0);");
   27662          26 :     CHECK_EQ(info.ncalls, 2);
   27663          13 :     CHECK(try_catch.HasTerminated());
   27664             :   }
   27665             : 
   27666             :   {
   27667          26 :     v8::TryCatch try_catch(isolate);
   27668          13 :     info.expected_offset = initial_offset + offset_multiplier;
   27669          13 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27670          13 :     info.expected_value = 1;
   27671          13 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kNotEqual;
   27672          13 :     info.action = AtomicsWaitCallbackAction::KeepWaiting;
   27673          13 :     info.ncalls = 0;
   27674             :     CompileRun("wait(1, 1);");  // real value is 0 != 1
   27675          26 :     CHECK_EQ(info.ncalls, 2);
   27676          13 :     CHECK(!try_catch.HasCaught());
   27677             :   }
   27678             : 
   27679             :   {
   27680          26 :     v8::TryCatch try_catch(isolate);
   27681          13 :     info.expected_offset = initial_offset + offset_multiplier;
   27682          13 :     info.expected_timeout = 0.125;
   27683          13 :     info.expected_value = 0;
   27684          13 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kTimedOut;
   27685          13 :     info.action = AtomicsWaitCallbackAction::KeepWaiting;
   27686          13 :     info.ncalls = 0;
   27687             :     CompileRun("wait(1, 0, 0.125);");  // timeout
   27688          26 :     CHECK_EQ(info.ncalls, 2);
   27689          13 :     CHECK(!try_catch.HasCaught());
   27690             :   }
   27691             : 
   27692             :   {
   27693          26 :     v8::TryCatch try_catch(isolate);
   27694          13 :     info.expected_offset = initial_offset + offset_multiplier;
   27695          13 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27696          13 :     info.expected_value = 0;
   27697          13 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   27698          13 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInFirstCall;
   27699          13 :     info.ncalls = 0;
   27700             :     CompileRun("wait(1, 0);");
   27701          26 :     CHECK_EQ(info.ncalls, 1);  // Only one extra call
   27702          13 :     CHECK(try_catch.HasCaught());
   27703          26 :     CHECK(try_catch.Exception()->IsInt32());
   27704          13 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   27705             :   }
   27706             : 
   27707             :   {
   27708          26 :     v8::TryCatch try_catch(isolate);
   27709          13 :     info.expected_offset = initial_offset + offset_multiplier;
   27710          13 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27711          13 :     info.expected_value = 0;
   27712          13 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   27713          13 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInSecondCall;
   27714          13 :     info.ncalls = 0;
   27715             :     CompileRun("wait(1, 0);");
   27716          26 :     CHECK_EQ(info.ncalls, 2);
   27717          13 :     CHECK(try_catch.HasCaught());
   27718          26 :     CHECK(try_catch.Exception()->IsInt32());
   27719          13 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   27720             :   }
   27721             : 
   27722             :   {
   27723             :     // Same test as before, but with a different `expected_value`.
   27724          26 :     v8::TryCatch try_catch(isolate);
   27725          13 :     info.expected_offset = initial_offset + offset_multiplier;
   27726          13 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27727          13 :     info.expected_value = 200;
   27728          13 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   27729          13 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInSecondCall;
   27730          13 :     info.ncalls = 0;
   27731             :     CompileRun(
   27732             :         "setArrayElemAs(1, 200);"
   27733             :         "wait(1, 200);");
   27734          26 :     CHECK_EQ(info.ncalls, 2);
   27735          13 :     CHECK(try_catch.HasCaught());
   27736          26 :     CHECK(try_catch.Exception()->IsInt32());
   27737          13 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   27738             :   }
   27739             : 
   27740             :   {
   27741             :     // Wake the `Atomics.wait()` call from a thread.
   27742          26 :     v8::TryCatch try_catch(isolate);
   27743          13 :     info.expected_offset = initial_offset;
   27744          13 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27745          13 :     info.expected_value = 0;
   27746          13 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   27747          13 :     info.action = AtomicsWaitCallbackAction::StopFromThreadAndThrow;
   27748          13 :     info.ncalls = 0;
   27749             :     CompileRun(
   27750             :         "setArrayElemAs(1, 0);"
   27751             :         "wait(0, 0);");
   27752          26 :     CHECK_EQ(info.ncalls, 2);
   27753          13 :     CHECK(try_catch.HasCaught());
   27754          26 :     CHECK(try_catch.Exception()->IsInt32());
   27755          13 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   27756             :   }
   27757          13 : }
   27758             : 
   27759       26644 : TEST(AtomicsWaitCallback) {
   27760           5 :   LocalContext env;
   27761           5 :   v8::Isolate* isolate = env->GetIsolate();
   27762          10 :   v8::HandleScope scope(isolate);
   27763             :   const char* init = R"(
   27764             :       let sab = new SharedArrayBuffer(16);
   27765             :       let int32arr = new Int32Array(sab, 4);
   27766             :       let setArrayElemAs = function(id, val) {
   27767             :         int32arr[id] = val;
   27768             :       };
   27769             :       let wait = function(id, val, timeout) {
   27770             :         if(arguments.length == 2) return Atomics.wait(int32arr, id, val);
   27771             :         return Atomics.wait(int32arr, id, val, timeout);
   27772             :       };
   27773             :       sab;)";
   27774           5 :   AtomicsWaitCallbackCommon(isolate, CompileRun(init), 4, 4);
   27775           5 : }
   27776             : 
   27777             : namespace v8 {
   27778             : namespace internal {
   27779             : namespace wasm {
   27780       26643 : TEST(WasmI32AtomicWaitCallback) {
   27781             :   FlagScope<bool> wasm_threads_flag(&i::FLAG_experimental_wasm_threads, true);
   27782           8 :   WasmRunner<int32_t, int32_t, int32_t, double> r(ExecutionTier::kTurbofan);
   27783           4 :   r.builder().AddMemory(kWasmPageSize, SharedFlag::kShared);
   27784             :   r.builder().SetHasSharedMemory();
   27785           4 :   BUILD(r, WASM_ATOMICS_WAIT(kExprI32AtomicWait, WASM_GET_LOCAL(0),
   27786             :                              WASM_GET_LOCAL(1),
   27787             :                              WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(2)), 4));
   27788           4 :   LocalContext env;
   27789           4 :   v8::Isolate* isolate = env->GetIsolate();
   27790           8 :   v8::HandleScope scope(isolate);
   27791             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27792           4 :   Handle<JSFunction> func = r.builder().WrapCode(0);
   27793          16 :   CHECK(env->Global()
   27794             :             ->Set(env.local(), v8_str("func"), v8::Utils::ToLocal(func))
   27795             :             .FromJust());
   27796             :   Handle<JSArrayBuffer> memory(
   27797             :       r.builder().instance_object()->memory_object()->array_buffer(),
   27798             :       i_isolate);
   27799          16 :   CHECK(env->Global()
   27800             :             ->Set(env.local(), v8_str("sab"), v8::Utils::ToLocal(memory))
   27801             :             .FromJust());
   27802             : 
   27803             :   const char* init = R"(
   27804             :       let int32arr = new Int32Array(sab, 4);
   27805             :       let setArrayElemAs = function(id, val) {
   27806             :         int32arr[id] = val;
   27807             :       };
   27808             :       let wait = function(id, val, timeout) {
   27809             :         if(arguments.length === 2)
   27810             :           return func(id << 2, val, -1);
   27811             :         return func(id << 2, val, timeout*1000000);
   27812             :       };
   27813             :       sab;)";
   27814           4 :   AtomicsWaitCallbackCommon(isolate, CompileRun(init), 4, 4);
   27815           4 : }
   27816             : 
   27817       26643 : TEST(WasmI64AtomicWaitCallback) {
   27818             :   FlagScope<bool> wasm_threads_flag(&i::FLAG_experimental_wasm_threads, true);
   27819           8 :   WasmRunner<int32_t, int32_t, double, double> r(ExecutionTier::kTurbofan);
   27820           4 :   r.builder().AddMemory(kWasmPageSize, SharedFlag::kShared);
   27821             :   r.builder().SetHasSharedMemory();
   27822           4 :   BUILD(r, WASM_ATOMICS_WAIT(kExprI64AtomicWait, WASM_GET_LOCAL(0),
   27823             :                              WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(1)),
   27824             :                              WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(2)), 8));
   27825           4 :   LocalContext env;
   27826           4 :   v8::Isolate* isolate = env->GetIsolate();
   27827           8 :   v8::HandleScope scope(isolate);
   27828             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27829           4 :   Handle<JSFunction> func = r.builder().WrapCode(0);
   27830          16 :   CHECK(env->Global()
   27831             :             ->Set(env.local(), v8_str("func"), v8::Utils::ToLocal(func))
   27832             :             .FromJust());
   27833             :   Handle<JSArrayBuffer> memory(
   27834             :       r.builder().instance_object()->memory_object()->array_buffer(),
   27835             :       i_isolate);
   27836          16 :   CHECK(env->Global()
   27837             :             ->Set(env.local(), v8_str("sab"), v8::Utils::ToLocal(memory))
   27838             :             .FromJust());
   27839             : 
   27840             :   const char* init = R"(
   27841             :       let int64arr = new BigInt64Array(sab, 8);
   27842             :       let setArrayElemAs = function(id, val) {
   27843             :         int64arr[id] = BigInt(val);
   27844             :       };
   27845             :       let wait = function(id, val, timeout) {
   27846             :         if(arguments.length === 2)
   27847             :           return func(id << 3, val, -1);
   27848             :         return func(id << 3, val, timeout*1000000);
   27849             :       };
   27850             :       sab;)";
   27851           4 :   AtomicsWaitCallbackCommon(isolate, CompileRun(init), 8, 8);
   27852           4 : }
   27853             : 
   27854             : }  // namespace wasm
   27855             : }  // namespace internal
   27856             : }  // namespace v8
   27857             : 
   27858             : // TODO(mstarzinger): Move this into a test-api-wasm.cc file when this large
   27859             : // test file is being split up into chunks.
   27860       26644 : TEST(WasmModuleObjectCompileFailure) {
   27861           5 :   LocalContext env;
   27862           5 :   v8::Isolate* isolate = env->GetIsolate();
   27863          10 :   v8::HandleScope scope(isolate);
   27864             : 
   27865             :   {
   27866          10 :     v8::TryCatch try_catch(isolate);
   27867           5 :     uint8_t buffer[] = {0xDE, 0xAD, 0xBE, 0xEF};
   27868           5 :     v8::MemorySpan<const uint8_t> serialized_module;
   27869             :     v8::MemorySpan<const uint8_t> wire_bytes = {buffer, arraysize(buffer)};
   27870             :     v8::MaybeLocal<v8::WasmModuleObject> maybe_module =
   27871             :         v8::WasmModuleObject::DeserializeOrCompile(isolate, serialized_module,
   27872           5 :                                                    wire_bytes);
   27873           5 :     CHECK(maybe_module.IsEmpty());
   27874           5 :     CHECK(try_catch.HasCaught());
   27875             :   }
   27876           5 : }
   27877             : 
   27878       26644 : TEST(BigIntAPI) {
   27879           5 :   LocalContext env;
   27880           5 :   v8::Isolate* isolate = env->GetIsolate();
   27881          10 :   v8::HandleScope scope(isolate);
   27882             :   bool lossless;
   27883             :   uint64_t words1[10];
   27884             :   uint64_t words2[10];
   27885             : 
   27886             :   {
   27887             :     Local<Value> bi = CompileRun("12n");
   27888           5 :     CHECK(bi->IsBigInt());
   27889             : 
   27890          10 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 12);
   27891          10 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless), 12);
   27892           5 :     CHECK_EQ(lossless, true);
   27893           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), 12);
   27894           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), 12);
   27895           5 :     CHECK_EQ(lossless, true);
   27896             :   }
   27897             : 
   27898             :   {
   27899             :     Local<Value> bi = CompileRun("-12n");
   27900           5 :     CHECK(bi->IsBigInt());
   27901             : 
   27902           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), static_cast<uint64_t>(-12));
   27903           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   27904             :              static_cast<uint64_t>(-12));
   27905           5 :     CHECK_EQ(lossless, false);
   27906           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), -12);
   27907           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), -12);
   27908           5 :     CHECK_EQ(lossless, true);
   27909             :   }
   27910             : 
   27911             :   {
   27912             :     Local<Value> bi = CompileRun("123456789012345678901234567890n");
   27913           5 :     CHECK(bi->IsBigInt());
   27914             : 
   27915           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 14083847773837265618ULL);
   27916           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   27917             :              14083847773837265618ULL);
   27918           5 :     CHECK_EQ(lossless, false);
   27919           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), -4362896299872285998LL);
   27920           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless),
   27921             :              -4362896299872285998LL);
   27922           5 :     CHECK_EQ(lossless, false);
   27923             :   }
   27924             : 
   27925             :   {
   27926             :     Local<Value> bi = CompileRun("-123456789012345678901234567890n");
   27927           5 :     CHECK(bi->IsBigInt());
   27928             : 
   27929           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 4362896299872285998LL);
   27930           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   27931             :              4362896299872285998LL);
   27932           5 :     CHECK_EQ(lossless, false);
   27933           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), 4362896299872285998LL);
   27934           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), 4362896299872285998LL);
   27935           5 :     CHECK_EQ(lossless, false);
   27936             :   }
   27937             : 
   27938             :   {
   27939             :     Local<v8::BigInt> bi =
   27940           5 :         v8::BigInt::NewFromWords(env.local(), 0, 0, words1).ToLocalChecked();
   27941          10 :     CHECK_EQ(bi->Uint64Value(), 0);
   27942           5 :     CHECK_EQ(bi->WordCount(), 0);
   27943             :   }
   27944             : 
   27945             :   {
   27946          10 :     TryCatch try_catch(isolate);
   27947             :     v8::MaybeLocal<v8::BigInt> bi = v8::BigInt::NewFromWords(
   27948           5 :         env.local(), 0, std::numeric_limits<int>::max(), words1);
   27949           5 :     CHECK(bi.IsEmpty());
   27950           5 :     CHECK(try_catch.HasCaught());
   27951             :   }
   27952             : 
   27953             :   {
   27954          10 :     TryCatch try_catch(isolate);
   27955             :     v8::MaybeLocal<v8::BigInt> bi =
   27956           5 :         v8::BigInt::NewFromWords(env.local(), 0, -1, words1);
   27957           5 :     CHECK(bi.IsEmpty());
   27958           5 :     CHECK(try_catch.HasCaught());
   27959             :   }
   27960             : 
   27961             :   {
   27962          10 :     TryCatch try_catch(isolate);
   27963             :     v8::MaybeLocal<v8::BigInt> bi =
   27964           5 :         v8::BigInt::NewFromWords(env.local(), 0, 1 << 30, words1);
   27965           5 :     CHECK(bi.IsEmpty());
   27966           5 :     CHECK(try_catch.HasCaught());
   27967             :   }
   27968             : 
   27969          25 :   for (int sign_bit = 0; sign_bit <= 1; sign_bit++) {
   27970          10 :     words1[0] = 0xffffffff00000000ULL;
   27971          10 :     words1[1] = 0x00000000ffffffffULL;
   27972             :     v8::Local<v8::BigInt> bi =
   27973          10 :         v8::BigInt::NewFromWords(env.local(), sign_bit, 2, words1)
   27974             :             .ToLocalChecked();
   27975          10 :     CHECK_EQ(bi->Uint64Value(&lossless),
   27976             :              sign_bit ? static_cast<uint64_t>(-static_cast<int64_t>(words1[0]))
   27977             :                       : words1[0]);
   27978          10 :     CHECK_EQ(lossless, false);
   27979          10 :     CHECK_EQ(bi->Int64Value(&lossless), sign_bit
   27980             :                                             ? -static_cast<int64_t>(words1[0])
   27981             :                                             : static_cast<int64_t>(words1[0]));
   27982          10 :     CHECK_EQ(lossless, false);
   27983          10 :     CHECK_EQ(bi->WordCount(), 2);
   27984             :     int real_sign_bit;
   27985          10 :     int word_count = arraysize(words2);
   27986          10 :     bi->ToWordsArray(&real_sign_bit, &word_count, words2);
   27987          10 :     CHECK_EQ(real_sign_bit, sign_bit);
   27988          10 :     CHECK_EQ(word_count, 2);
   27989             :   }
   27990           5 : }
   27991             : 
   27992             : namespace {
   27993             : 
   27994             : bool wasm_threads_enabled_value = false;
   27995             : 
   27996          10 : bool MockWasmThreadsEnabledCallback(Local<Context>) {
   27997          10 :   return wasm_threads_enabled_value;
   27998             : }
   27999             : 
   28000             : }  // namespace
   28001             : 
   28002       26644 : TEST(TestSetWasmThreadsEnabledCallback) {
   28003           5 :   LocalContext env;
   28004           5 :   v8::Isolate* isolate = env->GetIsolate();
   28005             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   28006          10 :   v8::HandleScope scope(isolate);
   28007           5 :   v8::Local<Context> context = Context::New(CcTest::isolate());
   28008           5 :   i::Handle<i::Context> i_context = v8::Utils::OpenHandle(*context);
   28009             : 
   28010             :   // {Isolate::AreWasmThreadsEnabled} calls the callback set by the embedder if
   28011             :   // such a callback exists. Otherwise it returns
   28012             :   // {FLAG_experimental_wasm_threads}. First we test that the flag is returned
   28013             :   // correctly if no callback is set. Then we test that the flag is ignored if
   28014             :   // the callback is set.
   28015             : 
   28016           5 :   i::FLAG_experimental_wasm_threads = false;
   28017           5 :   CHECK(!i_isolate->AreWasmThreadsEnabled(i_context));
   28018             : 
   28019           5 :   i::FLAG_experimental_wasm_threads = true;
   28020           5 :   CHECK(i_isolate->AreWasmThreadsEnabled(i_context));
   28021             : 
   28022           5 :   isolate->SetWasmThreadsEnabledCallback(MockWasmThreadsEnabledCallback);
   28023           5 :   wasm_threads_enabled_value = false;
   28024           5 :   CHECK(!i_isolate->AreWasmThreadsEnabled(i_context));
   28025             : 
   28026           5 :   wasm_threads_enabled_value = true;
   28027           5 :   i::FLAG_experimental_wasm_threads = false;
   28028           5 :   CHECK(i_isolate->AreWasmThreadsEnabled(i_context));
   28029           5 : }
   28030             : 
   28031       26644 : TEST(TestGetUnwindState) {
   28032           5 :   LocalContext env;
   28033           5 :   v8::Isolate* isolate = env->GetIsolate();
   28034             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   28035             : 
   28036           5 :   v8::UnwindState unwind_state = isolate->GetUnwindState();
   28037           5 :   v8::MemoryRange builtins_range = unwind_state.embedded_code_range;
   28038             : 
   28039             :   // Check that each off-heap builtin is within the builtins code range.
   28040             :   if (i::FLAG_embedded_builtins) {
   28041       15215 :     for (int id = 0; id < i::Builtins::builtin_count; id++) {
   28042             :       if (!i::Builtins::IsIsolateIndependent(id)) continue;
   28043        7605 :       i::Code builtin = i_isolate->builtins()->builtin(id);
   28044             :       i::Address start = builtin->InstructionStart();
   28045        7605 :       i::Address end = start + builtin->InstructionSize();
   28046             : 
   28047             :       i::Address builtins_start =
   28048        7605 :           reinterpret_cast<i::Address>(builtins_range.start);
   28049        7605 :       CHECK(start >= builtins_start &&
   28050             :             end < builtins_start + builtins_range.length_in_bytes);
   28051             :     }
   28052             :   } else {
   28053             :     CHECK_EQ(nullptr, builtins_range.start);
   28054             :     CHECK_EQ(0, builtins_range.length_in_bytes);
   28055             :   }
   28056             : 
   28057           5 :   v8::JSEntryStub js_entry_stub = unwind_state.js_entry_stub;
   28058             : 
   28059          15 :   CHECK_EQ(
   28060             :       i_isolate->heap()->builtin(i::Builtins::kJSEntry)->InstructionStart(),
   28061             :       reinterpret_cast<i::Address>(js_entry_stub.code.start));
   28062           5 : }
   28063             : 
   28064       26644 : TEST(MicrotaskContextShouldBeNativeContext) {
   28065           5 :   LocalContext env;
   28066           5 :   v8::Isolate* isolate = env->GetIsolate();
   28067          10 :   v8::HandleScope scope(isolate);
   28068             : 
   28069          10 :   auto callback = [](const v8::FunctionCallbackInfo<v8::Value>& info) {
   28070             :     v8::Isolate* isolate = info.GetIsolate();
   28071          10 :     v8::HandleScope scope(isolate);
   28072             :     i::Handle<i::Context> context =
   28073          10 :         v8::Utils::OpenHandle(*isolate->GetEnteredOrMicrotaskContext());
   28074             : 
   28075           5 :     CHECK(context->IsNativeContext());
   28076             :     info.GetReturnValue().SetUndefined();
   28077          10 :   };
   28078             : 
   28079           5 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   28080          10 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(callback);
   28081           5 :   Local<v8::Object> obj = desc->GetFunction(env.local())
   28082             :                               .ToLocalChecked()
   28083             :                               ->NewInstance(env.local())
   28084             :                               .ToLocalChecked();
   28085             : 
   28086          20 :   CHECK(env->Global()->Set(env.local(), v8_str("callback"), obj).FromJust());
   28087             :   CompileRun(
   28088             :       "with({}){(async ()=>{"
   28089             :       "  await 42;"
   28090             :       "})().then(callback);}");
   28091             : 
   28092           5 :   isolate->RunMicrotasks();
   28093           5 : }
   28094             : 
   28095       26644 : TEST(PreviewSetKeysIteratorEntriesWithDeleted) {
   28096           5 :   LocalContext env;
   28097          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28098           5 :   v8::Local<v8::Context> context = env.local();
   28099             : 
   28100             :   {
   28101             :     // Create set, delete entry, create iterator, preview.
   28102             :     v8::Local<v8::Object> iterator =
   28103             :         CompileRun("var set = new Set([1,2,3]); set.delete(1); set.keys()")
   28104           5 :             ->ToObject(context)
   28105             :             .ToLocalChecked();
   28106             :     bool is_key;
   28107             :     v8::Local<v8::Array> entries =
   28108           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28109           5 :     CHECK(!is_key);
   28110           5 :     CHECK_EQ(2, entries->Length());
   28111          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28112             :                     .ToLocalChecked()
   28113             :                     ->Int32Value(context)
   28114             :                     .FromJust());
   28115          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28116             :                     .ToLocalChecked()
   28117             :                     ->Int32Value(context)
   28118             :                     .FromJust());
   28119             :   }
   28120             :   {
   28121             :     // Create set, create iterator, delete entry, preview.
   28122             :     v8::Local<v8::Object> iterator =
   28123             :         CompileRun("var set = new Set([1,2,3]); set.keys()")
   28124           5 :             ->ToObject(context)
   28125             :             .ToLocalChecked();
   28126             :     CompileRun("set.delete(1);");
   28127             :     bool is_key;
   28128             :     v8::Local<v8::Array> entries =
   28129           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28130           5 :     CHECK(!is_key);
   28131           5 :     CHECK_EQ(2, entries->Length());
   28132          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28133             :                     .ToLocalChecked()
   28134             :                     ->Int32Value(context)
   28135             :                     .FromJust());
   28136          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28137             :                     .ToLocalChecked()
   28138             :                     ->Int32Value(context)
   28139             :                     .FromJust());
   28140             :   }
   28141             :   {
   28142             :     // Create set, create iterator, delete entry, iterate, preview.
   28143             :     v8::Local<v8::Object> iterator =
   28144             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   28145           5 :             ->ToObject(context)
   28146             :             .ToLocalChecked();
   28147             :     CompileRun("set.delete(1); it.next();");
   28148             :     bool is_key;
   28149             :     v8::Local<v8::Array> entries =
   28150           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28151           5 :     CHECK(!is_key);
   28152           5 :     CHECK_EQ(1, entries->Length());
   28153          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28154             :                     .ToLocalChecked()
   28155             :                     ->Int32Value(context)
   28156             :                     .FromJust());
   28157             :   }
   28158             :   {
   28159             :     // Create set, create iterator, delete entry, iterate until empty, preview.
   28160             :     v8::Local<v8::Object> iterator =
   28161             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   28162           5 :             ->ToObject(context)
   28163             :             .ToLocalChecked();
   28164             :     CompileRun("set.delete(1); it.next(); it.next();");
   28165             :     bool is_key;
   28166             :     v8::Local<v8::Array> entries =
   28167           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28168           5 :     CHECK(!is_key);
   28169           5 :     CHECK_EQ(0, entries->Length());
   28170             :   }
   28171             :   {
   28172             :     // Create set, create iterator, delete entry, iterate, trigger rehash,
   28173             :     // preview.
   28174             :     v8::Local<v8::Object> iterator =
   28175             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   28176           5 :             ->ToObject(context)
   28177             :             .ToLocalChecked();
   28178             :     CompileRun("set.delete(1); it.next();");
   28179             :     CompileRun("for (var i = 4; i < 20; i++) set.add(i);");
   28180             :     bool is_key;
   28181             :     v8::Local<v8::Array> entries =
   28182           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28183           5 :     CHECK(!is_key);
   28184           5 :     CHECK_EQ(17, entries->Length());
   28185         175 :     for (uint32_t i = 0; i < 17; i++) {
   28186         340 :       CHECK_EQ(i + 3, entries->Get(context, i)
   28187             :                           .ToLocalChecked()
   28188             :                           ->Int32Value(context)
   28189             :                           .FromJust());
   28190             :     }
   28191             :   }
   28192           5 : }
   28193             : 
   28194       26644 : TEST(PreviewSetValuesIteratorEntriesWithDeleted) {
   28195           5 :   LocalContext env;
   28196          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28197           5 :   v8::Local<v8::Context> context = env.local();
   28198             : 
   28199             :   {
   28200             :     // Create set, delete entry, create iterator, preview.
   28201             :     v8::Local<v8::Object> iterator =
   28202             :         CompileRun("var set = new Set([1,2,3]); set.delete(1); set.values()")
   28203           5 :             ->ToObject(context)
   28204             :             .ToLocalChecked();
   28205             :     bool is_key;
   28206             :     v8::Local<v8::Array> entries =
   28207           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28208           5 :     CHECK(!is_key);
   28209           5 :     CHECK_EQ(2, entries->Length());
   28210          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28211             :                     .ToLocalChecked()
   28212             :                     ->Int32Value(context)
   28213             :                     .FromJust());
   28214          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28215             :                     .ToLocalChecked()
   28216             :                     ->Int32Value(context)
   28217             :                     .FromJust());
   28218             :   }
   28219             :   {
   28220             :     // Create set, create iterator, delete entry, preview.
   28221             :     v8::Local<v8::Object> iterator =
   28222             :         CompileRun("var set = new Set([1,2,3]); set.values()")
   28223           5 :             ->ToObject(context)
   28224             :             .ToLocalChecked();
   28225             :     CompileRun("set.delete(1);");
   28226             :     bool is_key;
   28227             :     v8::Local<v8::Array> entries =
   28228           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28229           5 :     CHECK(!is_key);
   28230           5 :     CHECK_EQ(2, entries->Length());
   28231          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28232             :                     .ToLocalChecked()
   28233             :                     ->Int32Value(context)
   28234             :                     .FromJust());
   28235          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28236             :                     .ToLocalChecked()
   28237             :                     ->Int32Value(context)
   28238             :                     .FromJust());
   28239             :   }
   28240             :   {
   28241             :     // Create set, create iterator, delete entry, iterate, preview.
   28242             :     v8::Local<v8::Object> iterator =
   28243             :         CompileRun("var set = new Set([1,2,3]); var it = set.values(); it")
   28244           5 :             ->ToObject(context)
   28245             :             .ToLocalChecked();
   28246             :     CompileRun("set.delete(1); it.next();");
   28247             :     bool is_key;
   28248             :     v8::Local<v8::Array> entries =
   28249           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28250           5 :     CHECK(!is_key);
   28251           5 :     CHECK_EQ(1, entries->Length());
   28252          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28253             :                     .ToLocalChecked()
   28254             :                     ->Int32Value(context)
   28255             :                     .FromJust());
   28256             :   }
   28257             :   {
   28258             :     // Create set, create iterator, delete entry, iterate until empty, preview.
   28259             :     v8::Local<v8::Object> iterator =
   28260             :         CompileRun("var set = new Set([1,2,3]); var it = set.values(); it")
   28261           5 :             ->ToObject(context)
   28262             :             .ToLocalChecked();
   28263             :     CompileRun("set.delete(1); it.next(); it.next();");
   28264             :     bool is_key;
   28265             :     v8::Local<v8::Array> entries =
   28266           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28267           5 :     CHECK(!is_key);
   28268           5 :     CHECK_EQ(0, entries->Length());
   28269             :   }
   28270             :   {
   28271             :     // Create set, create iterator, delete entry, iterate, trigger rehash,
   28272             :     // preview.
   28273             :     v8::Local<v8::Object> iterator =
   28274             :         CompileRun("var set = new Set([1,2,3]); var it = set.values(); it")
   28275           5 :             ->ToObject(context)
   28276             :             .ToLocalChecked();
   28277             :     CompileRun("set.delete(1); it.next();");
   28278             :     CompileRun("for (var i = 4; i < 20; i++) set.add(i);");
   28279             :     bool is_key;
   28280             :     v8::Local<v8::Array> entries =
   28281           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28282           5 :     CHECK(!is_key);
   28283           5 :     CHECK_EQ(17, entries->Length());
   28284         175 :     for (uint32_t i = 0; i < 17; i++) {
   28285         340 :       CHECK_EQ(i + 3, entries->Get(context, i)
   28286             :                           .ToLocalChecked()
   28287             :                           ->Int32Value(context)
   28288             :                           .FromJust());
   28289             :     }
   28290             :   }
   28291           5 : }
   28292             : 
   28293       26644 : TEST(PreviewMapEntriesIteratorEntries) {
   28294           5 :   LocalContext env;
   28295          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28296           5 :   v8::Local<v8::Context> context = env.local();
   28297             :   {
   28298             :     // Create set, delete entry, create entries iterator, preview.
   28299             :     v8::Local<v8::Object> iterator =
   28300             :         CompileRun("var set = new Set([1,2,3]); set.delete(2); set.entries()")
   28301           5 :             ->ToObject(context)
   28302             :             .ToLocalChecked();
   28303             :     bool is_key;
   28304             :     v8::Local<v8::Array> entries =
   28305           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28306           5 :     CHECK(is_key);
   28307           5 :     CHECK_EQ(4, entries->Length());
   28308           5 :     uint32_t first = entries->Get(context, 0)
   28309             :                          .ToLocalChecked()
   28310          10 :                          ->Int32Value(context)
   28311           5 :                          .FromJust();
   28312           5 :     uint32_t second = entries->Get(context, 2)
   28313             :                           .ToLocalChecked()
   28314          10 :                           ->Int32Value(context)
   28315           5 :                           .FromJust();
   28316           5 :     CHECK_EQ(1, first);
   28317           5 :     CHECK_EQ(3, second);
   28318          15 :     CHECK_EQ(first, entries->Get(context, 1)
   28319             :                         .ToLocalChecked()
   28320             :                         ->Int32Value(context)
   28321             :                         .FromJust());
   28322          15 :     CHECK_EQ(second, entries->Get(context, 3)
   28323             :                          .ToLocalChecked()
   28324             :                          ->Int32Value(context)
   28325             :                          .FromJust());
   28326             :   }
   28327           5 : }
   28328             : 
   28329       26644 : TEST(PreviewMapValuesIteratorEntriesWithDeleted) {
   28330           5 :   LocalContext env;
   28331          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28332           5 :   v8::Local<v8::Context> context = env.local();
   28333             : 
   28334             :   {
   28335             :     // Create map, delete entry, create iterator, preview.
   28336             :     v8::Local<v8::Object> iterator = CompileRun(
   28337             :                                          "var map = new Map();"
   28338             :                                          "var key = {}; map.set(key, 1);"
   28339             :                                          "map.set({}, 2); map.set({}, 3);"
   28340             :                                          "map.delete(key);"
   28341             :                                          "map.values()")
   28342           5 :                                          ->ToObject(context)
   28343             :                                          .ToLocalChecked();
   28344             :     bool is_key;
   28345             :     v8::Local<v8::Array> entries =
   28346           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28347           5 :     CHECK(!is_key);
   28348           5 :     CHECK_EQ(2, entries->Length());
   28349          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28350             :                     .ToLocalChecked()
   28351             :                     ->Int32Value(context)
   28352             :                     .FromJust());
   28353          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28354             :                     .ToLocalChecked()
   28355             :                     ->Int32Value(context)
   28356             :                     .FromJust());
   28357             :   }
   28358             :   {
   28359             :     // Create map, create iterator, delete entry, preview.
   28360             :     v8::Local<v8::Object> iterator = CompileRun(
   28361             :                                          "var map = new Map();"
   28362             :                                          "var key = {}; map.set(key, 1);"
   28363             :                                          "map.set({}, 2); map.set({}, 3);"
   28364             :                                          "map.values()")
   28365           5 :                                          ->ToObject(context)
   28366             :                                          .ToLocalChecked();
   28367             :     CompileRun("map.delete(key);");
   28368             :     bool is_key;
   28369             :     v8::Local<v8::Array> entries =
   28370           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28371           5 :     CHECK(!is_key);
   28372           5 :     CHECK_EQ(2, entries->Length());
   28373          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28374             :                     .ToLocalChecked()
   28375             :                     ->Int32Value(context)
   28376             :                     .FromJust());
   28377          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28378             :                     .ToLocalChecked()
   28379             :                     ->Int32Value(context)
   28380             :                     .FromJust());
   28381             :   }
   28382             :   {
   28383             :     // Create map, create iterator, delete entry, iterate, preview.
   28384             :     v8::Local<v8::Object> iterator = CompileRun(
   28385             :                                          "var map = new Map();"
   28386             :                                          "var key = {}; map.set(key, 1);"
   28387             :                                          "map.set({}, 2); map.set({}, 3);"
   28388             :                                          "var it = map.values(); it")
   28389           5 :                                          ->ToObject(context)
   28390             :                                          .ToLocalChecked();
   28391             :     CompileRun("map.delete(key); it.next();");
   28392             :     bool is_key;
   28393             :     v8::Local<v8::Array> entries =
   28394           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28395           5 :     CHECK(!is_key);
   28396           5 :     CHECK_EQ(1, entries->Length());
   28397          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28398             :                     .ToLocalChecked()
   28399             :                     ->Int32Value(context)
   28400             :                     .FromJust());
   28401             :   }
   28402             :   {
   28403             :     // Create map, create iterator, delete entry, iterate until empty, preview.
   28404             :     v8::Local<v8::Object> iterator = CompileRun(
   28405             :                                          "var map = new Map();"
   28406             :                                          "var key = {}; map.set(key, 1);"
   28407             :                                          "map.set({}, 2); map.set({}, 3);"
   28408             :                                          "var it = map.values(); it")
   28409           5 :                                          ->ToObject(context)
   28410             :                                          .ToLocalChecked();
   28411             :     CompileRun("map.delete(key); it.next(); it.next();");
   28412             :     bool is_key;
   28413             :     v8::Local<v8::Array> entries =
   28414           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28415           5 :     CHECK(!is_key);
   28416           5 :     CHECK_EQ(0, entries->Length());
   28417             :   }
   28418             :   {
   28419             :     // Create map, create iterator, delete entry, iterate, trigger rehash,
   28420             :     // preview.
   28421             :     v8::Local<v8::Object> iterator = CompileRun(
   28422             :                                          "var map = new Map();"
   28423             :                                          "var key = {}; map.set(key, 1);"
   28424             :                                          "map.set({}, 2); map.set({}, 3);"
   28425             :                                          "var it = map.values(); it")
   28426           5 :                                          ->ToObject(context)
   28427             :                                          .ToLocalChecked();
   28428             :     CompileRun("map.delete(key); it.next();");
   28429             :     CompileRun("for (var i = 4; i < 20; i++) map.set({}, i);");
   28430             :     bool is_key;
   28431             :     v8::Local<v8::Array> entries =
   28432           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28433           5 :     CHECK(!is_key);
   28434           5 :     CHECK_EQ(17, entries->Length());
   28435         175 :     for (uint32_t i = 0; i < 17; i++) {
   28436         340 :       CHECK_EQ(i + 3, entries->Get(context, i)
   28437             :                           .ToLocalChecked()
   28438             :                           ->Int32Value(context)
   28439             :                           .FromJust());
   28440             :     }
   28441             :   }
   28442           5 : }
   28443             : 
   28444       26644 : TEST(PreviewMapKeysIteratorEntriesWithDeleted) {
   28445           5 :   LocalContext env;
   28446          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28447           5 :   v8::Local<v8::Context> context = env.local();
   28448             : 
   28449             :   {
   28450             :     // Create map, delete entry, create iterator, preview.
   28451             :     v8::Local<v8::Object> iterator = CompileRun(
   28452             :                                          "var map = new Map();"
   28453             :                                          "var key = 1; map.set(key, {});"
   28454             :                                          "map.set(2, {}); map.set(3, {});"
   28455             :                                          "map.delete(key);"
   28456             :                                          "map.keys()")
   28457           5 :                                          ->ToObject(context)
   28458             :                                          .ToLocalChecked();
   28459             :     bool is_key;
   28460             :     v8::Local<v8::Array> entries =
   28461           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28462           5 :     CHECK(!is_key);
   28463           5 :     CHECK_EQ(2, entries->Length());
   28464          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28465             :                     .ToLocalChecked()
   28466             :                     ->Int32Value(context)
   28467             :                     .FromJust());
   28468          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28469             :                     .ToLocalChecked()
   28470             :                     ->Int32Value(context)
   28471             :                     .FromJust());
   28472             :   }
   28473             :   {
   28474             :     // Create map, create iterator, delete entry, preview.
   28475             :     v8::Local<v8::Object> iterator = CompileRun(
   28476             :                                          "var map = new Map();"
   28477             :                                          "var key = 1; map.set(key, {});"
   28478             :                                          "map.set(2, {}); map.set(3, {});"
   28479             :                                          "map.keys()")
   28480           5 :                                          ->ToObject(context)
   28481             :                                          .ToLocalChecked();
   28482             :     CompileRun("map.delete(key);");
   28483             :     bool is_key;
   28484             :     v8::Local<v8::Array> entries =
   28485           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28486           5 :     CHECK(!is_key);
   28487           5 :     CHECK_EQ(2, entries->Length());
   28488          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28489             :                     .ToLocalChecked()
   28490             :                     ->Int32Value(context)
   28491             :                     .FromJust());
   28492          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28493             :                     .ToLocalChecked()
   28494             :                     ->Int32Value(context)
   28495             :                     .FromJust());
   28496             :   }
   28497             :   {
   28498             :     // Create map, create iterator, delete entry, iterate, preview.
   28499             :     v8::Local<v8::Object> iterator = CompileRun(
   28500             :                                          "var map = new Map();"
   28501             :                                          "var key = 1; map.set(key, {});"
   28502             :                                          "map.set(2, {}); map.set(3, {});"
   28503             :                                          "var it = map.keys(); it")
   28504           5 :                                          ->ToObject(context)
   28505             :                                          .ToLocalChecked();
   28506             :     CompileRun("map.delete(key); it.next();");
   28507             :     bool is_key;
   28508             :     v8::Local<v8::Array> entries =
   28509           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28510           5 :     CHECK(!is_key);
   28511           5 :     CHECK_EQ(1, entries->Length());
   28512          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28513             :                     .ToLocalChecked()
   28514             :                     ->Int32Value(context)
   28515             :                     .FromJust());
   28516             :   }
   28517             :   {
   28518             :     // Create map, create iterator, delete entry, iterate until empty, preview.
   28519             :     v8::Local<v8::Object> iterator = CompileRun(
   28520             :                                          "var map = new Map();"
   28521             :                                          "var key = 1; map.set(key, {});"
   28522             :                                          "map.set(2, {}); map.set(3, {});"
   28523             :                                          "var it = map.keys(); it")
   28524           5 :                                          ->ToObject(context)
   28525             :                                          .ToLocalChecked();
   28526             :     CompileRun("map.delete(key); it.next(); it.next();");
   28527             :     bool is_key;
   28528             :     v8::Local<v8::Array> entries =
   28529           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28530           5 :     CHECK(!is_key);
   28531           5 :     CHECK_EQ(0, entries->Length());
   28532             :   }
   28533           5 : }
   28534             : 
   28535             : namespace {
   28536             : static v8::Isolate* isolate_1;
   28537             : static v8::Isolate* isolate_2;
   28538       26639 : v8::Persistent<v8::Context> context_1;
   28539       26639 : v8::Persistent<v8::Context> context_2;
   28540             : 
   28541          20 : static void CallIsolate1(const v8::FunctionCallbackInfo<v8::Value>& args) {
   28542          20 :   v8::Isolate::Scope isolate_scope(isolate_1);
   28543          40 :   v8::HandleScope handle_scope(isolate_1);
   28544             :   v8::Local<v8::Context> context =
   28545          20 :       v8::Local<v8::Context>::New(isolate_1, context_1);
   28546             :   v8::Context::Scope context_scope(context);
   28547             :   CompileRun("f1() //# sourceURL=isolate1b");
   28548          20 : }
   28549             : 
   28550          20 : static void CallIsolate2(const v8::FunctionCallbackInfo<v8::Value>& args) {
   28551          20 :   v8::Isolate::Scope isolate_scope(isolate_2);
   28552          40 :   v8::HandleScope handle_scope(isolate_2);
   28553             :   v8::Local<v8::Context> context =
   28554          20 :       v8::Local<v8::Context>::New(isolate_2, context_2);
   28555             :   v8::Context::Scope context_scope(context);
   28556          20 :   reinterpret_cast<i::Isolate*>(isolate_2)->heap()->CollectAllGarbage(
   28557             :       i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting,
   28558          20 :       v8::kGCCallbackFlagForced);
   28559             :   CompileRun("f2() //# sourceURL=isolate2b");
   28560          20 : }
   28561             : 
   28562             : }  // anonymous namespace
   28563             : 
   28564       26644 : UNINITIALIZED_TEST(NestedIsolates) {
   28565             : #ifdef VERIFY_HEAP
   28566             :   i::FLAG_verify_heap = true;
   28567             : #endif  // VERIFY_HEAP
   28568             :   // Create two isolates and set up C++ functions via function templates that
   28569             :   // call into the other isolate. Recurse a few times, trigger GC along the way,
   28570             :   // and finally capture a stack trace. Check that the stack trace only includes
   28571             :   // frames from its own isolate.
   28572             :   v8::Isolate::CreateParams create_params;
   28573           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   28574           5 :   isolate_1 = v8::Isolate::New(create_params);
   28575           5 :   isolate_2 = v8::Isolate::New(create_params);
   28576             : 
   28577             :   {
   28578           5 :     v8::Isolate::Scope isolate_scope(isolate_1);
   28579          10 :     v8::HandleScope handle_scope(isolate_1);
   28580             : 
   28581           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate_1);
   28582             :     v8::Context::Scope context_scope(context);
   28583             : 
   28584             :     v8::Local<v8::FunctionTemplate> fun_templ =
   28585           5 :         v8::FunctionTemplate::New(isolate_1, CallIsolate2);
   28586           5 :     fun_templ->SetClassName(v8_str(isolate_1, "call_isolate_2"));
   28587           5 :     Local<Function> fun = fun_templ->GetFunction(context).ToLocalChecked();
   28588          20 :     CHECK(context->Global()
   28589             :               ->Set(context, v8_str(isolate_1, "call_isolate_2"), fun)
   28590             :               .FromJust());
   28591             :     CompileRun(
   28592             :         "let c = 0;"
   28593             :         "function f1() {"
   28594             :         "  c++;"
   28595             :         "  return call_isolate_2();"
   28596             :         "} //# sourceURL=isolate1a");
   28597           5 :     context_1.Reset(isolate_1, context);
   28598             :   }
   28599             : 
   28600             :   {
   28601           5 :     v8::Isolate::Scope isolate_scope(isolate_2);
   28602          10 :     v8::HandleScope handle_scope(isolate_2);
   28603             : 
   28604           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate_2);
   28605             :     v8::Context::Scope context_scope(context);
   28606             : 
   28607             :     v8::Local<v8::FunctionTemplate> fun_templ =
   28608           5 :         v8::FunctionTemplate::New(isolate_2, CallIsolate1);
   28609           5 :     fun_templ->SetClassName(v8_str(isolate_2, "call_isolate_1"));
   28610           5 :     Local<Function> fun = fun_templ->GetFunction(context).ToLocalChecked();
   28611             : 
   28612          20 :     CHECK(context->Global()
   28613             :               ->Set(context, v8_str(isolate_2, "call_isolate_1"), fun)
   28614             :               .FromJust());
   28615             :     CompileRun(
   28616             :         "let c = 4;"
   28617             :         "let result = undefined;"
   28618             :         "function f2() {"
   28619             :         "  if (c-- > 0) return call_isolate_1();"
   28620             :         "  else result = new Error().stack;"
   28621             :         "} //# sourceURL=isolate2a");
   28622           5 :     context_2.Reset(isolate_2, context);
   28623             : 
   28624             :     v8::Local<v8::String> result =
   28625             :         CompileRun("f2(); result //# sourceURL=isolate2c")
   28626           5 :             ->ToString(context)
   28627             :             .ToLocalChecked();
   28628             :     v8::Local<v8::String> expectation = v8_str(isolate_2,
   28629             :                                                "Error\n"
   28630             :                                                "    at f2 (isolate2a:1:104)\n"
   28631             :                                                "    at isolate2b:1:1\n"
   28632             :                                                "    at f2 (isolate2a:1:71)\n"
   28633             :                                                "    at isolate2b:1:1\n"
   28634             :                                                "    at f2 (isolate2a:1:71)\n"
   28635             :                                                "    at isolate2b:1:1\n"
   28636             :                                                "    at f2 (isolate2a:1:71)\n"
   28637             :                                                "    at isolate2b:1:1\n"
   28638             :                                                "    at f2 (isolate2a:1:71)\n"
   28639           5 :                                                "    at isolate2c:1:1");
   28640           5 :     CHECK(result->StrictEquals(expectation));
   28641             :   }
   28642             : 
   28643             :   {
   28644           5 :     v8::Isolate::Scope isolate_scope(isolate_1);
   28645          10 :     v8::HandleScope handle_scope(isolate_1);
   28646             :     v8::Local<v8::Context> context =
   28647           5 :         v8::Local<v8::Context>::New(isolate_1, context_1);
   28648             :     v8::Context::Scope context_scope(context);
   28649           5 :     ExpectInt32("c", 4);
   28650             :   }
   28651             : 
   28652           5 :   isolate_1->Dispose();
   28653           5 :   isolate_2->Dispose();
   28654       79922 : }

Generated by: LCOV version 1.10