Home | History | Annotate | Download | only in cctest
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <climits>
     29 #include <csignal>
     30 #include <string>
     31 #include <map>
     32 
     33 #include "v8.h"
     34 
     35 #if V8_OS_POSIX
     36 #include <unistd.h>  // NOLINT
     37 #endif
     38 
     39 #include "api.h"
     40 #include "arguments.h"
     41 #include "cctest.h"
     42 #include "compilation-cache.h"
     43 #include "cpu-profiler.h"
     44 #include "execution.h"
     45 #include "isolate.h"
     46 #include "objects.h"
     47 #include "parser.h"
     48 #include "platform.h"
     49 #include "snapshot.h"
     50 #include "unicode-inl.h"
     51 #include "utils.h"
     52 #include "vm-state.h"
     53 
     54 static const bool kLogThreading = false;
     55 
     56 using ::v8::Boolean;
     57 using ::v8::BooleanObject;
     58 using ::v8::Context;
     59 using ::v8::Extension;
     60 using ::v8::Function;
     61 using ::v8::FunctionTemplate;
     62 using ::v8::Handle;
     63 using ::v8::HandleScope;
     64 using ::v8::Local;
     65 using ::v8::Message;
     66 using ::v8::MessageCallback;
     67 using ::v8::Object;
     68 using ::v8::ObjectTemplate;
     69 using ::v8::Persistent;
     70 using ::v8::Script;
     71 using ::v8::StackTrace;
     72 using ::v8::String;
     73 using ::v8::TryCatch;
     74 using ::v8::Undefined;
     75 using ::v8::UniqueId;
     76 using ::v8::V8;
     77 using ::v8::Value;
     78 
     79 
     80 #define THREADED_PROFILED_TEST(Name)                                 \
     81   static void Test##Name();                                          \
     82   TEST(Name##WithProfiler) {                                         \
     83     RunWithProfiler(&Test##Name);                                    \
     84   }                                                                  \
     85   THREADED_TEST(Name)
     86 
     87 
     88 void RunWithProfiler(void (*test)()) {
     89   LocalContext env;
     90   v8::HandleScope scope(env->GetIsolate());
     91   v8::Local<v8::String> profile_name =
     92       v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
     93   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
     94 
     95   cpu_profiler->StartCpuProfiling(profile_name);
     96   (*test)();
     97   cpu_profiler->DeleteAllCpuProfiles();
     98 }
     99 
    100 
    101 static void ExpectString(const char* code, const char* expected) {
    102   Local<Value> result = CompileRun(code);
    103   CHECK(result->IsString());
    104   String::Utf8Value utf8(result);
    105   CHECK_EQ(expected, *utf8);
    106 }
    107 
    108 
    109 static void ExpectInt32(const char* code, int expected) {
    110   Local<Value> result = CompileRun(code);
    111   CHECK(result->IsInt32());
    112   CHECK_EQ(expected, result->Int32Value());
    113 }
    114 
    115 
    116 static void ExpectBoolean(const char* code, bool expected) {
    117   Local<Value> result = CompileRun(code);
    118   CHECK(result->IsBoolean());
    119   CHECK_EQ(expected, result->BooleanValue());
    120 }
    121 
    122 
    123 static void ExpectTrue(const char* code) {
    124   ExpectBoolean(code, true);
    125 }
    126 
    127 
    128 static void ExpectFalse(const char* code) {
    129   ExpectBoolean(code, false);
    130 }
    131 
    132 
    133 static void ExpectObject(const char* code, Local<Value> expected) {
    134   Local<Value> result = CompileRun(code);
    135   CHECK(result->Equals(expected));
    136 }
    137 
    138 
    139 static void ExpectUndefined(const char* code) {
    140   Local<Value> result = CompileRun(code);
    141   CHECK(result->IsUndefined());
    142 }
    143 
    144 
    145 static int signature_callback_count;
    146 static Local<Value> signature_expected_receiver;
    147 static void IncrementingSignatureCallback(
    148     const v8::FunctionCallbackInfo<v8::Value>& args) {
    149   ApiTestFuzzer::Fuzz();
    150   signature_callback_count++;
    151   CHECK_EQ(signature_expected_receiver, args.Holder());
    152   CHECK_EQ(signature_expected_receiver, args.This());
    153   v8::Handle<v8::Array> result =
    154       v8::Array::New(args.GetIsolate(), args.Length());
    155   for (int i = 0; i < args.Length(); i++)
    156     result->Set(v8::Integer::New(i), args[i]);
    157   args.GetReturnValue().Set(result);
    158 }
    159 
    160 
    161 static void SignatureCallback(
    162     const v8::FunctionCallbackInfo<v8::Value>& args) {
    163   ApiTestFuzzer::Fuzz();
    164   v8::Handle<v8::Array> result =
    165       v8::Array::New(args.GetIsolate(), args.Length());
    166   for (int i = 0; i < args.Length(); i++) {
    167     result->Set(v8::Integer::New(i), args[i]);
    168   }
    169   args.GetReturnValue().Set(result);
    170 }
    171 
    172 
    173 // Tests that call v8::V8::Dispose() cannot be threaded.
    174 TEST(InitializeAndDisposeOnce) {
    175   CHECK(v8::V8::Initialize());
    176   CHECK(v8::V8::Dispose());
    177 }
    178 
    179 
    180 // Tests that call v8::V8::Dispose() cannot be threaded.
    181 TEST(InitializeAndDisposeMultiple) {
    182   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    183   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
    184   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    185   // TODO(mstarzinger): This should fail gracefully instead of asserting.
    186   // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
    187   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    188 }
    189 
    190 
    191 THREADED_TEST(Handles) {
    192   v8::HandleScope scope(CcTest::isolate());
    193   Local<Context> local_env;
    194   {
    195     LocalContext env;
    196     local_env = env.local();
    197   }
    198 
    199   // Local context should still be live.
    200   CHECK(!local_env.IsEmpty());
    201   local_env->Enter();
    202 
    203   v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
    204   CHECK(!undef.IsEmpty());
    205   CHECK(undef->IsUndefined());
    206 
    207   const char* c_source = "1 + 2 + 3";
    208   Local<String> source = String::NewFromUtf8(CcTest::isolate(), c_source);
    209   Local<Script> script = Script::Compile(source);
    210   CHECK_EQ(6, script->Run()->Int32Value());
    211 
    212   local_env->Exit();
    213 }
    214 
    215 
    216 THREADED_TEST(IsolateOfContext) {
    217   v8::HandleScope scope(CcTest::isolate());
    218   v8::Handle<Context> env = Context::New(CcTest::isolate());
    219 
    220   CHECK(!env->GetIsolate()->InContext());
    221   CHECK(env->GetIsolate() == CcTest::isolate());
    222   env->Enter();
    223   CHECK(env->GetIsolate()->InContext());
    224   CHECK(env->GetIsolate() == CcTest::isolate());
    225   env->Exit();
    226   CHECK(!env->GetIsolate()->InContext());
    227   CHECK(env->GetIsolate() == CcTest::isolate());
    228 }
    229 
    230 
    231 static void TestSignature(const char* loop_js, Local<Value> receiver) {
    232   i::ScopedVector<char> source(200);
    233   i::OS::SNPrintF(source,
    234                   "for (var i = 0; i < 10; i++) {"
    235                   "  %s"
    236                   "}",
    237                   loop_js);
    238   signature_callback_count = 0;
    239   signature_expected_receiver = receiver;
    240   bool expected_to_throw = receiver.IsEmpty();
    241   v8::TryCatch try_catch;
    242   CompileRun(source.start());
    243   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
    244   if (!expected_to_throw) {
    245     CHECK_EQ(10, signature_callback_count);
    246   } else {
    247     CHECK_EQ(v8_str("TypeError: Illegal invocation"),
    248              try_catch.Exception()->ToString());
    249   }
    250 }
    251 
    252 
    253 THREADED_TEST(ReceiverSignature) {
    254   LocalContext env;
    255   v8::HandleScope scope(env->GetIsolate());
    256   // Setup templates.
    257   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
    258   v8::Handle<v8::Signature> sig = v8::Signature::New(env->GetIsolate(), fun);
    259   v8::Handle<v8::FunctionTemplate> callback_sig =
    260       v8::FunctionTemplate::New(
    261           IncrementingSignatureCallback, Local<Value>(), sig);
    262   v8::Handle<v8::FunctionTemplate> callback =
    263       v8::FunctionTemplate::New(IncrementingSignatureCallback);
    264   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
    265   sub_fun->Inherit(fun);
    266   v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
    267   // Install properties.
    268   v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
    269   fun_proto->Set(v8_str("prop_sig"), callback_sig);
    270   fun_proto->Set(v8_str("prop"), callback);
    271   fun_proto->SetAccessorProperty(
    272       v8_str("accessor_sig"), callback_sig, callback_sig);
    273   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
    274   // Instantiate templates.
    275   Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
    276   Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
    277   // Setup global variables.
    278   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
    279   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
    280   env->Global()->Set(v8_str("fun_instance"), fun_instance);
    281   env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
    282   CompileRun(
    283       "var accessor_sig_key = 'accessor_sig';"
    284       "var accessor_key = 'accessor';"
    285       "var prop_sig_key = 'prop_sig';"
    286       "var prop_key = 'prop';"
    287       ""
    288       "function copy_props(obj) {"
    289       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
    290       "  var source = Fun.prototype;"
    291       "  for (var i in keys) {"
    292       "    var key = keys[i];"
    293       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
    294       "    Object.defineProperty(obj, key, desc);"
    295       "  }"
    296       "}"
    297       ""
    298       "var obj = {};"
    299       "copy_props(obj);"
    300       "var unrel = new UnrelFun();"
    301       "copy_props(unrel);");
    302   // Test with and without ICs
    303   const char* test_objects[] = {
    304       "fun_instance", "sub_fun_instance", "obj", "unrel" };
    305   unsigned bad_signature_start_offset = 2;
    306   for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
    307     i::ScopedVector<char> source(200);
    308     i::OS::SNPrintF(
    309         source, "var test_object = %s; test_object", test_objects[i]);
    310     Local<Value> test_object = CompileRun(source.start());
    311     TestSignature("test_object.prop();", test_object);
    312     TestSignature("test_object.accessor;", test_object);
    313     TestSignature("test_object[accessor_key];", test_object);
    314     TestSignature("test_object.accessor = 1;", test_object);
    315     TestSignature("test_object[accessor_key] = 1;", test_object);
    316     if (i >= bad_signature_start_offset) test_object = Local<Value>();
    317     TestSignature("test_object.prop_sig();", test_object);
    318     TestSignature("test_object.accessor_sig;", test_object);
    319     TestSignature("test_object[accessor_sig_key];", test_object);
    320     TestSignature("test_object.accessor_sig = 1;", test_object);
    321     TestSignature("test_object[accessor_sig_key] = 1;", test_object);
    322   }
    323 }
    324 
    325 
    326 THREADED_TEST(ArgumentSignature) {
    327   LocalContext env;
    328   v8::HandleScope scope(env->GetIsolate());
    329   v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
    330   cons->SetClassName(v8_str("Cons"));
    331   v8::Handle<v8::Signature> sig = v8::Signature::New(
    332       env->GetIsolate(), v8::Handle<v8::FunctionTemplate>(), 1, &cons);
    333   v8::Handle<v8::FunctionTemplate> fun =
    334       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
    335   env->Global()->Set(v8_str("Cons"), cons->GetFunction());
    336   env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
    337 
    338   v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
    339   CHECK(value1->IsTrue());
    340 
    341   v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
    342   CHECK(value2->IsTrue());
    343 
    344   v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
    345   CHECK(value3->IsTrue());
    346 
    347   v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
    348   cons1->SetClassName(v8_str("Cons1"));
    349   v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
    350   cons2->SetClassName(v8_str("Cons2"));
    351   v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
    352   cons3->SetClassName(v8_str("Cons3"));
    353 
    354   v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
    355   v8::Handle<v8::Signature> wsig = v8::Signature::New(
    356       env->GetIsolate(), v8::Handle<v8::FunctionTemplate>(), 3, args);
    357   v8::Handle<v8::FunctionTemplate> fun2 =
    358       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
    359 
    360   env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
    361   env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
    362   env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
    363   env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
    364   v8::Handle<Value> value4 = CompileRun(
    365       "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
    366       "'[object Cons1],[object Cons2],[object Cons3]'");
    367   CHECK(value4->IsTrue());
    368 
    369   v8::Handle<Value> value5 = CompileRun(
    370       "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
    371   CHECK(value5->IsTrue());
    372 
    373   v8::Handle<Value> value6 = CompileRun(
    374       "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
    375   CHECK(value6->IsTrue());
    376 
    377   v8::Handle<Value> value7 = CompileRun(
    378       "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
    379       "'[object Cons1],[object Cons2],[object Cons3],d';");
    380   CHECK(value7->IsTrue());
    381 
    382   v8::Handle<Value> value8 = CompileRun(
    383       "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
    384   CHECK(value8->IsTrue());
    385 }
    386 
    387 
    388 THREADED_TEST(HulIgennem) {
    389   LocalContext env;
    390   v8::Isolate* isolate = env->GetIsolate();
    391   v8::HandleScope scope(isolate);
    392   v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
    393   Local<String> undef_str = undef->ToString();
    394   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
    395   undef_str->WriteUtf8(value);
    396   CHECK_EQ(0, strcmp(value, "undefined"));
    397   i::DeleteArray(value);
    398 }
    399 
    400 
    401 THREADED_TEST(Access) {
    402   LocalContext env;
    403   v8::Isolate* isolate = env->GetIsolate();
    404   v8::HandleScope scope(isolate);
    405   Local<v8::Object> obj = v8::Object::New();
    406   Local<Value> foo_before = obj->Get(v8_str("foo"));
    407   CHECK(foo_before->IsUndefined());
    408   Local<String> bar_str = v8_str("bar");
    409   obj->Set(v8_str("foo"), bar_str);
    410   Local<Value> foo_after = obj->Get(v8_str("foo"));
    411   CHECK(!foo_after->IsUndefined());
    412   CHECK(foo_after->IsString());
    413   CHECK_EQ(bar_str, foo_after);
    414 }
    415 
    416 
    417 THREADED_TEST(AccessElement) {
    418   LocalContext env;
    419   v8::HandleScope scope(env->GetIsolate());
    420   Local<v8::Object> obj = v8::Object::New();
    421   Local<Value> before = obj->Get(1);
    422   CHECK(before->IsUndefined());
    423   Local<String> bar_str = v8_str("bar");
    424   obj->Set(1, bar_str);
    425   Local<Value> after = obj->Get(1);
    426   CHECK(!after->IsUndefined());
    427   CHECK(after->IsString());
    428   CHECK_EQ(bar_str, after);
    429 
    430   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
    431   CHECK_EQ(v8_str("a"), value->Get(0));
    432   CHECK_EQ(v8_str("b"), value->Get(1));
    433 }
    434 
    435 
    436 THREADED_TEST(Script) {
    437   LocalContext env;
    438   v8::HandleScope scope(env->GetIsolate());
    439   const char* c_source = "1 + 2 + 3";
    440   Local<String> source = String::NewFromUtf8(env->GetIsolate(), c_source);
    441   Local<Script> script = Script::Compile(source);
    442   CHECK_EQ(6, script->Run()->Int32Value());
    443 }
    444 
    445 
    446 static uint16_t* AsciiToTwoByteString(const char* source) {
    447   int array_length = i::StrLength(source) + 1;
    448   uint16_t* converted = i::NewArray<uint16_t>(array_length);
    449   for (int i = 0; i < array_length; i++) converted[i] = source[i];
    450   return converted;
    451 }
    452 
    453 
    454 class TestResource: public String::ExternalStringResource {
    455  public:
    456   explicit TestResource(uint16_t* data, int* counter = NULL)
    457     : data_(data), length_(0), counter_(counter) {
    458     while (data[length_]) ++length_;
    459   }
    460 
    461   ~TestResource() {
    462     i::DeleteArray(data_);
    463     if (counter_ != NULL) ++*counter_;
    464   }
    465 
    466   const uint16_t* data() const {
    467     return data_;
    468   }
    469 
    470   size_t length() const {
    471     return length_;
    472   }
    473  private:
    474   uint16_t* data_;
    475   size_t length_;
    476   int* counter_;
    477 };
    478 
    479 
    480 class TestAsciiResource: public String::ExternalAsciiStringResource {
    481  public:
    482   explicit TestAsciiResource(const char* data, int* counter = NULL)
    483     : data_(data), length_(strlen(data)), counter_(counter) { }
    484 
    485   ~TestAsciiResource() {
    486     i::DeleteArray(data_);
    487     if (counter_ != NULL) ++*counter_;
    488   }
    489 
    490   const char* data() const {
    491     return data_;
    492   }
    493 
    494   size_t length() const {
    495     return length_;
    496   }
    497  private:
    498   const char* data_;
    499   size_t length_;
    500   int* counter_;
    501 };
    502 
    503 
    504 THREADED_TEST(ScriptUsingStringResource) {
    505   int dispose_count = 0;
    506   const char* c_source = "1 + 2 * 3";
    507   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
    508   {
    509     LocalContext env;
    510     v8::HandleScope scope(env->GetIsolate());
    511     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
    512     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
    513     Local<Script> script = Script::Compile(source);
    514     Local<Value> value = script->Run();
    515     CHECK(value->IsNumber());
    516     CHECK_EQ(7, value->Int32Value());
    517     CHECK(source->IsExternal());
    518     CHECK_EQ(resource,
    519              static_cast<TestResource*>(source->GetExternalStringResource()));
    520     String::Encoding encoding = String::UNKNOWN_ENCODING;
    521     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    522              source->GetExternalStringResourceBase(&encoding));
    523     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
    524     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    525     CHECK_EQ(0, dispose_count);
    526   }
    527   CcTest::i_isolate()->compilation_cache()->Clear();
    528   CcTest::heap()->CollectAllAvailableGarbage();
    529   CHECK_EQ(1, dispose_count);
    530 }
    531 
    532 
    533 THREADED_TEST(ScriptUsingAsciiStringResource) {
    534   int dispose_count = 0;
    535   const char* c_source = "1 + 2 * 3";
    536   {
    537     LocalContext env;
    538     v8::HandleScope scope(env->GetIsolate());
    539     TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
    540                                                         &dispose_count);
    541     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
    542     CHECK(source->IsExternalAscii());
    543     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    544              source->GetExternalAsciiStringResource());
    545     String::Encoding encoding = String::UNKNOWN_ENCODING;
    546     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    547              source->GetExternalStringResourceBase(&encoding));
    548     CHECK_EQ(String::ASCII_ENCODING, encoding);
    549     Local<Script> script = Script::Compile(source);
    550     Local<Value> value = script->Run();
    551     CHECK(value->IsNumber());
    552     CHECK_EQ(7, value->Int32Value());
    553     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    554     CHECK_EQ(0, dispose_count);
    555   }
    556   CcTest::i_isolate()->compilation_cache()->Clear();
    557   CcTest::heap()->CollectAllAvailableGarbage();
    558   CHECK_EQ(1, dispose_count);
    559 }
    560 
    561 
    562 THREADED_TEST(ScriptMakingExternalString) {
    563   int dispose_count = 0;
    564   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
    565   {
    566     LocalContext env;
    567     v8::HandleScope scope(env->GetIsolate());
    568     Local<String> source =
    569         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
    570     // Trigger GCs so that the newly allocated string moves to old gen.
    571     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    572     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    573     CHECK_EQ(source->IsExternal(), false);
    574     CHECK_EQ(source->IsExternalAscii(), false);
    575     String::Encoding encoding = String::UNKNOWN_ENCODING;
    576     CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
    577     CHECK_EQ(String::ASCII_ENCODING, encoding);
    578     bool success = source->MakeExternal(new TestResource(two_byte_source,
    579                                                          &dispose_count));
    580     CHECK(success);
    581     Local<Script> script = Script::Compile(source);
    582     Local<Value> value = script->Run();
    583     CHECK(value->IsNumber());
    584     CHECK_EQ(7, value->Int32Value());
    585     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    586     CHECK_EQ(0, dispose_count);
    587   }
    588   CcTest::i_isolate()->compilation_cache()->Clear();
    589   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    590   CHECK_EQ(1, dispose_count);
    591 }
    592 
    593 
    594 THREADED_TEST(ScriptMakingExternalAsciiString) {
    595   int dispose_count = 0;
    596   const char* c_source = "1 + 2 * 3";
    597   {
    598     LocalContext env;
    599     v8::HandleScope scope(env->GetIsolate());
    600     Local<String> source = v8_str(c_source);
    601     // Trigger GCs so that the newly allocated string moves to old gen.
    602     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    603     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    604     bool success = source->MakeExternal(
    605         new TestAsciiResource(i::StrDup(c_source), &dispose_count));
    606     CHECK(success);
    607     Local<Script> script = Script::Compile(source);
    608     Local<Value> value = script->Run();
    609     CHECK(value->IsNumber());
    610     CHECK_EQ(7, value->Int32Value());
    611     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    612     CHECK_EQ(0, dispose_count);
    613   }
    614   CcTest::i_isolate()->compilation_cache()->Clear();
    615   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    616   CHECK_EQ(1, dispose_count);
    617 }
    618 
    619 
    620 TEST(MakingExternalStringConditions) {
    621   LocalContext env;
    622   v8::HandleScope scope(env->GetIsolate());
    623 
    624   // Free some space in the new space so that we can check freshness.
    625   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    626   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    627 
    628   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
    629   Local<String> small_string =
    630       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
    631   i::DeleteArray(two_byte_string);
    632 
    633   // We should refuse to externalize newly created small string.
    634   CHECK(!small_string->CanMakeExternal());
    635   // Trigger GCs so that the newly allocated string moves to old gen.
    636   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    637   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    638   // Old space strings should be accepted.
    639   CHECK(small_string->CanMakeExternal());
    640 
    641   two_byte_string = AsciiToTwoByteString("small string 2");
    642   small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
    643   i::DeleteArray(two_byte_string);
    644 
    645   // We should refuse externalizing newly created small string.
    646   CHECK(!small_string->CanMakeExternal());
    647   for (int i = 0; i < 100; i++) {
    648     String::Value value(small_string);
    649   }
    650   // Frequently used strings should be accepted.
    651   CHECK(small_string->CanMakeExternal());
    652 
    653   const int buf_size = 10 * 1024;
    654   char* buf = i::NewArray<char>(buf_size);
    655   memset(buf, 'a', buf_size);
    656   buf[buf_size - 1] = '\0';
    657 
    658   two_byte_string = AsciiToTwoByteString(buf);
    659   Local<String> large_string =
    660       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
    661   i::DeleteArray(buf);
    662   i::DeleteArray(two_byte_string);
    663   // Large strings should be immediately accepted.
    664   CHECK(large_string->CanMakeExternal());
    665 }
    666 
    667 
    668 TEST(MakingExternalAsciiStringConditions) {
    669   LocalContext env;
    670   v8::HandleScope scope(env->GetIsolate());
    671 
    672   // Free some space in the new space so that we can check freshness.
    673   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    674   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    675 
    676   Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
    677   // We should refuse to externalize newly created small string.
    678   CHECK(!small_string->CanMakeExternal());
    679   // Trigger GCs so that the newly allocated string moves to old gen.
    680   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    681   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    682   // Old space strings should be accepted.
    683   CHECK(small_string->CanMakeExternal());
    684 
    685   small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
    686   // We should refuse externalizing newly created small string.
    687   CHECK(!small_string->CanMakeExternal());
    688   for (int i = 0; i < 100; i++) {
    689     String::Value value(small_string);
    690   }
    691   // Frequently used strings should be accepted.
    692   CHECK(small_string->CanMakeExternal());
    693 
    694   const int buf_size = 10 * 1024;
    695   char* buf = i::NewArray<char>(buf_size);
    696   memset(buf, 'a', buf_size);
    697   buf[buf_size - 1] = '\0';
    698   Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
    699   i::DeleteArray(buf);
    700   // Large strings should be immediately accepted.
    701   CHECK(large_string->CanMakeExternal());
    702 }
    703 
    704 
    705 TEST(MakingExternalUnalignedAsciiString) {
    706   LocalContext env;
    707   v8::HandleScope scope(env->GetIsolate());
    708 
    709   CompileRun("function cons(a, b) { return a + b; }"
    710              "function slice(a) { return a.substring(1); }");
    711   // Create a cons string that will land in old pointer space.
    712   Local<String> cons = Local<String>::Cast(CompileRun(
    713       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
    714   // Create a sliced string that will land in old pointer space.
    715   Local<String> slice = Local<String>::Cast(CompileRun(
    716       "slice('abcdefghijklmnopqrstuvwxyz');"));
    717 
    718   // Trigger GCs so that the newly allocated string moves to old gen.
    719   SimulateFullSpace(CcTest::heap()->old_pointer_space());
    720   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    721   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    722 
    723   // Turn into external string with unaligned resource data.
    724   int dispose_count = 0;
    725   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
    726   bool success = cons->MakeExternal(
    727       new TestAsciiResource(i::StrDup(c_cons) + 1, &dispose_count));
    728   CHECK(success);
    729   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
    730   success = slice->MakeExternal(
    731       new TestAsciiResource(i::StrDup(c_slice) + 1, &dispose_count));
    732   CHECK(success);
    733 
    734   // Trigger GCs and force evacuation.
    735   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    736   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
    737 }
    738 
    739 
    740 THREADED_TEST(UsingExternalString) {
    741   i::Factory* factory = CcTest::i_isolate()->factory();
    742   {
    743     v8::HandleScope scope(CcTest::isolate());
    744     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    745     Local<String> string = String::NewExternal(
    746         CcTest::isolate(), new TestResource(two_byte_string));
    747     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    748     // Trigger GCs so that the newly allocated string moves to old gen.
    749     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    750     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    751     i::Handle<i::String> isymbol =
    752         factory->InternalizedStringFromString(istring);
    753     CHECK(isymbol->IsInternalizedString());
    754   }
    755   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    756   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    757 }
    758 
    759 
    760 THREADED_TEST(UsingExternalAsciiString) {
    761   i::Factory* factory = CcTest::i_isolate()->factory();
    762   {
    763     v8::HandleScope scope(CcTest::isolate());
    764     const char* one_byte_string = "test string";
    765     Local<String> string = String::NewExternal(
    766         CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string)));
    767     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    768     // Trigger GCs so that the newly allocated string moves to old gen.
    769     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    770     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    771     i::Handle<i::String> isymbol =
    772         factory->InternalizedStringFromString(istring);
    773     CHECK(isymbol->IsInternalizedString());
    774   }
    775   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    776   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    777 }
    778 
    779 
    780 THREADED_TEST(ScavengeExternalString) {
    781   i::FLAG_stress_compaction = false;
    782   i::FLAG_gc_global = false;
    783   int dispose_count = 0;
    784   bool in_new_space = false;
    785   {
    786     v8::HandleScope scope(CcTest::isolate());
    787     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    788     Local<String> string = String::NewExternal(
    789         CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
    790     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    791     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    792     in_new_space = CcTest::heap()->InNewSpace(*istring);
    793     CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
    794     CHECK_EQ(0, dispose_count);
    795   }
    796   CcTest::heap()->CollectGarbage(
    797       in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    798   CHECK_EQ(1, dispose_count);
    799 }
    800 
    801 
    802 THREADED_TEST(ScavengeExternalAsciiString) {
    803   i::FLAG_stress_compaction = false;
    804   i::FLAG_gc_global = false;
    805   int dispose_count = 0;
    806   bool in_new_space = false;
    807   {
    808     v8::HandleScope scope(CcTest::isolate());
    809     const char* one_byte_string = "test string";
    810     Local<String> string = String::NewExternal(
    811         CcTest::isolate(),
    812         new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
    813     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    814     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    815     in_new_space = CcTest::heap()->InNewSpace(*istring);
    816     CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
    817     CHECK_EQ(0, dispose_count);
    818   }
    819   CcTest::heap()->CollectGarbage(
    820       in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    821   CHECK_EQ(1, dispose_count);
    822 }
    823 
    824 
    825 class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
    826  public:
    827   // Only used by non-threaded tests, so it can use static fields.
    828   static int dispose_calls;
    829   static int dispose_count;
    830 
    831   TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
    832       : TestAsciiResource(data, &dispose_count),
    833         dispose_(dispose) { }
    834 
    835   void Dispose() {
    836     ++dispose_calls;
    837     if (dispose_) delete this;
    838   }
    839  private:
    840   bool dispose_;
    841 };
    842 
    843 
    844 int TestAsciiResourceWithDisposeControl::dispose_count = 0;
    845 int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    846 
    847 
    848 TEST(ExternalStringWithDisposeHandling) {
    849   const char* c_source = "1 + 2 * 3";
    850 
    851   // Use a stack allocated external string resource allocated object.
    852   TestAsciiResourceWithDisposeControl::dispose_count = 0;
    853   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    854   TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
    855   {
    856     LocalContext env;
    857     v8::HandleScope scope(env->GetIsolate());
    858     Local<String> source =  String::NewExternal(env->GetIsolate(), &res_stack);
    859     Local<Script> script = Script::Compile(source);
    860     Local<Value> value = script->Run();
    861     CHECK(value->IsNumber());
    862     CHECK_EQ(7, value->Int32Value());
    863     CcTest::heap()->CollectAllAvailableGarbage();
    864     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    865   }
    866   CcTest::i_isolate()->compilation_cache()->Clear();
    867   CcTest::heap()->CollectAllAvailableGarbage();
    868   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
    869   CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    870 
    871   // Use a heap allocated external string resource allocated object.
    872   TestAsciiResourceWithDisposeControl::dispose_count = 0;
    873   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    874   TestAsciiResource* res_heap =
    875       new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
    876   {
    877     LocalContext env;
    878     v8::HandleScope scope(env->GetIsolate());
    879     Local<String> source =  String::NewExternal(env->GetIsolate(), res_heap);
    880     Local<Script> script = Script::Compile(source);
    881     Local<Value> value = script->Run();
    882     CHECK(value->IsNumber());
    883     CHECK_EQ(7, value->Int32Value());
    884     CcTest::heap()->CollectAllAvailableGarbage();
    885     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    886   }
    887   CcTest::i_isolate()->compilation_cache()->Clear();
    888   CcTest::heap()->CollectAllAvailableGarbage();
    889   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
    890   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
    891 }
    892 
    893 
    894 THREADED_TEST(StringConcat) {
    895   {
    896     LocalContext env;
    897     v8::HandleScope scope(env->GetIsolate());
    898     const char* one_byte_string_1 = "function a_times_t";
    899     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
    900     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
    901     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
    902     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    903     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    904     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
    905     Local<String> left = v8_str(one_byte_string_1);
    906 
    907     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
    908     Local<String> right =
    909         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
    910     i::DeleteArray(two_byte_source);
    911 
    912     Local<String> source = String::Concat(left, right);
    913     right = String::NewExternal(
    914         env->GetIsolate(), new TestAsciiResource(i::StrDup(one_byte_extern_1)));
    915     source = String::Concat(source, right);
    916     right = String::NewExternal(
    917         env->GetIsolate(),
    918         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
    919     source = String::Concat(source, right);
    920     right = v8_str(one_byte_string_2);
    921     source = String::Concat(source, right);
    922 
    923     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
    924     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
    925     i::DeleteArray(two_byte_source);
    926 
    927     source = String::Concat(source, right);
    928     right = String::NewExternal(
    929         env->GetIsolate(),
    930         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
    931     source = String::Concat(source, right);
    932     Local<Script> script = Script::Compile(source);
    933     Local<Value> value = script->Run();
    934     CHECK(value->IsNumber());
    935     CHECK_EQ(68, value->Int32Value());
    936   }
    937   CcTest::i_isolate()->compilation_cache()->Clear();
    938   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    939   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    940 }
    941 
    942 
    943 THREADED_TEST(GlobalProperties) {
    944   LocalContext env;
    945   v8::HandleScope scope(env->GetIsolate());
    946   v8::Handle<v8::Object> global = env->Global();
    947   global->Set(v8_str("pi"), v8_num(3.1415926));
    948   Local<Value> pi = global->Get(v8_str("pi"));
    949   CHECK_EQ(3.1415926, pi->NumberValue());
    950 }
    951 
    952 
    953 template<typename T>
    954 static void CheckReturnValue(const T& t, i::Address callback) {
    955   v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
    956   i::Object** o = *reinterpret_cast<i::Object***>(&rv);
    957   CHECK_EQ(CcTest::isolate(), t.GetIsolate());
    958   CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
    959   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
    960   // Verify reset
    961   bool is_runtime = (*o)->IsTheHole();
    962   rv.Set(true);
    963   CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
    964   rv.Set(v8::Handle<v8::Object>());
    965   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
    966   CHECK_EQ(is_runtime, (*o)->IsTheHole());
    967 
    968   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
    969   // If CPU profiler is active check that when API callback is invoked
    970   // VMState is set to EXTERNAL.
    971   if (isolate->cpu_profiler()->is_profiling()) {
    972     CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
    973     CHECK(isolate->external_callback_scope());
    974     CHECK_EQ(callback, isolate->external_callback_scope()->callback());
    975   }
    976 }
    977 
    978 
    979 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
    980                                  i::Address callback) {
    981   ApiTestFuzzer::Fuzz();
    982   CheckReturnValue(info, callback);
    983   info.GetReturnValue().Set(v8_str("bad value"));
    984   info.GetReturnValue().Set(v8_num(102));
    985 }
    986 
    987 
    988 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
    989   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
    990 }
    991 
    992 
    993 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
    994   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
    995 }
    996 
    997 static void construct_callback(
    998     const v8::FunctionCallbackInfo<Value>& info) {
    999   ApiTestFuzzer::Fuzz();
   1000   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
   1001   info.This()->Set(v8_str("x"), v8_num(1));
   1002   info.This()->Set(v8_str("y"), v8_num(2));
   1003   info.GetReturnValue().Set(v8_str("bad value"));
   1004   info.GetReturnValue().Set(info.This());
   1005 }
   1006 
   1007 
   1008 static void Return239Callback(
   1009     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
   1010   ApiTestFuzzer::Fuzz();
   1011   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
   1012   info.GetReturnValue().Set(v8_str("bad value"));
   1013   info.GetReturnValue().Set(v8_num(239));
   1014 }
   1015 
   1016 
   1017 template<typename Handler>
   1018 static void TestFunctionTemplateInitializer(Handler handler,
   1019                                             Handler handler_2) {
   1020   // Test constructor calls.
   1021   {
   1022     LocalContext env;
   1023     v8::HandleScope scope(env->GetIsolate());
   1024 
   1025     Local<v8::FunctionTemplate> fun_templ =
   1026         v8::FunctionTemplate::New(handler);
   1027     Local<Function> fun = fun_templ->GetFunction();
   1028     env->Global()->Set(v8_str("obj"), fun);
   1029     Local<Script> script = v8_compile("obj()");
   1030     for (int i = 0; i < 30; i++) {
   1031       CHECK_EQ(102, script->Run()->Int32Value());
   1032     }
   1033   }
   1034   // Use SetCallHandler to initialize a function template, should work like
   1035   // the previous one.
   1036   {
   1037     LocalContext env;
   1038     v8::HandleScope scope(env->GetIsolate());
   1039 
   1040     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   1041     fun_templ->SetCallHandler(handler_2);
   1042     Local<Function> fun = fun_templ->GetFunction();
   1043     env->Global()->Set(v8_str("obj"), fun);
   1044     Local<Script> script = v8_compile("obj()");
   1045     for (int i = 0; i < 30; i++) {
   1046       CHECK_EQ(102, script->Run()->Int32Value());
   1047     }
   1048   }
   1049 }
   1050 
   1051 
   1052 template<typename Constructor, typename Accessor>
   1053 static void TestFunctionTemplateAccessor(Constructor constructor,
   1054                                          Accessor accessor) {
   1055   LocalContext env;
   1056   v8::HandleScope scope(env->GetIsolate());
   1057 
   1058   Local<v8::FunctionTemplate> fun_templ =
   1059       v8::FunctionTemplate::New(constructor);
   1060   fun_templ->SetClassName(v8_str("funky"));
   1061   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
   1062   Local<Function> fun = fun_templ->GetFunction();
   1063   env->Global()->Set(v8_str("obj"), fun);
   1064   Local<Value> result = v8_compile("(new obj()).toString()")->Run();
   1065   CHECK_EQ(v8_str("[object funky]"), result);
   1066   CompileRun("var obj_instance = new obj();");
   1067   Local<Script> script;
   1068   script = v8_compile("obj_instance.x");
   1069   for (int i = 0; i < 30; i++) {
   1070     CHECK_EQ(1, script->Run()->Int32Value());
   1071   }
   1072   script = v8_compile("obj_instance.m");
   1073   for (int i = 0; i < 30; i++) {
   1074     CHECK_EQ(239, script->Run()->Int32Value());
   1075   }
   1076 }
   1077 
   1078 
   1079 THREADED_PROFILED_TEST(FunctionTemplate) {
   1080   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
   1081   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
   1082 }
   1083 
   1084 
   1085 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   1086   ApiTestFuzzer::Fuzz();
   1087   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
   1088   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
   1089 }
   1090 
   1091 
   1092 template<typename Callback>
   1093 static void TestSimpleCallback(Callback callback) {
   1094   LocalContext env;
   1095   v8::HandleScope scope(env->GetIsolate());
   1096 
   1097   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   1098   object_template->Set(env->GetIsolate(), "callback",
   1099                        v8::FunctionTemplate::New(callback));
   1100   v8::Local<v8::Object> object = object_template->NewInstance();
   1101   (*env)->Global()->Set(v8_str("callback_object"), object);
   1102   v8::Handle<v8::Script> script;
   1103   script = v8_compile("callback_object.callback(17)");
   1104   for (int i = 0; i < 30; i++) {
   1105     CHECK_EQ(51424, script->Run()->Int32Value());
   1106   }
   1107   script = v8_compile("callback_object.callback(17, 24)");
   1108   for (int i = 0; i < 30; i++) {
   1109     CHECK_EQ(51425, script->Run()->Int32Value());
   1110   }
   1111 }
   1112 
   1113 
   1114 THREADED_PROFILED_TEST(SimpleCallback) {
   1115   TestSimpleCallback(SimpleCallback);
   1116 }
   1117 
   1118 
   1119 template<typename T>
   1120 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
   1121 
   1122 // constant return values
   1123 static int32_t fast_return_value_int32 = 471;
   1124 static uint32_t fast_return_value_uint32 = 571;
   1125 static const double kFastReturnValueDouble = 2.7;
   1126 // variable return values
   1127 static bool fast_return_value_bool = false;
   1128 enum ReturnValueOddball {
   1129   kNullReturnValue,
   1130   kUndefinedReturnValue,
   1131   kEmptyStringReturnValue
   1132 };
   1133 static ReturnValueOddball fast_return_value_void;
   1134 static bool fast_return_value_object_is_empty = false;
   1135 
   1136 // Helper function to avoid compiler error: insufficient contextual information
   1137 // to determine type when applying FUNCTION_ADDR to a template function.
   1138 static i::Address address_of(v8::FunctionCallback callback) {
   1139   return FUNCTION_ADDR(callback);
   1140 }
   1141 
   1142 template<>
   1143 void FastReturnValueCallback<int32_t>(
   1144     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1145   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
   1146   info.GetReturnValue().Set(fast_return_value_int32);
   1147 }
   1148 
   1149 template<>
   1150 void FastReturnValueCallback<uint32_t>(
   1151     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1152   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
   1153   info.GetReturnValue().Set(fast_return_value_uint32);
   1154 }
   1155 
   1156 template<>
   1157 void FastReturnValueCallback<double>(
   1158     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1159   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
   1160   info.GetReturnValue().Set(kFastReturnValueDouble);
   1161 }
   1162 
   1163 template<>
   1164 void FastReturnValueCallback<bool>(
   1165     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1166   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
   1167   info.GetReturnValue().Set(fast_return_value_bool);
   1168 }
   1169 
   1170 template<>
   1171 void FastReturnValueCallback<void>(
   1172     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1173   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
   1174   switch (fast_return_value_void) {
   1175     case kNullReturnValue:
   1176       info.GetReturnValue().SetNull();
   1177       break;
   1178     case kUndefinedReturnValue:
   1179       info.GetReturnValue().SetUndefined();
   1180       break;
   1181     case kEmptyStringReturnValue:
   1182       info.GetReturnValue().SetEmptyString();
   1183       break;
   1184   }
   1185 }
   1186 
   1187 template<>
   1188 void FastReturnValueCallback<Object>(
   1189     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1190   v8::Handle<v8::Object> object;
   1191   if (!fast_return_value_object_is_empty) object = Object::New();
   1192   info.GetReturnValue().Set(object);
   1193 }
   1194 
   1195 template<typename T>
   1196 Handle<Value> TestFastReturnValues() {
   1197   LocalContext env;
   1198   v8::HandleScope scope(env->GetIsolate());
   1199   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   1200   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
   1201   object_template->Set(env->GetIsolate(), "callback",
   1202                        v8::FunctionTemplate::New(callback));
   1203   v8::Local<v8::Object> object = object_template->NewInstance();
   1204   (*env)->Global()->Set(v8_str("callback_object"), object);
   1205   return scope.Close(CompileRun("callback_object.callback()"));
   1206 }
   1207 
   1208 
   1209 THREADED_PROFILED_TEST(FastReturnValues) {
   1210   LocalContext env;
   1211   v8::HandleScope scope(CcTest::isolate());
   1212   v8::Handle<v8::Value> value;
   1213   // check int32_t and uint32_t
   1214   int32_t int_values[] = {
   1215       0, 234, -723,
   1216       i::Smi::kMinValue, i::Smi::kMaxValue
   1217   };
   1218   for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
   1219     for (int modifier = -1; modifier <= 1; modifier++) {
   1220       int int_value = int_values[i] + modifier;
   1221       // check int32_t
   1222       fast_return_value_int32 = int_value;
   1223       value = TestFastReturnValues<int32_t>();
   1224       CHECK(value->IsInt32());
   1225       CHECK(fast_return_value_int32 == value->Int32Value());
   1226       // check uint32_t
   1227       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
   1228       value = TestFastReturnValues<uint32_t>();
   1229       CHECK(value->IsUint32());
   1230       CHECK(fast_return_value_uint32 == value->Uint32Value());
   1231     }
   1232   }
   1233   // check double
   1234   value = TestFastReturnValues<double>();
   1235   CHECK(value->IsNumber());
   1236   CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
   1237   // check bool values
   1238   for (int i = 0; i < 2; i++) {
   1239     fast_return_value_bool = i == 0;
   1240     value = TestFastReturnValues<bool>();
   1241     CHECK(value->IsBoolean());
   1242     CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
   1243   }
   1244   // check oddballs
   1245   ReturnValueOddball oddballs[] = {
   1246       kNullReturnValue,
   1247       kUndefinedReturnValue,
   1248       kEmptyStringReturnValue
   1249   };
   1250   for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
   1251     fast_return_value_void = oddballs[i];
   1252     value = TestFastReturnValues<void>();
   1253     switch (fast_return_value_void) {
   1254       case kNullReturnValue:
   1255         CHECK(value->IsNull());
   1256         break;
   1257       case kUndefinedReturnValue:
   1258         CHECK(value->IsUndefined());
   1259         break;
   1260       case kEmptyStringReturnValue:
   1261         CHECK(value->IsString());
   1262         CHECK_EQ(0, v8::String::Cast(*value)->Length());
   1263         break;
   1264     }
   1265   }
   1266   // check handles
   1267   fast_return_value_object_is_empty = false;
   1268   value = TestFastReturnValues<Object>();
   1269   CHECK(value->IsObject());
   1270   fast_return_value_object_is_empty = true;
   1271   value = TestFastReturnValues<Object>();
   1272   CHECK(value->IsUndefined());
   1273 }
   1274 
   1275 
   1276 THREADED_TEST(FunctionTemplateSetLength) {
   1277   LocalContext env;
   1278   v8::HandleScope scope(env->GetIsolate());
   1279   {
   1280     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(
   1281         handle_callback, Handle<v8::Value>(), Handle<v8::Signature>(), 23);
   1282     Local<Function> fun = fun_templ->GetFunction();
   1283     env->Global()->Set(v8_str("obj"), fun);
   1284     Local<Script> script = v8_compile("obj.length");
   1285     CHECK_EQ(23, script->Run()->Int32Value());
   1286   }
   1287   {
   1288     Local<v8::FunctionTemplate> fun_templ =
   1289         v8::FunctionTemplate::New(handle_callback);
   1290     fun_templ->SetLength(22);
   1291     Local<Function> fun = fun_templ->GetFunction();
   1292     env->Global()->Set(v8_str("obj"), fun);
   1293     Local<Script> script = v8_compile("obj.length");
   1294     CHECK_EQ(22, script->Run()->Int32Value());
   1295   }
   1296   {
   1297     // Without setting length it defaults to 0.
   1298     Local<v8::FunctionTemplate> fun_templ =
   1299         v8::FunctionTemplate::New(handle_callback);
   1300     Local<Function> fun = fun_templ->GetFunction();
   1301     env->Global()->Set(v8_str("obj"), fun);
   1302     Local<Script> script = v8_compile("obj.length");
   1303     CHECK_EQ(0, script->Run()->Int32Value());
   1304   }
   1305 }
   1306 
   1307 
   1308 static void* expected_ptr;
   1309 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1310   void* ptr = v8::External::Cast(*args.Data())->Value();
   1311   CHECK_EQ(expected_ptr, ptr);
   1312   args.GetReturnValue().Set(true);
   1313 }
   1314 
   1315 
   1316 static void TestExternalPointerWrapping() {
   1317   LocalContext env;
   1318   v8::HandleScope scope(env->GetIsolate());
   1319 
   1320   v8::Handle<v8::Value> data =
   1321       v8::External::New(env->GetIsolate(), expected_ptr);
   1322 
   1323   v8::Handle<v8::Object> obj = v8::Object::New();
   1324   obj->Set(v8_str("func"),
   1325            v8::FunctionTemplate::New(callback, data)->GetFunction());
   1326   env->Global()->Set(v8_str("obj"), obj);
   1327 
   1328   CHECK(CompileRun(
   1329         "function foo() {\n"
   1330         "  for (var i = 0; i < 13; i++) obj.func();\n"
   1331         "}\n"
   1332         "foo(), true")->BooleanValue());
   1333 }
   1334 
   1335 
   1336 THREADED_TEST(ExternalWrap) {
   1337   // Check heap allocated object.
   1338   int* ptr = new int;
   1339   expected_ptr = ptr;
   1340   TestExternalPointerWrapping();
   1341   delete ptr;
   1342 
   1343   // Check stack allocated object.
   1344   int foo;
   1345   expected_ptr = &foo;
   1346   TestExternalPointerWrapping();
   1347 
   1348   // Check not aligned addresses.
   1349   const int n = 100;
   1350   char* s = new char[n];
   1351   for (int i = 0; i < n; i++) {
   1352     expected_ptr = s + i;
   1353     TestExternalPointerWrapping();
   1354   }
   1355 
   1356   delete[] s;
   1357 
   1358   // Check several invalid addresses.
   1359   expected_ptr = reinterpret_cast<void*>(1);
   1360   TestExternalPointerWrapping();
   1361 
   1362   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
   1363   TestExternalPointerWrapping();
   1364 
   1365   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
   1366   TestExternalPointerWrapping();
   1367 
   1368 #if defined(V8_HOST_ARCH_X64)
   1369   // Check a value with a leading 1 bit in x64 Smi encoding.
   1370   expected_ptr = reinterpret_cast<void*>(0x400000000);
   1371   TestExternalPointerWrapping();
   1372 
   1373   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
   1374   TestExternalPointerWrapping();
   1375 
   1376   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
   1377   TestExternalPointerWrapping();
   1378 #endif
   1379 }
   1380 
   1381 
   1382 THREADED_TEST(FindInstanceInPrototypeChain) {
   1383   LocalContext env;
   1384   v8::HandleScope scope(env->GetIsolate());
   1385 
   1386   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
   1387   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
   1388   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
   1389   derived->Inherit(base);
   1390 
   1391   Local<v8::Function> base_function = base->GetFunction();
   1392   Local<v8::Function> derived_function = derived->GetFunction();
   1393   Local<v8::Function> other_function = other->GetFunction();
   1394 
   1395   Local<v8::Object> base_instance = base_function->NewInstance();
   1396   Local<v8::Object> derived_instance = derived_function->NewInstance();
   1397   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
   1398   Local<v8::Object> other_instance = other_function->NewInstance();
   1399   derived_instance2->Set(v8_str("__proto__"), derived_instance);
   1400   other_instance->Set(v8_str("__proto__"), derived_instance2);
   1401 
   1402   // base_instance is only an instance of base.
   1403   CHECK_EQ(base_instance,
   1404            base_instance->FindInstanceInPrototypeChain(base));
   1405   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
   1406   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1407 
   1408   // derived_instance is an instance of base and derived.
   1409   CHECK_EQ(derived_instance,
   1410            derived_instance->FindInstanceInPrototypeChain(base));
   1411   CHECK_EQ(derived_instance,
   1412            derived_instance->FindInstanceInPrototypeChain(derived));
   1413   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1414 
   1415   // other_instance is an instance of other and its immediate
   1416   // prototype derived_instance2 is an instance of base and derived.
   1417   // Note, derived_instance is an instance of base and derived too,
   1418   // but it comes after derived_instance2 in the prototype chain of
   1419   // other_instance.
   1420   CHECK_EQ(derived_instance2,
   1421            other_instance->FindInstanceInPrototypeChain(base));
   1422   CHECK_EQ(derived_instance2,
   1423            other_instance->FindInstanceInPrototypeChain(derived));
   1424   CHECK_EQ(other_instance,
   1425            other_instance->FindInstanceInPrototypeChain(other));
   1426 }
   1427 
   1428 
   1429 THREADED_TEST(TinyInteger) {
   1430   LocalContext env;
   1431   v8::HandleScope scope(env->GetIsolate());
   1432   v8::Isolate* isolate = CcTest::isolate();
   1433 
   1434   int32_t value = 239;
   1435   Local<v8::Integer> value_obj = v8::Integer::New(value);
   1436   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1437 
   1438   value_obj = v8::Integer::New(value, isolate);
   1439   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1440 }
   1441 
   1442 
   1443 THREADED_TEST(BigSmiInteger) {
   1444   LocalContext env;
   1445   v8::HandleScope scope(env->GetIsolate());
   1446   v8::Isolate* isolate = CcTest::isolate();
   1447 
   1448   int32_t value = i::Smi::kMaxValue;
   1449   // We cannot add one to a Smi::kMaxValue without wrapping.
   1450   if (i::SmiValuesAre31Bits()) {
   1451     CHECK(i::Smi::IsValid(value));
   1452     CHECK(!i::Smi::IsValid(value + 1));
   1453 
   1454     Local<v8::Integer> value_obj = v8::Integer::New(value);
   1455     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1456 
   1457     value_obj = v8::Integer::New(value, isolate);
   1458     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1459   }
   1460 }
   1461 
   1462 
   1463 THREADED_TEST(BigInteger) {
   1464   LocalContext env;
   1465   v8::HandleScope scope(env->GetIsolate());
   1466   v8::Isolate* isolate = CcTest::isolate();
   1467 
   1468   // We cannot add one to a Smi::kMaxValue without wrapping.
   1469   if (i::SmiValuesAre31Bits()) {
   1470     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
   1471     // The code will not be run in that case, due to the "if" guard.
   1472     int32_t value =
   1473         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
   1474     CHECK(value > i::Smi::kMaxValue);
   1475     CHECK(!i::Smi::IsValid(value));
   1476 
   1477     Local<v8::Integer> value_obj = v8::Integer::New(value);
   1478     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1479 
   1480     value_obj = v8::Integer::New(value, isolate);
   1481     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1482   }
   1483 }
   1484 
   1485 
   1486 THREADED_TEST(TinyUnsignedInteger) {
   1487   LocalContext env;
   1488   v8::HandleScope scope(env->GetIsolate());
   1489   v8::Isolate* isolate = CcTest::isolate();
   1490 
   1491   uint32_t value = 239;
   1492 
   1493   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1494   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1495 
   1496   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
   1497   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1498 }
   1499 
   1500 
   1501 THREADED_TEST(BigUnsignedSmiInteger) {
   1502   LocalContext env;
   1503   v8::HandleScope scope(env->GetIsolate());
   1504   v8::Isolate* isolate = CcTest::isolate();
   1505 
   1506   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
   1507   CHECK(i::Smi::IsValid(value));
   1508   CHECK(!i::Smi::IsValid(value + 1));
   1509 
   1510   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1511   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1512 
   1513   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
   1514   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1515 }
   1516 
   1517 
   1518 THREADED_TEST(BigUnsignedInteger) {
   1519   LocalContext env;
   1520   v8::HandleScope scope(env->GetIsolate());
   1521   v8::Isolate* isolate = CcTest::isolate();
   1522 
   1523   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
   1524   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
   1525   CHECK(!i::Smi::IsValid(value));
   1526 
   1527   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1528   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1529 
   1530   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
   1531   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1532 }
   1533 
   1534 
   1535 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
   1536   LocalContext env;
   1537   v8::HandleScope scope(env->GetIsolate());
   1538   v8::Isolate* isolate = CcTest::isolate();
   1539 
   1540   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
   1541   uint32_t value = INT32_MAX_AS_UINT + 1;
   1542   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
   1543 
   1544   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1545   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1546 
   1547   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
   1548   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1549 }
   1550 
   1551 
   1552 THREADED_TEST(IsNativeError) {
   1553   LocalContext env;
   1554   v8::HandleScope scope(env->GetIsolate());
   1555   v8::Handle<Value> syntax_error = CompileRun(
   1556       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
   1557   CHECK(syntax_error->IsNativeError());
   1558   v8::Handle<Value> not_error = CompileRun("{a:42}");
   1559   CHECK(!not_error->IsNativeError());
   1560   v8::Handle<Value> not_object = CompileRun("42");
   1561   CHECK(!not_object->IsNativeError());
   1562 }
   1563 
   1564 
   1565 THREADED_TEST(StringObject) {
   1566   LocalContext env;
   1567   v8::HandleScope scope(env->GetIsolate());
   1568   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
   1569   CHECK(boxed_string->IsStringObject());
   1570   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
   1571   CHECK(!unboxed_string->IsStringObject());
   1572   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
   1573   CHECK(!boxed_not_string->IsStringObject());
   1574   v8::Handle<Value> not_object = CompileRun("0");
   1575   CHECK(!not_object->IsStringObject());
   1576   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
   1577   CHECK(!as_boxed.IsEmpty());
   1578   Local<v8::String> the_string = as_boxed->ValueOf();
   1579   CHECK(!the_string.IsEmpty());
   1580   ExpectObject("\"test\"", the_string);
   1581   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
   1582   CHECK(new_boxed_string->IsStringObject());
   1583   as_boxed = new_boxed_string.As<v8::StringObject>();
   1584   the_string = as_boxed->ValueOf();
   1585   CHECK(!the_string.IsEmpty());
   1586   ExpectObject("\"test\"", the_string);
   1587 }
   1588 
   1589 
   1590 THREADED_TEST(NumberObject) {
   1591   LocalContext env;
   1592   v8::HandleScope scope(env->GetIsolate());
   1593   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
   1594   CHECK(boxed_number->IsNumberObject());
   1595   v8::Handle<Value> unboxed_number = CompileRun("42");
   1596   CHECK(!unboxed_number->IsNumberObject());
   1597   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
   1598   CHECK(!boxed_not_number->IsNumberObject());
   1599   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
   1600   CHECK(!as_boxed.IsEmpty());
   1601   double the_number = as_boxed->ValueOf();
   1602   CHECK_EQ(42.0, the_number);
   1603   v8::Handle<v8::Value> new_boxed_number =
   1604       v8::NumberObject::New(env->GetIsolate(), 43);
   1605   CHECK(new_boxed_number->IsNumberObject());
   1606   as_boxed = new_boxed_number.As<v8::NumberObject>();
   1607   the_number = as_boxed->ValueOf();
   1608   CHECK_EQ(43.0, the_number);
   1609 }
   1610 
   1611 
   1612 THREADED_TEST(BooleanObject) {
   1613   LocalContext env;
   1614   v8::HandleScope scope(env->GetIsolate());
   1615   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
   1616   CHECK(boxed_boolean->IsBooleanObject());
   1617   v8::Handle<Value> unboxed_boolean = CompileRun("true");
   1618   CHECK(!unboxed_boolean->IsBooleanObject());
   1619   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
   1620   CHECK(!boxed_not_boolean->IsBooleanObject());
   1621   v8::Handle<v8::BooleanObject> as_boxed =
   1622       boxed_boolean.As<v8::BooleanObject>();
   1623   CHECK(!as_boxed.IsEmpty());
   1624   bool the_boolean = as_boxed->ValueOf();
   1625   CHECK_EQ(true, the_boolean);
   1626   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
   1627   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
   1628   CHECK(boxed_true->IsBooleanObject());
   1629   CHECK(boxed_false->IsBooleanObject());
   1630   as_boxed = boxed_true.As<v8::BooleanObject>();
   1631   CHECK_EQ(true, as_boxed->ValueOf());
   1632   as_boxed = boxed_false.As<v8::BooleanObject>();
   1633   CHECK_EQ(false, as_boxed->ValueOf());
   1634 }
   1635 
   1636 
   1637 THREADED_TEST(PrimitiveAndWrappedBooleans) {
   1638   LocalContext env;
   1639   v8::HandleScope scope(env->GetIsolate());
   1640 
   1641   Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
   1642   CHECK(primitive_false->IsBoolean());
   1643   CHECK(!primitive_false->IsBooleanObject());
   1644   CHECK(!primitive_false->BooleanValue());
   1645   CHECK(!primitive_false->IsTrue());
   1646   CHECK(primitive_false->IsFalse());
   1647 
   1648   Local<Value> false_value = BooleanObject::New(false);
   1649   CHECK(!false_value->IsBoolean());
   1650   CHECK(false_value->IsBooleanObject());
   1651   CHECK(false_value->BooleanValue());
   1652   CHECK(!false_value->IsTrue());
   1653   CHECK(!false_value->IsFalse());
   1654 
   1655   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
   1656   CHECK(!false_boolean_object->IsBoolean());
   1657   CHECK(false_boolean_object->IsBooleanObject());
   1658   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
   1659   // CHECK(false_boolean_object->BooleanValue());
   1660   CHECK(!false_boolean_object->ValueOf());
   1661   CHECK(!false_boolean_object->IsTrue());
   1662   CHECK(!false_boolean_object->IsFalse());
   1663 
   1664   Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
   1665   CHECK(primitive_true->IsBoolean());
   1666   CHECK(!primitive_true->IsBooleanObject());
   1667   CHECK(primitive_true->BooleanValue());
   1668   CHECK(primitive_true->IsTrue());
   1669   CHECK(!primitive_true->IsFalse());
   1670 
   1671   Local<Value> true_value = BooleanObject::New(true);
   1672   CHECK(!true_value->IsBoolean());
   1673   CHECK(true_value->IsBooleanObject());
   1674   CHECK(true_value->BooleanValue());
   1675   CHECK(!true_value->IsTrue());
   1676   CHECK(!true_value->IsFalse());
   1677 
   1678   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
   1679   CHECK(!true_boolean_object->IsBoolean());
   1680   CHECK(true_boolean_object->IsBooleanObject());
   1681   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
   1682   // CHECK(true_boolean_object->BooleanValue());
   1683   CHECK(true_boolean_object->ValueOf());
   1684   CHECK(!true_boolean_object->IsTrue());
   1685   CHECK(!true_boolean_object->IsFalse());
   1686 }
   1687 
   1688 
   1689 THREADED_TEST(Number) {
   1690   LocalContext env;
   1691   v8::HandleScope scope(env->GetIsolate());
   1692   double PI = 3.1415926;
   1693   Local<v8::Number> pi_obj = v8::Number::New(PI);
   1694   CHECK_EQ(PI, pi_obj->NumberValue());
   1695 }
   1696 
   1697 
   1698 THREADED_TEST(ToNumber) {
   1699   LocalContext env;
   1700   v8::Isolate* isolate = CcTest::isolate();
   1701   v8::HandleScope scope(isolate);
   1702   Local<String> str = v8_str("3.1415926");
   1703   CHECK_EQ(3.1415926, str->NumberValue());
   1704   v8::Handle<v8::Boolean> t = v8::True(isolate);
   1705   CHECK_EQ(1.0, t->NumberValue());
   1706   v8::Handle<v8::Boolean> f = v8::False(isolate);
   1707   CHECK_EQ(0.0, f->NumberValue());
   1708 }
   1709 
   1710 
   1711 THREADED_TEST(Date) {
   1712   LocalContext env;
   1713   v8::HandleScope scope(env->GetIsolate());
   1714   double PI = 3.1415926;
   1715   Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
   1716   CHECK_EQ(3.0, date->NumberValue());
   1717   date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42));
   1718   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
   1719 }
   1720 
   1721 
   1722 THREADED_TEST(Boolean) {
   1723   LocalContext env;
   1724   v8::HandleScope scope(env->GetIsolate());
   1725   v8::Handle<v8::Boolean> t = v8::True(CcTest::isolate());
   1726   CHECK(t->Value());
   1727   v8::Handle<v8::Boolean> f = v8::False(CcTest::isolate());
   1728   CHECK(!f->Value());
   1729   v8::Handle<v8::Primitive> u = v8::Undefined(CcTest::isolate());
   1730   CHECK(!u->BooleanValue());
   1731   v8::Handle<v8::Primitive> n = v8::Null(CcTest::isolate());
   1732   CHECK(!n->BooleanValue());
   1733   v8::Handle<String> str1 = v8_str("");
   1734   CHECK(!str1->BooleanValue());
   1735   v8::Handle<String> str2 = v8_str("x");
   1736   CHECK(str2->BooleanValue());
   1737   CHECK(!v8::Number::New(0)->BooleanValue());
   1738   CHECK(v8::Number::New(-1)->BooleanValue());
   1739   CHECK(v8::Number::New(1)->BooleanValue());
   1740   CHECK(v8::Number::New(42)->BooleanValue());
   1741   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
   1742 }
   1743 
   1744 
   1745 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1746   ApiTestFuzzer::Fuzz();
   1747   args.GetReturnValue().Set(v8_num(13.4));
   1748 }
   1749 
   1750 
   1751 static void GetM(Local<String> name,
   1752                  const v8::PropertyCallbackInfo<v8::Value>& info) {
   1753   ApiTestFuzzer::Fuzz();
   1754   info.GetReturnValue().Set(v8_num(876));
   1755 }
   1756 
   1757 
   1758 THREADED_TEST(GlobalPrototype) {
   1759   v8::HandleScope scope(CcTest::isolate());
   1760   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
   1761   func_templ->PrototypeTemplate()->Set(
   1762       CcTest::isolate(), "dummy", v8::FunctionTemplate::New(DummyCallHandler));
   1763   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
   1764   templ->Set(CcTest::isolate(), "x", v8_num(200));
   1765   templ->SetAccessor(v8_str("m"), GetM);
   1766   LocalContext env(0, templ);
   1767   v8::Handle<Script> script(v8_compile("dummy()"));
   1768   v8::Handle<Value> result(script->Run());
   1769   CHECK_EQ(13.4, result->NumberValue());
   1770   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
   1771   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
   1772 }
   1773 
   1774 
   1775 THREADED_TEST(ObjectTemplate) {
   1776   v8::HandleScope scope(CcTest::isolate());
   1777   Local<ObjectTemplate> templ1 = ObjectTemplate::New();
   1778   templ1->Set(CcTest::isolate(), "x", v8_num(10));
   1779   templ1->Set(CcTest::isolate(), "y", v8_num(13));
   1780   LocalContext env;
   1781   Local<v8::Object> instance1 = templ1->NewInstance();
   1782   env->Global()->Set(v8_str("p"), instance1);
   1783   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
   1784   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
   1785   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
   1786   fun->PrototypeTemplate()->Set(CcTest::isolate(), "nirk", v8_num(123));
   1787   Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
   1788   templ2->Set(CcTest::isolate(), "a", v8_num(12));
   1789   templ2->Set(CcTest::isolate(), "b", templ1);
   1790   Local<v8::Object> instance2 = templ2->NewInstance();
   1791   env->Global()->Set(v8_str("q"), instance2);
   1792   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
   1793   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
   1794   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
   1795   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
   1796 }
   1797 
   1798 
   1799 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1800   ApiTestFuzzer::Fuzz();
   1801   args.GetReturnValue().Set(v8_num(17.2));
   1802 }
   1803 
   1804 
   1805 static void GetKnurd(Local<String> property,
   1806                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   1807   ApiTestFuzzer::Fuzz();
   1808   info.GetReturnValue().Set(v8_num(15.2));
   1809 }
   1810 
   1811 
   1812 THREADED_TEST(DescriptorInheritance) {
   1813   v8::HandleScope scope(CcTest::isolate());
   1814   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
   1815   super->PrototypeTemplate()->Set(CcTest::isolate(), "flabby",
   1816                                   v8::FunctionTemplate::New(GetFlabby));
   1817   super->PrototypeTemplate()->Set(CcTest::isolate(), "PI", v8_num(3.14));
   1818 
   1819   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
   1820 
   1821   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
   1822   base1->Inherit(super);
   1823   base1->PrototypeTemplate()->Set(CcTest::isolate(), "v1", v8_num(20.1));
   1824 
   1825   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
   1826   base2->Inherit(super);
   1827   base2->PrototypeTemplate()->Set(CcTest::isolate(), "v2", v8_num(10.1));
   1828 
   1829   LocalContext env;
   1830 
   1831   env->Global()->Set(v8_str("s"), super->GetFunction());
   1832   env->Global()->Set(v8_str("base1"), base1->GetFunction());
   1833   env->Global()->Set(v8_str("base2"), base2->GetFunction());
   1834 
   1835   // Checks right __proto__ chain.
   1836   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
   1837   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
   1838 
   1839   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
   1840 
   1841   // Instance accessor should not be visible on function object or its prototype
   1842   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
   1843   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
   1844   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
   1845 
   1846   env->Global()->Set(v8_str("obj"),
   1847                      base1->GetFunction()->NewInstance());
   1848   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
   1849   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
   1850   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
   1851   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
   1852   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
   1853 
   1854   env->Global()->Set(v8_str("obj2"),
   1855                      base2->GetFunction()->NewInstance());
   1856   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
   1857   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
   1858   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
   1859   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
   1860   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
   1861 
   1862   // base1 and base2 cannot cross reference to each's prototype
   1863   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
   1864   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
   1865 }
   1866 
   1867 
   1868 int echo_named_call_count;
   1869 
   1870 
   1871 static void EchoNamedProperty(Local<String> name,
   1872                               const v8::PropertyCallbackInfo<v8::Value>& info) {
   1873   ApiTestFuzzer::Fuzz();
   1874   CHECK_EQ(v8_str("data"), info.Data());
   1875   echo_named_call_count++;
   1876   info.GetReturnValue().Set(name);
   1877 }
   1878 
   1879 
   1880 // Helper functions for Interceptor/Accessor interaction tests
   1881 
   1882 void SimpleAccessorGetter(Local<String> name,
   1883                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   1884   Handle<Object> self = info.This();
   1885   info.GetReturnValue().Set(
   1886       self->Get(String::Concat(v8_str("accessor_"), name)));
   1887 }
   1888 
   1889 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
   1890                           const v8::PropertyCallbackInfo<void>& info) {
   1891   Handle<Object> self = info.This();
   1892   self->Set(String::Concat(v8_str("accessor_"), name), value);
   1893 }
   1894 
   1895 void EmptyInterceptorGetter(Local<String> name,
   1896                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   1897 }
   1898 
   1899 void EmptyInterceptorSetter(Local<String> name,
   1900                             Local<Value> value,
   1901                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   1902 }
   1903 
   1904 void InterceptorGetter(Local<String> name,
   1905                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   1906   // Intercept names that start with 'interceptor_'.
   1907   String::Utf8Value utf8(name);
   1908   char* name_str = *utf8;
   1909   char prefix[] = "interceptor_";
   1910   int i;
   1911   for (i = 0; name_str[i] && prefix[i]; ++i) {
   1912     if (name_str[i] != prefix[i]) return;
   1913   }
   1914   Handle<Object> self = info.This();
   1915   info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
   1916 }
   1917 
   1918 void InterceptorSetter(Local<String> name,
   1919                        Local<Value> value,
   1920                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   1921   // Intercept accesses that set certain integer values, for which the name does
   1922   // not start with 'accessor_'.
   1923   String::Utf8Value utf8(name);
   1924   char* name_str = *utf8;
   1925   char prefix[] = "accessor_";
   1926   int i;
   1927   for (i = 0; name_str[i] && prefix[i]; ++i) {
   1928     if (name_str[i] != prefix[i]) break;
   1929   }
   1930   if (!prefix[i]) return;
   1931 
   1932   if (value->IsInt32() && value->Int32Value() < 10000) {
   1933     Handle<Object> self = info.This();
   1934     self->SetHiddenValue(name, value);
   1935     info.GetReturnValue().Set(value);
   1936   }
   1937 }
   1938 
   1939 void AddAccessor(Handle<FunctionTemplate> templ,
   1940                  Handle<String> name,
   1941                  v8::AccessorGetterCallback getter,
   1942                  v8::AccessorSetterCallback setter) {
   1943   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
   1944 }
   1945 
   1946 void AddInterceptor(Handle<FunctionTemplate> templ,
   1947                     v8::NamedPropertyGetterCallback getter,
   1948                     v8::NamedPropertySetterCallback setter) {
   1949   templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
   1950 }
   1951 
   1952 
   1953 THREADED_TEST(EmptyInterceptorBreakTransitions) {
   1954   v8::HandleScope scope(CcTest::isolate());
   1955   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   1956   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1957   LocalContext env;
   1958   env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
   1959   CompileRun("var o1 = new Constructor;"
   1960              "o1.a = 1;"  // Ensure a and x share the descriptor array.
   1961              "Object.defineProperty(o1, 'x', {value: 10});");
   1962   CompileRun("var o2 = new Constructor;"
   1963              "o2.a = 1;"
   1964              "Object.defineProperty(o2, 'x', {value: 10});");
   1965 }
   1966 
   1967 
   1968 THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
   1969   v8::HandleScope scope(CcTest::isolate());
   1970   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1971   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1972   child->Inherit(parent);
   1973   AddAccessor(parent, v8_str("age"),
   1974               SimpleAccessorGetter, SimpleAccessorSetter);
   1975   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1976   LocalContext env;
   1977   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1978   CompileRun("var child = new Child;"
   1979              "child.age = 10;");
   1980   ExpectBoolean("child.hasOwnProperty('age')", false);
   1981   ExpectInt32("child.age", 10);
   1982   ExpectInt32("child.accessor_age", 10);
   1983 }
   1984 
   1985 
   1986 THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
   1987   v8::HandleScope scope(CcTest::isolate());
   1988   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1989   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1990   child->Inherit(parent);
   1991   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1992   LocalContext env;
   1993   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1994   CompileRun("var child = new Child;"
   1995              "var parent = child.__proto__;"
   1996              "Object.defineProperty(parent, 'age', "
   1997              "  {get: function(){ return this.accessor_age; }, "
   1998              "   set: function(v){ this.accessor_age = v; }, "
   1999              "   enumerable: true, configurable: true});"
   2000              "child.age = 10;");
   2001   ExpectBoolean("child.hasOwnProperty('age')", false);
   2002   ExpectInt32("child.age", 10);
   2003   ExpectInt32("child.accessor_age", 10);
   2004 }
   2005 
   2006 
   2007 THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
   2008   v8::HandleScope scope(CcTest::isolate());
   2009   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   2010   Handle<FunctionTemplate> child = FunctionTemplate::New();
   2011   child->Inherit(parent);
   2012   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   2013   LocalContext env;
   2014   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2015   CompileRun("var child = new Child;"
   2016              "var parent = child.__proto__;"
   2017              "parent.name = 'Alice';");
   2018   ExpectBoolean("child.hasOwnProperty('name')", false);
   2019   ExpectString("child.name", "Alice");
   2020   CompileRun("child.name = 'Bob';");
   2021   ExpectString("child.name", "Bob");
   2022   ExpectBoolean("child.hasOwnProperty('name')", true);
   2023   ExpectString("parent.name", "Alice");
   2024 }
   2025 
   2026 
   2027 THREADED_TEST(SwitchFromInterceptorToAccessor) {
   2028   v8::HandleScope scope(CcTest::isolate());
   2029   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   2030   AddAccessor(templ, v8_str("age"),
   2031               SimpleAccessorGetter, SimpleAccessorSetter);
   2032   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2033   LocalContext env;
   2034   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2035   CompileRun("var obj = new Obj;"
   2036              "function setAge(i){ obj.age = i; };"
   2037              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2038   // All i < 10000 go to the interceptor.
   2039   ExpectInt32("obj.interceptor_age", 9999);
   2040   // The last i goes to the accessor.
   2041   ExpectInt32("obj.accessor_age", 10000);
   2042 }
   2043 
   2044 
   2045 THREADED_TEST(SwitchFromAccessorToInterceptor) {
   2046   v8::HandleScope scope(CcTest::isolate());
   2047   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   2048   AddAccessor(templ, v8_str("age"),
   2049               SimpleAccessorGetter, SimpleAccessorSetter);
   2050   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2051   LocalContext env;
   2052   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2053   CompileRun("var obj = new Obj;"
   2054              "function setAge(i){ obj.age = i; };"
   2055              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2056   // All i >= 10000 go to the accessor.
   2057   ExpectInt32("obj.accessor_age", 10000);
   2058   // The last i goes to the interceptor.
   2059   ExpectInt32("obj.interceptor_age", 9999);
   2060 }
   2061 
   2062 
   2063 THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
   2064   v8::HandleScope scope(CcTest::isolate());
   2065   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   2066   Handle<FunctionTemplate> child = FunctionTemplate::New();
   2067   child->Inherit(parent);
   2068   AddAccessor(parent, v8_str("age"),
   2069               SimpleAccessorGetter, SimpleAccessorSetter);
   2070   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2071   LocalContext env;
   2072   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2073   CompileRun("var child = new Child;"
   2074              "function setAge(i){ child.age = i; };"
   2075              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2076   // All i < 10000 go to the interceptor.
   2077   ExpectInt32("child.interceptor_age", 9999);
   2078   // The last i goes to the accessor.
   2079   ExpectInt32("child.accessor_age", 10000);
   2080 }
   2081 
   2082 
   2083 THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
   2084   v8::HandleScope scope(CcTest::isolate());
   2085   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   2086   Handle<FunctionTemplate> child = FunctionTemplate::New();
   2087   child->Inherit(parent);
   2088   AddAccessor(parent, v8_str("age"),
   2089               SimpleAccessorGetter, SimpleAccessorSetter);
   2090   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2091   LocalContext env;
   2092   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2093   CompileRun("var child = new Child;"
   2094              "function setAge(i){ child.age = i; };"
   2095              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2096   // All i >= 10000 go to the accessor.
   2097   ExpectInt32("child.accessor_age", 10000);
   2098   // The last i goes to the interceptor.
   2099   ExpectInt32("child.interceptor_age", 9999);
   2100 }
   2101 
   2102 
   2103 THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
   2104   v8::HandleScope scope(CcTest::isolate());
   2105   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   2106   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2107   LocalContext env;
   2108   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2109   CompileRun("var obj = new Obj;"
   2110              "function setter(i) { this.accessor_age = i; };"
   2111              "function getter() { return this.accessor_age; };"
   2112              "function setAge(i) { obj.age = i; };"
   2113              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   2114              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2115   // All i < 10000 go to the interceptor.
   2116   ExpectInt32("obj.interceptor_age", 9999);
   2117   // The last i goes to the JavaScript accessor.
   2118   ExpectInt32("obj.accessor_age", 10000);
   2119   // The installed JavaScript getter is still intact.
   2120   // This last part is a regression test for issue 1651 and relies on the fact
   2121   // that both interceptor and accessor are being installed on the same object.
   2122   ExpectInt32("obj.age", 10000);
   2123   ExpectBoolean("obj.hasOwnProperty('age')", true);
   2124   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
   2125 }
   2126 
   2127 
   2128 THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
   2129   v8::HandleScope scope(CcTest::isolate());
   2130   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   2131   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2132   LocalContext env;
   2133   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2134   CompileRun("var obj = new Obj;"
   2135              "function setter(i) { this.accessor_age = i; };"
   2136              "function getter() { return this.accessor_age; };"
   2137              "function setAge(i) { obj.age = i; };"
   2138              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   2139              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2140   // All i >= 10000 go to the accessor.
   2141   ExpectInt32("obj.accessor_age", 10000);
   2142   // The last i goes to the interceptor.
   2143   ExpectInt32("obj.interceptor_age", 9999);
   2144   // The installed JavaScript getter is still intact.
   2145   // This last part is a regression test for issue 1651 and relies on the fact
   2146   // that both interceptor and accessor are being installed on the same object.
   2147   ExpectInt32("obj.age", 10000);
   2148   ExpectBoolean("obj.hasOwnProperty('age')", true);
   2149   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
   2150 }
   2151 
   2152 
   2153 THREADED_TEST(SwitchFromInterceptorToProperty) {
   2154   v8::HandleScope scope(CcTest::isolate());
   2155   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   2156   Handle<FunctionTemplate> child = FunctionTemplate::New();
   2157   child->Inherit(parent);
   2158   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2159   LocalContext env;
   2160   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2161   CompileRun("var child = new Child;"
   2162              "function setAge(i){ child.age = i; };"
   2163              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2164   // All i < 10000 go to the interceptor.
   2165   ExpectInt32("child.interceptor_age", 9999);
   2166   // The last i goes to child's own property.
   2167   ExpectInt32("child.age", 10000);
   2168 }
   2169 
   2170 
   2171 THREADED_TEST(SwitchFromPropertyToInterceptor) {
   2172   v8::HandleScope scope(CcTest::isolate());
   2173   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   2174   Handle<FunctionTemplate> child = FunctionTemplate::New();
   2175   child->Inherit(parent);
   2176   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2177   LocalContext env;
   2178   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2179   CompileRun("var child = new Child;"
   2180              "function setAge(i){ child.age = i; };"
   2181              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2182   // All i >= 10000 go to child's own property.
   2183   ExpectInt32("child.age", 10000);
   2184   // The last i goes to the interceptor.
   2185   ExpectInt32("child.interceptor_age", 9999);
   2186 }
   2187 
   2188 
   2189 THREADED_TEST(NamedPropertyHandlerGetter) {
   2190   echo_named_call_count = 0;
   2191   v8::HandleScope scope(CcTest::isolate());
   2192   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2193   templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
   2194                                                      0, 0, 0, 0,
   2195                                                      v8_str("data"));
   2196   LocalContext env;
   2197   env->Global()->Set(v8_str("obj"),
   2198                      templ->GetFunction()->NewInstance());
   2199   CHECK_EQ(echo_named_call_count, 0);
   2200   v8_compile("obj.x")->Run();
   2201   CHECK_EQ(echo_named_call_count, 1);
   2202   const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
   2203   v8::Handle<Value> str = CompileRun(code);
   2204   String::Utf8Value value(str);
   2205   CHECK_EQ(*value, "oddlepoddle");
   2206   // Check default behavior
   2207   CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
   2208   CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
   2209   CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
   2210 }
   2211 
   2212 
   2213 int echo_indexed_call_count = 0;
   2214 
   2215 
   2216 static void EchoIndexedProperty(
   2217     uint32_t index,
   2218     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2219   ApiTestFuzzer::Fuzz();
   2220   CHECK_EQ(v8_num(637), info.Data());
   2221   echo_indexed_call_count++;
   2222   info.GetReturnValue().Set(v8_num(index));
   2223 }
   2224 
   2225 
   2226 THREADED_TEST(IndexedPropertyHandlerGetter) {
   2227   v8::HandleScope scope(CcTest::isolate());
   2228   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2229   templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
   2230                                                        0, 0, 0, 0,
   2231                                                        v8_num(637));
   2232   LocalContext env;
   2233   env->Global()->Set(v8_str("obj"),
   2234                      templ->GetFunction()->NewInstance());
   2235   Local<Script> script = v8_compile("obj[900]");
   2236   CHECK_EQ(script->Run()->Int32Value(), 900);
   2237 }
   2238 
   2239 
   2240 v8::Handle<v8::Object> bottom;
   2241 
   2242 static void CheckThisIndexedPropertyHandler(
   2243     uint32_t index,
   2244     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2245   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
   2246   ApiTestFuzzer::Fuzz();
   2247   CHECK(info.This()->Equals(bottom));
   2248 }
   2249 
   2250 static void CheckThisNamedPropertyHandler(
   2251     Local<String> name,
   2252     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2253   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
   2254   ApiTestFuzzer::Fuzz();
   2255   CHECK(info.This()->Equals(bottom));
   2256 }
   2257 
   2258 void CheckThisIndexedPropertySetter(
   2259     uint32_t index,
   2260     Local<Value> value,
   2261     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2262   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
   2263   ApiTestFuzzer::Fuzz();
   2264   CHECK(info.This()->Equals(bottom));
   2265 }
   2266 
   2267 
   2268 void CheckThisNamedPropertySetter(
   2269     Local<String> property,
   2270     Local<Value> value,
   2271     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2272   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
   2273   ApiTestFuzzer::Fuzz();
   2274   CHECK(info.This()->Equals(bottom));
   2275 }
   2276 
   2277 void CheckThisIndexedPropertyQuery(
   2278     uint32_t index,
   2279     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2280   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
   2281   ApiTestFuzzer::Fuzz();
   2282   CHECK(info.This()->Equals(bottom));
   2283 }
   2284 
   2285 
   2286 void CheckThisNamedPropertyQuery(
   2287     Local<String> property,
   2288     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2289   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
   2290   ApiTestFuzzer::Fuzz();
   2291   CHECK(info.This()->Equals(bottom));
   2292 }
   2293 
   2294 
   2295 void CheckThisIndexedPropertyDeleter(
   2296     uint32_t index,
   2297     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   2298   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
   2299   ApiTestFuzzer::Fuzz();
   2300   CHECK(info.This()->Equals(bottom));
   2301 }
   2302 
   2303 
   2304 void CheckThisNamedPropertyDeleter(
   2305     Local<String> property,
   2306     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   2307   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
   2308   ApiTestFuzzer::Fuzz();
   2309   CHECK(info.This()->Equals(bottom));
   2310 }
   2311 
   2312 
   2313 void CheckThisIndexedPropertyEnumerator(
   2314     const v8::PropertyCallbackInfo<v8::Array>& info) {
   2315   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
   2316   ApiTestFuzzer::Fuzz();
   2317   CHECK(info.This()->Equals(bottom));
   2318 }
   2319 
   2320 
   2321 void CheckThisNamedPropertyEnumerator(
   2322     const v8::PropertyCallbackInfo<v8::Array>& info) {
   2323   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
   2324   ApiTestFuzzer::Fuzz();
   2325   CHECK(info.This()->Equals(bottom));
   2326 }
   2327 
   2328 
   2329 THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
   2330   LocalContext env;
   2331   v8::HandleScope scope(env->GetIsolate());
   2332 
   2333   // Set up a prototype chain with three interceptors.
   2334   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2335   templ->InstanceTemplate()->SetIndexedPropertyHandler(
   2336       CheckThisIndexedPropertyHandler,
   2337       CheckThisIndexedPropertySetter,
   2338       CheckThisIndexedPropertyQuery,
   2339       CheckThisIndexedPropertyDeleter,
   2340       CheckThisIndexedPropertyEnumerator);
   2341 
   2342   templ->InstanceTemplate()->SetNamedPropertyHandler(
   2343       CheckThisNamedPropertyHandler,
   2344       CheckThisNamedPropertySetter,
   2345       CheckThisNamedPropertyQuery,
   2346       CheckThisNamedPropertyDeleter,
   2347       CheckThisNamedPropertyEnumerator);
   2348 
   2349   bottom = templ->GetFunction()->NewInstance();
   2350   Local<v8::Object> top = templ->GetFunction()->NewInstance();
   2351   Local<v8::Object> middle = templ->GetFunction()->NewInstance();
   2352 
   2353   bottom->SetPrototype(middle);
   2354   middle->SetPrototype(top);
   2355   env->Global()->Set(v8_str("obj"), bottom);
   2356 
   2357   // Indexed and named get.
   2358   Script::Compile(v8_str("obj[0]"))->Run();
   2359   Script::Compile(v8_str("obj.x"))->Run();
   2360 
   2361   // Indexed and named set.
   2362   Script::Compile(v8_str("obj[1] = 42"))->Run();
   2363   Script::Compile(v8_str("obj.y = 42"))->Run();
   2364 
   2365   // Indexed and named query.
   2366   Script::Compile(v8_str("0 in obj"))->Run();
   2367   Script::Compile(v8_str("'x' in obj"))->Run();
   2368 
   2369   // Indexed and named deleter.
   2370   Script::Compile(v8_str("delete obj[0]"))->Run();
   2371   Script::Compile(v8_str("delete obj.x"))->Run();
   2372 
   2373   // Enumerators.
   2374   Script::Compile(v8_str("for (var p in obj) ;"))->Run();
   2375 }
   2376 
   2377 
   2378 static void PrePropertyHandlerGet(
   2379     Local<String> key,
   2380     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2381   ApiTestFuzzer::Fuzz();
   2382   if (v8_str("pre")->Equals(key)) {
   2383     info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
   2384   }
   2385 }
   2386 
   2387 
   2388 static void PrePropertyHandlerQuery(
   2389     Local<String> key,
   2390     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2391   if (v8_str("pre")->Equals(key)) {
   2392     info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
   2393   }
   2394 }
   2395 
   2396 
   2397 THREADED_TEST(PrePropertyHandler) {
   2398   v8::HandleScope scope(CcTest::isolate());
   2399   v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   2400   desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
   2401                                                     0,
   2402                                                     PrePropertyHandlerQuery);
   2403   LocalContext env(NULL, desc->InstanceTemplate());
   2404   Script::Compile(v8_str(
   2405       "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
   2406   v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
   2407   CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
   2408   v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
   2409   CHECK_EQ(v8_str("Object: on"), result_on);
   2410   v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
   2411   CHECK(result_post.IsEmpty());
   2412 }
   2413 
   2414 
   2415 THREADED_TEST(UndefinedIsNotEnumerable) {
   2416   LocalContext env;
   2417   v8::HandleScope scope(env->GetIsolate());
   2418   v8::Handle<Value> result = Script::Compile(v8_str(
   2419       "this.propertyIsEnumerable(undefined)"))->Run();
   2420   CHECK(result->IsFalse());
   2421 }
   2422 
   2423 
   2424 v8::Handle<Script> call_recursively_script;
   2425 static const int kTargetRecursionDepth = 200;  // near maximum
   2426 
   2427 
   2428 static void CallScriptRecursivelyCall(
   2429     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2430   ApiTestFuzzer::Fuzz();
   2431   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   2432   if (depth == kTargetRecursionDepth) return;
   2433   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
   2434   args.GetReturnValue().Set(call_recursively_script->Run());
   2435 }
   2436 
   2437 
   2438 static void CallFunctionRecursivelyCall(
   2439     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2440   ApiTestFuzzer::Fuzz();
   2441   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   2442   if (depth == kTargetRecursionDepth) {
   2443     printf("[depth = %d]\n", depth);
   2444     return;
   2445   }
   2446   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
   2447   v8::Handle<Value> function =
   2448       args.This()->Get(v8_str("callFunctionRecursively"));
   2449   args.GetReturnValue().Set(
   2450       function.As<Function>()->Call(args.This(), 0, NULL));
   2451 }
   2452 
   2453 
   2454 THREADED_TEST(DeepCrossLanguageRecursion) {
   2455   v8::HandleScope scope(CcTest::isolate());
   2456   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
   2457   global->Set(v8_str("callScriptRecursively"),
   2458               v8::FunctionTemplate::New(CallScriptRecursivelyCall));
   2459   global->Set(v8_str("callFunctionRecursively"),
   2460               v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
   2461   LocalContext env(NULL, global);
   2462 
   2463   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
   2464   call_recursively_script = v8_compile("callScriptRecursively()");
   2465   call_recursively_script->Run();
   2466   call_recursively_script = v8::Handle<Script>();
   2467 
   2468   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
   2469   Script::Compile(v8_str("callFunctionRecursively()"))->Run();
   2470 }
   2471 
   2472 
   2473 static void ThrowingPropertyHandlerGet(
   2474     Local<String> key,
   2475     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2476   ApiTestFuzzer::Fuzz();
   2477   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
   2478 }
   2479 
   2480 
   2481 static void ThrowingPropertyHandlerSet(
   2482     Local<String> key,
   2483     Local<Value>,
   2484     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2485   info.GetIsolate()->ThrowException(key);
   2486   info.GetReturnValue().SetUndefined();  // not the same as empty handle
   2487 }
   2488 
   2489 
   2490 THREADED_TEST(CallbackExceptionRegression) {
   2491   v8::HandleScope scope(CcTest::isolate());
   2492   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   2493   obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
   2494                                ThrowingPropertyHandlerSet);
   2495   LocalContext env;
   2496   env->Global()->Set(v8_str("obj"), obj->NewInstance());
   2497   v8::Handle<Value> otto = Script::Compile(v8_str(
   2498       "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
   2499   CHECK_EQ(v8_str("otto"), otto);
   2500   v8::Handle<Value> netto = Script::Compile(v8_str(
   2501       "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
   2502   CHECK_EQ(v8_str("netto"), netto);
   2503 }
   2504 
   2505 
   2506 THREADED_TEST(FunctionPrototype) {
   2507   v8::HandleScope scope(CcTest::isolate());
   2508   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
   2509   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
   2510   LocalContext env;
   2511   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
   2512   Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
   2513   CHECK_EQ(script->Run()->Int32Value(), 321);
   2514 }
   2515 
   2516 
   2517 THREADED_TEST(InternalFields) {
   2518   LocalContext env;
   2519   v8::HandleScope scope(env->GetIsolate());
   2520 
   2521   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2522   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2523   instance_templ->SetInternalFieldCount(1);
   2524   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   2525   CHECK_EQ(1, obj->InternalFieldCount());
   2526   CHECK(obj->GetInternalField(0)->IsUndefined());
   2527   obj->SetInternalField(0, v8_num(17));
   2528   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
   2529 }
   2530 
   2531 
   2532 THREADED_TEST(GlobalObjectInternalFields) {
   2533   v8::HandleScope scope(CcTest::isolate());
   2534   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   2535   global_template->SetInternalFieldCount(1);
   2536   LocalContext env(NULL, global_template);
   2537   v8::Handle<v8::Object> global_proxy = env->Global();
   2538   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
   2539   CHECK_EQ(1, global->InternalFieldCount());
   2540   CHECK(global->GetInternalField(0)->IsUndefined());
   2541   global->SetInternalField(0, v8_num(17));
   2542   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
   2543 }
   2544 
   2545 
   2546 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
   2547   LocalContext env;
   2548   v8::HandleScope scope(CcTest::isolate());
   2549 
   2550   v8::Local<v8::Object> global = env->Global();
   2551   global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
   2552   CHECK(global->HasRealIndexedProperty(0));
   2553 }
   2554 
   2555 
   2556 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
   2557                                                void* value) {
   2558   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2559   obj->SetAlignedPointerInInternalField(0, value);
   2560   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2561   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
   2562 }
   2563 
   2564 
   2565 THREADED_TEST(InternalFieldsAlignedPointers) {
   2566   LocalContext env;
   2567   v8::HandleScope scope(env->GetIsolate());
   2568 
   2569   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2570   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2571   instance_templ->SetInternalFieldCount(1);
   2572   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   2573   CHECK_EQ(1, obj->InternalFieldCount());
   2574 
   2575   CheckAlignedPointerInInternalField(obj, NULL);
   2576 
   2577   int* heap_allocated = new int[100];
   2578   CheckAlignedPointerInInternalField(obj, heap_allocated);
   2579   delete[] heap_allocated;
   2580 
   2581   int stack_allocated[100];
   2582   CheckAlignedPointerInInternalField(obj, stack_allocated);
   2583 
   2584   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2585   CheckAlignedPointerInInternalField(obj, huge);
   2586 }
   2587 
   2588 
   2589 static void CheckAlignedPointerInEmbedderData(LocalContext* env,
   2590                                               int index,
   2591                                               void* value) {
   2592   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2593   (*env)->SetAlignedPointerInEmbedderData(index, value);
   2594   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2595   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
   2596 }
   2597 
   2598 
   2599 static void* AlignedTestPointer(int i) {
   2600   return reinterpret_cast<void*>(i * 1234);
   2601 }
   2602 
   2603 
   2604 THREADED_TEST(EmbedderDataAlignedPointers) {
   2605   LocalContext env;
   2606   v8::HandleScope scope(env->GetIsolate());
   2607 
   2608   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
   2609 
   2610   int* heap_allocated = new int[100];
   2611   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
   2612   delete[] heap_allocated;
   2613 
   2614   int stack_allocated[100];
   2615   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
   2616 
   2617   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2618   CheckAlignedPointerInEmbedderData(&env, 3, huge);
   2619 
   2620   // Test growing of the embedder data's backing store.
   2621   for (int i = 0; i < 100; i++) {
   2622     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
   2623   }
   2624   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2625   for (int i = 0; i < 100; i++) {
   2626     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
   2627   }
   2628 }
   2629 
   2630 
   2631 static void CheckEmbedderData(LocalContext* env,
   2632                               int index,
   2633                               v8::Handle<Value> data) {
   2634   (*env)->SetEmbedderData(index, data);
   2635   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
   2636 }
   2637 
   2638 
   2639 THREADED_TEST(EmbedderData) {
   2640   LocalContext env;
   2641   v8::HandleScope scope(env->GetIsolate());
   2642 
   2643   CheckEmbedderData(
   2644       &env, 3,
   2645       v8::String::NewFromUtf8(env->GetIsolate(), "The quick brown fox jumps"));
   2646   CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(env->GetIsolate(),
   2647                                                      "over the lazy dog."));
   2648   CheckEmbedderData(&env, 1, v8::Number::New(1.2345));
   2649   CheckEmbedderData(&env, 0, v8::Boolean::New(env->GetIsolate(), true));
   2650 }
   2651 
   2652 
   2653 THREADED_TEST(IdentityHash) {
   2654   LocalContext env;
   2655   v8::HandleScope scope(env->GetIsolate());
   2656 
   2657   // Ensure that the test starts with an fresh heap to test whether the hash
   2658   // code is based on the address.
   2659   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2660   Local<v8::Object> obj = v8::Object::New();
   2661   int hash = obj->GetIdentityHash();
   2662   int hash1 = obj->GetIdentityHash();
   2663   CHECK_EQ(hash, hash1);
   2664   int hash2 = v8::Object::New()->GetIdentityHash();
   2665   // Since the identity hash is essentially a random number two consecutive
   2666   // objects should not be assigned the same hash code. If the test below fails
   2667   // the random number generator should be evaluated.
   2668   CHECK_NE(hash, hash2);
   2669   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2670   int hash3 = v8::Object::New()->GetIdentityHash();
   2671   // Make sure that the identity hash is not based on the initial address of
   2672   // the object alone. If the test below fails the random number generator
   2673   // should be evaluated.
   2674   CHECK_NE(hash, hash3);
   2675   int hash4 = obj->GetIdentityHash();
   2676   CHECK_EQ(hash, hash4);
   2677 
   2678   // Check identity hashes behaviour in the presence of JS accessors.
   2679   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
   2680   {
   2681     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
   2682     Local<v8::Object> o1 = v8::Object::New();
   2683     Local<v8::Object> o2 = v8::Object::New();
   2684     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2685   }
   2686   {
   2687     CompileRun(
   2688         "function cnst() { return 42; };\n"
   2689         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
   2690     Local<v8::Object> o1 = v8::Object::New();
   2691     Local<v8::Object> o2 = v8::Object::New();
   2692     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2693   }
   2694 }
   2695 
   2696 
   2697 THREADED_TEST(SymbolProperties) {
   2698   i::FLAG_harmony_symbols = true;
   2699 
   2700   LocalContext env;
   2701   v8::Isolate* isolate = env->GetIsolate();
   2702   v8::HandleScope scope(isolate);
   2703 
   2704   v8::Local<v8::Object> obj = v8::Object::New();
   2705   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
   2706   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
   2707 
   2708   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2709 
   2710   // Check basic symbol functionality.
   2711   CHECK(sym1->IsSymbol());
   2712   CHECK(sym2->IsSymbol());
   2713   CHECK(!obj->IsSymbol());
   2714 
   2715   CHECK(sym1->Equals(sym1));
   2716   CHECK(sym2->Equals(sym2));
   2717   CHECK(!sym1->Equals(sym2));
   2718   CHECK(!sym2->Equals(sym1));
   2719   CHECK(sym1->StrictEquals(sym1));
   2720   CHECK(sym2->StrictEquals(sym2));
   2721   CHECK(!sym1->StrictEquals(sym2));
   2722   CHECK(!sym2->StrictEquals(sym1));
   2723 
   2724   CHECK(sym2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-symbol")));
   2725 
   2726   v8::Local<v8::Value> sym_val = sym2;
   2727   CHECK(sym_val->IsSymbol());
   2728   CHECK(sym_val->Equals(sym2));
   2729   CHECK(sym_val->StrictEquals(sym2));
   2730   CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
   2731 
   2732   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
   2733   CHECK(sym_obj->IsSymbolObject());
   2734   CHECK(!sym2->IsSymbolObject());
   2735   CHECK(!obj->IsSymbolObject());
   2736   CHECK(sym_obj->Equals(sym2));
   2737   CHECK(!sym_obj->StrictEquals(sym2));
   2738   CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
   2739   CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
   2740 
   2741   // Make sure delete of a non-existent symbol property works.
   2742   CHECK(obj->Delete(sym1));
   2743   CHECK(!obj->Has(sym1));
   2744 
   2745   CHECK(obj->Set(sym1, v8::Integer::New(1503)));
   2746   CHECK(obj->Has(sym1));
   2747   CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
   2748   CHECK(obj->Set(sym1, v8::Integer::New(2002)));
   2749   CHECK(obj->Has(sym1));
   2750   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2751   CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
   2752 
   2753   CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
   2754   int num_props = obj->GetPropertyNames()->Length();
   2755   CHECK(
   2756       obj->Set(v8::String::NewFromUtf8(isolate, "bla"), v8::Integer::New(20)));
   2757   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2758   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
   2759 
   2760   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2761 
   2762   // Add another property and delete it afterwards to force the object in
   2763   // slow case.
   2764   CHECK(obj->Set(sym2, v8::Integer::New(2008)));
   2765   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2766   CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
   2767   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2768   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2769 
   2770   CHECK(obj->Has(sym1));
   2771   CHECK(obj->Has(sym2));
   2772   CHECK(obj->Delete(sym2));
   2773   CHECK(obj->Has(sym1));
   2774   CHECK(!obj->Has(sym2));
   2775   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2776   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2777 
   2778   // Symbol properties are inherited.
   2779   v8::Local<v8::Object> child = v8::Object::New();
   2780   child->SetPrototype(obj);
   2781   CHECK(child->Has(sym1));
   2782   CHECK_EQ(2002, child->Get(sym1)->Int32Value());
   2783   CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
   2784 }
   2785 
   2786 
   2787 THREADED_TEST(PrivateProperties) {
   2788   LocalContext env;
   2789   v8::Isolate* isolate = env->GetIsolate();
   2790   v8::HandleScope scope(isolate);
   2791 
   2792   v8::Local<v8::Object> obj = v8::Object::New();
   2793   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
   2794   v8::Local<v8::Private> priv2 = v8::Private::New(isolate, "my-private");
   2795 
   2796   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2797 
   2798   CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
   2799 
   2800   // Make sure delete of a non-existent private symbol property works.
   2801   CHECK(obj->DeletePrivate(priv1));
   2802   CHECK(!obj->HasPrivate(priv1));
   2803 
   2804   CHECK(obj->SetPrivate(priv1, v8::Integer::New(1503)));
   2805   CHECK(obj->HasPrivate(priv1));
   2806   CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
   2807   CHECK(obj->SetPrivate(priv1, v8::Integer::New(2002)));
   2808   CHECK(obj->HasPrivate(priv1));
   2809   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
   2810 
   2811   CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
   2812   int num_props = obj->GetPropertyNames()->Length();
   2813   CHECK(
   2814       obj->Set(v8::String::NewFromUtf8(isolate, "bla"), v8::Integer::New(20)));
   2815   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2816   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
   2817 
   2818   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2819 
   2820   // Add another property and delete it afterwards to force the object in
   2821   // slow case.
   2822   CHECK(obj->SetPrivate(priv2, v8::Integer::New(2008)));
   2823   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
   2824   CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
   2825   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
   2826   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2827 
   2828   CHECK(obj->HasPrivate(priv1));
   2829   CHECK(obj->HasPrivate(priv2));
   2830   CHECK(obj->DeletePrivate(priv2));
   2831   CHECK(obj->HasPrivate(priv1));
   2832   CHECK(!obj->HasPrivate(priv2));
   2833   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
   2834   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2835 
   2836   // Private properties are inherited (for the time being).
   2837   v8::Local<v8::Object> child = v8::Object::New();
   2838   child->SetPrototype(obj);
   2839   CHECK(child->HasPrivate(priv1));
   2840   CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
   2841   CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
   2842 }
   2843 
   2844 
   2845 class ScopedArrayBufferContents {
   2846  public:
   2847   explicit ScopedArrayBufferContents(
   2848       const v8::ArrayBuffer::Contents& contents)
   2849     : contents_(contents) {}
   2850   ~ScopedArrayBufferContents() { free(contents_.Data()); }
   2851   void* Data() const { return contents_.Data(); }
   2852   size_t ByteLength() const { return contents_.ByteLength(); }
   2853  private:
   2854   const v8::ArrayBuffer::Contents contents_;
   2855 };
   2856 
   2857 template <typename T>
   2858 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
   2859   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
   2860   for (int i = 0; i < value->InternalFieldCount(); i++) {
   2861     CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
   2862   }
   2863 }
   2864 
   2865 
   2866 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
   2867   LocalContext env;
   2868   v8::Isolate* isolate = env->GetIsolate();
   2869   v8::HandleScope handle_scope(isolate);
   2870 
   2871   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
   2872   CheckInternalFieldsAreZero(ab);
   2873   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
   2874   CHECK(!ab->IsExternal());
   2875   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2876 
   2877   ScopedArrayBufferContents ab_contents(ab->Externalize());
   2878   CHECK(ab->IsExternal());
   2879 
   2880   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
   2881   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
   2882   ASSERT(data != NULL);
   2883   env->Global()->Set(v8_str("ab"), ab);
   2884 
   2885   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
   2886   CHECK_EQ(1024, result->Int32Value());
   2887 
   2888   result = CompileRun("var u8 = new Uint8Array(ab);"
   2889                       "u8[0] = 0xFF;"
   2890                       "u8[1] = 0xAA;"
   2891                       "u8.length");
   2892   CHECK_EQ(1024, result->Int32Value());
   2893   CHECK_EQ(0xFF, data[0]);
   2894   CHECK_EQ(0xAA, data[1]);
   2895   data[0] = 0xCC;
   2896   data[1] = 0x11;
   2897   result = CompileRun("u8[0] + u8[1]");
   2898   CHECK_EQ(0xDD, result->Int32Value());
   2899 }
   2900 
   2901 
   2902 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
   2903   LocalContext env;
   2904   v8::Isolate* isolate = env->GetIsolate();
   2905   v8::HandleScope handle_scope(isolate);
   2906 
   2907 
   2908   v8::Local<v8::Value> result =
   2909       CompileRun("var ab1 = new ArrayBuffer(2);"
   2910                  "var u8_a = new Uint8Array(ab1);"
   2911                  "u8_a[0] = 0xAA;"
   2912                  "u8_a[1] = 0xFF; u8_a.buffer");
   2913   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
   2914   CheckInternalFieldsAreZero(ab1);
   2915   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
   2916   CHECK(!ab1->IsExternal());
   2917   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
   2918   CHECK(ab1->IsExternal());
   2919 
   2920   result = CompileRun("ab1.byteLength");
   2921   CHECK_EQ(2, result->Int32Value());
   2922   result = CompileRun("u8_a[0]");
   2923   CHECK_EQ(0xAA, result->Int32Value());
   2924   result = CompileRun("u8_a[1]");
   2925   CHECK_EQ(0xFF, result->Int32Value());
   2926   result = CompileRun("var u8_b = new Uint8Array(ab1);"
   2927                       "u8_b[0] = 0xBB;"
   2928                       "u8_a[0]");
   2929   CHECK_EQ(0xBB, result->Int32Value());
   2930   result = CompileRun("u8_b[1]");
   2931   CHECK_EQ(0xFF, result->Int32Value());
   2932 
   2933   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
   2934   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
   2935   CHECK_EQ(0xBB, ab1_data[0]);
   2936   CHECK_EQ(0xFF, ab1_data[1]);
   2937   ab1_data[0] = 0xCC;
   2938   ab1_data[1] = 0x11;
   2939   result = CompileRun("u8_a[0] + u8_a[1]");
   2940   CHECK_EQ(0xDD, result->Int32Value());
   2941 }
   2942 
   2943 
   2944 THREADED_TEST(ArrayBuffer_External) {
   2945   LocalContext env;
   2946   v8::Isolate* isolate = env->GetIsolate();
   2947   v8::HandleScope handle_scope(isolate);
   2948 
   2949   i::ScopedVector<uint8_t> my_data(100);
   2950   memset(my_data.start(), 0, 100);
   2951   Local<v8::ArrayBuffer> ab3 =
   2952       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
   2953   CheckInternalFieldsAreZero(ab3);
   2954   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
   2955   CHECK(ab3->IsExternal());
   2956 
   2957   env->Global()->Set(v8_str("ab3"), ab3);
   2958 
   2959   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
   2960   CHECK_EQ(100, result->Int32Value());
   2961 
   2962   result = CompileRun("var u8_b = new Uint8Array(ab3);"
   2963                       "u8_b[0] = 0xBB;"
   2964                       "u8_b[1] = 0xCC;"
   2965                       "u8_b.length");
   2966   CHECK_EQ(100, result->Int32Value());
   2967   CHECK_EQ(0xBB, my_data[0]);
   2968   CHECK_EQ(0xCC, my_data[1]);
   2969   my_data[0] = 0xCC;
   2970   my_data[1] = 0x11;
   2971   result = CompileRun("u8_b[0] + u8_b[1]");
   2972   CHECK_EQ(0xDD, result->Int32Value());
   2973 }
   2974 
   2975 
   2976 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
   2977   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
   2978   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
   2979 }
   2980 
   2981 
   2982 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
   2983   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
   2984   CHECK_EQ(0, static_cast<int>(ta->Length()));
   2985   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
   2986 }
   2987 
   2988 
   2989 static void CheckIsTypedArrayVarNeutered(const char* name) {
   2990   i::ScopedVector<char> source(1024);
   2991   i::OS::SNPrintF(source,
   2992       "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
   2993       name, name, name);
   2994   CHECK(CompileRun(source.start())->IsTrue());
   2995   v8::Handle<v8::TypedArray> ta =
   2996     v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
   2997   CheckIsNeutered(ta);
   2998 }
   2999 
   3000 
   3001 template <typename TypedArray, int kElementSize>
   3002 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
   3003                                          int byteOffset,
   3004                                          int length) {
   3005   v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
   3006   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   3007   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
   3008   CHECK_EQ(length, static_cast<int>(ta->Length()));
   3009   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
   3010   return ta;
   3011 }
   3012 
   3013 
   3014 THREADED_TEST(ArrayBuffer_NeuteringApi) {
   3015   LocalContext env;
   3016   v8::Isolate* isolate = env->GetIsolate();
   3017   v8::HandleScope handle_scope(isolate);
   3018 
   3019   v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
   3020 
   3021   v8::Handle<v8::Uint8Array> u8a =
   3022     CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
   3023   v8::Handle<v8::Uint8ClampedArray> u8c =
   3024     CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
   3025   v8::Handle<v8::Int8Array> i8a =
   3026     CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
   3027 
   3028   v8::Handle<v8::Uint16Array> u16a =
   3029     CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
   3030   v8::Handle<v8::Int16Array> i16a =
   3031     CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
   3032 
   3033   v8::Handle<v8::Uint32Array> u32a =
   3034     CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
   3035   v8::Handle<v8::Int32Array> i32a =
   3036     CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
   3037 
   3038   v8::Handle<v8::Float32Array> f32a =
   3039     CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
   3040   v8::Handle<v8::Float64Array> f64a =
   3041     CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
   3042 
   3043   v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
   3044   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   3045   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
   3046   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
   3047 
   3048   ScopedArrayBufferContents contents(buffer->Externalize());
   3049   buffer->Neuter();
   3050   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
   3051   CheckIsNeutered(u8a);
   3052   CheckIsNeutered(u8c);
   3053   CheckIsNeutered(i8a);
   3054   CheckIsNeutered(u16a);
   3055   CheckIsNeutered(i16a);
   3056   CheckIsNeutered(u32a);
   3057   CheckIsNeutered(i32a);
   3058   CheckIsNeutered(f32a);
   3059   CheckIsNeutered(f64a);
   3060   CheckDataViewIsNeutered(dv);
   3061 }
   3062 
   3063 
   3064 THREADED_TEST(ArrayBuffer_NeuteringScript) {
   3065   LocalContext env;
   3066   v8::Isolate* isolate = env->GetIsolate();
   3067   v8::HandleScope handle_scope(isolate);
   3068 
   3069   CompileRun(
   3070       "var ab = new ArrayBuffer(1024);"
   3071       "var u8a = new Uint8Array(ab, 1, 1023);"
   3072       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
   3073       "var i8a = new Int8Array(ab, 1, 1023);"
   3074       "var u16a = new Uint16Array(ab, 2, 511);"
   3075       "var i16a = new Int16Array(ab, 2, 511);"
   3076       "var u32a = new Uint32Array(ab, 4, 255);"
   3077       "var i32a = new Int32Array(ab, 4, 255);"
   3078       "var f32a = new Float32Array(ab, 4, 255);"
   3079       "var f64a = new Float64Array(ab, 8, 127);"
   3080       "var dv = new DataView(ab, 1, 1023);");
   3081 
   3082   v8::Handle<v8::ArrayBuffer> ab =
   3083       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
   3084 
   3085   v8::Handle<v8::DataView> dv =
   3086     v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
   3087 
   3088   ScopedArrayBufferContents contents(ab->Externalize());
   3089   ab->Neuter();
   3090   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
   3091   CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
   3092 
   3093   CheckIsTypedArrayVarNeutered("u8a");
   3094   CheckIsTypedArrayVarNeutered("u8c");
   3095   CheckIsTypedArrayVarNeutered("i8a");
   3096   CheckIsTypedArrayVarNeutered("u16a");
   3097   CheckIsTypedArrayVarNeutered("i16a");
   3098   CheckIsTypedArrayVarNeutered("u32a");
   3099   CheckIsTypedArrayVarNeutered("i32a");
   3100   CheckIsTypedArrayVarNeutered("f32a");
   3101   CheckIsTypedArrayVarNeutered("f64a");
   3102 
   3103   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
   3104   CheckDataViewIsNeutered(dv);
   3105 }
   3106 
   3107 
   3108 
   3109 THREADED_TEST(HiddenProperties) {
   3110   LocalContext env;
   3111   v8::HandleScope scope(env->GetIsolate());
   3112 
   3113   v8::Local<v8::Object> obj = v8::Object::New();
   3114   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   3115   v8::Local<v8::String> empty = v8_str("");
   3116   v8::Local<v8::String> prop_name = v8_str("prop_name");
   3117 
   3118   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3119 
   3120   // Make sure delete of a non-existent hidden value works
   3121   CHECK(obj->DeleteHiddenValue(key));
   3122 
   3123   CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
   3124   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
   3125   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
   3126   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3127 
   3128   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3129 
   3130   // Make sure we do not find the hidden property.
   3131   CHECK(!obj->Has(empty));
   3132   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3133   CHECK(obj->Get(empty)->IsUndefined());
   3134   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3135   CHECK(obj->Set(empty, v8::Integer::New(2003)));
   3136   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3137   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
   3138 
   3139   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3140 
   3141   // Add another property and delete it afterwards to force the object in
   3142   // slow case.
   3143   CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
   3144   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3145   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
   3146   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3147   CHECK(obj->Delete(prop_name));
   3148   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3149 
   3150   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3151 
   3152   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
   3153   CHECK(obj->GetHiddenValue(key).IsEmpty());
   3154 
   3155   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
   3156   CHECK(obj->DeleteHiddenValue(key));
   3157   CHECK(obj->GetHiddenValue(key).IsEmpty());
   3158 }
   3159 
   3160 
   3161 THREADED_TEST(Regress97784) {
   3162   // Regression test for crbug.com/97784
   3163   // Messing with the Object.prototype should not have effect on
   3164   // hidden properties.
   3165   LocalContext env;
   3166   v8::HandleScope scope(env->GetIsolate());
   3167 
   3168   v8::Local<v8::Object> obj = v8::Object::New();
   3169   v8::Local<v8::String> key = v8_str("hidden");
   3170 
   3171   CompileRun(
   3172       "set_called = false;"
   3173       "Object.defineProperty("
   3174       "    Object.prototype,"
   3175       "    'hidden',"
   3176       "    {get: function() { return 45; },"
   3177       "     set: function() { set_called = true; }})");
   3178 
   3179   CHECK(obj->GetHiddenValue(key).IsEmpty());
   3180   // Make sure that the getter and setter from Object.prototype is not invoked.
   3181   // If it did we would have full access to the hidden properties in
   3182   // the accessor.
   3183   CHECK(obj->SetHiddenValue(key, v8::Integer::New(42)));
   3184   ExpectFalse("set_called");
   3185   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
   3186 }
   3187 
   3188 
   3189 static bool interceptor_for_hidden_properties_called;
   3190 static void InterceptorForHiddenProperties(
   3191     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   3192   interceptor_for_hidden_properties_called = true;
   3193 }
   3194 
   3195 
   3196 THREADED_TEST(HiddenPropertiesWithInterceptors) {
   3197   LocalContext context;
   3198   v8::HandleScope scope(context->GetIsolate());
   3199 
   3200   interceptor_for_hidden_properties_called = false;
   3201 
   3202   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   3203 
   3204   // Associate an interceptor with an object and start setting hidden values.
   3205   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   3206   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   3207   instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
   3208   Local<v8::Function> function = fun_templ->GetFunction();
   3209   Local<v8::Object> obj = function->NewInstance();
   3210   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
   3211   CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
   3212   CHECK(!interceptor_for_hidden_properties_called);
   3213 }
   3214 
   3215 
   3216 THREADED_TEST(External) {
   3217   v8::HandleScope scope(CcTest::isolate());
   3218   int x = 3;
   3219   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
   3220   LocalContext env;
   3221   env->Global()->Set(v8_str("ext"), ext);
   3222   Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
   3223   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
   3224   int* ptr = static_cast<int*>(reext->Value());
   3225   CHECK_EQ(x, 3);
   3226   *ptr = 10;
   3227   CHECK_EQ(x, 10);
   3228 
   3229   // Make sure unaligned pointers are wrapped properly.
   3230   char* data = i::StrDup("0123456789");
   3231   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
   3232   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
   3233   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
   3234   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
   3235 
   3236   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
   3237   CHECK_EQ('0', *char_ptr);
   3238   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
   3239   CHECK_EQ('1', *char_ptr);
   3240   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
   3241   CHECK_EQ('2', *char_ptr);
   3242   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
   3243   CHECK_EQ('3', *char_ptr);
   3244   i::DeleteArray(data);
   3245 }
   3246 
   3247 
   3248 THREADED_TEST(GlobalHandle) {
   3249   v8::Isolate* isolate = CcTest::isolate();
   3250   v8::Persistent<String> global;
   3251   {
   3252     v8::HandleScope scope(isolate);
   3253     global.Reset(isolate, v8_str("str"));
   3254   }
   3255   {
   3256     v8::HandleScope scope(isolate);
   3257     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3258   }
   3259   global.Reset();
   3260   {
   3261     v8::HandleScope scope(isolate);
   3262     global.Reset(isolate, v8_str("str"));
   3263   }
   3264   {
   3265     v8::HandleScope scope(isolate);
   3266     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3267   }
   3268   global.Reset();
   3269 }
   3270 
   3271 
   3272 THREADED_TEST(ResettingGlobalHandle) {
   3273   v8::Isolate* isolate = CcTest::isolate();
   3274   v8::Persistent<String> global;
   3275   {
   3276     v8::HandleScope scope(isolate);
   3277     global.Reset(isolate, v8_str("str"));
   3278   }
   3279   v8::internal::GlobalHandles* global_handles =
   3280       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3281   int initial_handle_count = global_handles->global_handles_count();
   3282   {
   3283     v8::HandleScope scope(isolate);
   3284     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3285   }
   3286   {
   3287     v8::HandleScope scope(isolate);
   3288     global.Reset(isolate, v8_str("longer"));
   3289   }
   3290   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
   3291   {
   3292     v8::HandleScope scope(isolate);
   3293     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
   3294   }
   3295   global.Reset();
   3296   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3297 }
   3298 
   3299 
   3300 THREADED_TEST(ResettingGlobalHandleToEmpty) {
   3301   v8::Isolate* isolate = CcTest::isolate();
   3302   v8::Persistent<String> global;
   3303   {
   3304     v8::HandleScope scope(isolate);
   3305     global.Reset(isolate, v8_str("str"));
   3306   }
   3307   v8::internal::GlobalHandles* global_handles =
   3308       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3309   int initial_handle_count = global_handles->global_handles_count();
   3310   {
   3311     v8::HandleScope scope(isolate);
   3312     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3313   }
   3314   {
   3315     v8::HandleScope scope(isolate);
   3316     Local<String> empty;
   3317     global.Reset(isolate, empty);
   3318   }
   3319   CHECK(global.IsEmpty());
   3320   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3321 }
   3322 
   3323 
   3324 template<class T>
   3325 static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
   3326   return unique.Pass();
   3327 }
   3328 
   3329 
   3330 template<class T>
   3331 static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
   3332                                             const v8::Persistent<T> & global) {
   3333   v8::UniquePersistent<String> unique(isolate, global);
   3334   return unique.Pass();
   3335 }
   3336 
   3337 
   3338 THREADED_TEST(UniquePersistent) {
   3339   v8::Isolate* isolate = CcTest::isolate();
   3340   v8::Persistent<String> global;
   3341   {
   3342     v8::HandleScope scope(isolate);
   3343     global.Reset(isolate, v8_str("str"));
   3344   }
   3345   v8::internal::GlobalHandles* global_handles =
   3346       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3347   int initial_handle_count = global_handles->global_handles_count();
   3348   {
   3349     v8::UniquePersistent<String> unique(isolate, global);
   3350     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3351     // Test assignment via Pass
   3352     {
   3353       v8::UniquePersistent<String> copy = unique.Pass();
   3354       CHECK(unique.IsEmpty());
   3355       CHECK(copy == global);
   3356       CHECK_EQ(initial_handle_count + 1,
   3357                global_handles->global_handles_count());
   3358       unique = copy.Pass();
   3359     }
   3360     // Test ctor via Pass
   3361     {
   3362       v8::UniquePersistent<String> copy(unique.Pass());
   3363       CHECK(unique.IsEmpty());
   3364       CHECK(copy == global);
   3365       CHECK_EQ(initial_handle_count + 1,
   3366                global_handles->global_handles_count());
   3367       unique = copy.Pass();
   3368     }
   3369     // Test pass through function call
   3370     {
   3371       v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
   3372       CHECK(unique.IsEmpty());
   3373       CHECK(copy == global);
   3374       CHECK_EQ(initial_handle_count + 1,
   3375                global_handles->global_handles_count());
   3376       unique = copy.Pass();
   3377     }
   3378     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3379   }
   3380   // Test pass from function call
   3381   {
   3382     v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
   3383     CHECK(unique == global);
   3384     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3385   }
   3386   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   3387   global.Reset();
   3388 }
   3389 
   3390 
   3391 THREADED_TEST(GlobalHandleUpcast) {
   3392   v8::Isolate* isolate = CcTest::isolate();
   3393   v8::HandleScope scope(isolate);
   3394   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
   3395   v8::Persistent<String> global_string(isolate, local);
   3396   v8::Persistent<Value>& global_value =
   3397       v8::Persistent<Value>::Cast(global_string);
   3398   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
   3399   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
   3400   global_string.Reset();
   3401 }
   3402 
   3403 
   3404 THREADED_TEST(HandleEquality) {
   3405   v8::Isolate* isolate = CcTest::isolate();
   3406   v8::Persistent<String> global1;
   3407   v8::Persistent<String> global2;
   3408   {
   3409     v8::HandleScope scope(isolate);
   3410     global1.Reset(isolate, v8_str("str"));
   3411     global2.Reset(isolate, v8_str("str2"));
   3412   }
   3413   CHECK_EQ(global1 == global1, true);
   3414   CHECK_EQ(global1 != global1, false);
   3415   {
   3416     v8::HandleScope scope(isolate);
   3417     Local<String> local1 = Local<String>::New(isolate, global1);
   3418     Local<String> local2 = Local<String>::New(isolate, global2);
   3419 
   3420     CHECK_EQ(global1 == local1, true);
   3421     CHECK_EQ(global1 != local1, false);
   3422     CHECK_EQ(local1 == global1, true);
   3423     CHECK_EQ(local1 != global1, false);
   3424 
   3425     CHECK_EQ(global1 == local2, false);
   3426     CHECK_EQ(global1 != local2, true);
   3427     CHECK_EQ(local2 == global1, false);
   3428     CHECK_EQ(local2 != global1, true);
   3429 
   3430     CHECK_EQ(local1 == local2, false);
   3431     CHECK_EQ(local1 != local2, true);
   3432 
   3433     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
   3434     CHECK_EQ(local1 == anotherLocal1, true);
   3435     CHECK_EQ(local1 != anotherLocal1, false);
   3436   }
   3437   global1.Reset();
   3438   global2.Reset();
   3439 }
   3440 
   3441 
   3442 THREADED_TEST(LocalHandle) {
   3443   v8::HandleScope scope(CcTest::isolate());
   3444   v8::Local<String> local =
   3445       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
   3446   CHECK_EQ(local->Length(), 3);
   3447 }
   3448 
   3449 
   3450 class WeakCallCounter {
   3451  public:
   3452   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
   3453   int id() { return id_; }
   3454   void increment() { number_of_weak_calls_++; }
   3455   int NumberOfWeakCalls() { return number_of_weak_calls_; }
   3456  private:
   3457   int id_;
   3458   int number_of_weak_calls_;
   3459 };
   3460 
   3461 
   3462 template<typename T>
   3463 struct WeakCallCounterAndPersistent {
   3464   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
   3465       : counter(counter) {}
   3466   WeakCallCounter* counter;
   3467   v8::Persistent<T> handle;
   3468 };
   3469 
   3470 
   3471 template <typename T>
   3472 static void WeakPointerCallback(
   3473     const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T> >& data) {
   3474   CHECK_EQ(1234, data.GetParameter()->counter->id());
   3475   data.GetParameter()->counter->increment();
   3476   data.GetParameter()->handle.Reset();
   3477 }
   3478 
   3479 
   3480 template<typename T>
   3481 static UniqueId MakeUniqueId(const Persistent<T>& p) {
   3482   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
   3483 }
   3484 
   3485 
   3486 THREADED_TEST(ApiObjectGroups) {
   3487   LocalContext env;
   3488   v8::Isolate* iso = env->GetIsolate();
   3489   HandleScope scope(iso);
   3490 
   3491   WeakCallCounter counter(1234);
   3492 
   3493   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   3494   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   3495   WeakCallCounterAndPersistent<Value> g1c1(&counter);
   3496   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   3497   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   3498   WeakCallCounterAndPersistent<Value> g2c1(&counter);
   3499 
   3500   {
   3501     HandleScope scope(iso);
   3502     g1s1.handle.Reset(iso, Object::New());
   3503     g1s2.handle.Reset(iso, Object::New());
   3504     g1c1.handle.Reset(iso, Object::New());
   3505     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
   3506     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
   3507     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
   3508 
   3509     g2s1.handle.Reset(iso, Object::New());
   3510     g2s2.handle.Reset(iso, Object::New());
   3511     g2c1.handle.Reset(iso, Object::New());
   3512     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
   3513     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
   3514     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
   3515   }
   3516 
   3517   WeakCallCounterAndPersistent<Value> root(&counter);
   3518   root.handle.Reset(iso, g1s1.handle);  // make a root.
   3519 
   3520   // Connect group 1 and 2, make a cycle.
   3521   {
   3522     HandleScope scope(iso);
   3523     CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
   3524             Set(0, Local<Value>::New(iso, g2s2.handle)));
   3525     CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
   3526             Set(0, Local<Value>::New(iso, g1s1.handle)));
   3527   }
   3528 
   3529   {
   3530     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3531     UniqueId id2 = MakeUniqueId(g2s2.handle);
   3532     iso->SetObjectGroupId(g1s1.handle, id1);
   3533     iso->SetObjectGroupId(g1s2.handle, id1);
   3534     iso->SetReferenceFromGroup(id1, g1c1.handle);
   3535     iso->SetObjectGroupId(g2s1.handle, id2);
   3536     iso->SetObjectGroupId(g2s2.handle, id2);
   3537     iso->SetReferenceFromGroup(id2, g2c1.handle);
   3538   }
   3539   // Do a single full GC, ensure incremental marking is stopped.
   3540   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3541       iso)->heap();
   3542   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3543 
   3544   // All object should be alive.
   3545   CHECK_EQ(0, counter.NumberOfWeakCalls());
   3546 
   3547   // Weaken the root.
   3548   root.handle.SetWeak(&root, &WeakPointerCallback);
   3549   // But make children strong roots---all the objects (except for children)
   3550   // should be collectable now.
   3551   g1c1.handle.ClearWeak();
   3552   g2c1.handle.ClearWeak();
   3553 
   3554   // Groups are deleted, rebuild groups.
   3555   {
   3556     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3557     UniqueId id2 = MakeUniqueId(g2s2.handle);
   3558     iso->SetObjectGroupId(g1s1.handle, id1);
   3559     iso->SetObjectGroupId(g1s2.handle, id1);
   3560     iso->SetReferenceFromGroup(id1, g1c1.handle);
   3561     iso->SetObjectGroupId(g2s1.handle, id2);
   3562     iso->SetObjectGroupId(g2s2.handle, id2);
   3563     iso->SetReferenceFromGroup(id2, g2c1.handle);
   3564   }
   3565 
   3566   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3567 
   3568   // All objects should be gone. 5 global handles in total.
   3569   CHECK_EQ(5, counter.NumberOfWeakCalls());
   3570 
   3571   // And now make children weak again and collect them.
   3572   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
   3573   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
   3574 
   3575   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3576   CHECK_EQ(7, counter.NumberOfWeakCalls());
   3577 }
   3578 
   3579 
   3580 THREADED_TEST(ApiObjectGroupsForSubtypes) {
   3581   LocalContext env;
   3582   v8::Isolate* iso = env->GetIsolate();
   3583   HandleScope scope(iso);
   3584 
   3585   WeakCallCounter counter(1234);
   3586 
   3587   WeakCallCounterAndPersistent<Object> g1s1(&counter);
   3588   WeakCallCounterAndPersistent<String> g1s2(&counter);
   3589   WeakCallCounterAndPersistent<String> g1c1(&counter);
   3590   WeakCallCounterAndPersistent<Object> g2s1(&counter);
   3591   WeakCallCounterAndPersistent<String> g2s2(&counter);
   3592   WeakCallCounterAndPersistent<String> g2c1(&counter);
   3593 
   3594   {
   3595     HandleScope scope(iso);
   3596     g1s1.handle.Reset(iso, Object::New());
   3597     g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
   3598     g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
   3599     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
   3600     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
   3601     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
   3602 
   3603     g2s1.handle.Reset(iso, Object::New());
   3604     g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
   3605     g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
   3606     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
   3607     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
   3608     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
   3609   }
   3610 
   3611   WeakCallCounterAndPersistent<Value> root(&counter);
   3612   root.handle.Reset(iso, g1s1.handle);  // make a root.
   3613 
   3614   // Connect group 1 and 2, make a cycle.
   3615   {
   3616     HandleScope scope(iso);
   3617     CHECK(Local<Object>::New(iso, g1s1.handle)
   3618               ->Set(0, Local<Object>::New(iso, g2s1.handle)));
   3619     CHECK(Local<Object>::New(iso, g2s1.handle)
   3620               ->Set(0, Local<Object>::New(iso, g1s1.handle)));
   3621   }
   3622 
   3623   {
   3624     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3625     UniqueId id2 = MakeUniqueId(g2s2.handle);
   3626     iso->SetObjectGroupId(g1s1.handle, id1);
   3627     iso->SetObjectGroupId(g1s2.handle, id1);
   3628     iso->SetReference(g1s1.handle, g1c1.handle);
   3629     iso->SetObjectGroupId(g2s1.handle, id2);
   3630     iso->SetObjectGroupId(g2s2.handle, id2);
   3631     iso->SetReferenceFromGroup(id2, g2c1.handle);
   3632   }
   3633   // Do a single full GC, ensure incremental marking is stopped.
   3634   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3635       iso)->heap();
   3636   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3637 
   3638   // All object should be alive.
   3639   CHECK_EQ(0, counter.NumberOfWeakCalls());
   3640 
   3641   // Weaken the root.
   3642   root.handle.SetWeak(&root, &WeakPointerCallback);
   3643   // But make children strong roots---all the objects (except for children)
   3644   // should be collectable now.
   3645   g1c1.handle.ClearWeak();
   3646   g2c1.handle.ClearWeak();
   3647 
   3648   // Groups are deleted, rebuild groups.
   3649   {
   3650     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3651     UniqueId id2 = MakeUniqueId(g2s2.handle);
   3652     iso->SetObjectGroupId(g1s1.handle, id1);
   3653     iso->SetObjectGroupId(g1s2.handle, id1);
   3654     iso->SetReference(g1s1.handle, g1c1.handle);
   3655     iso->SetObjectGroupId(g2s1.handle, id2);
   3656     iso->SetObjectGroupId(g2s2.handle, id2);
   3657     iso->SetReferenceFromGroup(id2, g2c1.handle);
   3658   }
   3659 
   3660   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3661 
   3662   // All objects should be gone. 5 global handles in total.
   3663   CHECK_EQ(5, counter.NumberOfWeakCalls());
   3664 
   3665   // And now make children weak again and collect them.
   3666   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
   3667   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
   3668 
   3669   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3670   CHECK_EQ(7, counter.NumberOfWeakCalls());
   3671 }
   3672 
   3673 
   3674 THREADED_TEST(ApiObjectGroupsCycle) {
   3675   LocalContext env;
   3676   v8::Isolate* iso = env->GetIsolate();
   3677   HandleScope scope(iso);
   3678 
   3679   WeakCallCounter counter(1234);
   3680 
   3681   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   3682   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   3683   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   3684   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   3685   WeakCallCounterAndPersistent<Value> g3s1(&counter);
   3686   WeakCallCounterAndPersistent<Value> g3s2(&counter);
   3687   WeakCallCounterAndPersistent<Value> g4s1(&counter);
   3688   WeakCallCounterAndPersistent<Value> g4s2(&counter);
   3689 
   3690   {
   3691     HandleScope scope(iso);
   3692     g1s1.handle.Reset(iso, Object::New());
   3693     g1s2.handle.Reset(iso, Object::New());
   3694     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
   3695     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
   3696     CHECK(g1s1.handle.IsWeak());
   3697     CHECK(g1s2.handle.IsWeak());
   3698 
   3699     g2s1.handle.Reset(iso, Object::New());
   3700     g2s2.handle.Reset(iso, Object::New());
   3701     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
   3702     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
   3703     CHECK(g2s1.handle.IsWeak());
   3704     CHECK(g2s2.handle.IsWeak());
   3705 
   3706     g3s1.handle.Reset(iso, Object::New());
   3707     g3s2.handle.Reset(iso, Object::New());
   3708     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
   3709     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
   3710     CHECK(g3s1.handle.IsWeak());
   3711     CHECK(g3s2.handle.IsWeak());
   3712 
   3713     g4s1.handle.Reset(iso, Object::New());
   3714     g4s2.handle.Reset(iso, Object::New());
   3715     g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
   3716     g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
   3717     CHECK(g4s1.handle.IsWeak());
   3718     CHECK(g4s2.handle.IsWeak());
   3719   }
   3720 
   3721   WeakCallCounterAndPersistent<Value> root(&counter);
   3722   root.handle.Reset(iso, g1s1.handle);  // make a root.
   3723 
   3724   // Connect groups.  We're building the following cycle:
   3725   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   3726   // groups.
   3727   {
   3728     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3729     UniqueId id2 = MakeUniqueId(g2s1.handle);
   3730     UniqueId id3 = MakeUniqueId(g3s1.handle);
   3731     UniqueId id4 = MakeUniqueId(g4s1.handle);
   3732     iso->SetObjectGroupId(g1s1.handle, id1);
   3733     iso->SetObjectGroupId(g1s2.handle, id1);
   3734     iso->SetReferenceFromGroup(id1, g2s1.handle);
   3735     iso->SetObjectGroupId(g2s1.handle, id2);
   3736     iso->SetObjectGroupId(g2s2.handle, id2);
   3737     iso->SetReferenceFromGroup(id2, g3s1.handle);
   3738     iso->SetObjectGroupId(g3s1.handle, id3);
   3739     iso->SetObjectGroupId(g3s2.handle, id3);
   3740     iso->SetReferenceFromGroup(id3, g4s1.handle);
   3741     iso->SetObjectGroupId(g4s1.handle, id4);
   3742     iso->SetObjectGroupId(g4s2.handle, id4);
   3743     iso->SetReferenceFromGroup(id4, g1s1.handle);
   3744   }
   3745   // Do a single full GC
   3746   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3747       iso)->heap();
   3748   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3749 
   3750   // All object should be alive.
   3751   CHECK_EQ(0, counter.NumberOfWeakCalls());
   3752 
   3753   // Weaken the root.
   3754   root.handle.SetWeak(&root, &WeakPointerCallback);
   3755 
   3756   // Groups are deleted, rebuild groups.
   3757   {
   3758     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3759     UniqueId id2 = MakeUniqueId(g2s1.handle);
   3760     UniqueId id3 = MakeUniqueId(g3s1.handle);
   3761     UniqueId id4 = MakeUniqueId(g4s1.handle);
   3762     iso->SetObjectGroupId(g1s1.handle, id1);
   3763     iso->SetObjectGroupId(g1s2.handle, id1);
   3764     iso->SetReferenceFromGroup(id1, g2s1.handle);
   3765     iso->SetObjectGroupId(g2s1.handle, id2);
   3766     iso->SetObjectGroupId(g2s2.handle, id2);
   3767     iso->SetReferenceFromGroup(id2, g3s1.handle);
   3768     iso->SetObjectGroupId(g3s1.handle, id3);
   3769     iso->SetObjectGroupId(g3s2.handle, id3);
   3770     iso->SetReferenceFromGroup(id3, g4s1.handle);
   3771     iso->SetObjectGroupId(g4s1.handle, id4);
   3772     iso->SetObjectGroupId(g4s2.handle, id4);
   3773     iso->SetReferenceFromGroup(id4, g1s1.handle);
   3774   }
   3775 
   3776   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3777 
   3778   // All objects should be gone. 9 global handles in total.
   3779   CHECK_EQ(9, counter.NumberOfWeakCalls());
   3780 }
   3781 
   3782 
   3783 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
   3784 // on the buildbots, so was made non-threaded for the time being.
   3785 TEST(ApiObjectGroupsCycleForScavenger) {
   3786   i::FLAG_stress_compaction = false;
   3787   i::FLAG_gc_global = false;
   3788   LocalContext env;
   3789   v8::Isolate* iso = env->GetIsolate();
   3790   HandleScope scope(iso);
   3791 
   3792   WeakCallCounter counter(1234);
   3793 
   3794   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   3795   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   3796   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   3797   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   3798   WeakCallCounterAndPersistent<Value> g3s1(&counter);
   3799   WeakCallCounterAndPersistent<Value> g3s2(&counter);
   3800 
   3801   {
   3802     HandleScope scope(iso);
   3803     g1s1.handle.Reset(iso, Object::New());
   3804     g1s2.handle.Reset(iso, Object::New());
   3805     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
   3806     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
   3807 
   3808     g2s1.handle.Reset(iso, Object::New());
   3809     g2s2.handle.Reset(iso, Object::New());
   3810     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
   3811     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
   3812 
   3813     g3s1.handle.Reset(iso, Object::New());
   3814     g3s2.handle.Reset(iso, Object::New());
   3815     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
   3816     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
   3817   }
   3818 
   3819   // Make a root.
   3820   WeakCallCounterAndPersistent<Value> root(&counter);
   3821   root.handle.Reset(iso, g1s1.handle);
   3822   root.handle.MarkPartiallyDependent();
   3823 
   3824   // Connect groups.  We're building the following cycle:
   3825   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   3826   // groups.
   3827   {
   3828     HandleScope handle_scope(iso);
   3829     g1s1.handle.MarkPartiallyDependent();
   3830     g1s2.handle.MarkPartiallyDependent();
   3831     g2s1.handle.MarkPartiallyDependent();
   3832     g2s2.handle.MarkPartiallyDependent();
   3833     g3s1.handle.MarkPartiallyDependent();
   3834     g3s2.handle.MarkPartiallyDependent();
   3835     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
   3836     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
   3837     Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
   3838         v8_str("x"), Local<Value>::New(iso, g2s1.handle));
   3839     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
   3840     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
   3841     Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
   3842         v8_str("x"), Local<Value>::New(iso, g3s1.handle));
   3843     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
   3844     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
   3845     Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
   3846         v8_str("x"), Local<Value>::New(iso, g1s1.handle));
   3847   }
   3848 
   3849   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3850       iso)->heap();
   3851   heap->CollectGarbage(i::NEW_SPACE);
   3852 
   3853   // All objects should be alive.
   3854   CHECK_EQ(0, counter.NumberOfWeakCalls());
   3855 
   3856   // Weaken the root.
   3857   root.handle.SetWeak(&root, &WeakPointerCallback);
   3858   root.handle.MarkPartiallyDependent();
   3859 
   3860   // Groups are deleted, rebuild groups.
   3861   {
   3862     HandleScope handle_scope(iso);
   3863     g1s1.handle.MarkPartiallyDependent();
   3864     g1s2.handle.MarkPartiallyDependent();
   3865     g2s1.handle.MarkPartiallyDependent();
   3866     g2s2.handle.MarkPartiallyDependent();
   3867     g3s1.handle.MarkPartiallyDependent();
   3868     g3s2.handle.MarkPartiallyDependent();
   3869     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
   3870     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
   3871     Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
   3872         v8_str("x"), Local<Value>::New(iso, g2s1.handle));
   3873     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
   3874     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
   3875     Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
   3876         v8_str("x"), Local<Value>::New(iso, g3s1.handle));
   3877     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
   3878     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
   3879     Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
   3880         v8_str("x"), Local<Value>::New(iso, g1s1.handle));
   3881   }
   3882 
   3883   heap->CollectGarbage(i::NEW_SPACE);
   3884 
   3885   // All objects should be gone. 7 global handles in total.
   3886   CHECK_EQ(7, counter.NumberOfWeakCalls());
   3887 }
   3888 
   3889 
   3890 THREADED_TEST(ScriptException) {
   3891   LocalContext env;
   3892   v8::HandleScope scope(env->GetIsolate());
   3893   Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
   3894   v8::TryCatch try_catch;
   3895   Local<Value> result = script->Run();
   3896   CHECK(result.IsEmpty());
   3897   CHECK(try_catch.HasCaught());
   3898   String::Utf8Value exception_value(try_catch.Exception());
   3899   CHECK_EQ(*exception_value, "panama!");
   3900 }
   3901 
   3902 
   3903 TEST(TryCatchCustomException) {
   3904   LocalContext env;
   3905   v8::HandleScope scope(env->GetIsolate());
   3906   v8::TryCatch try_catch;
   3907   CompileRun("function CustomError() { this.a = 'b'; }"
   3908              "(function f() { throw new CustomError(); })();");
   3909   CHECK(try_catch.HasCaught());
   3910   CHECK(try_catch.Exception()->ToObject()->
   3911             Get(v8_str("a"))->Equals(v8_str("b")));
   3912 }
   3913 
   3914 
   3915 bool message_received;
   3916 
   3917 
   3918 static void check_message_0(v8::Handle<v8::Message> message,
   3919                             v8::Handle<Value> data) {
   3920   CHECK_EQ(5.76, data->NumberValue());
   3921   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   3922   CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
   3923   CHECK(!message->IsSharedCrossOrigin());
   3924   message_received = true;
   3925 }
   3926 
   3927 
   3928 THREADED_TEST(MessageHandler0) {
   3929   message_received = false;
   3930   v8::HandleScope scope(CcTest::isolate());
   3931   CHECK(!message_received);
   3932   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
   3933   LocalContext context;
   3934   v8::ScriptOrigin origin =
   3935       v8::ScriptOrigin(v8_str("6.75"));
   3936   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   3937                                                   &origin);
   3938   script->SetData(v8_str("7.56"));
   3939   script->Run();
   3940   CHECK(message_received);
   3941   // clear out the message listener
   3942   v8::V8::RemoveMessageListeners(check_message_0);
   3943 }
   3944 
   3945 
   3946 static void check_message_1(v8::Handle<v8::Message> message,
   3947                             v8::Handle<Value> data) {
   3948   CHECK(data->IsNumber());
   3949   CHECK_EQ(1337, data->Int32Value());
   3950   CHECK(!message->IsSharedCrossOrigin());
   3951   message_received = true;
   3952 }
   3953 
   3954 
   3955 TEST(MessageHandler1) {
   3956   message_received = false;
   3957   v8::HandleScope scope(CcTest::isolate());
   3958   CHECK(!message_received);
   3959   v8::V8::AddMessageListener(check_message_1);
   3960   LocalContext context;
   3961   CompileRun("throw 1337;");
   3962   CHECK(message_received);
   3963   // clear out the message listener
   3964   v8::V8::RemoveMessageListeners(check_message_1);
   3965 }
   3966 
   3967 
   3968 static void check_message_2(v8::Handle<v8::Message> message,
   3969                             v8::Handle<Value> data) {
   3970   LocalContext context;
   3971   CHECK(data->IsObject());
   3972   v8::Local<v8::Value> hidden_property =
   3973       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
   3974   CHECK(v8_str("hidden value")->Equals(hidden_property));
   3975   CHECK(!message->IsSharedCrossOrigin());
   3976   message_received = true;
   3977 }
   3978 
   3979 
   3980 TEST(MessageHandler2) {
   3981   message_received = false;
   3982   v8::HandleScope scope(CcTest::isolate());
   3983   CHECK(!message_received);
   3984   v8::V8::AddMessageListener(check_message_2);
   3985   LocalContext context;
   3986   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
   3987   v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
   3988                                            v8_str("hidden value"));
   3989   context->Global()->Set(v8_str("error"), error);
   3990   CompileRun("throw error;");
   3991   CHECK(message_received);
   3992   // clear out the message listener
   3993   v8::V8::RemoveMessageListeners(check_message_2);
   3994 }
   3995 
   3996 
   3997 static void check_message_3(v8::Handle<v8::Message> message,
   3998                             v8::Handle<Value> data) {
   3999   CHECK(message->IsSharedCrossOrigin());
   4000   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   4001   message_received = true;
   4002 }
   4003 
   4004 
   4005 TEST(MessageHandler3) {
   4006   message_received = false;
   4007   v8::Isolate* isolate = CcTest::isolate();
   4008   v8::HandleScope scope(isolate);
   4009   CHECK(!message_received);
   4010   v8::V8::AddMessageListener(check_message_3);
   4011   LocalContext context;
   4012   v8::ScriptOrigin origin =
   4013       v8::ScriptOrigin(v8_str("6.75"),
   4014                        v8::Integer::New(1, isolate),
   4015                        v8::Integer::New(2, isolate),
   4016                        v8::True(isolate));
   4017   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   4018                                                   &origin);
   4019   script->Run();
   4020   CHECK(message_received);
   4021   // clear out the message listener
   4022   v8::V8::RemoveMessageListeners(check_message_3);
   4023 }
   4024 
   4025 
   4026 static void check_message_4(v8::Handle<v8::Message> message,
   4027                             v8::Handle<Value> data) {
   4028   CHECK(!message->IsSharedCrossOrigin());
   4029   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   4030   message_received = true;
   4031 }
   4032 
   4033 
   4034 TEST(MessageHandler4) {
   4035   message_received = false;
   4036   v8::Isolate* isolate = CcTest::isolate();
   4037   v8::HandleScope scope(isolate);
   4038   CHECK(!message_received);
   4039   v8::V8::AddMessageListener(check_message_4);
   4040   LocalContext context;
   4041   v8::ScriptOrigin origin =
   4042       v8::ScriptOrigin(v8_str("6.75"),
   4043                        v8::Integer::New(1, isolate),
   4044                        v8::Integer::New(2, isolate),
   4045                        v8::False(isolate));
   4046   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   4047                                                   &origin);
   4048   script->Run();
   4049   CHECK(message_received);
   4050   // clear out the message listener
   4051   v8::V8::RemoveMessageListeners(check_message_4);
   4052 }
   4053 
   4054 
   4055 static void check_message_5a(v8::Handle<v8::Message> message,
   4056                             v8::Handle<Value> data) {
   4057   CHECK(message->IsSharedCrossOrigin());
   4058   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   4059   message_received = true;
   4060 }
   4061 
   4062 
   4063 static void check_message_5b(v8::Handle<v8::Message> message,
   4064                             v8::Handle<Value> data) {
   4065   CHECK(!message->IsSharedCrossOrigin());
   4066   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   4067   message_received = true;
   4068 }
   4069 
   4070 
   4071 TEST(MessageHandler5) {
   4072   message_received = false;
   4073   v8::Isolate* isolate = CcTest::isolate();
   4074   v8::HandleScope scope(isolate);
   4075   CHECK(!message_received);
   4076   v8::V8::AddMessageListener(check_message_5a);
   4077   LocalContext context;
   4078   v8::ScriptOrigin origin =
   4079       v8::ScriptOrigin(v8_str("6.75"),
   4080                        v8::Integer::New(1, isolate),
   4081                        v8::Integer::New(2, isolate),
   4082                        v8::True(isolate));
   4083   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   4084                                                   &origin);
   4085   script->Run();
   4086   CHECK(message_received);
   4087   // clear out the message listener
   4088   v8::V8::RemoveMessageListeners(check_message_5a);
   4089 
   4090   message_received = false;
   4091   v8::V8::AddMessageListener(check_message_5b);
   4092   origin =
   4093       v8::ScriptOrigin(v8_str("6.75"),
   4094                        v8::Integer::New(1, isolate),
   4095                        v8::Integer::New(2, isolate),
   4096                        v8::False(isolate));
   4097   script = Script::Compile(v8_str("throw 'error'"),
   4098                            &origin);
   4099   script->Run();
   4100   CHECK(message_received);
   4101   // clear out the message listener
   4102   v8::V8::RemoveMessageListeners(check_message_5b);
   4103 }
   4104 
   4105 
   4106 THREADED_TEST(GetSetProperty) {
   4107   LocalContext context;
   4108   v8::HandleScope scope(context->GetIsolate());
   4109   context->Global()->Set(v8_str("foo"), v8_num(14));
   4110   context->Global()->Set(v8_str("12"), v8_num(92));
   4111   context->Global()->Set(v8::Integer::New(16), v8_num(32));
   4112   context->Global()->Set(v8_num(13), v8_num(56));
   4113   Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
   4114   CHECK_EQ(14, foo->Int32Value());
   4115   Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
   4116   CHECK_EQ(92, twelve->Int32Value());
   4117   Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
   4118   CHECK_EQ(32, sixteen->Int32Value());
   4119   Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
   4120   CHECK_EQ(56, thirteen->Int32Value());
   4121   CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
   4122   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
   4123   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
   4124   CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
   4125   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
   4126   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
   4127   CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
   4128   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
   4129   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
   4130 }
   4131 
   4132 
   4133 THREADED_TEST(PropertyAttributes) {
   4134   LocalContext context;
   4135   v8::HandleScope scope(context->GetIsolate());
   4136   // none
   4137   Local<String> prop = v8_str("none");
   4138   context->Global()->Set(prop, v8_num(7));
   4139   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   4140   // read-only
   4141   prop = v8_str("read_only");
   4142   context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
   4143   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   4144   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
   4145   Script::Compile(v8_str("read_only = 9"))->Run();
   4146   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   4147   context->Global()->Set(prop, v8_num(10));
   4148   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   4149   // dont-delete
   4150   prop = v8_str("dont_delete");
   4151   context->Global()->Set(prop, v8_num(13), v8::DontDelete);
   4152   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   4153   Script::Compile(v8_str("delete dont_delete"))->Run();
   4154   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   4155   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
   4156   // dont-enum
   4157   prop = v8_str("dont_enum");
   4158   context->Global()->Set(prop, v8_num(28), v8::DontEnum);
   4159   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
   4160   // absent
   4161   prop = v8_str("absent");
   4162   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   4163   Local<Value> fake_prop = v8_num(1);
   4164   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
   4165   // exception
   4166   TryCatch try_catch;
   4167   Local<Value> exception =
   4168       CompileRun("({ toString: function() { throw 'exception';} })");
   4169   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
   4170   CHECK(try_catch.HasCaught());
   4171   String::Utf8Value exception_value(try_catch.Exception());
   4172   CHECK_EQ("exception", *exception_value);
   4173   try_catch.Reset();
   4174 }
   4175 
   4176 
   4177 THREADED_TEST(Array) {
   4178   LocalContext context;
   4179   v8::HandleScope scope(context->GetIsolate());
   4180   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
   4181   CHECK_EQ(0, array->Length());
   4182   CHECK(array->Get(0)->IsUndefined());
   4183   CHECK(!array->Has(0));
   4184   CHECK(array->Get(100)->IsUndefined());
   4185   CHECK(!array->Has(100));
   4186   array->Set(2, v8_num(7));
   4187   CHECK_EQ(3, array->Length());
   4188   CHECK(!array->Has(0));
   4189   CHECK(!array->Has(1));
   4190   CHECK(array->Has(2));
   4191   CHECK_EQ(7, array->Get(2)->Int32Value());
   4192   Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
   4193   Local<v8::Array> arr = obj.As<v8::Array>();
   4194   CHECK_EQ(3, arr->Length());
   4195   CHECK_EQ(1, arr->Get(0)->Int32Value());
   4196   CHECK_EQ(2, arr->Get(1)->Int32Value());
   4197   CHECK_EQ(3, arr->Get(2)->Int32Value());
   4198   array = v8::Array::New(context->GetIsolate(), 27);
   4199   CHECK_EQ(27, array->Length());
   4200   array = v8::Array::New(context->GetIsolate(), -27);
   4201   CHECK_EQ(0, array->Length());
   4202 }
   4203 
   4204 
   4205 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4206   v8::HandleScope scope(args.GetIsolate());
   4207   ApiTestFuzzer::Fuzz();
   4208   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
   4209   for (int i = 0; i < args.Length(); i++)
   4210     result->Set(i, args[i]);
   4211   args.GetReturnValue().Set(scope.Close(result));
   4212 }
   4213 
   4214 
   4215 THREADED_TEST(Vector) {
   4216   v8::HandleScope scope(CcTest::isolate());
   4217   Local<ObjectTemplate> global = ObjectTemplate::New();
   4218   global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
   4219   LocalContext context(0, global);
   4220 
   4221   const char* fun = "f()";
   4222   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
   4223   CHECK_EQ(0, a0->Length());
   4224 
   4225   const char* fun2 = "f(11)";
   4226   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
   4227   CHECK_EQ(1, a1->Length());
   4228   CHECK_EQ(11, a1->Get(0)->Int32Value());
   4229 
   4230   const char* fun3 = "f(12, 13)";
   4231   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
   4232   CHECK_EQ(2, a2->Length());
   4233   CHECK_EQ(12, a2->Get(0)->Int32Value());
   4234   CHECK_EQ(13, a2->Get(1)->Int32Value());
   4235 
   4236   const char* fun4 = "f(14, 15, 16)";
   4237   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
   4238   CHECK_EQ(3, a3->Length());
   4239   CHECK_EQ(14, a3->Get(0)->Int32Value());
   4240   CHECK_EQ(15, a3->Get(1)->Int32Value());
   4241   CHECK_EQ(16, a3->Get(2)->Int32Value());
   4242 
   4243   const char* fun5 = "f(17, 18, 19, 20)";
   4244   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
   4245   CHECK_EQ(4, a4->Length());
   4246   CHECK_EQ(17, a4->Get(0)->Int32Value());
   4247   CHECK_EQ(18, a4->Get(1)->Int32Value());
   4248   CHECK_EQ(19, a4->Get(2)->Int32Value());
   4249   CHECK_EQ(20, a4->Get(3)->Int32Value());
   4250 }
   4251 
   4252 
   4253 THREADED_TEST(FunctionCall) {
   4254   LocalContext context;
   4255   v8::Isolate* isolate = context->GetIsolate();
   4256   v8::HandleScope scope(isolate);
   4257   CompileRun(
   4258     "function Foo() {"
   4259     "  var result = [];"
   4260     "  for (var i = 0; i < arguments.length; i++) {"
   4261     "    result.push(arguments[i]);"
   4262     "  }"
   4263     "  return result;"
   4264     "}"
   4265     "function ReturnThisSloppy() {"
   4266     "  return this;"
   4267     "}"
   4268     "function ReturnThisStrict() {"
   4269     "  'use strict';"
   4270     "  return this;"
   4271     "}");
   4272   Local<Function> Foo =
   4273       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   4274   Local<Function> ReturnThisSloppy =
   4275       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
   4276   Local<Function> ReturnThisStrict =
   4277       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
   4278 
   4279   v8::Handle<Value>* args0 = NULL;
   4280   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
   4281   CHECK_EQ(0, a0->Length());
   4282 
   4283   v8::Handle<Value> args1[] = { v8_num(1.1) };
   4284   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
   4285   CHECK_EQ(1, a1->Length());
   4286   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
   4287 
   4288   v8::Handle<Value> args2[] = { v8_num(2.2),
   4289                                 v8_num(3.3) };
   4290   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
   4291   CHECK_EQ(2, a2->Length());
   4292   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
   4293   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
   4294 
   4295   v8::Handle<Value> args3[] = { v8_num(4.4),
   4296                                 v8_num(5.5),
   4297                                 v8_num(6.6) };
   4298   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
   4299   CHECK_EQ(3, a3->Length());
   4300   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
   4301   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
   4302   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
   4303 
   4304   v8::Handle<Value> args4[] = { v8_num(7.7),
   4305                                 v8_num(8.8),
   4306                                 v8_num(9.9),
   4307                                 v8_num(10.11) };
   4308   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
   4309   CHECK_EQ(4, a4->Length());
   4310   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
   4311   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   4312   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   4313   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
   4314 
   4315   Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
   4316   CHECK(r1->StrictEquals(context->Global()));
   4317   Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
   4318   CHECK(r2->StrictEquals(context->Global()));
   4319   Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
   4320   CHECK(r3->IsNumberObject());
   4321   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
   4322   Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
   4323   CHECK(r4->IsStringObject());
   4324   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   4325   Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
   4326   CHECK(r5->IsBooleanObject());
   4327   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
   4328 
   4329   Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
   4330   CHECK(r6->IsUndefined());
   4331   Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
   4332   CHECK(r7->IsNull());
   4333   Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
   4334   CHECK(r8->StrictEquals(v8_num(42)));
   4335   Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
   4336   CHECK(r9->StrictEquals(v8_str("hello")));
   4337   Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
   4338   CHECK(r10->StrictEquals(v8::True(isolate)));
   4339 }
   4340 
   4341 
   4342 static const char* js_code_causing_out_of_memory =
   4343     "var a = new Array(); while(true) a.push(a);";
   4344 
   4345 
   4346 // These tests run for a long time and prevent us from running tests
   4347 // that come after them so they cannot run in parallel.
   4348 TEST(OutOfMemory) {
   4349   // It's not possible to read a snapshot into a heap with different dimensions.
   4350   if (i::Snapshot::IsEnabled()) return;
   4351   // Set heap limits.
   4352   static const int K = 1024;
   4353   v8::ResourceConstraints constraints;
   4354   constraints.set_max_young_space_size(256 * K);
   4355   constraints.set_max_old_space_size(5 * K * K);
   4356   v8::SetResourceConstraints(CcTest::isolate(), &constraints);
   4357 
   4358   // Execute a script that causes out of memory.
   4359   LocalContext context;
   4360   v8::HandleScope scope(context->GetIsolate());
   4361   v8::V8::IgnoreOutOfMemoryException();
   4362   Local<Script> script = Script::Compile(String::NewFromUtf8(
   4363       context->GetIsolate(), js_code_causing_out_of_memory));
   4364   Local<Value> result = script->Run();
   4365 
   4366   // Check for out of memory state.
   4367   CHECK(result.IsEmpty());
   4368   CHECK(context->HasOutOfMemoryException());
   4369 }
   4370 
   4371 
   4372 void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4373   ApiTestFuzzer::Fuzz();
   4374 
   4375   LocalContext context;
   4376   v8::HandleScope scope(context->GetIsolate());
   4377   Local<Script> script = Script::Compile(String::NewFromUtf8(
   4378       context->GetIsolate(), js_code_causing_out_of_memory));
   4379   Local<Value> result = script->Run();
   4380 
   4381   // Check for out of memory state.
   4382   CHECK(result.IsEmpty());
   4383   CHECK(context->HasOutOfMemoryException());
   4384 
   4385   args.GetReturnValue().Set(result);
   4386 }
   4387 
   4388 
   4389 TEST(OutOfMemoryNested) {
   4390   // It's not possible to read a snapshot into a heap with different dimensions.
   4391   if (i::Snapshot::IsEnabled()) return;
   4392   // Set heap limits.
   4393   static const int K = 1024;
   4394   v8::ResourceConstraints constraints;
   4395   constraints.set_max_young_space_size(256 * K);
   4396   constraints.set_max_old_space_size(5 * K * K);
   4397   v8::SetResourceConstraints(CcTest::isolate(), &constraints);
   4398 
   4399   v8::HandleScope scope(CcTest::isolate());
   4400   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4401   templ->Set(v8_str("ProvokeOutOfMemory"),
   4402              v8::FunctionTemplate::New(ProvokeOutOfMemory));
   4403   LocalContext context(0, templ);
   4404   v8::V8::IgnoreOutOfMemoryException();
   4405   Local<Value> result = CompileRun(
   4406     "var thrown = false;"
   4407     "try {"
   4408     "  ProvokeOutOfMemory();"
   4409     "} catch (e) {"
   4410     "  thrown = true;"
   4411     "}");
   4412   // Check for out of memory state.
   4413   CHECK(result.IsEmpty());
   4414   CHECK(context->HasOutOfMemoryException());
   4415 }
   4416 
   4417 
   4418 TEST(HugeConsStringOutOfMemory) {
   4419   // It's not possible to read a snapshot into a heap with different dimensions.
   4420   if (i::Snapshot::IsEnabled()) return;
   4421   // Set heap limits.
   4422   static const int K = 1024;
   4423   v8::ResourceConstraints constraints;
   4424   constraints.set_max_young_space_size(256 * K);
   4425   constraints.set_max_old_space_size(4 * K * K);
   4426   v8::SetResourceConstraints(CcTest::isolate(), &constraints);
   4427 
   4428   // Execute a script that causes out of memory.
   4429   v8::V8::IgnoreOutOfMemoryException();
   4430 
   4431   LocalContext context;
   4432   v8::HandleScope scope(context->GetIsolate());
   4433 
   4434   // Build huge string. This should fail with out of memory exception.
   4435   Local<Value> result = CompileRun(
   4436     "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
   4437     "for (var i = 0; i < 22; i++) { str = str + str; }");
   4438 
   4439   // Check for out of memory state.
   4440   CHECK(result.IsEmpty());
   4441   CHECK(context->HasOutOfMemoryException());
   4442 }
   4443 
   4444 
   4445 THREADED_TEST(ConstructCall) {
   4446   LocalContext context;
   4447   v8::HandleScope scope(context->GetIsolate());
   4448   CompileRun(
   4449     "function Foo() {"
   4450     "  var result = [];"
   4451     "  for (var i = 0; i < arguments.length; i++) {"
   4452     "    result.push(arguments[i]);"
   4453     "  }"
   4454     "  return result;"
   4455     "}");
   4456   Local<Function> Foo =
   4457       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   4458 
   4459   v8::Handle<Value>* args0 = NULL;
   4460   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
   4461   CHECK_EQ(0, a0->Length());
   4462 
   4463   v8::Handle<Value> args1[] = { v8_num(1.1) };
   4464   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
   4465   CHECK_EQ(1, a1->Length());
   4466   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
   4467 
   4468   v8::Handle<Value> args2[] = { v8_num(2.2),
   4469                                 v8_num(3.3) };
   4470   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
   4471   CHECK_EQ(2, a2->Length());
   4472   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
   4473   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
   4474 
   4475   v8::Handle<Value> args3[] = { v8_num(4.4),
   4476                                 v8_num(5.5),
   4477                                 v8_num(6.6) };
   4478   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
   4479   CHECK_EQ(3, a3->Length());
   4480   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
   4481   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
   4482   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
   4483 
   4484   v8::Handle<Value> args4[] = { v8_num(7.7),
   4485                                 v8_num(8.8),
   4486                                 v8_num(9.9),
   4487                                 v8_num(10.11) };
   4488   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
   4489   CHECK_EQ(4, a4->Length());
   4490   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
   4491   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   4492   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   4493   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
   4494 }
   4495 
   4496 
   4497 static void CheckUncle(v8::TryCatch* try_catch) {
   4498   CHECK(try_catch->HasCaught());
   4499   String::Utf8Value str_value(try_catch->Exception());
   4500   CHECK_EQ(*str_value, "uncle?");
   4501   try_catch->Reset();
   4502 }
   4503 
   4504 
   4505 THREADED_TEST(ConversionNumber) {
   4506   LocalContext env;
   4507   v8::HandleScope scope(env->GetIsolate());
   4508   // Very large number.
   4509   CompileRun("var obj = Math.pow(2,32) * 1237;");
   4510   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4511   CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
   4512   CHECK_EQ(0, obj->ToInt32()->Value());
   4513   CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
   4514   // Large number.
   4515   CompileRun("var obj = -1234567890123;");
   4516   obj = env->Global()->Get(v8_str("obj"));
   4517   CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
   4518   CHECK_EQ(-1912276171, obj->ToInt32()->Value());
   4519   CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
   4520   // Small positive integer.
   4521   CompileRun("var obj = 42;");
   4522   obj = env->Global()->Get(v8_str("obj"));
   4523   CHECK_EQ(42.0, obj->ToNumber()->Value());
   4524   CHECK_EQ(42, obj->ToInt32()->Value());
   4525   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   4526   // Negative integer.
   4527   CompileRun("var obj = -37;");
   4528   obj = env->Global()->Get(v8_str("obj"));
   4529   CHECK_EQ(-37.0, obj->ToNumber()->Value());
   4530   CHECK_EQ(-37, obj->ToInt32()->Value());
   4531   CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
   4532   // Positive non-int32 integer.
   4533   CompileRun("var obj = 0x81234567;");
   4534   obj = env->Global()->Get(v8_str("obj"));
   4535   CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
   4536   CHECK_EQ(-2128394905, obj->ToInt32()->Value());
   4537   CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
   4538   // Fraction.
   4539   CompileRun("var obj = 42.3;");
   4540   obj = env->Global()->Get(v8_str("obj"));
   4541   CHECK_EQ(42.3, obj->ToNumber()->Value());
   4542   CHECK_EQ(42, obj->ToInt32()->Value());
   4543   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   4544   // Large negative fraction.
   4545   CompileRun("var obj = -5726623061.75;");
   4546   obj = env->Global()->Get(v8_str("obj"));
   4547   CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
   4548   CHECK_EQ(-1431655765, obj->ToInt32()->Value());
   4549   CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
   4550 }
   4551 
   4552 
   4553 THREADED_TEST(isNumberType) {
   4554   LocalContext env;
   4555   v8::HandleScope scope(env->GetIsolate());
   4556   // Very large number.
   4557   CompileRun("var obj = Math.pow(2,32) * 1237;");
   4558   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4559   CHECK(!obj->IsInt32());
   4560   CHECK(!obj->IsUint32());
   4561   // Large negative number.
   4562   CompileRun("var obj = -1234567890123;");
   4563   obj = env->Global()->Get(v8_str("obj"));
   4564   CHECK(!obj->IsInt32());
   4565   CHECK(!obj->IsUint32());
   4566   // Small positive integer.
   4567   CompileRun("var obj = 42;");
   4568   obj = env->Global()->Get(v8_str("obj"));
   4569   CHECK(obj->IsInt32());
   4570   CHECK(obj->IsUint32());
   4571   // Negative integer.
   4572   CompileRun("var obj = -37;");
   4573   obj = env->Global()->Get(v8_str("obj"));
   4574   CHECK(obj->IsInt32());
   4575   CHECK(!obj->IsUint32());
   4576   // Positive non-int32 integer.
   4577   CompileRun("var obj = 0x81234567;");
   4578   obj = env->Global()->Get(v8_str("obj"));
   4579   CHECK(!obj->IsInt32());
   4580   CHECK(obj->IsUint32());
   4581   // Fraction.
   4582   CompileRun("var obj = 42.3;");
   4583   obj = env->Global()->Get(v8_str("obj"));
   4584   CHECK(!obj->IsInt32());
   4585   CHECK(!obj->IsUint32());
   4586   // Large negative fraction.
   4587   CompileRun("var obj = -5726623061.75;");
   4588   obj = env->Global()->Get(v8_str("obj"));
   4589   CHECK(!obj->IsInt32());
   4590   CHECK(!obj->IsUint32());
   4591   // Positive zero
   4592   CompileRun("var obj = 0.0;");
   4593   obj = env->Global()->Get(v8_str("obj"));
   4594   CHECK(obj->IsInt32());
   4595   CHECK(obj->IsUint32());
   4596   // Positive zero
   4597   CompileRun("var obj = -0.0;");
   4598   obj = env->Global()->Get(v8_str("obj"));
   4599   CHECK(!obj->IsInt32());
   4600   CHECK(!obj->IsUint32());
   4601 }
   4602 
   4603 
   4604 THREADED_TEST(ConversionException) {
   4605   LocalContext env;
   4606   v8::Isolate* isolate = env->GetIsolate();
   4607   v8::HandleScope scope(isolate);
   4608   CompileRun(
   4609     "function TestClass() { };"
   4610     "TestClass.prototype.toString = function () { throw 'uncle?'; };"
   4611     "var obj = new TestClass();");
   4612   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4613 
   4614   v8::TryCatch try_catch;
   4615 
   4616   Local<Value> to_string_result = obj->ToString();
   4617   CHECK(to_string_result.IsEmpty());
   4618   CheckUncle(&try_catch);
   4619 
   4620   Local<Value> to_number_result = obj->ToNumber();
   4621   CHECK(to_number_result.IsEmpty());
   4622   CheckUncle(&try_catch);
   4623 
   4624   Local<Value> to_integer_result = obj->ToInteger();
   4625   CHECK(to_integer_result.IsEmpty());
   4626   CheckUncle(&try_catch);
   4627 
   4628   Local<Value> to_uint32_result = obj->ToUint32();
   4629   CHECK(to_uint32_result.IsEmpty());
   4630   CheckUncle(&try_catch);
   4631 
   4632   Local<Value> to_int32_result = obj->ToInt32();
   4633   CHECK(to_int32_result.IsEmpty());
   4634   CheckUncle(&try_catch);
   4635 
   4636   Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
   4637   CHECK(to_object_result.IsEmpty());
   4638   CHECK(try_catch.HasCaught());
   4639   try_catch.Reset();
   4640 
   4641   int32_t int32_value = obj->Int32Value();
   4642   CHECK_EQ(0, int32_value);
   4643   CheckUncle(&try_catch);
   4644 
   4645   uint32_t uint32_value = obj->Uint32Value();
   4646   CHECK_EQ(0, uint32_value);
   4647   CheckUncle(&try_catch);
   4648 
   4649   double number_value = obj->NumberValue();
   4650   CHECK_NE(0, std::isnan(number_value));
   4651   CheckUncle(&try_catch);
   4652 
   4653   int64_t integer_value = obj->IntegerValue();
   4654   CHECK_EQ(0.0, static_cast<double>(integer_value));
   4655   CheckUncle(&try_catch);
   4656 }
   4657 
   4658 
   4659 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4660   ApiTestFuzzer::Fuzz();
   4661   args.GetIsolate()->ThrowException(v8_str("konto"));
   4662 }
   4663 
   4664 
   4665 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4666   if (args.Length() < 1) {
   4667     args.GetReturnValue().Set(false);
   4668     return;
   4669   }
   4670   v8::HandleScope scope(args.GetIsolate());
   4671   v8::TryCatch try_catch;
   4672   Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
   4673   CHECK(!try_catch.HasCaught() || result.IsEmpty());
   4674   args.GetReturnValue().Set(try_catch.HasCaught());
   4675 }
   4676 
   4677 
   4678 THREADED_TEST(APICatch) {
   4679   v8::HandleScope scope(CcTest::isolate());
   4680   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4681   templ->Set(v8_str("ThrowFromC"),
   4682              v8::FunctionTemplate::New(ThrowFromC));
   4683   LocalContext context(0, templ);
   4684   CompileRun(
   4685     "var thrown = false;"
   4686     "try {"
   4687     "  ThrowFromC();"
   4688     "} catch (e) {"
   4689     "  thrown = true;"
   4690     "}");
   4691   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
   4692   CHECK(thrown->BooleanValue());
   4693 }
   4694 
   4695 
   4696 THREADED_TEST(APIThrowTryCatch) {
   4697   v8::HandleScope scope(CcTest::isolate());
   4698   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4699   templ->Set(v8_str("ThrowFromC"),
   4700              v8::FunctionTemplate::New(ThrowFromC));
   4701   LocalContext context(0, templ);
   4702   v8::TryCatch try_catch;
   4703   CompileRun("ThrowFromC();");
   4704   CHECK(try_catch.HasCaught());
   4705 }
   4706 
   4707 
   4708 // Test that a try-finally block doesn't shadow a try-catch block
   4709 // when setting up an external handler.
   4710 //
   4711 // BUG(271): Some of the exception propagation does not work on the
   4712 // ARM simulator because the simulator separates the C++ stack and the
   4713 // JS stack.  This test therefore fails on the simulator.  The test is
   4714 // not threaded to allow the threading tests to run on the simulator.
   4715 TEST(TryCatchInTryFinally) {
   4716   v8::HandleScope scope(CcTest::isolate());
   4717   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4718   templ->Set(v8_str("CCatcher"),
   4719              v8::FunctionTemplate::New(CCatcher));
   4720   LocalContext context(0, templ);
   4721   Local<Value> result = CompileRun("try {"
   4722                                    "  try {"
   4723                                    "    CCatcher('throw 7;');"
   4724                                    "  } finally {"
   4725                                    "  }"
   4726                                    "} catch (e) {"
   4727                                    "}");
   4728   CHECK(result->IsTrue());
   4729 }
   4730 
   4731 
   4732 static void check_reference_error_message(
   4733     v8::Handle<v8::Message> message,
   4734     v8::Handle<v8::Value> data) {
   4735   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
   4736   CHECK(message->Get()->Equals(v8_str(reference_error)));
   4737 }
   4738 
   4739 
   4740 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4741   ApiTestFuzzer::Fuzz();
   4742   CHECK(false);
   4743 }
   4744 
   4745 
   4746 // Test that overwritten methods are not invoked on uncaught exception
   4747 // formatting. However, they are invoked when performing normal error
   4748 // string conversions.
   4749 TEST(APIThrowMessageOverwrittenToString) {
   4750   v8::HandleScope scope(CcTest::isolate());
   4751   v8::V8::AddMessageListener(check_reference_error_message);
   4752   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4753   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
   4754   LocalContext context(NULL, templ);
   4755   CompileRun("asdf;");
   4756   CompileRun("var limit = {};"
   4757              "limit.valueOf = fail;"
   4758              "Error.stackTraceLimit = limit;");
   4759   CompileRun("asdf");
   4760   CompileRun("Array.prototype.pop = fail;");
   4761   CompileRun("Object.prototype.hasOwnProperty = fail;");
   4762   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
   4763   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
   4764   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
   4765   CompileRun("ReferenceError.prototype.toString ="
   4766              "  function() { return 'Whoops' }");
   4767   CompileRun("asdf;");
   4768   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
   4769   CompileRun("asdf;");
   4770   CompileRun("ReferenceError.prototype.constructor = void 0;");
   4771   CompileRun("asdf;");
   4772   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
   4773   CompileRun("asdf;");
   4774   CompileRun("ReferenceError.prototype = new Object();");
   4775   CompileRun("asdf;");
   4776   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
   4777   CHECK(string->Equals(v8_str("Whoops")));
   4778   CompileRun("ReferenceError.prototype.constructor = new Object();"
   4779              "ReferenceError.prototype.constructor.name = 1;"
   4780              "Number.prototype.toString = function() { return 'Whoops'; };"
   4781              "ReferenceError.prototype.toString = Object.prototype.toString;");
   4782   CompileRun("asdf;");
   4783   v8::V8::RemoveMessageListeners(check_reference_error_message);
   4784 }
   4785 
   4786 
   4787 static void check_custom_error_tostring(
   4788     v8::Handle<v8::Message> message,
   4789     v8::Handle<v8::Value> data) {
   4790   const char* uncaught_error = "Uncaught MyError toString";
   4791   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
   4792 }
   4793 
   4794 
   4795 TEST(CustomErrorToString) {
   4796   LocalContext context;
   4797   v8::HandleScope scope(context->GetIsolate());
   4798   v8::V8::AddMessageListener(check_custom_error_tostring);
   4799   CompileRun(
   4800     "function MyError(name, message) {                   "
   4801     "  this.name = name;                                 "
   4802     "  this.message = message;                           "
   4803     "}                                                   "
   4804     "MyError.prototype = Object.create(Error.prototype); "
   4805     "MyError.prototype.toString = function() {           "
   4806     "  return 'MyError toString';                        "
   4807     "};                                                  "
   4808     "throw new MyError('my name', 'my message');         ");
   4809   v8::V8::RemoveMessageListeners(check_custom_error_tostring);
   4810 }
   4811 
   4812 
   4813 static void check_custom_error_message(
   4814     v8::Handle<v8::Message> message,
   4815     v8::Handle<v8::Value> data) {
   4816   const char* uncaught_error = "Uncaught MyError: my message";
   4817   printf("%s\n", *v8::String::Utf8Value(message->Get()));
   4818   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
   4819 }
   4820 
   4821 
   4822 TEST(CustomErrorMessage) {
   4823   LocalContext context;
   4824   v8::HandleScope scope(context->GetIsolate());
   4825   v8::V8::AddMessageListener(check_custom_error_message);
   4826 
   4827   // Handlebars.
   4828   CompileRun(
   4829     "function MyError(msg) {                             "
   4830     "  this.name = 'MyError';                            "
   4831     "  this.message = msg;                               "
   4832     "}                                                   "
   4833     "MyError.prototype = new Error();                    "
   4834     "throw new MyError('my message');                    ");
   4835 
   4836   // Closure.
   4837   CompileRun(
   4838     "function MyError(msg) {                             "
   4839     "  this.name = 'MyError';                            "
   4840     "  this.message = msg;                               "
   4841     "}                                                   "
   4842     "inherits = function(childCtor, parentCtor) {        "
   4843     "    function tempCtor() {};                         "
   4844     "    tempCtor.prototype = parentCtor.prototype;      "
   4845     "    childCtor.superClass_ = parentCtor.prototype;   "
   4846     "    childCtor.prototype = new tempCtor();           "
   4847     "    childCtor.prototype.constructor = childCtor;    "
   4848     "};                                                  "
   4849     "inherits(MyError, Error);                           "
   4850     "throw new MyError('my message');                    ");
   4851 
   4852   // Object.create.
   4853   CompileRun(
   4854     "function MyError(msg) {                             "
   4855     "  this.name = 'MyError';                            "
   4856     "  this.message = msg;                               "
   4857     "}                                                   "
   4858     "MyError.prototype = Object.create(Error.prototype); "
   4859     "throw new MyError('my message');                    ");
   4860 
   4861   v8::V8::RemoveMessageListeners(check_custom_error_message);
   4862 }
   4863 
   4864 
   4865 static void receive_message(v8::Handle<v8::Message> message,
   4866                             v8::Handle<v8::Value> data) {
   4867   message->Get();
   4868   message_received = true;
   4869 }
   4870 
   4871 
   4872 TEST(APIThrowMessage) {
   4873   message_received = false;
   4874   v8::HandleScope scope(CcTest::isolate());
   4875   v8::V8::AddMessageListener(receive_message);
   4876   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4877   templ->Set(v8_str("ThrowFromC"),
   4878              v8::FunctionTemplate::New(ThrowFromC));
   4879   LocalContext context(0, templ);
   4880   CompileRun("ThrowFromC();");
   4881   CHECK(message_received);
   4882   v8::V8::RemoveMessageListeners(receive_message);
   4883 }
   4884 
   4885 
   4886 TEST(APIThrowMessageAndVerboseTryCatch) {
   4887   message_received = false;
   4888   v8::HandleScope scope(CcTest::isolate());
   4889   v8::V8::AddMessageListener(receive_message);
   4890   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4891   templ->Set(v8_str("ThrowFromC"),
   4892              v8::FunctionTemplate::New(ThrowFromC));
   4893   LocalContext context(0, templ);
   4894   v8::TryCatch try_catch;
   4895   try_catch.SetVerbose(true);
   4896   Local<Value> result = CompileRun("ThrowFromC();");
   4897   CHECK(try_catch.HasCaught());
   4898   CHECK(result.IsEmpty());
   4899   CHECK(message_received);
   4900   v8::V8::RemoveMessageListeners(receive_message);
   4901 }
   4902 
   4903 
   4904 TEST(APIStackOverflowAndVerboseTryCatch) {
   4905   message_received = false;
   4906   LocalContext context;
   4907   v8::HandleScope scope(context->GetIsolate());
   4908   v8::V8::AddMessageListener(receive_message);
   4909   v8::TryCatch try_catch;
   4910   try_catch.SetVerbose(true);
   4911   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
   4912   CHECK(try_catch.HasCaught());
   4913   CHECK(result.IsEmpty());
   4914   CHECK(message_received);
   4915   v8::V8::RemoveMessageListeners(receive_message);
   4916 }
   4917 
   4918 
   4919 THREADED_TEST(ExternalScriptException) {
   4920   v8::HandleScope scope(CcTest::isolate());
   4921   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4922   templ->Set(v8_str("ThrowFromC"),
   4923              v8::FunctionTemplate::New(ThrowFromC));
   4924   LocalContext context(0, templ);
   4925 
   4926   v8::TryCatch try_catch;
   4927   Local<Script> script
   4928       = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
   4929   Local<Value> result = script->Run();
   4930   CHECK(result.IsEmpty());
   4931   CHECK(try_catch.HasCaught());
   4932   String::Utf8Value exception_value(try_catch.Exception());
   4933   CHECK_EQ("konto", *exception_value);
   4934 }
   4935 
   4936 
   4937 
   4938 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4939   ApiTestFuzzer::Fuzz();
   4940   CHECK_EQ(4, args.Length());
   4941   int count = args[0]->Int32Value();
   4942   int cInterval = args[2]->Int32Value();
   4943   if (count == 0) {
   4944     args.GetIsolate()->ThrowException(v8_str("FromC"));
   4945     return;
   4946   } else {
   4947     Local<v8::Object> global =
   4948         args.GetIsolate()->GetCurrentContext()->Global();
   4949     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
   4950     v8::Handle<Value> argv[] = { v8_num(count - 1),
   4951                                  args[1],
   4952                                  args[2],
   4953                                  args[3] };
   4954     if (count % cInterval == 0) {
   4955       v8::TryCatch try_catch;
   4956       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
   4957       int expected = args[3]->Int32Value();
   4958       if (try_catch.HasCaught()) {
   4959         CHECK_EQ(expected, count);
   4960         CHECK(result.IsEmpty());
   4961         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   4962       } else {
   4963         CHECK_NE(expected, count);
   4964       }
   4965       args.GetReturnValue().Set(result);
   4966       return;
   4967     } else {
   4968       args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
   4969       return;
   4970     }
   4971   }
   4972 }
   4973 
   4974 
   4975 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4976   ApiTestFuzzer::Fuzz();
   4977   CHECK_EQ(3, args.Length());
   4978   bool equality = args[0]->BooleanValue();
   4979   int count = args[1]->Int32Value();
   4980   int expected = args[2]->Int32Value();
   4981   if (equality) {
   4982     CHECK_EQ(count, expected);
   4983   } else {
   4984     CHECK_NE(count, expected);
   4985   }
   4986 }
   4987 
   4988 
   4989 THREADED_TEST(EvalInTryFinally) {
   4990   LocalContext context;
   4991   v8::HandleScope scope(context->GetIsolate());
   4992   v8::TryCatch try_catch;
   4993   CompileRun("(function() {"
   4994              "  try {"
   4995              "    eval('asldkf (*&^&*^');"
   4996              "  } finally {"
   4997              "    return;"
   4998              "  }"
   4999              "})()");
   5000   CHECK(!try_catch.HasCaught());
   5001 }
   5002 
   5003 
   5004 // This test works by making a stack of alternating JavaScript and C
   5005 // activations.  These activations set up exception handlers with regular
   5006 // intervals, one interval for C activations and another for JavaScript
   5007 // activations.  When enough activations have been created an exception is
   5008 // thrown and we check that the right activation catches the exception and that
   5009 // no other activations do.  The right activation is always the topmost one with
   5010 // a handler, regardless of whether it is in JavaScript or C.
   5011 //
   5012 // The notation used to describe a test case looks like this:
   5013 //
   5014 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
   5015 //
   5016 // Each entry is an activation, either JS or C.  The index is the count at that
   5017 // level.  Stars identify activations with exception handlers, the @ identifies
   5018 // the exception handler that should catch the exception.
   5019 //
   5020 // BUG(271): Some of the exception propagation does not work on the
   5021 // ARM simulator because the simulator separates the C++ stack and the
   5022 // JS stack.  This test therefore fails on the simulator.  The test is
   5023 // not threaded to allow the threading tests to run on the simulator.
   5024 TEST(ExceptionOrder) {
   5025   v8::HandleScope scope(CcTest::isolate());
   5026   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5027   templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
   5028   templ->Set(v8_str("CThrowCountDown"),
   5029              v8::FunctionTemplate::New(CThrowCountDown));
   5030   LocalContext context(0, templ);
   5031   CompileRun(
   5032     "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
   5033     "  if (count == 0) throw 'FromJS';"
   5034     "  if (count % jsInterval == 0) {"
   5035     "    try {"
   5036     "      var value = CThrowCountDown(count - 1,"
   5037     "                                  jsInterval,"
   5038     "                                  cInterval,"
   5039     "                                  expected);"
   5040     "      check(false, count, expected);"
   5041     "      return value;"
   5042     "    } catch (e) {"
   5043     "      check(true, count, expected);"
   5044     "    }"
   5045     "  } else {"
   5046     "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
   5047     "  }"
   5048     "}");
   5049   Local<Function> fun =
   5050       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
   5051 
   5052   const int argc = 4;
   5053   //                             count      jsInterval cInterval  expected
   5054 
   5055   // *JS[4] *C[3] @JS[2] C[1] JS[0]
   5056   v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
   5057   fun->Call(fun, argc, a0);
   5058 
   5059   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
   5060   v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
   5061   fun->Call(fun, argc, a1);
   5062 
   5063   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
   5064   v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
   5065   fun->Call(fun, argc, a2);
   5066 
   5067   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
   5068   v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
   5069   fun->Call(fun, argc, a3);
   5070 
   5071   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
   5072   v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
   5073   fun->Call(fun, argc, a4);
   5074 
   5075   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
   5076   v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
   5077   fun->Call(fun, argc, a5);
   5078 }
   5079 
   5080 
   5081 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5082   ApiTestFuzzer::Fuzz();
   5083   CHECK_EQ(1, args.Length());
   5084   args.GetIsolate()->ThrowException(args[0]);
   5085 }
   5086 
   5087 
   5088 THREADED_TEST(ThrowValues) {
   5089   v8::HandleScope scope(CcTest::isolate());
   5090   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5091   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
   5092   LocalContext context(0, templ);
   5093   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   5094     "function Run(obj) {"
   5095     "  try {"
   5096     "    Throw(obj);"
   5097     "  } catch (e) {"
   5098     "    return e;"
   5099     "  }"
   5100     "  return 'no exception';"
   5101     "}"
   5102     "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
   5103   CHECK_EQ(5, result->Length());
   5104   CHECK(result->Get(v8::Integer::New(0))->IsString());
   5105   CHECK(result->Get(v8::Integer::New(1))->IsNumber());
   5106   CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
   5107   CHECK(result->Get(v8::Integer::New(2))->IsNumber());
   5108   CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
   5109   CHECK(result->Get(v8::Integer::New(3))->IsNull());
   5110   CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
   5111 }
   5112 
   5113 
   5114 THREADED_TEST(CatchZero) {
   5115   LocalContext context;
   5116   v8::HandleScope scope(context->GetIsolate());
   5117   v8::TryCatch try_catch;
   5118   CHECK(!try_catch.HasCaught());
   5119   Script::Compile(v8_str("throw 10"))->Run();
   5120   CHECK(try_catch.HasCaught());
   5121   CHECK_EQ(10, try_catch.Exception()->Int32Value());
   5122   try_catch.Reset();
   5123   CHECK(!try_catch.HasCaught());
   5124   Script::Compile(v8_str("throw 0"))->Run();
   5125   CHECK(try_catch.HasCaught());
   5126   CHECK_EQ(0, try_catch.Exception()->Int32Value());
   5127 }
   5128 
   5129 
   5130 THREADED_TEST(CatchExceptionFromWith) {
   5131   LocalContext context;
   5132   v8::HandleScope scope(context->GetIsolate());
   5133   v8::TryCatch try_catch;
   5134   CHECK(!try_catch.HasCaught());
   5135   Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
   5136   CHECK(try_catch.HasCaught());
   5137 }
   5138 
   5139 
   5140 THREADED_TEST(TryCatchAndFinallyHidingException) {
   5141   LocalContext context;
   5142   v8::HandleScope scope(context->GetIsolate());
   5143   v8::TryCatch try_catch;
   5144   CHECK(!try_catch.HasCaught());
   5145   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
   5146   CompileRun("f({toString: function() { throw 42; }});");
   5147   CHECK(!try_catch.HasCaught());
   5148 }
   5149 
   5150 
   5151 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5152   v8::TryCatch try_catch;
   5153 }
   5154 
   5155 
   5156 THREADED_TEST(TryCatchAndFinally) {
   5157   LocalContext context;
   5158   v8::HandleScope scope(context->GetIsolate());
   5159   context->Global()->Set(
   5160       v8_str("native_with_try_catch"),
   5161       v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
   5162   v8::TryCatch try_catch;
   5163   CHECK(!try_catch.HasCaught());
   5164   CompileRun(
   5165       "try {\n"
   5166       "  throw new Error('a');\n"
   5167       "} finally {\n"
   5168       "  native_with_try_catch();\n"
   5169       "}\n");
   5170   CHECK(try_catch.HasCaught());
   5171 }
   5172 
   5173 
   5174 static void TryCatchNestedHelper(int depth) {
   5175   if (depth > 0) {
   5176     v8::TryCatch try_catch;
   5177     try_catch.SetVerbose(true);
   5178     TryCatchNestedHelper(depth - 1);
   5179     CHECK(try_catch.HasCaught());
   5180     try_catch.ReThrow();
   5181   } else {
   5182     CcTest::isolate()->ThrowException(v8_str("back"));
   5183   }
   5184 }
   5185 
   5186 
   5187 TEST(TryCatchNested) {
   5188   v8::V8::Initialize();
   5189   LocalContext context;
   5190   v8::HandleScope scope(context->GetIsolate());
   5191   v8::TryCatch try_catch;
   5192   TryCatchNestedHelper(5);
   5193   CHECK(try_catch.HasCaught());
   5194   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
   5195 }
   5196 
   5197 
   5198 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
   5199   CHECK(try_catch->HasCaught());
   5200   Handle<Message> message = try_catch->Message();
   5201   Handle<Value> resource = message->GetScriptResourceName();
   5202   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
   5203   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
   5204                      "Uncaught Error: a"));
   5205   CHECK_EQ(1, message->GetLineNumber());
   5206   CHECK_EQ(6, message->GetStartColumn());
   5207 }
   5208 
   5209 
   5210 void TryCatchMixedNestingHelper(
   5211     const v8::FunctionCallbackInfo<v8::Value>& args) {
   5212   ApiTestFuzzer::Fuzz();
   5213   v8::TryCatch try_catch;
   5214   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
   5215   CHECK(try_catch.HasCaught());
   5216   TryCatchMixedNestingCheck(&try_catch);
   5217   try_catch.ReThrow();
   5218 }
   5219 
   5220 
   5221 // This test ensures that an outer TryCatch in the following situation:
   5222 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
   5223 // does not clobber the Message object generated for the inner TryCatch.
   5224 // This exercises the ability of TryCatch.ReThrow() to restore the
   5225 // inner pending Message before throwing the exception again.
   5226 TEST(TryCatchMixedNesting) {
   5227   v8::HandleScope scope(CcTest::isolate());
   5228   v8::V8::Initialize();
   5229   v8::TryCatch try_catch;
   5230   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5231   templ->Set(v8_str("TryCatchMixedNestingHelper"),
   5232              v8::FunctionTemplate::New(TryCatchMixedNestingHelper));
   5233   LocalContext context(0, templ);
   5234   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
   5235   TryCatchMixedNestingCheck(&try_catch);
   5236 }
   5237 
   5238 
   5239 THREADED_TEST(Equality) {
   5240   LocalContext context;
   5241   v8::Isolate* isolate = context->GetIsolate();
   5242   v8::HandleScope scope(context->GetIsolate());
   5243   // Check that equality works at all before relying on CHECK_EQ
   5244   CHECK(v8_str("a")->Equals(v8_str("a")));
   5245   CHECK(!v8_str("a")->Equals(v8_str("b")));
   5246 
   5247   CHECK_EQ(v8_str("a"), v8_str("a"));
   5248   CHECK_NE(v8_str("a"), v8_str("b"));
   5249   CHECK_EQ(v8_num(1), v8_num(1));
   5250   CHECK_EQ(v8_num(1.00), v8_num(1));
   5251   CHECK_NE(v8_num(1), v8_num(2));
   5252 
   5253   // Assume String is not internalized.
   5254   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
   5255   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
   5256   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   5257   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   5258   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
   5259   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
   5260   Local<Value> not_a_number = v8_num(i::OS::nan_value());
   5261   CHECK(!not_a_number->StrictEquals(not_a_number));
   5262   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
   5263   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
   5264 
   5265   v8::Handle<v8::Object> obj = v8::Object::New();
   5266   v8::Persistent<v8::Object> alias(isolate, obj);
   5267   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
   5268   alias.Reset();
   5269 
   5270   CHECK(v8_str("a")->SameValue(v8_str("a")));
   5271   CHECK(!v8_str("a")->SameValue(v8_str("b")));
   5272   CHECK(!v8_str("5")->SameValue(v8_num(5)));
   5273   CHECK(v8_num(1)->SameValue(v8_num(1)));
   5274   CHECK(!v8_num(1)->SameValue(v8_num(2)));
   5275   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
   5276   CHECK(not_a_number->SameValue(not_a_number));
   5277   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
   5278   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
   5279 }
   5280 
   5281 
   5282 THREADED_TEST(MultiRun) {
   5283   LocalContext context;
   5284   v8::HandleScope scope(context->GetIsolate());
   5285   Local<Script> script = Script::Compile(v8_str("x"));
   5286   for (int i = 0; i < 10; i++)
   5287     script->Run();
   5288 }
   5289 
   5290 
   5291 static void GetXValue(Local<String> name,
   5292                       const v8::PropertyCallbackInfo<v8::Value>& info) {
   5293   ApiTestFuzzer::Fuzz();
   5294   CHECK_EQ(info.Data(), v8_str("donut"));
   5295   CHECK_EQ(name, v8_str("x"));
   5296   info.GetReturnValue().Set(name);
   5297 }
   5298 
   5299 
   5300 THREADED_TEST(SimplePropertyRead) {
   5301   LocalContext context;
   5302   v8::HandleScope scope(context->GetIsolate());
   5303   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5304   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   5305   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5306   Local<Script> script = Script::Compile(v8_str("obj.x"));
   5307   for (int i = 0; i < 10; i++) {
   5308     Local<Value> result = script->Run();
   5309     CHECK_EQ(result, v8_str("x"));
   5310   }
   5311 }
   5312 
   5313 
   5314 THREADED_TEST(DefinePropertyOnAPIAccessor) {
   5315   LocalContext context;
   5316   v8::HandleScope scope(context->GetIsolate());
   5317   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5318   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   5319   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5320 
   5321   // Uses getOwnPropertyDescriptor to check the configurable status
   5322   Local<Script> script_desc
   5323     = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
   5324                              "obj, 'x');"
   5325                              "prop.configurable;"));
   5326   Local<Value> result = script_desc->Run();
   5327   CHECK_EQ(result->BooleanValue(), true);
   5328 
   5329   // Redefine get - but still configurable
   5330   Local<Script> script_define
   5331     = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
   5332                              "            configurable: true };"
   5333                              "Object.defineProperty(obj, 'x', desc);"
   5334                              "obj.x"));
   5335   result = script_define->Run();
   5336   CHECK_EQ(result, v8_num(42));
   5337 
   5338   // Check that the accessor is still configurable
   5339   result = script_desc->Run();
   5340   CHECK_EQ(result->BooleanValue(), true);
   5341 
   5342   // Redefine to a non-configurable
   5343   script_define
   5344     = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
   5345                              "             configurable: false };"
   5346                              "Object.defineProperty(obj, 'x', desc);"
   5347                              "obj.x"));
   5348   result = script_define->Run();
   5349   CHECK_EQ(result, v8_num(43));
   5350   result = script_desc->Run();
   5351   CHECK_EQ(result->BooleanValue(), false);
   5352 
   5353   // Make sure that it is not possible to redefine again
   5354   v8::TryCatch try_catch;
   5355   result = script_define->Run();
   5356   CHECK(try_catch.HasCaught());
   5357   String::Utf8Value exception_value(try_catch.Exception());
   5358   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5359 }
   5360 
   5361 
   5362 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
   5363   v8::HandleScope scope(CcTest::isolate());
   5364   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5365   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   5366   LocalContext context;
   5367   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5368 
   5369   Local<Script> script_desc = Script::Compile(v8_str("var prop ="
   5370                                     "Object.getOwnPropertyDescriptor( "
   5371                                     "obj, 'x');"
   5372                                     "prop.configurable;"));
   5373   Local<Value> result = script_desc->Run();
   5374   CHECK_EQ(result->BooleanValue(), true);
   5375 
   5376   Local<Script> script_define =
   5377     Script::Compile(v8_str("var desc = {get: function(){return 42; },"
   5378                            "            configurable: true };"
   5379                            "Object.defineProperty(obj, 'x', desc);"
   5380                            "obj.x"));
   5381   result = script_define->Run();
   5382   CHECK_EQ(result, v8_num(42));
   5383 
   5384 
   5385   result = script_desc->Run();
   5386   CHECK_EQ(result->BooleanValue(), true);
   5387 
   5388 
   5389   script_define =
   5390     Script::Compile(v8_str("var desc = {get: function(){return 43; },"
   5391                            "            configurable: false };"
   5392                            "Object.defineProperty(obj, 'x', desc);"
   5393                            "obj.x"));
   5394   result = script_define->Run();
   5395   CHECK_EQ(result, v8_num(43));
   5396   result = script_desc->Run();
   5397 
   5398   CHECK_EQ(result->BooleanValue(), false);
   5399 
   5400   v8::TryCatch try_catch;
   5401   result = script_define->Run();
   5402   CHECK(try_catch.HasCaught());
   5403   String::Utf8Value exception_value(try_catch.Exception());
   5404   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5405 }
   5406 
   5407 
   5408 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
   5409                                                 char const* name) {
   5410   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
   5411 }
   5412 
   5413 
   5414 THREADED_TEST(DefineAPIAccessorOnObject) {
   5415   v8::HandleScope scope(CcTest::isolate());
   5416   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5417   LocalContext context;
   5418 
   5419   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5420   CompileRun("var obj2 = {};");
   5421 
   5422   CHECK(CompileRun("obj1.x")->IsUndefined());
   5423   CHECK(CompileRun("obj2.x")->IsUndefined());
   5424 
   5425   CHECK(GetGlobalProperty(&context, "obj1")->
   5426       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5427 
   5428   ExpectString("obj1.x", "x");
   5429   CHECK(CompileRun("obj2.x")->IsUndefined());
   5430 
   5431   CHECK(GetGlobalProperty(&context, "obj2")->
   5432       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5433 
   5434   ExpectString("obj1.x", "x");
   5435   ExpectString("obj2.x", "x");
   5436 
   5437   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5438   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5439 
   5440   CompileRun("Object.defineProperty(obj1, 'x',"
   5441              "{ get: function() { return 'y'; }, configurable: true })");
   5442 
   5443   ExpectString("obj1.x", "y");
   5444   ExpectString("obj2.x", "x");
   5445 
   5446   CompileRun("Object.defineProperty(obj2, 'x',"
   5447              "{ get: function() { return 'y'; }, configurable: true })");
   5448 
   5449   ExpectString("obj1.x", "y");
   5450   ExpectString("obj2.x", "y");
   5451 
   5452   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5453   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5454 
   5455   CHECK(GetGlobalProperty(&context, "obj1")->
   5456       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5457   CHECK(GetGlobalProperty(&context, "obj2")->
   5458       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5459 
   5460   ExpectString("obj1.x", "x");
   5461   ExpectString("obj2.x", "x");
   5462 
   5463   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5464   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5465 
   5466   // Define getters/setters, but now make them not configurable.
   5467   CompileRun("Object.defineProperty(obj1, 'x',"
   5468              "{ get: function() { return 'z'; }, configurable: false })");
   5469   CompileRun("Object.defineProperty(obj2, 'x',"
   5470              "{ get: function() { return 'z'; }, configurable: false })");
   5471 
   5472   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5473   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5474 
   5475   ExpectString("obj1.x", "z");
   5476   ExpectString("obj2.x", "z");
   5477 
   5478   CHECK(!GetGlobalProperty(&context, "obj1")->
   5479       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5480   CHECK(!GetGlobalProperty(&context, "obj2")->
   5481       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5482 
   5483   ExpectString("obj1.x", "z");
   5484   ExpectString("obj2.x", "z");
   5485 }
   5486 
   5487 
   5488 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   5489   v8::HandleScope scope(CcTest::isolate());
   5490   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5491   LocalContext context;
   5492 
   5493   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5494   CompileRun("var obj2 = {};");
   5495 
   5496   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   5497         v8_str("x"),
   5498         GetXValue, NULL,
   5499         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   5500   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   5501         v8_str("x"),
   5502         GetXValue, NULL,
   5503         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   5504 
   5505   ExpectString("obj1.x", "x");
   5506   ExpectString("obj2.x", "x");
   5507 
   5508   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5509   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5510 
   5511   CHECK(!GetGlobalProperty(&context, "obj1")->
   5512       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5513   CHECK(!GetGlobalProperty(&context, "obj2")->
   5514       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5515 
   5516   {
   5517     v8::TryCatch try_catch;
   5518     CompileRun("Object.defineProperty(obj1, 'x',"
   5519         "{get: function() { return 'func'; }})");
   5520     CHECK(try_catch.HasCaught());
   5521     String::Utf8Value exception_value(try_catch.Exception());
   5522     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5523   }
   5524   {
   5525     v8::TryCatch try_catch;
   5526     CompileRun("Object.defineProperty(obj2, 'x',"
   5527         "{get: function() { return 'func'; }})");
   5528     CHECK(try_catch.HasCaught());
   5529     String::Utf8Value exception_value(try_catch.Exception());
   5530     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5531   }
   5532 }
   5533 
   5534 
   5535 static void Get239Value(Local<String> name,
   5536                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   5537   ApiTestFuzzer::Fuzz();
   5538   CHECK_EQ(info.Data(), v8_str("donut"));
   5539   CHECK_EQ(name, v8_str("239"));
   5540   info.GetReturnValue().Set(name);
   5541 }
   5542 
   5543 
   5544 THREADED_TEST(ElementAPIAccessor) {
   5545   v8::HandleScope scope(CcTest::isolate());
   5546   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5547   LocalContext context;
   5548 
   5549   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5550   CompileRun("var obj2 = {};");
   5551 
   5552   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   5553         v8_str("239"),
   5554         Get239Value, NULL,
   5555         v8_str("donut")));
   5556   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   5557         v8_str("239"),
   5558         Get239Value, NULL,
   5559         v8_str("donut")));
   5560 
   5561   ExpectString("obj1[239]", "239");
   5562   ExpectString("obj2[239]", "239");
   5563   ExpectString("obj1['239']", "239");
   5564   ExpectString("obj2['239']", "239");
   5565 }
   5566 
   5567 
   5568 v8::Persistent<Value> xValue;
   5569 
   5570 
   5571 static void SetXValue(Local<String> name,
   5572                       Local<Value> value,
   5573                       const v8::PropertyCallbackInfo<void>& info) {
   5574   CHECK_EQ(value, v8_num(4));
   5575   CHECK_EQ(info.Data(), v8_str("donut"));
   5576   CHECK_EQ(name, v8_str("x"));
   5577   CHECK(xValue.IsEmpty());
   5578   xValue.Reset(info.GetIsolate(), value);
   5579 }
   5580 
   5581 
   5582 THREADED_TEST(SimplePropertyWrite) {
   5583   v8::HandleScope scope(CcTest::isolate());
   5584   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5585   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
   5586   LocalContext context;
   5587   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5588   Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
   5589   for (int i = 0; i < 10; i++) {
   5590     CHECK(xValue.IsEmpty());
   5591     script->Run();
   5592     CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
   5593     xValue.Reset();
   5594   }
   5595 }
   5596 
   5597 
   5598 THREADED_TEST(SetterOnly) {
   5599   v8::HandleScope scope(CcTest::isolate());
   5600   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5601   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
   5602   LocalContext context;
   5603   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5604   Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
   5605   for (int i = 0; i < 10; i++) {
   5606     CHECK(xValue.IsEmpty());
   5607     script->Run();
   5608     CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
   5609     xValue.Reset();
   5610   }
   5611 }
   5612 
   5613 
   5614 THREADED_TEST(NoAccessors) {
   5615   v8::HandleScope scope(CcTest::isolate());
   5616   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5617   templ->SetAccessor(v8_str("x"),
   5618                      static_cast<v8::AccessorGetterCallback>(NULL),
   5619                      NULL,
   5620                      v8_str("donut"));
   5621   LocalContext context;
   5622   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5623   Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
   5624   for (int i = 0; i < 10; i++) {
   5625     script->Run();
   5626   }
   5627 }
   5628 
   5629 
   5630 static void XPropertyGetter(Local<String> property,
   5631                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   5632   ApiTestFuzzer::Fuzz();
   5633   CHECK(info.Data()->IsUndefined());
   5634   info.GetReturnValue().Set(property);
   5635 }
   5636 
   5637 
   5638 THREADED_TEST(NamedInterceptorPropertyRead) {
   5639   v8::HandleScope scope(CcTest::isolate());
   5640   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5641   templ->SetNamedPropertyHandler(XPropertyGetter);
   5642   LocalContext context;
   5643   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5644   Local<Script> script = Script::Compile(v8_str("obj.x"));
   5645   for (int i = 0; i < 10; i++) {
   5646     Local<Value> result = script->Run();
   5647     CHECK_EQ(result, v8_str("x"));
   5648   }
   5649 }
   5650 
   5651 
   5652 THREADED_TEST(NamedInterceptorDictionaryIC) {
   5653   v8::HandleScope scope(CcTest::isolate());
   5654   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5655   templ->SetNamedPropertyHandler(XPropertyGetter);
   5656   LocalContext context;
   5657   // Create an object with a named interceptor.
   5658   context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
   5659   Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
   5660   for (int i = 0; i < 10; i++) {
   5661     Local<Value> result = script->Run();
   5662     CHECK_EQ(result, v8_str("x"));
   5663   }
   5664   // Create a slow case object and a function accessing a property in
   5665   // that slow case object (with dictionary probing in generated
   5666   // code). Then force object with a named interceptor into slow-case,
   5667   // pass it to the function, and check that the interceptor is called
   5668   // instead of accessing the local property.
   5669   Local<Value> result =
   5670       CompileRun("function get_x(o) { return o.x; };"
   5671                  "var obj = { x : 42, y : 0 };"
   5672                  "delete obj.y;"
   5673                  "for (var i = 0; i < 10; i++) get_x(obj);"
   5674                  "interceptor_obj.x = 42;"
   5675                  "interceptor_obj.y = 10;"
   5676                  "delete interceptor_obj.y;"
   5677                  "get_x(interceptor_obj)");
   5678   CHECK_EQ(result, v8_str("x"));
   5679 }
   5680 
   5681 
   5682 THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
   5683   v8::Isolate* isolate = CcTest::isolate();
   5684   v8::HandleScope scope(isolate);
   5685   v8::Local<Context> context1 = Context::New(isolate);
   5686 
   5687   context1->Enter();
   5688   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5689   templ->SetNamedPropertyHandler(XPropertyGetter);
   5690   // Create an object with a named interceptor.
   5691   v8::Local<v8::Object> object = templ->NewInstance();
   5692   context1->Global()->Set(v8_str("interceptor_obj"), object);
   5693 
   5694   // Force the object into the slow case.
   5695   CompileRun("interceptor_obj.y = 0;"
   5696              "delete interceptor_obj.y;");
   5697   context1->Exit();
   5698 
   5699   {
   5700     // Introduce the object into a different context.
   5701     // Repeat named loads to exercise ICs.
   5702     LocalContext context2;
   5703     context2->Global()->Set(v8_str("interceptor_obj"), object);
   5704     Local<Value> result =
   5705       CompileRun("function get_x(o) { return o.x; }"
   5706                  "interceptor_obj.x = 42;"
   5707                  "for (var i=0; i != 10; i++) {"
   5708                  "  get_x(interceptor_obj);"
   5709                  "}"
   5710                  "get_x(interceptor_obj)");
   5711     // Check that the interceptor was actually invoked.
   5712     CHECK_EQ(result, v8_str("x"));
   5713   }
   5714 
   5715   // Return to the original context and force some object to the slow case
   5716   // to cause the NormalizedMapCache to verify.
   5717   context1->Enter();
   5718   CompileRun("var obj = { x : 0 }; delete obj.x;");
   5719   context1->Exit();
   5720 }
   5721 
   5722 
   5723 static void SetXOnPrototypeGetter(
   5724     Local<String> property,
   5725     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5726   // Set x on the prototype object and do not handle the get request.
   5727   v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
   5728   proto.As<v8::Object>()->Set(v8_str("x"), v8::Integer::New(23));
   5729 }
   5730 
   5731 
   5732 // This is a regression test for http://crbug.com/20104. Map
   5733 // transitions should not interfere with post interceptor lookup.
   5734 THREADED_TEST(NamedInterceptorMapTransitionRead) {
   5735   v8::HandleScope scope(CcTest::isolate());
   5736   Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
   5737   Local<v8::ObjectTemplate> instance_template
   5738       = function_template->InstanceTemplate();
   5739   instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
   5740   LocalContext context;
   5741   context->Global()->Set(v8_str("F"), function_template->GetFunction());
   5742   // Create an instance of F and introduce a map transition for x.
   5743   CompileRun("var o = new F(); o.x = 23;");
   5744   // Create an instance of F and invoke the getter. The result should be 23.
   5745   Local<Value> result = CompileRun("o = new F(); o.x");
   5746   CHECK_EQ(result->Int32Value(), 23);
   5747 }
   5748 
   5749 
   5750 static void IndexedPropertyGetter(
   5751     uint32_t index,
   5752     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5753   ApiTestFuzzer::Fuzz();
   5754   if (index == 37) {
   5755     info.GetReturnValue().Set(v8_num(625));
   5756   }
   5757 }
   5758 
   5759 
   5760 static void IndexedPropertySetter(
   5761     uint32_t index,
   5762     Local<Value> value,
   5763     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5764   ApiTestFuzzer::Fuzz();
   5765   if (index == 39) {
   5766     info.GetReturnValue().Set(value);
   5767   }
   5768 }
   5769 
   5770 
   5771 THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
   5772   v8::HandleScope scope(CcTest::isolate());
   5773   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5774   templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
   5775                                    IndexedPropertySetter);
   5776   LocalContext context;
   5777   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5778   Local<Script> getter_script = Script::Compile(v8_str(
   5779       "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
   5780   Local<Script> setter_script = Script::Compile(v8_str(
   5781       "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
   5782       "obj[17] = 23;"
   5783       "obj.foo;"));
   5784   Local<Script> interceptor_setter_script = Script::Compile(v8_str(
   5785       "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
   5786       "obj[39] = 47;"
   5787       "obj.foo;"));  // This setter should not run, due to the interceptor.
   5788   Local<Script> interceptor_getter_script = Script::Compile(v8_str(
   5789       "obj[37];"));
   5790   Local<Value> result = getter_script->Run();
   5791   CHECK_EQ(v8_num(5), result);
   5792   result = setter_script->Run();
   5793   CHECK_EQ(v8_num(23), result);
   5794   result = interceptor_setter_script->Run();
   5795   CHECK_EQ(v8_num(23), result);
   5796   result = interceptor_getter_script->Run();
   5797   CHECK_EQ(v8_num(625), result);
   5798 }
   5799 
   5800 
   5801 static void UnboxedDoubleIndexedPropertyGetter(
   5802     uint32_t index,
   5803     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5804   ApiTestFuzzer::Fuzz();
   5805   if (index < 25) {
   5806     info.GetReturnValue().Set(v8_num(index));
   5807   }
   5808 }
   5809 
   5810 
   5811 static void UnboxedDoubleIndexedPropertySetter(
   5812     uint32_t index,
   5813     Local<Value> value,
   5814     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5815   ApiTestFuzzer::Fuzz();
   5816   if (index < 25) {
   5817     info.GetReturnValue().Set(v8_num(index));
   5818   }
   5819 }
   5820 
   5821 
   5822 void UnboxedDoubleIndexedPropertyEnumerator(
   5823     const v8::PropertyCallbackInfo<v8::Array>& info) {
   5824   // Force the list of returned keys to be stored in a FastDoubleArray.
   5825   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
   5826       "keys = new Array(); keys[125000] = 1;"
   5827       "for(i = 0; i < 80000; i++) { keys[i] = i; };"
   5828       "keys.length = 25; keys;"));
   5829   Local<Value> result = indexed_property_names_script->Run();
   5830   info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
   5831 }
   5832 
   5833 
   5834 // Make sure that the the interceptor code in the runtime properly handles
   5835 // merging property name lists for double-array-backed arrays.
   5836 THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
   5837   v8::HandleScope scope(CcTest::isolate());
   5838   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5839   templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
   5840                                    UnboxedDoubleIndexedPropertySetter,
   5841                                    0,
   5842                                    0,
   5843                                    UnboxedDoubleIndexedPropertyEnumerator);
   5844   LocalContext context;
   5845   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5846   // When obj is created, force it to be Stored in a FastDoubleArray.
   5847   Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
   5848       "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
   5849       "key_count = 0; "
   5850       "for (x in obj) {key_count++;};"
   5851       "obj;"));
   5852   Local<Value> result = create_unboxed_double_script->Run();
   5853   CHECK(result->ToObject()->HasRealIndexedProperty(2000));
   5854   Local<Script> key_count_check = Script::Compile(v8_str(
   5855       "key_count;"));
   5856   result = key_count_check->Run();
   5857   CHECK_EQ(v8_num(40013), result);
   5858 }
   5859 
   5860 
   5861 void NonStrictArgsIndexedPropertyEnumerator(
   5862     const v8::PropertyCallbackInfo<v8::Array>& info) {
   5863   // Force the list of returned keys to be stored in a Arguments object.
   5864   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
   5865       "function f(w,x) {"
   5866       " return arguments;"
   5867       "}"
   5868       "keys = f(0, 1, 2, 3);"
   5869       "keys;"));
   5870   Local<Object> result =
   5871       Local<Object>::Cast(indexed_property_names_script->Run());
   5872   // Have to populate the handle manually, as it's not Cast-able.
   5873   i::Handle<i::JSObject> o =
   5874       v8::Utils::OpenHandle<Object, i::JSObject>(result);
   5875   i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
   5876   info.GetReturnValue().Set(v8::Utils::ToLocal(array));
   5877 }
   5878 
   5879 
   5880 static void NonStrictIndexedPropertyGetter(
   5881     uint32_t index,
   5882     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5883   ApiTestFuzzer::Fuzz();
   5884   if (index < 4) {
   5885     info.GetReturnValue().Set(v8_num(index));
   5886   }
   5887 }
   5888 
   5889 
   5890 // Make sure that the the interceptor code in the runtime properly handles
   5891 // merging property name lists for non-string arguments arrays.
   5892 THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
   5893   v8::HandleScope scope(CcTest::isolate());
   5894   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5895   templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
   5896                                    0,
   5897                                    0,
   5898                                    0,
   5899                                    NonStrictArgsIndexedPropertyEnumerator);
   5900   LocalContext context;
   5901   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5902   Local<Script> create_args_script =
   5903       Script::Compile(v8_str(
   5904           "var key_count = 0;"
   5905           "for (x in obj) {key_count++;} key_count;"));
   5906   Local<Value> result = create_args_script->Run();
   5907   CHECK_EQ(v8_num(4), result);
   5908 }
   5909 
   5910 
   5911 static void IdentityIndexedPropertyGetter(
   5912     uint32_t index,
   5913     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5914   info.GetReturnValue().Set(index);
   5915 }
   5916 
   5917 
   5918 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
   5919   v8::HandleScope scope(CcTest::isolate());
   5920   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5921   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5922 
   5923   LocalContext context;
   5924   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5925 
   5926   // Check fast object case.
   5927   const char* fast_case_code =
   5928       "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
   5929   ExpectString(fast_case_code, "0");
   5930 
   5931   // Check slow case.
   5932   const char* slow_case_code =
   5933       "obj.x = 1; delete obj.x;"
   5934       "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
   5935   ExpectString(slow_case_code, "1");
   5936 }
   5937 
   5938 
   5939 THREADED_TEST(IndexedInterceptorWithNoSetter) {
   5940   v8::HandleScope scope(CcTest::isolate());
   5941   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5942   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5943 
   5944   LocalContext context;
   5945   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5946 
   5947   const char* code =
   5948       "try {"
   5949       "  obj[0] = 239;"
   5950       "  for (var i = 0; i < 100; i++) {"
   5951       "    var v = obj[0];"
   5952       "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5953       "  }"
   5954       "  'PASSED'"
   5955       "} catch(e) {"
   5956       "  e"
   5957       "}";
   5958   ExpectString(code, "PASSED");
   5959 }
   5960 
   5961 
   5962 THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
   5963   v8::HandleScope scope(CcTest::isolate());
   5964   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5965   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5966 
   5967   LocalContext context;
   5968   Local<v8::Object> obj = templ->NewInstance();
   5969   obj->TurnOnAccessCheck();
   5970   context->Global()->Set(v8_str("obj"), obj);
   5971 
   5972   const char* code =
   5973       "try {"
   5974       "  for (var i = 0; i < 100; i++) {"
   5975       "    var v = obj[0];"
   5976       "    if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5977       "  }"
   5978       "  'PASSED'"
   5979       "} catch(e) {"
   5980       "  e"
   5981       "}";
   5982   ExpectString(code, "PASSED");
   5983 }
   5984 
   5985 
   5986 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
   5987   i::FLAG_allow_natives_syntax = true;
   5988   v8::HandleScope scope(CcTest::isolate());
   5989   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5990   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5991 
   5992   LocalContext context;
   5993   Local<v8::Object> obj = templ->NewInstance();
   5994   context->Global()->Set(v8_str("obj"), obj);
   5995 
   5996   const char* code =
   5997       "try {"
   5998       "  for (var i = 0; i < 100; i++) {"
   5999       "    var expected = i;"
   6000       "    if (i == 5) {"
   6001       "      %EnableAccessChecks(obj);"
   6002       "      expected = undefined;"
   6003       "    }"
   6004       "    var v = obj[i];"
   6005       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6006       "    if (i == 5) %DisableAccessChecks(obj);"
   6007       "  }"
   6008       "  'PASSED'"
   6009       "} catch(e) {"
   6010       "  e"
   6011       "}";
   6012   ExpectString(code, "PASSED");
   6013 }
   6014 
   6015 
   6016 THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
   6017   v8::HandleScope scope(CcTest::isolate());
   6018   Local<ObjectTemplate> templ = ObjectTemplate::New();
   6019   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6020 
   6021   LocalContext context;
   6022   Local<v8::Object> obj = templ->NewInstance();
   6023   context->Global()->Set(v8_str("obj"), obj);
   6024 
   6025   const char* code =
   6026       "try {"
   6027       "  for (var i = 0; i < 100; i++) {"
   6028       "    var v = obj[i];"
   6029       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6030       "  }"
   6031       "  'PASSED'"
   6032       "} catch(e) {"
   6033       "  e"
   6034       "}";
   6035   ExpectString(code, "PASSED");
   6036 }
   6037 
   6038 
   6039 THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
   6040   v8::HandleScope scope(CcTest::isolate());
   6041   Local<ObjectTemplate> templ = ObjectTemplate::New();
   6042   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6043 
   6044   LocalContext context;
   6045   Local<v8::Object> obj = templ->NewInstance();
   6046   context->Global()->Set(v8_str("obj"), obj);
   6047 
   6048   const char* code =
   6049       "try {"
   6050       "  for (var i = 0; i < 100; i++) {"
   6051       "    var expected = i;"
   6052       "    var key = i;"
   6053       "    if (i == 25) {"
   6054       "       key = -1;"
   6055       "       expected = undefined;"
   6056       "    }"
   6057       "    if (i == 50) {"
   6058       "       /* probe minimal Smi number on 32-bit platforms */"
   6059       "       key = -(1 << 30);"
   6060       "       expected = undefined;"
   6061       "    }"
   6062       "    if (i == 75) {"
   6063       "       /* probe minimal Smi number on 64-bit platforms */"
   6064       "       key = 1 << 31;"
   6065       "       expected = undefined;"
   6066       "    }"
   6067       "    var v = obj[key];"
   6068       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6069       "  }"
   6070       "  'PASSED'"
   6071       "} catch(e) {"
   6072       "  e"
   6073       "}";
   6074   ExpectString(code, "PASSED");
   6075 }
   6076 
   6077 
   6078 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
   6079   v8::HandleScope scope(CcTest::isolate());
   6080   Local<ObjectTemplate> templ = ObjectTemplate::New();
   6081   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6082 
   6083   LocalContext context;
   6084   Local<v8::Object> obj = templ->NewInstance();
   6085   context->Global()->Set(v8_str("obj"), obj);
   6086 
   6087   const char* code =
   6088       "try {"
   6089       "  for (var i = 0; i < 100; i++) {"
   6090       "    var expected = i;"
   6091       "    var key = i;"
   6092       "    if (i == 50) {"
   6093       "       key = 'foobar';"
   6094       "       expected = undefined;"
   6095       "    }"
   6096       "    var v = obj[key];"
   6097       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6098       "  }"
   6099       "  'PASSED'"
   6100       "} catch(e) {"
   6101       "  e"
   6102       "}";
   6103   ExpectString(code, "PASSED");
   6104 }
   6105 
   6106 
   6107 THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
   6108   v8::HandleScope scope(CcTest::isolate());
   6109   Local<ObjectTemplate> templ = ObjectTemplate::New();
   6110   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6111 
   6112   LocalContext context;
   6113   Local<v8::Object> obj = templ->NewInstance();
   6114   context->Global()->Set(v8_str("obj"), obj);
   6115 
   6116   const char* code =
   6117       "var original = obj;"
   6118       "try {"
   6119       "  for (var i = 0; i < 100; i++) {"
   6120       "    var expected = i;"
   6121       "    if (i == 50) {"
   6122       "       obj = {50: 'foobar'};"
   6123       "       expected = 'foobar';"
   6124       "    }"
   6125       "    var v = obj[i];"
   6126       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6127       "    if (i == 50) obj = original;"
   6128       "  }"
   6129       "  'PASSED'"
   6130       "} catch(e) {"
   6131       "  e"
   6132       "}";
   6133   ExpectString(code, "PASSED");
   6134 }
   6135 
   6136 
   6137 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
   6138   v8::HandleScope scope(CcTest::isolate());
   6139   Local<ObjectTemplate> templ = ObjectTemplate::New();
   6140   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6141 
   6142   LocalContext context;
   6143   Local<v8::Object> obj = templ->NewInstance();
   6144   context->Global()->Set(v8_str("obj"), obj);
   6145 
   6146   const char* code =
   6147       "var original = obj;"
   6148       "try {"
   6149       "  for (var i = 0; i < 100; i++) {"
   6150       "    var expected = i;"
   6151       "    if (i == 5) {"
   6152       "       obj = 239;"
   6153       "       expected = undefined;"
   6154       "    }"
   6155       "    var v = obj[i];"
   6156       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6157       "    if (i == 5) obj = original;"
   6158       "  }"
   6159       "  'PASSED'"
   6160       "} catch(e) {"
   6161       "  e"
   6162       "}";
   6163   ExpectString(code, "PASSED");
   6164 }
   6165 
   6166 
   6167 THREADED_TEST(IndexedInterceptorOnProto) {
   6168   v8::HandleScope scope(CcTest::isolate());
   6169   Local<ObjectTemplate> templ = ObjectTemplate::New();
   6170   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6171 
   6172   LocalContext context;
   6173   Local<v8::Object> obj = templ->NewInstance();
   6174   context->Global()->Set(v8_str("obj"), obj);
   6175 
   6176   const char* code =
   6177       "var o = {__proto__: obj};"
   6178       "try {"
   6179       "  for (var i = 0; i < 100; i++) {"
   6180       "    var v = o[i];"
   6181       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6182       "  }"
   6183       "  'PASSED'"
   6184       "} catch(e) {"
   6185       "  e"
   6186       "}";
   6187   ExpectString(code, "PASSED");
   6188 }
   6189 
   6190 
   6191 THREADED_TEST(MultiContexts) {
   6192   v8::HandleScope scope(CcTest::isolate());
   6193   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
   6194   templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
   6195 
   6196   Local<String> password = v8_str("Password");
   6197 
   6198   // Create an environment
   6199   LocalContext context0(0, templ);
   6200   context0->SetSecurityToken(password);
   6201   v8::Handle<v8::Object> global0 = context0->Global();
   6202   global0->Set(v8_str("custom"), v8_num(1234));
   6203   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   6204 
   6205   // Create an independent environment
   6206   LocalContext context1(0, templ);
   6207   context1->SetSecurityToken(password);
   6208   v8::Handle<v8::Object> global1 = context1->Global();
   6209   global1->Set(v8_str("custom"), v8_num(1234));
   6210   CHECK_NE(global0, global1);
   6211   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   6212   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
   6213 
   6214   // Now create a new context with the old global
   6215   LocalContext context2(0, templ, global1);
   6216   context2->SetSecurityToken(password);
   6217   v8::Handle<v8::Object> global2 = context2->Global();
   6218   CHECK_EQ(global1, global2);
   6219   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
   6220   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
   6221 }
   6222 
   6223 
   6224 THREADED_TEST(FunctionPrototypeAcrossContexts) {
   6225   // Make sure that functions created by cloning boilerplates cannot
   6226   // communicate through their __proto__ field.
   6227 
   6228   v8::HandleScope scope(CcTest::isolate());
   6229 
   6230   LocalContext env0;
   6231   v8::Handle<v8::Object> global0 =
   6232       env0->Global();
   6233   v8::Handle<v8::Object> object0 =
   6234       global0->Get(v8_str("Object")).As<v8::Object>();
   6235   v8::Handle<v8::Object> tostring0 =
   6236       object0->Get(v8_str("toString")).As<v8::Object>();
   6237   v8::Handle<v8::Object> proto0 =
   6238       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
   6239   proto0->Set(v8_str("custom"), v8_num(1234));
   6240 
   6241   LocalContext env1;
   6242   v8::Handle<v8::Object> global1 =
   6243       env1->Global();
   6244   v8::Handle<v8::Object> object1 =
   6245       global1->Get(v8_str("Object")).As<v8::Object>();
   6246   v8::Handle<v8::Object> tostring1 =
   6247       object1->Get(v8_str("toString")).As<v8::Object>();
   6248   v8::Handle<v8::Object> proto1 =
   6249       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
   6250   CHECK(!proto1->Has(v8_str("custom")));
   6251 }
   6252 
   6253 
   6254 THREADED_TEST(Regress892105) {
   6255   // Make sure that object and array literals created by cloning
   6256   // boilerplates cannot communicate through their __proto__
   6257   // field. This is rather difficult to check, but we try to add stuff
   6258   // to Object.prototype and Array.prototype and create a new
   6259   // environment. This should succeed.
   6260 
   6261   v8::HandleScope scope(CcTest::isolate());
   6262 
   6263   Local<String> source = v8_str("Object.prototype.obj = 1234;"
   6264                                 "Array.prototype.arr = 4567;"
   6265                                 "8901");
   6266 
   6267   LocalContext env0;
   6268   Local<Script> script0 = Script::Compile(source);
   6269   CHECK_EQ(8901.0, script0->Run()->NumberValue());
   6270 
   6271   LocalContext env1;
   6272   Local<Script> script1 = Script::Compile(source);
   6273   CHECK_EQ(8901.0, script1->Run()->NumberValue());
   6274 }
   6275 
   6276 
   6277 THREADED_TEST(UndetectableObject) {
   6278   LocalContext env;
   6279   v8::HandleScope scope(env->GetIsolate());
   6280 
   6281   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   6282   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6283 
   6284   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   6285   env->Global()->Set(v8_str("undetectable"), obj);
   6286 
   6287   ExpectString("undetectable.toString()", "[object Object]");
   6288   ExpectString("typeof undetectable", "undefined");
   6289   ExpectString("typeof(undetectable)", "undefined");
   6290   ExpectBoolean("typeof undetectable == 'undefined'", true);
   6291   ExpectBoolean("typeof undetectable == 'object'", false);
   6292   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   6293   ExpectBoolean("!undetectable", true);
   6294 
   6295   ExpectObject("true&&undetectable", obj);
   6296   ExpectBoolean("false&&undetectable", false);
   6297   ExpectBoolean("true||undetectable", true);
   6298   ExpectObject("false||undetectable", obj);
   6299 
   6300   ExpectObject("undetectable&&true", obj);
   6301   ExpectObject("undetectable&&false", obj);
   6302   ExpectBoolean("undetectable||true", true);
   6303   ExpectBoolean("undetectable||false", false);
   6304 
   6305   ExpectBoolean("undetectable==null", true);
   6306   ExpectBoolean("null==undetectable", true);
   6307   ExpectBoolean("undetectable==undefined", true);
   6308   ExpectBoolean("undefined==undetectable", true);
   6309   ExpectBoolean("undetectable==undetectable", true);
   6310 
   6311 
   6312   ExpectBoolean("undetectable===null", false);
   6313   ExpectBoolean("null===undetectable", false);
   6314   ExpectBoolean("undetectable===undefined", false);
   6315   ExpectBoolean("undefined===undetectable", false);
   6316   ExpectBoolean("undetectable===undetectable", true);
   6317 }
   6318 
   6319 
   6320 THREADED_TEST(VoidLiteral) {
   6321   LocalContext env;
   6322   v8::HandleScope scope(env->GetIsolate());
   6323 
   6324   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   6325   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6326 
   6327   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   6328   env->Global()->Set(v8_str("undetectable"), obj);
   6329 
   6330   ExpectBoolean("undefined == void 0", true);
   6331   ExpectBoolean("undetectable == void 0", true);
   6332   ExpectBoolean("null == void 0", true);
   6333   ExpectBoolean("undefined === void 0", true);
   6334   ExpectBoolean("undetectable === void 0", false);
   6335   ExpectBoolean("null === void 0", false);
   6336 
   6337   ExpectBoolean("void 0 == undefined", true);
   6338   ExpectBoolean("void 0 == undetectable", true);
   6339   ExpectBoolean("void 0 == null", true);
   6340   ExpectBoolean("void 0 === undefined", true);
   6341   ExpectBoolean("void 0 === undetectable", false);
   6342   ExpectBoolean("void 0 === null", false);
   6343 
   6344   ExpectString("(function() {"
   6345                "  try {"
   6346                "    return x === void 0;"
   6347                "  } catch(e) {"
   6348                "    return e.toString();"
   6349                "  }"
   6350                "})()",
   6351                "ReferenceError: x is not defined");
   6352   ExpectString("(function() {"
   6353                "  try {"
   6354                "    return void 0 === x;"
   6355                "  } catch(e) {"
   6356                "    return e.toString();"
   6357                "  }"
   6358                "})()",
   6359                "ReferenceError: x is not defined");
   6360 }
   6361 
   6362 
   6363 THREADED_TEST(ExtensibleOnUndetectable) {
   6364   LocalContext env;
   6365   v8::HandleScope scope(env->GetIsolate());
   6366 
   6367   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   6368   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6369 
   6370   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   6371   env->Global()->Set(v8_str("undetectable"), obj);
   6372 
   6373   Local<String> source = v8_str("undetectable.x = 42;"
   6374                                 "undetectable.x");
   6375 
   6376   Local<Script> script = Script::Compile(source);
   6377 
   6378   CHECK_EQ(v8::Integer::New(42), script->Run());
   6379 
   6380   ExpectBoolean("Object.isExtensible(undetectable)", true);
   6381 
   6382   source = v8_str("Object.preventExtensions(undetectable);");
   6383   script = Script::Compile(source);
   6384   script->Run();
   6385   ExpectBoolean("Object.isExtensible(undetectable)", false);
   6386 
   6387   source = v8_str("undetectable.y = 2000;");
   6388   script = Script::Compile(source);
   6389   script->Run();
   6390   ExpectBoolean("undetectable.y == undefined", true);
   6391 }
   6392 
   6393 
   6394 
   6395 THREADED_TEST(UndetectableString) {
   6396   LocalContext env;
   6397   v8::HandleScope scope(env->GetIsolate());
   6398 
   6399   Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
   6400                                           String::kUndetectableString);
   6401   env->Global()->Set(v8_str("undetectable"), obj);
   6402 
   6403   ExpectString("undetectable", "foo");
   6404   ExpectString("typeof undetectable", "undefined");
   6405   ExpectString("typeof(undetectable)", "undefined");
   6406   ExpectBoolean("typeof undetectable == 'undefined'", true);
   6407   ExpectBoolean("typeof undetectable == 'string'", false);
   6408   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   6409   ExpectBoolean("!undetectable", true);
   6410 
   6411   ExpectObject("true&&undetectable", obj);
   6412   ExpectBoolean("false&&undetectable", false);
   6413   ExpectBoolean("true||undetectable", true);
   6414   ExpectObject("false||undetectable", obj);
   6415 
   6416   ExpectObject("undetectable&&true", obj);
   6417   ExpectObject("undetectable&&false", obj);
   6418   ExpectBoolean("undetectable||true", true);
   6419   ExpectBoolean("undetectable||false", false);
   6420 
   6421   ExpectBoolean("undetectable==null", true);
   6422   ExpectBoolean("null==undetectable", true);
   6423   ExpectBoolean("undetectable==undefined", true);
   6424   ExpectBoolean("undefined==undetectable", true);
   6425   ExpectBoolean("undetectable==undetectable", true);
   6426 
   6427 
   6428   ExpectBoolean("undetectable===null", false);
   6429   ExpectBoolean("null===undetectable", false);
   6430   ExpectBoolean("undetectable===undefined", false);
   6431   ExpectBoolean("undefined===undetectable", false);
   6432   ExpectBoolean("undetectable===undetectable", true);
   6433 }
   6434 
   6435 
   6436 TEST(UndetectableOptimized) {
   6437   i::FLAG_allow_natives_syntax = true;
   6438   LocalContext env;
   6439   v8::HandleScope scope(env->GetIsolate());
   6440 
   6441   Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
   6442                                           String::kUndetectableString);
   6443   env->Global()->Set(v8_str("undetectable"), obj);
   6444   env->Global()->Set(v8_str("detectable"), v8_str("bar"));
   6445 
   6446   ExpectString(
   6447       "function testBranch() {"
   6448       "  if (!%_IsUndetectableObject(undetectable)) throw 1;"
   6449       "  if (%_IsUndetectableObject(detectable)) throw 2;"
   6450       "}\n"
   6451       "function testBool() {"
   6452       "  var b1 = !%_IsUndetectableObject(undetectable);"
   6453       "  var b2 = %_IsUndetectableObject(detectable);"
   6454       "  if (b1) throw 3;"
   6455       "  if (b2) throw 4;"
   6456       "  return b1 == b2;"
   6457       "}\n"
   6458       "%OptimizeFunctionOnNextCall(testBranch);"
   6459       "%OptimizeFunctionOnNextCall(testBool);"
   6460       "for (var i = 0; i < 10; i++) {"
   6461       "  testBranch();"
   6462       "  testBool();"
   6463       "}\n"
   6464       "\"PASS\"",
   6465       "PASS");
   6466 }
   6467 
   6468 
   6469 template <typename T> static void USE(T) { }
   6470 
   6471 
   6472 // This test is not intended to be run, just type checked.
   6473 static inline void PersistentHandles(v8::Isolate* isolate) {
   6474   USE(PersistentHandles);
   6475   Local<String> str = v8_str("foo");
   6476   v8::Persistent<String> p_str(isolate, str);
   6477   p_str.Reset();
   6478   Local<Script> scr = Script::Compile(v8_str(""));
   6479   v8::Persistent<Script> p_scr(isolate, scr);
   6480   p_scr.Reset();
   6481   Local<ObjectTemplate> templ = ObjectTemplate::New();
   6482   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
   6483   p_templ.Reset();
   6484 }
   6485 
   6486 
   6487 static void HandleLogDelegator(
   6488     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6489   ApiTestFuzzer::Fuzz();
   6490 }
   6491 
   6492 
   6493 THREADED_TEST(GlobalObjectTemplate) {
   6494   v8::Isolate* isolate = CcTest::isolate();
   6495   v8::HandleScope handle_scope(isolate);
   6496   Local<ObjectTemplate> global_template = ObjectTemplate::New();
   6497   global_template->Set(v8_str("JSNI_Log"),
   6498                        v8::FunctionTemplate::New(HandleLogDelegator));
   6499   v8::Local<Context> context = Context::New(isolate, 0, global_template);
   6500   Context::Scope context_scope(context);
   6501   Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
   6502 }
   6503 
   6504 
   6505 static const char* kSimpleExtensionSource =
   6506   "function Foo() {"
   6507   "  return 4;"
   6508   "}";
   6509 
   6510 
   6511 THREADED_TEST(SimpleExtensions) {
   6512   v8::HandleScope handle_scope(CcTest::isolate());
   6513   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
   6514   const char* extension_names[] = { "simpletest" };
   6515   v8::ExtensionConfiguration extensions(1, extension_names);
   6516   v8::Handle<Context> context =
   6517       Context::New(CcTest::isolate(), &extensions);
   6518   Context::Scope lock(context);
   6519   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
   6520   CHECK_EQ(result, v8::Integer::New(4));
   6521 }
   6522 
   6523 
   6524 THREADED_TEST(NullExtensions) {
   6525   v8::HandleScope handle_scope(CcTest::isolate());
   6526   v8::RegisterExtension(new Extension("nulltest", NULL));
   6527   const char* extension_names[] = { "nulltest" };
   6528   v8::ExtensionConfiguration extensions(1, extension_names);
   6529   v8::Handle<Context> context =
   6530       Context::New(CcTest::isolate(), &extensions);
   6531   Context::Scope lock(context);
   6532   v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
   6533   CHECK_EQ(result, v8::Integer::New(4));
   6534 }
   6535 
   6536 
   6537 static const char* kEmbeddedExtensionSource =
   6538     "function Ret54321(){return 54321;}~~@@$"
   6539     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
   6540 static const int kEmbeddedExtensionSourceValidLen = 34;
   6541 
   6542 
   6543 THREADED_TEST(ExtensionMissingSourceLength) {
   6544   v8::HandleScope handle_scope(CcTest::isolate());
   6545   v8::RegisterExtension(new Extension("srclentest_fail",
   6546                                       kEmbeddedExtensionSource));
   6547   const char* extension_names[] = { "srclentest_fail" };
   6548   v8::ExtensionConfiguration extensions(1, extension_names);
   6549   v8::Handle<Context> context =
   6550       Context::New(CcTest::isolate(), &extensions);
   6551   CHECK_EQ(0, *context);
   6552 }
   6553 
   6554 
   6555 THREADED_TEST(ExtensionWithSourceLength) {
   6556   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
   6557        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
   6558     v8::HandleScope handle_scope(CcTest::isolate());
   6559     i::ScopedVector<char> extension_name(32);
   6560     i::OS::SNPrintF(extension_name, "ext #%d", source_len);
   6561     v8::RegisterExtension(new Extension(extension_name.start(),
   6562                                         kEmbeddedExtensionSource, 0, 0,
   6563                                         source_len));
   6564     const char* extension_names[1] = { extension_name.start() };
   6565     v8::ExtensionConfiguration extensions(1, extension_names);
   6566     v8::Handle<Context> context =
   6567       Context::New(CcTest::isolate(), &extensions);
   6568     if (source_len == kEmbeddedExtensionSourceValidLen) {
   6569       Context::Scope lock(context);
   6570       v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
   6571       CHECK_EQ(v8::Integer::New(54321), result);
   6572     } else {
   6573       // Anything but exactly the right length should fail to compile.
   6574       CHECK_EQ(0, *context);
   6575     }
   6576   }
   6577 }
   6578 
   6579 
   6580 static const char* kEvalExtensionSource1 =
   6581   "function UseEval1() {"
   6582   "  var x = 42;"
   6583   "  return eval('x');"
   6584   "}";
   6585 
   6586 
   6587 static const char* kEvalExtensionSource2 =
   6588   "(function() {"
   6589   "  var x = 42;"
   6590   "  function e() {"
   6591   "    return eval('x');"
   6592   "  }"
   6593   "  this.UseEval2 = e;"
   6594   "})()";
   6595 
   6596 
   6597 THREADED_TEST(UseEvalFromExtension) {
   6598   v8::HandleScope handle_scope(CcTest::isolate());
   6599   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
   6600   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
   6601   const char* extension_names[] = { "evaltest1", "evaltest2" };
   6602   v8::ExtensionConfiguration extensions(2, extension_names);
   6603   v8::Handle<Context> context =
   6604       Context::New(CcTest::isolate(), &extensions);
   6605   Context::Scope lock(context);
   6606   v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
   6607   CHECK_EQ(result, v8::Integer::New(42));
   6608   result = Script::Compile(v8_str("UseEval2()"))->Run();
   6609   CHECK_EQ(result, v8::Integer::New(42));
   6610 }
   6611 
   6612 
   6613 static const char* kWithExtensionSource1 =
   6614   "function UseWith1() {"
   6615   "  var x = 42;"
   6616   "  with({x:87}) { return x; }"
   6617   "}";
   6618 
   6619 
   6620 
   6621 static const char* kWithExtensionSource2 =
   6622   "(function() {"
   6623   "  var x = 42;"
   6624   "  function e() {"
   6625   "    with ({x:87}) { return x; }"
   6626   "  }"
   6627   "  this.UseWith2 = e;"
   6628   "})()";
   6629 
   6630 
   6631 THREADED_TEST(UseWithFromExtension) {
   6632   v8::HandleScope handle_scope(CcTest::isolate());
   6633   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
   6634   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
   6635   const char* extension_names[] = { "withtest1", "withtest2" };
   6636   v8::ExtensionConfiguration extensions(2, extension_names);
   6637   v8::Handle<Context> context =
   6638       Context::New(CcTest::isolate(), &extensions);
   6639   Context::Scope lock(context);
   6640   v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
   6641   CHECK_EQ(result, v8::Integer::New(87));
   6642   result = Script::Compile(v8_str("UseWith2()"))->Run();
   6643   CHECK_EQ(result, v8::Integer::New(87));
   6644 }
   6645 
   6646 
   6647 THREADED_TEST(AutoExtensions) {
   6648   v8::HandleScope handle_scope(CcTest::isolate());
   6649   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
   6650   extension->set_auto_enable(true);
   6651   v8::RegisterExtension(extension);
   6652   v8::Handle<Context> context =
   6653       Context::New(CcTest::isolate());
   6654   Context::Scope lock(context);
   6655   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
   6656   CHECK_EQ(result, v8::Integer::New(4));
   6657 }
   6658 
   6659 
   6660 static const char* kSyntaxErrorInExtensionSource =
   6661     "[";
   6662 
   6663 
   6664 // Test that a syntax error in an extension does not cause a fatal
   6665 // error but results in an empty context.
   6666 THREADED_TEST(SyntaxErrorExtensions) {
   6667   v8::HandleScope handle_scope(CcTest::isolate());
   6668   v8::RegisterExtension(new Extension("syntaxerror",
   6669                                       kSyntaxErrorInExtensionSource));
   6670   const char* extension_names[] = { "syntaxerror" };
   6671   v8::ExtensionConfiguration extensions(1, extension_names);
   6672   v8::Handle<Context> context =
   6673       Context::New(CcTest::isolate(), &extensions);
   6674   CHECK(context.IsEmpty());
   6675 }
   6676 
   6677 
   6678 static const char* kExceptionInExtensionSource =
   6679     "throw 42";
   6680 
   6681 
   6682 // Test that an exception when installing an extension does not cause
   6683 // a fatal error but results in an empty context.
   6684 THREADED_TEST(ExceptionExtensions) {
   6685   v8::HandleScope handle_scope(CcTest::isolate());
   6686   v8::RegisterExtension(new Extension("exception",
   6687                                       kExceptionInExtensionSource));
   6688   const char* extension_names[] = { "exception" };
   6689   v8::ExtensionConfiguration extensions(1, extension_names);
   6690   v8::Handle<Context> context =
   6691       Context::New(CcTest::isolate(), &extensions);
   6692   CHECK(context.IsEmpty());
   6693 }
   6694 
   6695 
   6696 static const char* kNativeCallInExtensionSource =
   6697     "function call_runtime_last_index_of(x) {"
   6698     "  return %StringLastIndexOf(x, 'bob', 10);"
   6699     "}";
   6700 
   6701 
   6702 static const char* kNativeCallTest =
   6703     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
   6704 
   6705 // Test that a native runtime calls are supported in extensions.
   6706 THREADED_TEST(NativeCallInExtensions) {
   6707   v8::HandleScope handle_scope(CcTest::isolate());
   6708   v8::RegisterExtension(new Extension("nativecall",
   6709                                       kNativeCallInExtensionSource));
   6710   const char* extension_names[] = { "nativecall" };
   6711   v8::ExtensionConfiguration extensions(1, extension_names);
   6712   v8::Handle<Context> context =
   6713       Context::New(CcTest::isolate(), &extensions);
   6714   Context::Scope lock(context);
   6715   v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
   6716   CHECK_EQ(result, v8::Integer::New(3));
   6717 }
   6718 
   6719 
   6720 class NativeFunctionExtension : public Extension {
   6721  public:
   6722   NativeFunctionExtension(const char* name,
   6723                           const char* source,
   6724                           v8::FunctionCallback fun = &Echo)
   6725       : Extension(name, source),
   6726         function_(fun) { }
   6727 
   6728   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
   6729       v8::Isolate* isolate,
   6730       v8::Handle<v8::String> name) {
   6731     return v8::FunctionTemplate::New(function_);
   6732   }
   6733 
   6734   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6735     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
   6736   }
   6737  private:
   6738   v8::FunctionCallback function_;
   6739 };
   6740 
   6741 
   6742 THREADED_TEST(NativeFunctionDeclaration) {
   6743   v8::HandleScope handle_scope(CcTest::isolate());
   6744   const char* name = "nativedecl";
   6745   v8::RegisterExtension(new NativeFunctionExtension(name,
   6746                                                     "native function foo();"));
   6747   const char* extension_names[] = { name };
   6748   v8::ExtensionConfiguration extensions(1, extension_names);
   6749   v8::Handle<Context> context =
   6750       Context::New(CcTest::isolate(), &extensions);
   6751   Context::Scope lock(context);
   6752   v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
   6753   CHECK_EQ(result, v8::Integer::New(42));
   6754 }
   6755 
   6756 
   6757 THREADED_TEST(NativeFunctionDeclarationError) {
   6758   v8::HandleScope handle_scope(CcTest::isolate());
   6759   const char* name = "nativedeclerr";
   6760   // Syntax error in extension code.
   6761   v8::RegisterExtension(new NativeFunctionExtension(name,
   6762                                                     "native\nfunction foo();"));
   6763   const char* extension_names[] = { name };
   6764   v8::ExtensionConfiguration extensions(1, extension_names);
   6765   v8::Handle<Context> context =
   6766       Context::New(CcTest::isolate(), &extensions);
   6767   CHECK(context.IsEmpty());
   6768 }
   6769 
   6770 
   6771 THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
   6772   v8::HandleScope handle_scope(CcTest::isolate());
   6773   const char* name = "nativedeclerresc";
   6774   // Syntax error in extension code - escape code in "native" means that
   6775   // it's not treated as a keyword.
   6776   v8::RegisterExtension(new NativeFunctionExtension(
   6777       name,
   6778       "nativ\\u0065 function foo();"));
   6779   const char* extension_names[] = { name };
   6780   v8::ExtensionConfiguration extensions(1, extension_names);
   6781   v8::Handle<Context> context =
   6782       Context::New(CcTest::isolate(), &extensions);
   6783   CHECK(context.IsEmpty());
   6784 }
   6785 
   6786 
   6787 static void CheckDependencies(const char* name, const char* expected) {
   6788   v8::HandleScope handle_scope(CcTest::isolate());
   6789   v8::ExtensionConfiguration config(1, &name);
   6790   LocalContext context(&config);
   6791   CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), expected),
   6792            context->Global()->Get(v8_str("loaded")));
   6793 }
   6794 
   6795 
   6796 /*
   6797  * Configuration:
   6798  *
   6799  *     /-- B <--\
   6800  * A <-          -- D <-- E
   6801  *     \-- C <--/
   6802  */
   6803 THREADED_TEST(ExtensionDependency) {
   6804   static const char* kEDeps[] = { "D" };
   6805   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
   6806   static const char* kDDeps[] = { "B", "C" };
   6807   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
   6808   static const char* kBCDeps[] = { "A" };
   6809   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
   6810   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
   6811   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
   6812   CheckDependencies("A", "undefinedA");
   6813   CheckDependencies("B", "undefinedAB");
   6814   CheckDependencies("C", "undefinedAC");
   6815   CheckDependencies("D", "undefinedABCD");
   6816   CheckDependencies("E", "undefinedABCDE");
   6817   v8::HandleScope handle_scope(CcTest::isolate());
   6818   static const char* exts[2] = { "C", "E" };
   6819   v8::ExtensionConfiguration config(2, exts);
   6820   LocalContext context(&config);
   6821   CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
   6822 }
   6823 
   6824 
   6825 static const char* kExtensionTestScript =
   6826   "native function A();"
   6827   "native function B();"
   6828   "native function C();"
   6829   "function Foo(i) {"
   6830   "  if (i == 0) return A();"
   6831   "  if (i == 1) return B();"
   6832   "  if (i == 2) return C();"
   6833   "}";
   6834 
   6835 
   6836 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6837   ApiTestFuzzer::Fuzz();
   6838   if (args.IsConstructCall()) {
   6839     args.This()->Set(v8_str("data"), args.Data());
   6840     args.GetReturnValue().SetNull();
   6841     return;
   6842   }
   6843   args.GetReturnValue().Set(args.Data());
   6844 }
   6845 
   6846 
   6847 class FunctionExtension : public Extension {
   6848  public:
   6849   FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
   6850   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
   6851       v8::Isolate* isolate,
   6852       v8::Handle<String> name);
   6853 };
   6854 
   6855 
   6856 static int lookup_count = 0;
   6857 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
   6858     v8::Isolate* isolate, v8::Handle<String> name) {
   6859   lookup_count++;
   6860   if (name->Equals(v8_str("A"))) {
   6861     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
   6862   } else if (name->Equals(v8_str("B"))) {
   6863     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
   6864   } else if (name->Equals(v8_str("C"))) {
   6865     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
   6866   } else {
   6867     return v8::Handle<v8::FunctionTemplate>();
   6868   }
   6869 }
   6870 
   6871 
   6872 THREADED_TEST(FunctionLookup) {
   6873   v8::RegisterExtension(new FunctionExtension());
   6874   v8::HandleScope handle_scope(CcTest::isolate());
   6875   static const char* exts[1] = { "functiontest" };
   6876   v8::ExtensionConfiguration config(1, exts);
   6877   LocalContext context(&config);
   6878   CHECK_EQ(3, lookup_count);
   6879   CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
   6880   CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
   6881   CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
   6882 }
   6883 
   6884 
   6885 THREADED_TEST(NativeFunctionConstructCall) {
   6886   v8::RegisterExtension(new FunctionExtension());
   6887   v8::HandleScope handle_scope(CcTest::isolate());
   6888   static const char* exts[1] = { "functiontest" };
   6889   v8::ExtensionConfiguration config(1, exts);
   6890   LocalContext context(&config);
   6891   for (int i = 0; i < 10; i++) {
   6892     // Run a few times to ensure that allocation of objects doesn't
   6893     // change behavior of a constructor function.
   6894     CHECK_EQ(v8::Integer::New(8),
   6895              Script::Compile(v8_str("(new A()).data"))->Run());
   6896     CHECK_EQ(v8::Integer::New(7),
   6897              Script::Compile(v8_str("(new B()).data"))->Run());
   6898     CHECK_EQ(v8::Integer::New(6),
   6899              Script::Compile(v8_str("(new C()).data"))->Run());
   6900   }
   6901 }
   6902 
   6903 
   6904 static const char* last_location;
   6905 static const char* last_message;
   6906 void StoringErrorCallback(const char* location, const char* message) {
   6907   if (last_location == NULL) {
   6908     last_location = location;
   6909     last_message = message;
   6910   }
   6911 }
   6912 
   6913 
   6914 // ErrorReporting creates a circular extensions configuration and
   6915 // tests that the fatal error handler gets called.  This renders V8
   6916 // unusable and therefore this test cannot be run in parallel.
   6917 TEST(ErrorReporting) {
   6918   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   6919   static const char* aDeps[] = { "B" };
   6920   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
   6921   static const char* bDeps[] = { "A" };
   6922   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
   6923   last_location = NULL;
   6924   v8::ExtensionConfiguration config(1, bDeps);
   6925   v8::Handle<Context> context =
   6926       Context::New(CcTest::isolate(), &config);
   6927   CHECK(context.IsEmpty());
   6928   CHECK_NE(last_location, NULL);
   6929 }
   6930 
   6931 
   6932 static const char* js_code_causing_huge_string_flattening =
   6933     "var str = 'X';"
   6934     "for (var i = 0; i < 30; i++) {"
   6935     "  str = str + str;"
   6936     "}"
   6937     "str.match(/X/);";
   6938 
   6939 
   6940 void OOMCallback(const char* location, const char* message) {
   6941   exit(0);
   6942 }
   6943 
   6944 
   6945 TEST(RegexpOutOfMemory) {
   6946   // Execute a script that causes out of memory when flattening a string.
   6947   v8::HandleScope scope(CcTest::isolate());
   6948   v8::V8::SetFatalErrorHandler(OOMCallback);
   6949   LocalContext context;
   6950   Local<Script> script = Script::Compile(String::NewFromUtf8(
   6951       CcTest::isolate(), js_code_causing_huge_string_flattening));
   6952   last_location = NULL;
   6953   script->Run();
   6954 
   6955   CHECK(false);  // Should not return.
   6956 }
   6957 
   6958 
   6959 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
   6960                                              v8::Handle<Value> data) {
   6961   CHECK(message->GetScriptResourceName()->IsUndefined());
   6962   CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName());
   6963   message->GetLineNumber();
   6964   message->GetSourceLine();
   6965 }
   6966 
   6967 
   6968 THREADED_TEST(ErrorWithMissingScriptInfo) {
   6969   LocalContext context;
   6970   v8::HandleScope scope(context->GetIsolate());
   6971   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
   6972   Script::Compile(v8_str("throw Error()"))->Run();
   6973   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
   6974 }
   6975 
   6976 
   6977 int global_index = 0;
   6978 
   6979 template<typename T>
   6980 class Snorkel {
   6981  public:
   6982   explicit Snorkel(v8::Persistent<T>* handle) : handle_(handle) {
   6983     index_ = global_index++;
   6984   }
   6985   v8::Persistent<T>* handle_;
   6986   int index_;
   6987 };
   6988 
   6989 class Whammy {
   6990  public:
   6991   explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
   6992   ~Whammy() { script_.Reset(); }
   6993   v8::Handle<Script> getScript() {
   6994     if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
   6995     return Local<Script>::New(isolate_, script_);
   6996   }
   6997 
   6998  public:
   6999   static const int kObjectCount = 256;
   7000   int cursor_;
   7001   v8::Isolate* isolate_;
   7002   v8::Persistent<v8::Object> objects_[kObjectCount];
   7003   v8::Persistent<Script> script_;
   7004 };
   7005 
   7006 static void HandleWeakReference(
   7007     const v8::WeakCallbackData<v8::Value, Snorkel<v8::Value> >& data) {
   7008   data.GetParameter()->handle_->ClearWeak();
   7009   delete data.GetParameter();
   7010 }
   7011 
   7012 void WhammyPropertyGetter(Local<String> name,
   7013                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   7014   Whammy* whammy =
   7015     static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
   7016 
   7017   v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_];
   7018 
   7019   v8::Handle<v8::Object> obj = v8::Object::New();
   7020   if (!prev.IsEmpty()) {
   7021     v8::Local<v8::Object>::New(info.GetIsolate(), prev)
   7022         ->Set(v8_str("next"), obj);
   7023     prev.SetWeak<Value, Snorkel<Value> >(new Snorkel<Value>(&prev.As<Value>()),
   7024                                          &HandleWeakReference);
   7025   }
   7026   whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj);
   7027   whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
   7028   info.GetReturnValue().Set(whammy->getScript()->Run());
   7029 }
   7030 
   7031 
   7032 THREADED_TEST(WeakReference) {
   7033   v8::HandleScope handle_scope(CcTest::isolate());
   7034   v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
   7035   Whammy* whammy = new Whammy(CcTest::isolate());
   7036   templ->SetNamedPropertyHandler(WhammyPropertyGetter,
   7037                                  0, 0, 0, 0,
   7038                                  v8::External::New(CcTest::isolate(), whammy));
   7039   const char* extension_list[] = { "v8/gc" };
   7040   v8::ExtensionConfiguration extensions(1, extension_list);
   7041   v8::Handle<Context> context =
   7042       Context::New(CcTest::isolate(), &extensions);
   7043   Context::Scope context_scope(context);
   7044 
   7045   v8::Handle<v8::Object> interceptor = templ->NewInstance();
   7046   context->Global()->Set(v8_str("whammy"), interceptor);
   7047   const char* code =
   7048       "var last;"
   7049       "for (var i = 0; i < 10000; i++) {"
   7050       "  var obj = whammy.length;"
   7051       "  if (last) last.next = obj;"
   7052       "  last = obj;"
   7053       "}"
   7054       "gc();"
   7055       "4";
   7056   v8::Handle<Value> result = CompileRun(code);
   7057   CHECK_EQ(4.0, result->NumberValue());
   7058   delete whammy;
   7059 }
   7060 
   7061 
   7062 struct FlagAndPersistent {
   7063   bool flag;
   7064   v8::Persistent<v8::Object> handle;
   7065 };
   7066 
   7067 
   7068 static void DisposeAndSetFlag(
   7069     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
   7070   data.GetParameter()->handle.Reset();
   7071   data.GetParameter()->flag = true;
   7072 }
   7073 
   7074 
   7075 THREADED_TEST(IndependentWeakHandle) {
   7076   v8::Isolate* iso = CcTest::isolate();
   7077   v8::HandleScope scope(iso);
   7078   v8::Handle<Context> context = Context::New(iso);
   7079   Context::Scope context_scope(context);
   7080 
   7081   FlagAndPersistent object_a, object_b;
   7082 
   7083   {
   7084     v8::HandleScope handle_scope(iso);
   7085     object_a.handle.Reset(iso, v8::Object::New());
   7086     object_b.handle.Reset(iso, v8::Object::New());
   7087   }
   7088 
   7089   object_a.flag = false;
   7090   object_b.flag = false;
   7091   object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
   7092   object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
   7093   CHECK(!object_b.handle.IsIndependent());
   7094   object_a.handle.MarkIndependent();
   7095   object_b.handle.MarkIndependent();
   7096   CHECK(object_b.handle.IsIndependent());
   7097   CcTest::heap()->PerformScavenge();
   7098   CHECK(object_a.flag);
   7099   CHECK(object_b.flag);
   7100 }
   7101 
   7102 
   7103 static void InvokeScavenge() {
   7104   CcTest::heap()->PerformScavenge();
   7105 }
   7106 
   7107 
   7108 static void InvokeMarkSweep() {
   7109   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   7110 }
   7111 
   7112 
   7113 static void ForceScavenge(
   7114     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
   7115   data.GetParameter()->handle.Reset();
   7116   data.GetParameter()->flag = true;
   7117   InvokeScavenge();
   7118 }
   7119 
   7120 
   7121 static void ForceMarkSweep(
   7122     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
   7123   data.GetParameter()->handle.Reset();
   7124   data.GetParameter()->flag = true;
   7125   InvokeMarkSweep();
   7126 }
   7127 
   7128 
   7129 THREADED_TEST(GCFromWeakCallbacks) {
   7130   v8::Isolate* isolate = CcTest::isolate();
   7131   v8::HandleScope scope(isolate);
   7132   v8::Handle<Context> context = Context::New(isolate);
   7133   Context::Scope context_scope(context);
   7134 
   7135   static const int kNumberOfGCTypes = 2;
   7136   typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
   7137       Callback;
   7138   Callback gc_forcing_callback[kNumberOfGCTypes] =
   7139       {&ForceScavenge, &ForceMarkSweep};
   7140 
   7141   typedef void (*GCInvoker)();
   7142   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
   7143 
   7144   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
   7145     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
   7146       FlagAndPersistent object;
   7147       {
   7148         v8::HandleScope handle_scope(isolate);
   7149         object.handle.Reset(isolate, v8::Object::New());
   7150       }
   7151       object.flag = false;
   7152       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
   7153       object.handle.MarkIndependent();
   7154       invoke_gc[outer_gc]();
   7155       CHECK(object.flag);
   7156     }
   7157   }
   7158 }
   7159 
   7160 
   7161 static void RevivingCallback(
   7162     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
   7163   data.GetParameter()->handle.ClearWeak();
   7164   data.GetParameter()->flag = true;
   7165 }
   7166 
   7167 
   7168 THREADED_TEST(IndependentHandleRevival) {
   7169   v8::Isolate* isolate = CcTest::isolate();
   7170   v8::HandleScope scope(isolate);
   7171   v8::Handle<Context> context = Context::New(isolate);
   7172   Context::Scope context_scope(context);
   7173 
   7174   FlagAndPersistent object;
   7175   {
   7176     v8::HandleScope handle_scope(isolate);
   7177     v8::Local<v8::Object> o = v8::Object::New();
   7178     object.handle.Reset(isolate, o);
   7179     o->Set(v8_str("x"), v8::Integer::New(1));
   7180     v8::Local<String> y_str = v8_str("y");
   7181     o->Set(y_str, y_str);
   7182   }
   7183   object.flag = false;
   7184   object.handle.SetWeak(&object, &RevivingCallback);
   7185   object.handle.MarkIndependent();
   7186   CcTest::heap()->PerformScavenge();
   7187   CHECK(object.flag);
   7188   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   7189   {
   7190     v8::HandleScope handle_scope(isolate);
   7191     v8::Local<v8::Object> o =
   7192         v8::Local<v8::Object>::New(isolate, object.handle);
   7193     v8::Local<String> y_str = v8_str("y");
   7194     CHECK_EQ(v8::Integer::New(1), o->Get(v8_str("x")));
   7195     CHECK(o->Get(y_str)->Equals(y_str));
   7196   }
   7197 }
   7198 
   7199 
   7200 v8::Handle<Function> args_fun;
   7201 
   7202 
   7203 static void ArgumentsTestCallback(
   7204     const v8::FunctionCallbackInfo<v8::Value>& args) {
   7205   ApiTestFuzzer::Fuzz();
   7206   v8::Isolate* isolate = args.GetIsolate();
   7207   CHECK_EQ(args_fun, args.Callee());
   7208   CHECK_EQ(3, args.Length());
   7209   CHECK_EQ(v8::Integer::New(1, isolate), args[0]);
   7210   CHECK_EQ(v8::Integer::New(2, isolate), args[1]);
   7211   CHECK_EQ(v8::Integer::New(3, isolate), args[2]);
   7212   CHECK_EQ(v8::Undefined(isolate), args[3]);
   7213   v8::HandleScope scope(args.GetIsolate());
   7214   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   7215 }
   7216 
   7217 
   7218 THREADED_TEST(Arguments) {
   7219   v8::HandleScope scope(CcTest::isolate());
   7220   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
   7221   global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
   7222   LocalContext context(NULL, global);
   7223   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
   7224   v8_compile("f(1, 2, 3)")->Run();
   7225 }
   7226 
   7227 
   7228 static void NoBlockGetterX(Local<String> name,
   7229                            const v8::PropertyCallbackInfo<v8::Value>&) {
   7230 }
   7231 
   7232 
   7233 static void NoBlockGetterI(uint32_t index,
   7234                            const v8::PropertyCallbackInfo<v8::Value>&) {
   7235 }
   7236 
   7237 
   7238 static void PDeleter(Local<String> name,
   7239                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   7240   if (!name->Equals(v8_str("foo"))) {
   7241     return;  // not intercepted
   7242   }
   7243 
   7244   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
   7245 }
   7246 
   7247 
   7248 static void IDeleter(uint32_t index,
   7249                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   7250   if (index != 2) {
   7251     return;  // not intercepted
   7252   }
   7253 
   7254   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
   7255 }
   7256 
   7257 
   7258 THREADED_TEST(Deleter) {
   7259   v8::HandleScope scope(CcTest::isolate());
   7260   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   7261   obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
   7262   obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
   7263   LocalContext context;
   7264   context->Global()->Set(v8_str("k"), obj->NewInstance());
   7265   CompileRun(
   7266     "k.foo = 'foo';"
   7267     "k.bar = 'bar';"
   7268     "k[2] = 2;"
   7269     "k[4] = 4;");
   7270   CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
   7271   CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
   7272 
   7273   CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
   7274   CHECK(v8_compile("k.bar")->Run()->IsUndefined());
   7275 
   7276   CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
   7277   CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
   7278 
   7279   CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
   7280   CHECK(v8_compile("k[4]")->Run()->IsUndefined());
   7281 }
   7282 
   7283 
   7284 static void GetK(Local<String> name,
   7285                  const v8::PropertyCallbackInfo<v8::Value>& info) {
   7286   ApiTestFuzzer::Fuzz();
   7287   if (name->Equals(v8_str("foo")) ||
   7288       name->Equals(v8_str("bar")) ||
   7289       name->Equals(v8_str("baz"))) {
   7290     info.GetReturnValue().SetUndefined();
   7291   }
   7292 }
   7293 
   7294 
   7295 static void IndexedGetK(uint32_t index,
   7296                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   7297   ApiTestFuzzer::Fuzz();
   7298   if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
   7299 }
   7300 
   7301 
   7302 static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
   7303   ApiTestFuzzer::Fuzz();
   7304   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
   7305   result->Set(v8::Integer::New(0), v8_str("foo"));
   7306   result->Set(v8::Integer::New(1), v8_str("bar"));
   7307   result->Set(v8::Integer::New(2), v8_str("baz"));
   7308   info.GetReturnValue().Set(result);
   7309 }
   7310 
   7311 
   7312 static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
   7313   ApiTestFuzzer::Fuzz();
   7314   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
   7315   result->Set(v8::Integer::New(0), v8_str("0"));
   7316   result->Set(v8::Integer::New(1), v8_str("1"));
   7317   info.GetReturnValue().Set(result);
   7318 }
   7319 
   7320 
   7321 THREADED_TEST(Enumerators) {
   7322   v8::HandleScope scope(CcTest::isolate());
   7323   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   7324   obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
   7325   obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
   7326   LocalContext context;
   7327   context->Global()->Set(v8_str("k"), obj->NewInstance());
   7328   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   7329     "k[10] = 0;"
   7330     "k.a = 0;"
   7331     "k[5] = 0;"
   7332     "k.b = 0;"
   7333     "k[4294967295] = 0;"
   7334     "k.c = 0;"
   7335     "k[4294967296] = 0;"
   7336     "k.d = 0;"
   7337     "k[140000] = 0;"
   7338     "k.e = 0;"
   7339     "k[30000000000] = 0;"
   7340     "k.f = 0;"
   7341     "var result = [];"
   7342     "for (var prop in k) {"
   7343     "  result.push(prop);"
   7344     "}"
   7345     "result"));
   7346   // Check that we get all the property names returned including the
   7347   // ones from the enumerators in the right order: indexed properties
   7348   // in numerical order, indexed interceptor properties, named
   7349   // properties in insertion order, named interceptor properties.
   7350   // This order is not mandated by the spec, so this test is just
   7351   // documenting our behavior.
   7352   CHECK_EQ(17, result->Length());
   7353   // Indexed properties in numerical order.
   7354   CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
   7355   CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
   7356   CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
   7357   CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
   7358   // Indexed interceptor properties in the order they are returned
   7359   // from the enumerator interceptor.
   7360   CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
   7361   CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
   7362   // Named properties in insertion order.
   7363   CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
   7364   CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
   7365   CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
   7366   CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
   7367   CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
   7368   CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
   7369   CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
   7370   CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
   7371   // Named interceptor properties.
   7372   CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
   7373   CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
   7374   CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
   7375 }
   7376 
   7377 
   7378 int p_getter_count;
   7379 int p_getter_count2;
   7380 
   7381 
   7382 static void PGetter(Local<String> name,
   7383                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   7384   ApiTestFuzzer::Fuzz();
   7385   p_getter_count++;
   7386   v8::Handle<v8::Object> global =
   7387       info.GetIsolate()->GetCurrentContext()->Global();
   7388   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   7389   if (name->Equals(v8_str("p1"))) {
   7390     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   7391   } else if (name->Equals(v8_str("p2"))) {
   7392     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   7393   } else if (name->Equals(v8_str("p3"))) {
   7394     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   7395   } else if (name->Equals(v8_str("p4"))) {
   7396     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   7397   }
   7398 }
   7399 
   7400 
   7401 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
   7402   ApiTestFuzzer::Fuzz();
   7403   LocalContext context;
   7404   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   7405   CompileRun(
   7406     "o1.__proto__ = { };"
   7407     "var o2 = { __proto__: o1 };"
   7408     "var o3 = { __proto__: o2 };"
   7409     "var o4 = { __proto__: o3 };"
   7410     "for (var i = 0; i < 10; i++) o4.p4;"
   7411     "for (var i = 0; i < 10; i++) o3.p3;"
   7412     "for (var i = 0; i < 10; i++) o2.p2;"
   7413     "for (var i = 0; i < 10; i++) o1.p1;");
   7414 }
   7415 
   7416 
   7417 static void PGetter2(Local<String> name,
   7418                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   7419   ApiTestFuzzer::Fuzz();
   7420   p_getter_count2++;
   7421   v8::Handle<v8::Object> global =
   7422       info.GetIsolate()->GetCurrentContext()->Global();
   7423   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   7424   if (name->Equals(v8_str("p1"))) {
   7425     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   7426   } else if (name->Equals(v8_str("p2"))) {
   7427     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   7428   } else if (name->Equals(v8_str("p3"))) {
   7429     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   7430   } else if (name->Equals(v8_str("p4"))) {
   7431     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   7432   }
   7433 }
   7434 
   7435 
   7436 THREADED_TEST(GetterHolders) {
   7437   v8::HandleScope scope(CcTest::isolate());
   7438   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   7439   obj->SetAccessor(v8_str("p1"), PGetter);
   7440   obj->SetAccessor(v8_str("p2"), PGetter);
   7441   obj->SetAccessor(v8_str("p3"), PGetter);
   7442   obj->SetAccessor(v8_str("p4"), PGetter);
   7443   p_getter_count = 0;
   7444   RunHolderTest(obj);
   7445   CHECK_EQ(40, p_getter_count);
   7446 }
   7447 
   7448 
   7449 THREADED_TEST(PreInterceptorHolders) {
   7450   v8::HandleScope scope(CcTest::isolate());
   7451   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   7452   obj->SetNamedPropertyHandler(PGetter2);
   7453   p_getter_count2 = 0;
   7454   RunHolderTest(obj);
   7455   CHECK_EQ(40, p_getter_count2);
   7456 }
   7457 
   7458 
   7459 THREADED_TEST(ObjectInstantiation) {
   7460   v8::Isolate* isolate = CcTest::isolate();
   7461   v8::HandleScope scope(isolate);
   7462   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7463   templ->SetAccessor(v8_str("t"), PGetter2);
   7464   LocalContext context;
   7465   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7466   for (int i = 0; i < 100; i++) {
   7467     v8::HandleScope inner_scope(CcTest::isolate());
   7468     v8::Handle<v8::Object> obj = templ->NewInstance();
   7469     CHECK_NE(obj, context->Global()->Get(v8_str("o")));
   7470     context->Global()->Set(v8_str("o2"), obj);
   7471     v8::Handle<Value> value =
   7472         Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
   7473     CHECK_EQ(v8::True(isolate), value);
   7474     context->Global()->Set(v8_str("o"), obj);
   7475   }
   7476 }
   7477 
   7478 
   7479 static int StrCmp16(uint16_t* a, uint16_t* b) {
   7480   while (true) {
   7481     if (*a == 0 && *b == 0) return 0;
   7482     if (*a != *b) return 0 + *a - *b;
   7483     a++;
   7484     b++;
   7485   }
   7486 }
   7487 
   7488 
   7489 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
   7490   while (true) {
   7491     if (n-- == 0) return 0;
   7492     if (*a == 0 && *b == 0) return 0;
   7493     if (*a != *b) return 0 + *a - *b;
   7494     a++;
   7495     b++;
   7496   }
   7497 }
   7498 
   7499 
   7500 int GetUtf8Length(Handle<String> str) {
   7501   int len = str->Utf8Length();
   7502   if (len < 0) {
   7503     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
   7504     i::FlattenString(istr);
   7505     len = str->Utf8Length();
   7506   }
   7507   return len;
   7508 }
   7509 
   7510 
   7511 THREADED_TEST(StringWrite) {
   7512   LocalContext context;
   7513   v8::HandleScope scope(context->GetIsolate());
   7514   v8::Handle<String> str = v8_str("abcde");
   7515   // abc<Icelandic eth><Unicode snowman>.
   7516   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
   7517   v8::Handle<String> str3 = v8::String::NewFromUtf8(
   7518       context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
   7519   const int kStride = 4;  // Must match stride in for loops in JS below.
   7520   CompileRun(
   7521       "var left = '';"
   7522       "for (var i = 0; i < 0xd800; i += 4) {"
   7523       "  left = left + String.fromCharCode(i);"
   7524       "}");
   7525   CompileRun(
   7526       "var right = '';"
   7527       "for (var i = 0; i < 0xd800; i += 4) {"
   7528       "  right = String.fromCharCode(i) + right;"
   7529       "}");
   7530   v8::Handle<v8::Object> global = context->Global();
   7531   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
   7532   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
   7533 
   7534   CHECK_EQ(5, str2->Length());
   7535   CHECK_EQ(0xd800 / kStride, left_tree->Length());
   7536   CHECK_EQ(0xd800 / kStride, right_tree->Length());
   7537 
   7538   char buf[100];
   7539   char utf8buf[0xd800 * 3];
   7540   uint16_t wbuf[100];
   7541   int len;
   7542   int charlen;
   7543 
   7544   memset(utf8buf, 0x1, 1000);
   7545   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   7546   CHECK_EQ(9, len);
   7547   CHECK_EQ(5, charlen);
   7548   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   7549 
   7550   memset(utf8buf, 0x1, 1000);
   7551   len = str2->WriteUtf8(utf8buf, 8, &charlen);
   7552   CHECK_EQ(8, len);
   7553   CHECK_EQ(5, charlen);
   7554   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
   7555 
   7556   memset(utf8buf, 0x1, 1000);
   7557   len = str2->WriteUtf8(utf8buf, 7, &charlen);
   7558   CHECK_EQ(5, len);
   7559   CHECK_EQ(4, charlen);
   7560   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7561 
   7562   memset(utf8buf, 0x1, 1000);
   7563   len = str2->WriteUtf8(utf8buf, 6, &charlen);
   7564   CHECK_EQ(5, len);
   7565   CHECK_EQ(4, charlen);
   7566   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7567 
   7568   memset(utf8buf, 0x1, 1000);
   7569   len = str2->WriteUtf8(utf8buf, 5, &charlen);
   7570   CHECK_EQ(5, len);
   7571   CHECK_EQ(4, charlen);
   7572   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7573 
   7574   memset(utf8buf, 0x1, 1000);
   7575   len = str2->WriteUtf8(utf8buf, 4, &charlen);
   7576   CHECK_EQ(3, len);
   7577   CHECK_EQ(3, charlen);
   7578   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   7579 
   7580   memset(utf8buf, 0x1, 1000);
   7581   len = str2->WriteUtf8(utf8buf, 3, &charlen);
   7582   CHECK_EQ(3, len);
   7583   CHECK_EQ(3, charlen);
   7584   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   7585 
   7586   memset(utf8buf, 0x1, 1000);
   7587   len = str2->WriteUtf8(utf8buf, 2, &charlen);
   7588   CHECK_EQ(2, len);
   7589   CHECK_EQ(2, charlen);
   7590   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
   7591 
   7592   memset(utf8buf, 0x1, sizeof(utf8buf));
   7593   len = GetUtf8Length(left_tree);
   7594   int utf8_expected =
   7595       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
   7596   CHECK_EQ(utf8_expected, len);
   7597   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   7598   CHECK_EQ(utf8_expected, len);
   7599   CHECK_EQ(0xd800 / kStride, charlen);
   7600   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
   7601   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
   7602   CHECK_EQ(0xc0 - kStride,
   7603            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
   7604   CHECK_EQ(1, utf8buf[utf8_expected]);
   7605 
   7606   memset(utf8buf, 0x1, sizeof(utf8buf));
   7607   len = GetUtf8Length(right_tree);
   7608   CHECK_EQ(utf8_expected, len);
   7609   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   7610   CHECK_EQ(utf8_expected, len);
   7611   CHECK_EQ(0xd800 / kStride, charlen);
   7612   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
   7613   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
   7614   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
   7615   CHECK_EQ(1, utf8buf[utf8_expected]);
   7616 
   7617   memset(buf, 0x1, sizeof(buf));
   7618   memset(wbuf, 0x1, sizeof(wbuf));
   7619   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   7620   CHECK_EQ(5, len);
   7621   len = str->Write(wbuf);
   7622   CHECK_EQ(5, len);
   7623   CHECK_EQ(0, strcmp("abcde", buf));
   7624   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   7625   CHECK_EQ(0, StrCmp16(answer1, wbuf));
   7626 
   7627   memset(buf, 0x1, sizeof(buf));
   7628   memset(wbuf, 0x1, sizeof(wbuf));
   7629   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
   7630   CHECK_EQ(4, len);
   7631   len = str->Write(wbuf, 0, 4);
   7632   CHECK_EQ(4, len);
   7633   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
   7634   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
   7635   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
   7636 
   7637   memset(buf, 0x1, sizeof(buf));
   7638   memset(wbuf, 0x1, sizeof(wbuf));
   7639   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
   7640   CHECK_EQ(5, len);
   7641   len = str->Write(wbuf, 0, 5);
   7642   CHECK_EQ(5, len);
   7643   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
   7644   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
   7645   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
   7646 
   7647   memset(buf, 0x1, sizeof(buf));
   7648   memset(wbuf, 0x1, sizeof(wbuf));
   7649   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
   7650   CHECK_EQ(5, len);
   7651   len = str->Write(wbuf, 0, 6);
   7652   CHECK_EQ(5, len);
   7653   CHECK_EQ(0, strcmp("abcde", buf));
   7654   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   7655   CHECK_EQ(0, StrCmp16(answer4, wbuf));
   7656 
   7657   memset(buf, 0x1, sizeof(buf));
   7658   memset(wbuf, 0x1, sizeof(wbuf));
   7659   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
   7660   CHECK_EQ(1, len);
   7661   len = str->Write(wbuf, 4, -1);
   7662   CHECK_EQ(1, len);
   7663   CHECK_EQ(0, strcmp("e", buf));
   7664   uint16_t answer5[] = {'e', '\0'};
   7665   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   7666 
   7667   memset(buf, 0x1, sizeof(buf));
   7668   memset(wbuf, 0x1, sizeof(wbuf));
   7669   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
   7670   CHECK_EQ(1, len);
   7671   len = str->Write(wbuf, 4, 6);
   7672   CHECK_EQ(1, len);
   7673   CHECK_EQ(0, strcmp("e", buf));
   7674   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   7675 
   7676   memset(buf, 0x1, sizeof(buf));
   7677   memset(wbuf, 0x1, sizeof(wbuf));
   7678   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
   7679   CHECK_EQ(1, len);
   7680   len = str->Write(wbuf, 4, 1);
   7681   CHECK_EQ(1, len);
   7682   CHECK_EQ(0, strncmp("e\1", buf, 2));
   7683   uint16_t answer6[] = {'e', 0x101};
   7684   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
   7685 
   7686   memset(buf, 0x1, sizeof(buf));
   7687   memset(wbuf, 0x1, sizeof(wbuf));
   7688   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
   7689   CHECK_EQ(1, len);
   7690   len = str->Write(wbuf, 3, 1);
   7691   CHECK_EQ(1, len);
   7692   CHECK_EQ(0, strncmp("d\1", buf, 2));
   7693   uint16_t answer7[] = {'d', 0x101};
   7694   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
   7695 
   7696   memset(wbuf, 0x1, sizeof(wbuf));
   7697   wbuf[5] = 'X';
   7698   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
   7699   CHECK_EQ(5, len);
   7700   CHECK_EQ('X', wbuf[5]);
   7701   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
   7702   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   7703   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
   7704   CHECK_NE(0, StrCmp16(answer8b, wbuf));
   7705   wbuf[5] = '\0';
   7706   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
   7707 
   7708   memset(buf, 0x1, sizeof(buf));
   7709   buf[5] = 'X';
   7710   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
   7711                           0,
   7712                           6,
   7713                           String::NO_NULL_TERMINATION);
   7714   CHECK_EQ(5, len);
   7715   CHECK_EQ('X', buf[5]);
   7716   CHECK_EQ(0, strncmp("abcde", buf, 5));
   7717   CHECK_NE(0, strcmp("abcde", buf));
   7718   buf[5] = '\0';
   7719   CHECK_EQ(0, strcmp("abcde", buf));
   7720 
   7721   memset(utf8buf, 0x1, sizeof(utf8buf));
   7722   utf8buf[8] = 'X';
   7723   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   7724                         String::NO_NULL_TERMINATION);
   7725   CHECK_EQ(8, len);
   7726   CHECK_EQ('X', utf8buf[8]);
   7727   CHECK_EQ(5, charlen);
   7728   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
   7729   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   7730   utf8buf[8] = '\0';
   7731   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   7732 
   7733   memset(utf8buf, 0x1, sizeof(utf8buf));
   7734   utf8buf[5] = 'X';
   7735   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   7736                         String::NO_NULL_TERMINATION);
   7737   CHECK_EQ(5, len);
   7738   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
   7739   CHECK_EQ(5, charlen);
   7740   utf8buf[5] = '\0';
   7741   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
   7742 
   7743   memset(buf, 0x1, sizeof(buf));
   7744   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   7745   CHECK_EQ(7, len);
   7746   CHECK_EQ(0, strcmp("abc", buf));
   7747   CHECK_EQ(0, buf[3]);
   7748   CHECK_EQ(0, strcmp("def", buf + 4));
   7749 
   7750   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
   7751   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
   7752   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
   7753 }
   7754 
   7755 
   7756 static void Utf16Helper(
   7757     LocalContext& context,
   7758     const char* name,
   7759     const char* lengths_name,
   7760     int len) {
   7761   Local<v8::Array> a =
   7762       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
   7763   Local<v8::Array> alens =
   7764       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
   7765   for (int i = 0; i < len; i++) {
   7766     Local<v8::String> string =
   7767       Local<v8::String>::Cast(a->Get(i));
   7768     Local<v8::Number> expected_len =
   7769       Local<v8::Number>::Cast(alens->Get(i));
   7770     int length = GetUtf8Length(string);
   7771     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
   7772   }
   7773 }
   7774 
   7775 
   7776 static uint16_t StringGet(Handle<String> str, int index) {
   7777   i::Handle<i::String> istring =
   7778       v8::Utils::OpenHandle(String::Cast(*str));
   7779   return istring->Get(index);
   7780 }
   7781 
   7782 
   7783 static void WriteUtf8Helper(
   7784     LocalContext& context,
   7785     const char* name,
   7786     const char* lengths_name,
   7787     int len) {
   7788   Local<v8::Array> b =
   7789       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
   7790   Local<v8::Array> alens =
   7791       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
   7792   char buffer[1000];
   7793   char buffer2[1000];
   7794   for (int i = 0; i < len; i++) {
   7795     Local<v8::String> string =
   7796       Local<v8::String>::Cast(b->Get(i));
   7797     Local<v8::Number> expected_len =
   7798       Local<v8::Number>::Cast(alens->Get(i));
   7799     int utf8_length = static_cast<int>(expected_len->Value());
   7800     for (int j = utf8_length + 1; j >= 0; j--) {
   7801       memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
   7802       memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
   7803       int nchars;
   7804       int utf8_written =
   7805           string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
   7806       int utf8_written2 =
   7807           string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
   7808       CHECK_GE(utf8_length + 1, utf8_written);
   7809       CHECK_GE(utf8_length, utf8_written2);
   7810       for (int k = 0; k < utf8_written2; k++) {
   7811         CHECK_EQ(buffer[k], buffer2[k]);
   7812       }
   7813       CHECK(nchars * 3 >= utf8_written - 1);
   7814       CHECK(nchars <= utf8_written);
   7815       if (j == utf8_length + 1) {
   7816         CHECK_EQ(utf8_written2, utf8_length);
   7817         CHECK_EQ(utf8_written2 + 1, utf8_written);
   7818       }
   7819       CHECK_EQ(buffer[utf8_written], 42);
   7820       if (j > utf8_length) {
   7821         if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
   7822         if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
   7823         Handle<String> roundtrip = v8_str(buffer);
   7824         CHECK(roundtrip->Equals(string));
   7825       } else {
   7826         if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
   7827       }
   7828       if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
   7829       if (nchars >= 2) {
   7830         uint16_t trail = StringGet(string, nchars - 1);
   7831         uint16_t lead = StringGet(string, nchars - 2);
   7832         if (((lead & 0xfc00) == 0xd800) &&
   7833             ((trail & 0xfc00) == 0xdc00)) {
   7834           unsigned char u1 = buffer2[utf8_written2 - 4];
   7835           unsigned char u2 = buffer2[utf8_written2 - 3];
   7836           unsigned char u3 = buffer2[utf8_written2 - 2];
   7837           unsigned char u4 = buffer2[utf8_written2 - 1];
   7838           CHECK_EQ((u1 & 0xf8), 0xf0);
   7839           CHECK_EQ((u2 & 0xc0), 0x80);
   7840           CHECK_EQ((u3 & 0xc0), 0x80);
   7841           CHECK_EQ((u4 & 0xc0), 0x80);
   7842           uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
   7843           CHECK_EQ((u4 & 0x3f), (c & 0x3f));
   7844           CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
   7845           CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
   7846           CHECK_EQ((u1 & 0x3), c >> 18);
   7847         }
   7848       }
   7849     }
   7850   }
   7851 }
   7852 
   7853 
   7854 THREADED_TEST(Utf16) {
   7855   LocalContext context;
   7856   v8::HandleScope scope(context->GetIsolate());
   7857   CompileRun(
   7858       "var pad = '01234567890123456789';"
   7859       "var p = [];"
   7860       "var plens = [20, 3, 3];"
   7861       "p.push('01234567890123456789');"
   7862       "var lead = 0xd800;"
   7863       "var trail = 0xdc00;"
   7864       "p.push(String.fromCharCode(0xd800));"
   7865       "p.push(String.fromCharCode(0xdc00));"
   7866       "var a = [];"
   7867       "var b = [];"
   7868       "var c = [];"
   7869       "var alens = [];"
   7870       "for (var i = 0; i < 3; i++) {"
   7871       "  p[1] = String.fromCharCode(lead++);"
   7872       "  for (var j = 0; j < 3; j++) {"
   7873       "    p[2] = String.fromCharCode(trail++);"
   7874       "    a.push(p[i] + p[j]);"
   7875       "    b.push(p[i] + p[j]);"
   7876       "    c.push(p[i] + p[j]);"
   7877       "    alens.push(plens[i] + plens[j]);"
   7878       "  }"
   7879       "}"
   7880       "alens[5] -= 2;"  // Here the surrogate pairs match up.
   7881       "var a2 = [];"
   7882       "var b2 = [];"
   7883       "var c2 = [];"
   7884       "var a2lens = [];"
   7885       "for (var m = 0; m < 9; m++) {"
   7886       "  for (var n = 0; n < 9; n++) {"
   7887       "    a2.push(a[m] + a[n]);"
   7888       "    b2.push(b[m] + b[n]);"
   7889       "    var newc = 'x' + c[m] + c[n] + 'y';"
   7890       "    c2.push(newc.substring(1, newc.length - 1));"
   7891       "    var utf = alens[m] + alens[n];"  // And here.
   7892            // The 'n's that start with 0xdc.. are 6-8
   7893            // The 'm's that end with 0xd8.. are 1, 4 and 7
   7894       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
   7895       "    a2lens.push(utf);"
   7896       "  }"
   7897       "}");
   7898   Utf16Helper(context, "a", "alens", 9);
   7899   Utf16Helper(context, "a2", "a2lens", 81);
   7900   WriteUtf8Helper(context, "b", "alens", 9);
   7901   WriteUtf8Helper(context, "b2", "a2lens", 81);
   7902   WriteUtf8Helper(context, "c2", "a2lens", 81);
   7903 }
   7904 
   7905 
   7906 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
   7907   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
   7908   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
   7909   return *is1 == *is2;
   7910 }
   7911 
   7912 static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
   7913                              const char* b) {
   7914   Handle<String> symbol1 =
   7915       v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
   7916   Handle<String> symbol2 =
   7917       v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
   7918   CHECK(SameSymbol(symbol1, symbol2));
   7919 }
   7920 
   7921 
   7922 THREADED_TEST(Utf16Symbol) {
   7923   LocalContext context;
   7924   v8::HandleScope scope(context->GetIsolate());
   7925 
   7926   Handle<String> symbol1 = v8::String::NewFromUtf8(
   7927       context->GetIsolate(), "abc", v8::String::kInternalizedString);
   7928   Handle<String> symbol2 = v8::String::NewFromUtf8(
   7929       context->GetIsolate(), "abc", v8::String::kInternalizedString);
   7930   CHECK(SameSymbol(symbol1, symbol2));
   7931 
   7932   SameSymbolHelper(context->GetIsolate(),
   7933                    "\360\220\220\205",  // 4 byte encoding.
   7934                    "\355\240\201\355\260\205");  // 2 3-byte surrogates.
   7935   SameSymbolHelper(context->GetIsolate(),
   7936                    "\355\240\201\355\260\206",  // 2 3-byte surrogates.
   7937                    "\360\220\220\206");  // 4 byte encoding.
   7938   SameSymbolHelper(context->GetIsolate(),
   7939                    "x\360\220\220\205",  // 4 byte encoding.
   7940                    "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
   7941   SameSymbolHelper(context->GetIsolate(),
   7942                    "x\355\240\201\355\260\206",  // 2 3-byte surrogates.
   7943                    "x\360\220\220\206");  // 4 byte encoding.
   7944   CompileRun(
   7945       "var sym0 = 'benedictus';"
   7946       "var sym0b = 'S\303\270ren';"
   7947       "var sym1 = '\355\240\201\355\260\207';"
   7948       "var sym2 = '\360\220\220\210';"
   7949       "var sym3 = 'x\355\240\201\355\260\207';"
   7950       "var sym4 = 'x\360\220\220\210';"
   7951       "if (sym1.length != 2) throw sym1;"
   7952       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
   7953       "if (sym2.length != 2) throw sym2;"
   7954       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
   7955       "if (sym3.length != 3) throw sym3;"
   7956       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
   7957       "if (sym4.length != 3) throw sym4;"
   7958       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
   7959   Handle<String> sym0 = v8::String::NewFromUtf8(
   7960       context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
   7961   Handle<String> sym0b = v8::String::NewFromUtf8(
   7962       context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
   7963   Handle<String> sym1 =
   7964       v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
   7965                               v8::String::kInternalizedString);
   7966   Handle<String> sym2 =
   7967       v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
   7968                               v8::String::kInternalizedString);
   7969   Handle<String> sym3 = v8::String::NewFromUtf8(
   7970       context->GetIsolate(), "x\355\240\201\355\260\207",
   7971       v8::String::kInternalizedString);
   7972   Handle<String> sym4 =
   7973       v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
   7974                               v8::String::kInternalizedString);
   7975   v8::Local<v8::Object> global = context->Global();
   7976   Local<Value> s0 = global->Get(v8_str("sym0"));
   7977   Local<Value> s0b = global->Get(v8_str("sym0b"));
   7978   Local<Value> s1 = global->Get(v8_str("sym1"));
   7979   Local<Value> s2 = global->Get(v8_str("sym2"));
   7980   Local<Value> s3 = global->Get(v8_str("sym3"));
   7981   Local<Value> s4 = global->Get(v8_str("sym4"));
   7982   CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
   7983   CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
   7984   CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
   7985   CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
   7986   CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
   7987   CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
   7988 }
   7989 
   7990 
   7991 THREADED_TEST(ToArrayIndex) {
   7992   LocalContext context;
   7993   v8::HandleScope scope(context->GetIsolate());
   7994 
   7995   v8::Handle<String> str = v8_str("42");
   7996   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
   7997   CHECK(!index.IsEmpty());
   7998   CHECK_EQ(42.0, index->Uint32Value());
   7999   str = v8_str("42asdf");
   8000   index = str->ToArrayIndex();
   8001   CHECK(index.IsEmpty());
   8002   str = v8_str("-42");
   8003   index = str->ToArrayIndex();
   8004   CHECK(index.IsEmpty());
   8005   str = v8_str("4294967295");
   8006   index = str->ToArrayIndex();
   8007   CHECK(!index.IsEmpty());
   8008   CHECK_EQ(4294967295.0, index->Uint32Value());
   8009   v8::Handle<v8::Number> num = v8::Number::New(1);
   8010   index = num->ToArrayIndex();
   8011   CHECK(!index.IsEmpty());
   8012   CHECK_EQ(1.0, index->Uint32Value());
   8013   num = v8::Number::New(-1);
   8014   index = num->ToArrayIndex();
   8015   CHECK(index.IsEmpty());
   8016   v8::Handle<v8::Object> obj = v8::Object::New();
   8017   index = obj->ToArrayIndex();
   8018   CHECK(index.IsEmpty());
   8019 }
   8020 
   8021 
   8022 THREADED_TEST(ErrorConstruction) {
   8023   LocalContext context;
   8024   v8::HandleScope scope(context->GetIsolate());
   8025 
   8026   v8::Handle<String> foo = v8_str("foo");
   8027   v8::Handle<String> message = v8_str("message");
   8028   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
   8029   CHECK(range_error->IsObject());
   8030   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
   8031   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
   8032   CHECK(reference_error->IsObject());
   8033   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
   8034   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
   8035   CHECK(syntax_error->IsObject());
   8036   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
   8037   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
   8038   CHECK(type_error->IsObject());
   8039   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
   8040   v8::Handle<Value> error = v8::Exception::Error(foo);
   8041   CHECK(error->IsObject());
   8042   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
   8043 }
   8044 
   8045 
   8046 static void YGetter(Local<String> name,
   8047                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8048   ApiTestFuzzer::Fuzz();
   8049   info.GetReturnValue().Set(v8_num(10));
   8050 }
   8051 
   8052 
   8053 static void YSetter(Local<String> name,
   8054                     Local<Value> value,
   8055                     const v8::PropertyCallbackInfo<void>& info) {
   8056   if (info.This()->Has(name)) {
   8057     info.This()->Delete(name);
   8058   }
   8059   info.This()->Set(name, value);
   8060 }
   8061 
   8062 
   8063 THREADED_TEST(DeleteAccessor) {
   8064   v8::HandleScope scope(CcTest::isolate());
   8065   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   8066   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
   8067   LocalContext context;
   8068   v8::Handle<v8::Object> holder = obj->NewInstance();
   8069   context->Global()->Set(v8_str("holder"), holder);
   8070   v8::Handle<Value> result = CompileRun(
   8071       "holder.y = 11; holder.y = 12; holder.y");
   8072   CHECK_EQ(12, result->Uint32Value());
   8073 }
   8074 
   8075 
   8076 THREADED_TEST(TypeSwitch) {
   8077   v8::HandleScope scope(CcTest::isolate());
   8078   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
   8079   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
   8080   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
   8081   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
   8082   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
   8083   LocalContext context;
   8084   v8::Handle<v8::Object> obj0 = v8::Object::New();
   8085   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
   8086   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
   8087   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
   8088   for (int i = 0; i < 10; i++) {
   8089     CHECK_EQ(0, type_switch->match(obj0));
   8090     CHECK_EQ(1, type_switch->match(obj1));
   8091     CHECK_EQ(2, type_switch->match(obj2));
   8092     CHECK_EQ(3, type_switch->match(obj3));
   8093     CHECK_EQ(3, type_switch->match(obj3));
   8094     CHECK_EQ(2, type_switch->match(obj2));
   8095     CHECK_EQ(1, type_switch->match(obj1));
   8096     CHECK_EQ(0, type_switch->match(obj0));
   8097   }
   8098 }
   8099 
   8100 
   8101 // For use within the TestSecurityHandler() test.
   8102 static bool g_security_callback_result = false;
   8103 static bool NamedSecurityTestCallback(Local<v8::Object> global,
   8104                                       Local<Value> name,
   8105                                       v8::AccessType type,
   8106                                       Local<Value> data) {
   8107   // Always allow read access.
   8108   if (type == v8::ACCESS_GET)
   8109     return true;
   8110 
   8111   // Sometimes allow other access.
   8112   return g_security_callback_result;
   8113 }
   8114 
   8115 
   8116 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
   8117                                         uint32_t key,
   8118                                         v8::AccessType type,
   8119                                         Local<Value> data) {
   8120   // Always allow read access.
   8121   if (type == v8::ACCESS_GET)
   8122     return true;
   8123 
   8124   // Sometimes allow other access.
   8125   return g_security_callback_result;
   8126 }
   8127 
   8128 
   8129 static int trouble_nesting = 0;
   8130 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   8131   ApiTestFuzzer::Fuzz();
   8132   trouble_nesting++;
   8133 
   8134   // Call a JS function that throws an uncaught exception.
   8135   Local<v8::Object> arg_this =
   8136       args.GetIsolate()->GetCurrentContext()->Global();
   8137   Local<Value> trouble_callee = (trouble_nesting == 3) ?
   8138     arg_this->Get(v8_str("trouble_callee")) :
   8139     arg_this->Get(v8_str("trouble_caller"));
   8140   CHECK(trouble_callee->IsFunction());
   8141   args.GetReturnValue().Set(
   8142       Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
   8143 }
   8144 
   8145 
   8146 static int report_count = 0;
   8147 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
   8148                                              v8::Handle<Value>) {
   8149   report_count++;
   8150 }
   8151 
   8152 
   8153 // Counts uncaught exceptions, but other tests running in parallel
   8154 // also have uncaught exceptions.
   8155 TEST(ApiUncaughtException) {
   8156   report_count = 0;
   8157   LocalContext env;
   8158   v8::HandleScope scope(env->GetIsolate());
   8159   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
   8160 
   8161   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
   8162   v8::Local<v8::Object> global = env->Global();
   8163   global->Set(v8_str("trouble"), fun->GetFunction());
   8164 
   8165   Script::Compile(v8_str("function trouble_callee() {"
   8166                          "  var x = null;"
   8167                          "  return x.foo;"
   8168                          "};"
   8169                          "function trouble_caller() {"
   8170                          "  trouble();"
   8171                          "};"))->Run();
   8172   Local<Value> trouble = global->Get(v8_str("trouble"));
   8173   CHECK(trouble->IsFunction());
   8174   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
   8175   CHECK(trouble_callee->IsFunction());
   8176   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
   8177   CHECK(trouble_caller->IsFunction());
   8178   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
   8179   CHECK_EQ(1, report_count);
   8180   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
   8181 }
   8182 
   8183 static const char* script_resource_name = "ExceptionInNativeScript.js";
   8184 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
   8185                                                 v8::Handle<Value>) {
   8186   v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
   8187   CHECK(!name_val.IsEmpty() && name_val->IsString());
   8188   v8::String::Utf8Value name(message->GetScriptResourceName());
   8189   CHECK_EQ(script_resource_name, *name);
   8190   CHECK_EQ(3, message->GetLineNumber());
   8191   v8::String::Utf8Value source_line(message->GetSourceLine());
   8192   CHECK_EQ("  new o.foo();", *source_line);
   8193 }
   8194 
   8195 
   8196 TEST(ExceptionInNativeScript) {
   8197   LocalContext env;
   8198   v8::HandleScope scope(env->GetIsolate());
   8199   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
   8200 
   8201   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
   8202   v8::Local<v8::Object> global = env->Global();
   8203   global->Set(v8_str("trouble"), fun->GetFunction());
   8204 
   8205   Script::Compile(
   8206       v8_str(
   8207           "function trouble() {\n"
   8208           "  var o = {};\n"
   8209           "  new o.foo();\n"
   8210           "};"),
   8211       v8::String::NewFromUtf8(env->GetIsolate(), script_resource_name))->Run();
   8212   Local<Value> trouble = global->Get(v8_str("trouble"));
   8213   CHECK(trouble->IsFunction());
   8214   Function::Cast(*trouble)->Call(global, 0, NULL);
   8215   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
   8216 }
   8217 
   8218 
   8219 TEST(CompilationErrorUsingTryCatchHandler) {
   8220   LocalContext env;
   8221   v8::HandleScope scope(env->GetIsolate());
   8222   v8::TryCatch try_catch;
   8223   Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
   8224   CHECK_NE(NULL, *try_catch.Exception());
   8225   CHECK(try_catch.HasCaught());
   8226 }
   8227 
   8228 
   8229 TEST(TryCatchFinallyUsingTryCatchHandler) {
   8230   LocalContext env;
   8231   v8::HandleScope scope(env->GetIsolate());
   8232   v8::TryCatch try_catch;
   8233   Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
   8234   CHECK(!try_catch.HasCaught());
   8235   Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
   8236   CHECK(try_catch.HasCaught());
   8237   try_catch.Reset();
   8238   Script::Compile(v8_str("(function() {"
   8239                          "try { throw ''; } finally { return; }"
   8240                          "})()"))->Run();
   8241   CHECK(!try_catch.HasCaught());
   8242   Script::Compile(v8_str("(function()"
   8243                          "  { try { throw ''; } finally { throw 0; }"
   8244                          "})()"))->Run();
   8245   CHECK(try_catch.HasCaught());
   8246 }
   8247 
   8248 
   8249 // SecurityHandler can't be run twice
   8250 TEST(SecurityHandler) {
   8251   v8::HandleScope scope0(CcTest::isolate());
   8252   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   8253   global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
   8254                                            IndexedSecurityTestCallback);
   8255   // Create an environment
   8256   v8::Handle<Context> context0 =
   8257     Context::New(CcTest::isolate(), NULL, global_template);
   8258   context0->Enter();
   8259 
   8260   v8::Handle<v8::Object> global0 = context0->Global();
   8261   v8::Handle<Script> script0 = v8_compile("foo = 111");
   8262   script0->Run();
   8263   global0->Set(v8_str("0"), v8_num(999));
   8264   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
   8265   CHECK_EQ(111, foo0->Int32Value());
   8266   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
   8267   CHECK_EQ(999, z0->Int32Value());
   8268 
   8269   // Create another environment, should fail security checks.
   8270   v8::HandleScope scope1(CcTest::isolate());
   8271 
   8272   v8::Handle<Context> context1 =
   8273     Context::New(CcTest::isolate(), NULL, global_template);
   8274   context1->Enter();
   8275 
   8276   v8::Handle<v8::Object> global1 = context1->Global();
   8277   global1->Set(v8_str("othercontext"), global0);
   8278   // This set will fail the security check.
   8279   v8::Handle<Script> script1 =
   8280     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
   8281   script1->Run();
   8282   // This read will pass the security check.
   8283   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
   8284   CHECK_EQ(111, foo1->Int32Value());
   8285   // This read will pass the security check.
   8286   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
   8287   CHECK_EQ(999, z1->Int32Value());
   8288 
   8289   // Create another environment, should pass security checks.
   8290   { g_security_callback_result = true;  // allow security handler to pass.
   8291     v8::HandleScope scope2(CcTest::isolate());
   8292     LocalContext context2;
   8293     v8::Handle<v8::Object> global2 = context2->Global();
   8294     global2->Set(v8_str("othercontext"), global0);
   8295     v8::Handle<Script> script2 =
   8296         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
   8297     script2->Run();
   8298     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
   8299     CHECK_EQ(333, foo2->Int32Value());
   8300     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
   8301     CHECK_EQ(888, z2->Int32Value());
   8302   }
   8303 
   8304   context1->Exit();
   8305   context0->Exit();
   8306 }
   8307 
   8308 
   8309 THREADED_TEST(SecurityChecks) {
   8310   LocalContext env1;
   8311   v8::HandleScope handle_scope(env1->GetIsolate());
   8312   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8313 
   8314   Local<Value> foo = v8_str("foo");
   8315   Local<Value> bar = v8_str("bar");
   8316 
   8317   // Set to the same domain.
   8318   env1->SetSecurityToken(foo);
   8319 
   8320   // Create a function in env1.
   8321   Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
   8322   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
   8323   CHECK(spy->IsFunction());
   8324 
   8325   // Create another function accessing global objects.
   8326   Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
   8327   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
   8328   CHECK(spy2->IsFunction());
   8329 
   8330   // Switch to env2 in the same domain and invoke spy on env2.
   8331   {
   8332     env2->SetSecurityToken(foo);
   8333     // Enter env2
   8334     Context::Scope scope_env2(env2);
   8335     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
   8336     CHECK(result->IsFunction());
   8337   }
   8338 
   8339   {
   8340     env2->SetSecurityToken(bar);
   8341     Context::Scope scope_env2(env2);
   8342 
   8343     // Call cross_domain_call, it should throw an exception
   8344     v8::TryCatch try_catch;
   8345     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
   8346     CHECK(try_catch.HasCaught());
   8347   }
   8348 }
   8349 
   8350 
   8351 // Regression test case for issue 1183439.
   8352 THREADED_TEST(SecurityChecksForPrototypeChain) {
   8353   LocalContext current;
   8354   v8::HandleScope scope(current->GetIsolate());
   8355   v8::Handle<Context> other = Context::New(current->GetIsolate());
   8356 
   8357   // Change context to be able to get to the Object function in the
   8358   // other context without hitting the security checks.
   8359   v8::Local<Value> other_object;
   8360   { Context::Scope scope(other);
   8361     other_object = other->Global()->Get(v8_str("Object"));
   8362     other->Global()->Set(v8_num(42), v8_num(87));
   8363   }
   8364 
   8365   current->Global()->Set(v8_str("other"), other->Global());
   8366   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
   8367 
   8368   // Make sure the security check fails here and we get an undefined
   8369   // result instead of getting the Object function. Repeat in a loop
   8370   // to make sure to exercise the IC code.
   8371   v8::Local<Script> access_other0 = v8_compile("other.Object");
   8372   v8::Local<Script> access_other1 = v8_compile("other[42]");
   8373   for (int i = 0; i < 5; i++) {
   8374     CHECK(!access_other0->Run()->Equals(other_object));
   8375     CHECK(access_other0->Run()->IsUndefined());
   8376     CHECK(!access_other1->Run()->Equals(v8_num(87)));
   8377     CHECK(access_other1->Run()->IsUndefined());
   8378   }
   8379 
   8380   // Create an object that has 'other' in its prototype chain and make
   8381   // sure we cannot access the Object function indirectly through
   8382   // that. Repeat in a loop to make sure to exercise the IC code.
   8383   v8_compile("function F() { };"
   8384              "F.prototype = other;"
   8385              "var f = new F();")->Run();
   8386   v8::Local<Script> access_f0 = v8_compile("f.Object");
   8387   v8::Local<Script> access_f1 = v8_compile("f[42]");
   8388   for (int j = 0; j < 5; j++) {
   8389     CHECK(!access_f0->Run()->Equals(other_object));
   8390     CHECK(access_f0->Run()->IsUndefined());
   8391     CHECK(!access_f1->Run()->Equals(v8_num(87)));
   8392     CHECK(access_f1->Run()->IsUndefined());
   8393   }
   8394 
   8395   // Now it gets hairy: Set the prototype for the other global object
   8396   // to be the current global object. The prototype chain for 'f' now
   8397   // goes through 'other' but ends up in the current global object.
   8398   { Context::Scope scope(other);
   8399     other->Global()->Set(v8_str("__proto__"), current->Global());
   8400   }
   8401   // Set a named and an index property on the current global
   8402   // object. To force the lookup to go through the other global object,
   8403   // the properties must not exist in the other global object.
   8404   current->Global()->Set(v8_str("foo"), v8_num(100));
   8405   current->Global()->Set(v8_num(99), v8_num(101));
   8406   // Try to read the properties from f and make sure that the access
   8407   // gets stopped by the security checks on the other global object.
   8408   Local<Script> access_f2 = v8_compile("f.foo");
   8409   Local<Script> access_f3 = v8_compile("f[99]");
   8410   for (int k = 0; k < 5; k++) {
   8411     CHECK(!access_f2->Run()->Equals(v8_num(100)));
   8412     CHECK(access_f2->Run()->IsUndefined());
   8413     CHECK(!access_f3->Run()->Equals(v8_num(101)));
   8414     CHECK(access_f3->Run()->IsUndefined());
   8415   }
   8416 }
   8417 
   8418 
   8419 THREADED_TEST(CrossDomainDelete) {
   8420   LocalContext env1;
   8421   v8::HandleScope handle_scope(env1->GetIsolate());
   8422   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8423 
   8424   Local<Value> foo = v8_str("foo");
   8425   Local<Value> bar = v8_str("bar");
   8426 
   8427   // Set to the same domain.
   8428   env1->SetSecurityToken(foo);
   8429   env2->SetSecurityToken(foo);
   8430 
   8431   env1->Global()->Set(v8_str("prop"), v8_num(3));
   8432   env2->Global()->Set(v8_str("env1"), env1->Global());
   8433 
   8434   // Change env2 to a different domain and delete env1.prop.
   8435   env2->SetSecurityToken(bar);
   8436   {
   8437     Context::Scope scope_env2(env2);
   8438     Local<Value> result =
   8439         Script::Compile(v8_str("delete env1.prop"))->Run();
   8440     CHECK(result->IsFalse());
   8441   }
   8442 
   8443   // Check that env1.prop still exists.
   8444   Local<Value> v = env1->Global()->Get(v8_str("prop"));
   8445   CHECK(v->IsNumber());
   8446   CHECK_EQ(3, v->Int32Value());
   8447 }
   8448 
   8449 
   8450 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
   8451   LocalContext env1;
   8452   v8::HandleScope handle_scope(env1->GetIsolate());
   8453   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8454 
   8455   Local<Value> foo = v8_str("foo");
   8456   Local<Value> bar = v8_str("bar");
   8457 
   8458   // Set to the same domain.
   8459   env1->SetSecurityToken(foo);
   8460   env2->SetSecurityToken(foo);
   8461 
   8462   env1->Global()->Set(v8_str("prop"), v8_num(3));
   8463   env2->Global()->Set(v8_str("env1"), env1->Global());
   8464 
   8465   // env1.prop is enumerable in env2.
   8466   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
   8467   {
   8468     Context::Scope scope_env2(env2);
   8469     Local<Value> result = Script::Compile(test)->Run();
   8470     CHECK(result->IsTrue());
   8471   }
   8472 
   8473   // Change env2 to a different domain and test again.
   8474   env2->SetSecurityToken(bar);
   8475   {
   8476     Context::Scope scope_env2(env2);
   8477     Local<Value> result = Script::Compile(test)->Run();
   8478     CHECK(result->IsFalse());
   8479   }
   8480 }
   8481 
   8482 
   8483 THREADED_TEST(CrossDomainForIn) {
   8484   LocalContext env1;
   8485   v8::HandleScope handle_scope(env1->GetIsolate());
   8486   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8487 
   8488   Local<Value> foo = v8_str("foo");
   8489   Local<Value> bar = v8_str("bar");
   8490 
   8491   // Set to the same domain.
   8492   env1->SetSecurityToken(foo);
   8493   env2->SetSecurityToken(foo);
   8494 
   8495   env1->Global()->Set(v8_str("prop"), v8_num(3));
   8496   env2->Global()->Set(v8_str("env1"), env1->Global());
   8497 
   8498   // Change env2 to a different domain and set env1's global object
   8499   // as the __proto__ of an object in env2 and enumerate properties
   8500   // in for-in. It shouldn't enumerate properties on env1's global
   8501   // object.
   8502   env2->SetSecurityToken(bar);
   8503   {
   8504     Context::Scope scope_env2(env2);
   8505     Local<Value> result =
   8506         CompileRun("(function(){var obj = {'__proto__':env1};"
   8507                    "for (var p in obj)"
   8508                    "   if (p == 'prop') return false;"
   8509                    "return true;})()");
   8510     CHECK(result->IsTrue());
   8511   }
   8512 }
   8513 
   8514 
   8515 TEST(ContextDetachGlobal) {
   8516   LocalContext env1;
   8517   v8::HandleScope handle_scope(env1->GetIsolate());
   8518   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8519 
   8520   Local<v8::Object> global1 = env1->Global();
   8521 
   8522   Local<Value> foo = v8_str("foo");
   8523 
   8524   // Set to the same domain.
   8525   env1->SetSecurityToken(foo);
   8526   env2->SetSecurityToken(foo);
   8527 
   8528   // Enter env2
   8529   env2->Enter();
   8530 
   8531   // Create a function in env2 and add a reference to it in env1.
   8532   Local<v8::Object> global2 = env2->Global();
   8533   global2->Set(v8_str("prop"), v8::Integer::New(1));
   8534   CompileRun("function getProp() {return prop;}");
   8535 
   8536   env1->Global()->Set(v8_str("getProp"),
   8537                       global2->Get(v8_str("getProp")));
   8538 
   8539   // Detach env2's global, and reuse the global object of env2
   8540   env2->Exit();
   8541   env2->DetachGlobal();
   8542 
   8543   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
   8544                                           0,
   8545                                           v8::Handle<v8::ObjectTemplate>(),
   8546                                           global2);
   8547   env3->SetSecurityToken(v8_str("bar"));
   8548   env3->Enter();
   8549 
   8550   Local<v8::Object> global3 = env3->Global();
   8551   CHECK_EQ(global2, global3);
   8552   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
   8553   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
   8554   global3->Set(v8_str("prop"), v8::Integer::New(-1));
   8555   global3->Set(v8_str("prop2"), v8::Integer::New(2));
   8556   env3->Exit();
   8557 
   8558   // Call getProp in env1, and it should return the value 1
   8559   {
   8560     Local<Value> get_prop = global1->Get(v8_str("getProp"));
   8561     CHECK(get_prop->IsFunction());
   8562     v8::TryCatch try_catch;
   8563     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
   8564     CHECK(!try_catch.HasCaught());
   8565     CHECK_EQ(1, r->Int32Value());
   8566   }
   8567 
   8568   // Check that env3 is not accessible from env1
   8569   {
   8570     Local<Value> r = global3->Get(v8_str("prop2"));
   8571     CHECK(r->IsUndefined());
   8572   }
   8573 }
   8574 
   8575 
   8576 TEST(DetachGlobal) {
   8577   LocalContext env1;
   8578   v8::HandleScope scope(env1->GetIsolate());
   8579 
   8580   // Create second environment.
   8581   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8582 
   8583   Local<Value> foo = v8_str("foo");
   8584 
   8585   // Set same security token for env1 and env2.
   8586   env1->SetSecurityToken(foo);
   8587   env2->SetSecurityToken(foo);
   8588 
   8589   // Create a property on the global object in env2.
   8590   {
   8591     v8::Context::Scope scope(env2);
   8592     env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
   8593   }
   8594 
   8595   // Create a reference to env2 global from env1 global.
   8596   env1->Global()->Set(v8_str("other"), env2->Global());
   8597 
   8598   // Check that we have access to other.p in env2 from env1.
   8599   Local<Value> result = CompileRun("other.p");
   8600   CHECK(result->IsInt32());
   8601   CHECK_EQ(42, result->Int32Value());
   8602 
   8603   // Hold on to global from env2 and detach global from env2.
   8604   Local<v8::Object> global2 = env2->Global();
   8605   env2->DetachGlobal();
   8606 
   8607   // Check that the global has been detached. No other.p property can
   8608   // be found.
   8609   result = CompileRun("other.p");
   8610   CHECK(result->IsUndefined());
   8611 
   8612   // Reuse global2 for env3.
   8613   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
   8614                                           0,
   8615                                           v8::Handle<v8::ObjectTemplate>(),
   8616                                           global2);
   8617   CHECK_EQ(global2, env3->Global());
   8618 
   8619   // Start by using the same security token for env3 as for env1 and env2.
   8620   env3->SetSecurityToken(foo);
   8621 
   8622   // Create a property on the global object in env3.
   8623   {
   8624     v8::Context::Scope scope(env3);
   8625     env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
   8626   }
   8627 
   8628   // Check that other.p is now the property in env3 and that we have access.
   8629   result = CompileRun("other.p");
   8630   CHECK(result->IsInt32());
   8631   CHECK_EQ(24, result->Int32Value());
   8632 
   8633   // Change security token for env3 to something different from env1 and env2.
   8634   env3->SetSecurityToken(v8_str("bar"));
   8635 
   8636   // Check that we do not have access to other.p in env1. |other| is now
   8637   // the global object for env3 which has a different security token,
   8638   // so access should be blocked.
   8639   result = CompileRun("other.p");
   8640   CHECK(result->IsUndefined());
   8641 }
   8642 
   8643 
   8644 TEST(DetachedAccesses) {
   8645   LocalContext env1;
   8646   v8::HandleScope scope(env1->GetIsolate());
   8647 
   8648   // Create second environment.
   8649   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8650 
   8651   Local<Value> foo = v8_str("foo");
   8652 
   8653   // Set same security token for env1 and env2.
   8654   env1->SetSecurityToken(foo);
   8655   env2->SetSecurityToken(foo);
   8656 
   8657   {
   8658     v8::Context::Scope scope(env2);
   8659     CompileRun(
   8660         "var x = 'x';"
   8661         "function get_x() { return this.x; }"
   8662         "function get_x_w() { return get_x(); }"
   8663         "");
   8664     env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
   8665     env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
   8666   }
   8667 
   8668   Local<Object> env2_global = env2->Global();
   8669   env2_global->TurnOnAccessCheck();
   8670   env2->DetachGlobal();
   8671 
   8672   Local<Value> result;
   8673   result = CompileRun("get_x()");
   8674   CHECK(result->IsUndefined());
   8675   result = CompileRun("get_x_w()");
   8676   CHECK(result->IsUndefined());
   8677 
   8678   // Reattach env2's proxy
   8679   env2 = Context::New(env1->GetIsolate(),
   8680                       0,
   8681                       v8::Handle<v8::ObjectTemplate>(),
   8682                       env2_global);
   8683   env2->SetSecurityToken(foo);
   8684   {
   8685     v8::Context::Scope scope(env2);
   8686     CompileRun("var x = 'x2';");
   8687   }
   8688 
   8689   result = CompileRun("get_x()");
   8690   CHECK(result->IsUndefined());
   8691   result = CompileRun("get_x_w()");
   8692   CHECK_EQ(v8_str("x2"), result);
   8693 }
   8694 
   8695 
   8696 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
   8697 static bool NamedAccessBlocker(Local<v8::Object> global,
   8698                                Local<Value> name,
   8699                                v8::AccessType type,
   8700                                Local<Value> data) {
   8701   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
   8702       allowed_access_type[type];
   8703 }
   8704 
   8705 
   8706 static bool IndexedAccessBlocker(Local<v8::Object> global,
   8707                                  uint32_t key,
   8708                                  v8::AccessType type,
   8709                                  Local<Value> data) {
   8710   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
   8711       allowed_access_type[type];
   8712 }
   8713 
   8714 
   8715 static int g_echo_value_1 = -1;
   8716 static int g_echo_value_2 = -1;
   8717 
   8718 
   8719 static void EchoGetter(
   8720     Local<String> name,
   8721     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8722   info.GetReturnValue().Set(v8_num(g_echo_value_1));
   8723 }
   8724 
   8725 
   8726 static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
   8727   info.GetReturnValue().Set(v8_num(g_echo_value_2));
   8728 }
   8729 
   8730 
   8731 static void EchoSetter(Local<String> name,
   8732                        Local<Value> value,
   8733                        const v8::PropertyCallbackInfo<void>&) {
   8734   if (value->IsNumber())
   8735     g_echo_value_1 = value->Int32Value();
   8736 }
   8737 
   8738 
   8739 static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
   8740   v8::Handle<v8::Value> value = info[0];
   8741   if (value->IsNumber())
   8742     g_echo_value_2 = value->Int32Value();
   8743 }
   8744 
   8745 
   8746 static void UnreachableGetter(
   8747     Local<String> name,
   8748     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8749   CHECK(false);  // This function should not be called..
   8750 }
   8751 
   8752 
   8753 static void UnreachableSetter(Local<String>,
   8754                               Local<Value>,
   8755                               const v8::PropertyCallbackInfo<void>&) {
   8756   CHECK(false);  // This function should nto be called.
   8757 }
   8758 
   8759 
   8760 static void UnreachableFunction(
   8761     const v8::FunctionCallbackInfo<v8::Value>& info) {
   8762   CHECK(false);  // This function should not be called..
   8763 }
   8764 
   8765 
   8766 TEST(AccessControl) {
   8767   v8::Isolate* isolate = CcTest::isolate();
   8768   v8::HandleScope handle_scope(isolate);
   8769   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   8770 
   8771   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   8772                                            IndexedAccessBlocker);
   8773 
   8774   // Add an accessor accessible by cross-domain JS code.
   8775   global_template->SetAccessor(
   8776       v8_str("accessible_prop"),
   8777       EchoGetter, EchoSetter,
   8778       v8::Handle<Value>(),
   8779       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   8780 
   8781 
   8782   global_template->SetAccessorProperty(
   8783       v8_str("accessible_js_prop"),
   8784       v8::FunctionTemplate::New(EchoGetter),
   8785       v8::FunctionTemplate::New(EchoSetter),
   8786       v8::None,
   8787       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   8788 
   8789   // Add an accessor that is not accessible by cross-domain JS code.
   8790   global_template->SetAccessor(v8_str("blocked_prop"),
   8791                                UnreachableGetter, UnreachableSetter,
   8792                                v8::Handle<Value>(),
   8793                                v8::DEFAULT);
   8794 
   8795   global_template->SetAccessorProperty(
   8796       v8_str("blocked_js_prop"),
   8797       v8::FunctionTemplate::New(UnreachableFunction),
   8798       v8::FunctionTemplate::New(UnreachableFunction),
   8799       v8::None,
   8800       v8::DEFAULT);
   8801 
   8802   // Create an environment
   8803   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   8804   context0->Enter();
   8805 
   8806   v8::Handle<v8::Object> global0 = context0->Global();
   8807 
   8808   // Define a property with JS getter and setter.
   8809   CompileRun(
   8810       "function getter() { return 'getter'; };\n"
   8811       "function setter() { return 'setter'; }\n"
   8812       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   8813 
   8814   Local<Value> getter = global0->Get(v8_str("getter"));
   8815   Local<Value> setter = global0->Get(v8_str("setter"));
   8816 
   8817   // And define normal element.
   8818   global0->Set(239, v8_str("239"));
   8819 
   8820   // Define an element with JS getter and setter.
   8821   CompileRun(
   8822       "function el_getter() { return 'el_getter'; };\n"
   8823       "function el_setter() { return 'el_setter'; };\n"
   8824       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   8825 
   8826   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
   8827   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
   8828 
   8829   v8::HandleScope scope1(isolate);
   8830 
   8831   v8::Local<Context> context1 = Context::New(isolate);
   8832   context1->Enter();
   8833 
   8834   v8::Handle<v8::Object> global1 = context1->Global();
   8835   global1->Set(v8_str("other"), global0);
   8836 
   8837   // Access blocked property.
   8838   CompileRun("other.blocked_prop = 1");
   8839 
   8840   ExpectUndefined("other.blocked_prop");
   8841   ExpectUndefined(
   8842       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
   8843   ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
   8844 
   8845   // Enable ACCESS_HAS
   8846   allowed_access_type[v8::ACCESS_HAS] = true;
   8847   ExpectUndefined("other.blocked_prop");
   8848   // ... and now we can get the descriptor...
   8849   ExpectUndefined(
   8850       "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
   8851   // ... and enumerate the property.
   8852   ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
   8853   allowed_access_type[v8::ACCESS_HAS] = false;
   8854 
   8855   // Access blocked element.
   8856   CompileRun("other[239] = 1");
   8857 
   8858   ExpectUndefined("other[239]");
   8859   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
   8860   ExpectFalse("propertyIsEnumerable.call(other, '239')");
   8861 
   8862   // Enable ACCESS_HAS
   8863   allowed_access_type[v8::ACCESS_HAS] = true;
   8864   ExpectUndefined("other[239]");
   8865   // ... and now we can get the descriptor...
   8866   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
   8867   // ... and enumerate the property.
   8868   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   8869   allowed_access_type[v8::ACCESS_HAS] = false;
   8870 
   8871   // Access a property with JS accessor.
   8872   CompileRun("other.js_accessor_p = 2");
   8873 
   8874   ExpectUndefined("other.js_accessor_p");
   8875   ExpectUndefined(
   8876       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
   8877 
   8878   // Enable ACCESS_HAS.
   8879   allowed_access_type[v8::ACCESS_HAS] = true;
   8880   ExpectUndefined("other.js_accessor_p");
   8881   ExpectUndefined(
   8882       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
   8883   ExpectUndefined(
   8884       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
   8885   ExpectUndefined(
   8886       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   8887   allowed_access_type[v8::ACCESS_HAS] = false;
   8888 
   8889   // Enable both ACCESS_HAS and ACCESS_GET.
   8890   allowed_access_type[v8::ACCESS_HAS] = true;
   8891   allowed_access_type[v8::ACCESS_GET] = true;
   8892 
   8893   ExpectString("other.js_accessor_p", "getter");
   8894   ExpectObject(
   8895       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   8896   ExpectUndefined(
   8897       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
   8898   ExpectUndefined(
   8899       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   8900 
   8901   allowed_access_type[v8::ACCESS_GET] = false;
   8902   allowed_access_type[v8::ACCESS_HAS] = false;
   8903 
   8904   // Enable both ACCESS_HAS and ACCESS_SET.
   8905   allowed_access_type[v8::ACCESS_HAS] = true;
   8906   allowed_access_type[v8::ACCESS_SET] = true;
   8907 
   8908   ExpectUndefined("other.js_accessor_p");
   8909   ExpectUndefined(
   8910       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
   8911   ExpectObject(
   8912       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   8913   ExpectUndefined(
   8914       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   8915 
   8916   allowed_access_type[v8::ACCESS_SET] = false;
   8917   allowed_access_type[v8::ACCESS_HAS] = false;
   8918 
   8919   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
   8920   allowed_access_type[v8::ACCESS_HAS] = true;
   8921   allowed_access_type[v8::ACCESS_GET] = true;
   8922   allowed_access_type[v8::ACCESS_SET] = true;
   8923 
   8924   ExpectString("other.js_accessor_p", "getter");
   8925   ExpectObject(
   8926       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   8927   ExpectObject(
   8928       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   8929   ExpectUndefined(
   8930       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   8931 
   8932   allowed_access_type[v8::ACCESS_SET] = false;
   8933   allowed_access_type[v8::ACCESS_GET] = false;
   8934   allowed_access_type[v8::ACCESS_HAS] = false;
   8935 
   8936   // Access an element with JS accessor.
   8937   CompileRun("other[42] = 2");
   8938 
   8939   ExpectUndefined("other[42]");
   8940   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
   8941 
   8942   // Enable ACCESS_HAS.
   8943   allowed_access_type[v8::ACCESS_HAS] = true;
   8944   ExpectUndefined("other[42]");
   8945   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
   8946   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
   8947   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   8948   allowed_access_type[v8::ACCESS_HAS] = false;
   8949 
   8950   // Enable both ACCESS_HAS and ACCESS_GET.
   8951   allowed_access_type[v8::ACCESS_HAS] = true;
   8952   allowed_access_type[v8::ACCESS_GET] = true;
   8953 
   8954   ExpectString("other[42]", "el_getter");
   8955   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   8956   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
   8957   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   8958 
   8959   allowed_access_type[v8::ACCESS_GET] = false;
   8960   allowed_access_type[v8::ACCESS_HAS] = false;
   8961 
   8962   // Enable both ACCESS_HAS and ACCESS_SET.
   8963   allowed_access_type[v8::ACCESS_HAS] = true;
   8964   allowed_access_type[v8::ACCESS_SET] = true;
   8965 
   8966   ExpectUndefined("other[42]");
   8967   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
   8968   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   8969   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   8970 
   8971   allowed_access_type[v8::ACCESS_SET] = false;
   8972   allowed_access_type[v8::ACCESS_HAS] = false;
   8973 
   8974   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
   8975   allowed_access_type[v8::ACCESS_HAS] = true;
   8976   allowed_access_type[v8::ACCESS_GET] = true;
   8977   allowed_access_type[v8::ACCESS_SET] = true;
   8978 
   8979   ExpectString("other[42]", "el_getter");
   8980   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   8981   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   8982   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   8983 
   8984   allowed_access_type[v8::ACCESS_SET] = false;
   8985   allowed_access_type[v8::ACCESS_GET] = false;
   8986   allowed_access_type[v8::ACCESS_HAS] = false;
   8987 
   8988   v8::Handle<Value> value;
   8989 
   8990   // Access accessible property
   8991   value = CompileRun("other.accessible_prop = 3");
   8992   CHECK(value->IsNumber());
   8993   CHECK_EQ(3, value->Int32Value());
   8994   CHECK_EQ(3, g_echo_value_1);
   8995 
   8996   // Access accessible js property
   8997   value = CompileRun("other.accessible_js_prop = 3");
   8998   CHECK(value->IsNumber());
   8999   CHECK_EQ(3, value->Int32Value());
   9000   CHECK_EQ(3, g_echo_value_2);
   9001 
   9002   value = CompileRun("other.accessible_prop");
   9003   CHECK(value->IsNumber());
   9004   CHECK_EQ(3, value->Int32Value());
   9005 
   9006   value = CompileRun("other.accessible_js_prop");
   9007   CHECK(value->IsNumber());
   9008   CHECK_EQ(3, value->Int32Value());
   9009 
   9010   value = CompileRun(
   9011       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   9012   CHECK(value->IsNumber());
   9013   CHECK_EQ(3, value->Int32Value());
   9014 
   9015   value = CompileRun(
   9016       "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
   9017   CHECK(value->IsNumber());
   9018   CHECK_EQ(3, value->Int32Value());
   9019 
   9020   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   9021   CHECK(value->IsTrue());
   9022 
   9023   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
   9024   CHECK(value->IsTrue());
   9025 
   9026   // Enumeration doesn't enumerate accessors from inaccessible objects in
   9027   // the prototype chain even if the accessors are in themselves accessible.
   9028   value =
   9029       CompileRun("(function(){var obj = {'__proto__':other};"
   9030                  "for (var p in obj)"
   9031                  "   if (p == 'accessible_prop' ||"
   9032                  "       p == 'accessible_js_prop' ||"
   9033                  "       p == 'blocked_js_prop' ||"
   9034                  "       p == 'blocked_js_prop') {"
   9035                  "     return false;"
   9036                  "   }"
   9037                  "return true;})()");
   9038   CHECK(value->IsTrue());
   9039 
   9040   context1->Exit();
   9041   context0->Exit();
   9042 }
   9043 
   9044 
   9045 TEST(AccessControlES5) {
   9046   v8::Isolate* isolate = CcTest::isolate();
   9047   v8::HandleScope handle_scope(isolate);
   9048   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   9049 
   9050   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   9051                                            IndexedAccessBlocker);
   9052 
   9053   // Add accessible accessor.
   9054   global_template->SetAccessor(
   9055       v8_str("accessible_prop"),
   9056       EchoGetter, EchoSetter,
   9057       v8::Handle<Value>(),
   9058       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   9059 
   9060 
   9061   // Add an accessor that is not accessible by cross-domain JS code.
   9062   global_template->SetAccessor(v8_str("blocked_prop"),
   9063                                UnreachableGetter, UnreachableSetter,
   9064                                v8::Handle<Value>(),
   9065                                v8::DEFAULT);
   9066 
   9067   // Create an environment
   9068   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9069   context0->Enter();
   9070 
   9071   v8::Handle<v8::Object> global0 = context0->Global();
   9072 
   9073   v8::Local<Context> context1 = Context::New(isolate);
   9074   context1->Enter();
   9075   v8::Handle<v8::Object> global1 = context1->Global();
   9076   global1->Set(v8_str("other"), global0);
   9077 
   9078   // Regression test for issue 1154.
   9079   ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
   9080 
   9081   ExpectUndefined("other.blocked_prop");
   9082 
   9083   // Regression test for issue 1027.
   9084   CompileRun("Object.defineProperty(\n"
   9085              "  other, 'blocked_prop', {configurable: false})");
   9086   ExpectUndefined("other.blocked_prop");
   9087   ExpectUndefined(
   9088       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
   9089 
   9090   // Regression test for issue 1171.
   9091   ExpectTrue("Object.isExtensible(other)");
   9092   CompileRun("Object.preventExtensions(other)");
   9093   ExpectTrue("Object.isExtensible(other)");
   9094 
   9095   // Object.seal and Object.freeze.
   9096   CompileRun("Object.freeze(other)");
   9097   ExpectTrue("Object.isExtensible(other)");
   9098 
   9099   CompileRun("Object.seal(other)");
   9100   ExpectTrue("Object.isExtensible(other)");
   9101 
   9102   // Regression test for issue 1250.
   9103   // Make sure that we can set the accessible accessors value using normal
   9104   // assignment.
   9105   CompileRun("other.accessible_prop = 42");
   9106   CHECK_EQ(42, g_echo_value_1);
   9107 
   9108   v8::Handle<Value> value;
   9109   // We follow Safari in ignoring assignments to host object accessors.
   9110   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
   9111   value = CompileRun("other.accessible_prop == 42");
   9112   CHECK(value->IsTrue());
   9113 }
   9114 
   9115 
   9116 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
   9117                                             Local<Value> name,
   9118                                             v8::AccessType type,
   9119                                             Local<Value> data) {
   9120   return false;
   9121 }
   9122 
   9123 
   9124 static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
   9125                                               uint32_t key,
   9126                                               v8::AccessType type,
   9127                                               Local<Value> data) {
   9128   return false;
   9129 }
   9130 
   9131 
   9132 THREADED_TEST(AccessControlGetOwnPropertyNames) {
   9133   v8::Isolate* isolate = CcTest::isolate();
   9134   v8::HandleScope handle_scope(isolate);
   9135   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
   9136 
   9137   obj_template->Set(v8_str("x"), v8::Integer::New(42));
   9138   obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
   9139                                         GetOwnPropertyNamesIndexedBlocker);
   9140 
   9141   // Create an environment
   9142   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
   9143   context0->Enter();
   9144 
   9145   v8::Handle<v8::Object> global0 = context0->Global();
   9146 
   9147   v8::HandleScope scope1(CcTest::isolate());
   9148 
   9149   v8::Local<Context> context1 = Context::New(isolate);
   9150   context1->Enter();
   9151 
   9152   v8::Handle<v8::Object> global1 = context1->Global();
   9153   global1->Set(v8_str("other"), global0);
   9154   global1->Set(v8_str("object"), obj_template->NewInstance());
   9155 
   9156   v8::Handle<Value> value;
   9157 
   9158   // Attempt to get the property names of the other global object and
   9159   // of an object that requires access checks.  Accessing the other
   9160   // global object should be blocked by access checks on the global
   9161   // proxy object.  Accessing the object that requires access checks
   9162   // is blocked by the access checks on the object itself.
   9163   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
   9164   CHECK(value->IsTrue());
   9165 
   9166   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
   9167   CHECK(value->IsTrue());
   9168 
   9169   context1->Exit();
   9170   context0->Exit();
   9171 }
   9172 
   9173 
   9174 static void IndexedPropertyEnumerator(
   9175     const v8::PropertyCallbackInfo<v8::Array>& info) {
   9176   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
   9177   result->Set(0, v8::Integer::New(7));
   9178   result->Set(1, v8::Object::New());
   9179   info.GetReturnValue().Set(result);
   9180 }
   9181 
   9182 
   9183 static void NamedPropertyEnumerator(
   9184     const v8::PropertyCallbackInfo<v8::Array>& info) {
   9185   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
   9186   result->Set(0, v8_str("x"));
   9187   result->Set(1, v8::Object::New());
   9188   info.GetReturnValue().Set(result);
   9189 }
   9190 
   9191 
   9192 THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
   9193   v8::HandleScope handle_scope(CcTest::isolate());
   9194   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
   9195 
   9196   obj_template->Set(v8_str("7"), v8::Integer::New(7));
   9197   obj_template->Set(v8_str("x"), v8::Integer::New(42));
   9198   obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
   9199                                           IndexedPropertyEnumerator);
   9200   obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
   9201                                         NamedPropertyEnumerator);
   9202 
   9203   LocalContext context;
   9204   v8::Handle<v8::Object> global = context->Global();
   9205   global->Set(v8_str("object"), obj_template->NewInstance());
   9206 
   9207   v8::Handle<v8::Value> result =
   9208       CompileRun("Object.getOwnPropertyNames(object)");
   9209   CHECK(result->IsArray());
   9210   v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
   9211   CHECK_EQ(3, result_array->Length());
   9212   CHECK(result_array->Get(0)->IsString());
   9213   CHECK(result_array->Get(1)->IsString());
   9214   CHECK(result_array->Get(2)->IsString());
   9215   CHECK_EQ(v8_str("7"), result_array->Get(0));
   9216   CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
   9217   CHECK_EQ(v8_str("x"), result_array->Get(2));
   9218 }
   9219 
   9220 
   9221 static void ConstTenGetter(Local<String> name,
   9222                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   9223   info.GetReturnValue().Set(v8_num(10));
   9224 }
   9225 
   9226 
   9227 THREADED_TEST(CrossDomainAccessors) {
   9228   v8::Isolate* isolate = CcTest::isolate();
   9229   v8::HandleScope handle_scope(isolate);
   9230 
   9231   v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
   9232 
   9233   v8::Handle<v8::ObjectTemplate> global_template =
   9234       func_template->InstanceTemplate();
   9235 
   9236   v8::Handle<v8::ObjectTemplate> proto_template =
   9237       func_template->PrototypeTemplate();
   9238 
   9239   // Add an accessor to proto that's accessible by cross-domain JS code.
   9240   proto_template->SetAccessor(v8_str("accessible"),
   9241                               ConstTenGetter, 0,
   9242                               v8::Handle<Value>(),
   9243                               v8::ALL_CAN_READ);
   9244 
   9245   // Add an accessor that is not accessible by cross-domain JS code.
   9246   global_template->SetAccessor(v8_str("unreachable"),
   9247                                UnreachableGetter, 0,
   9248                                v8::Handle<Value>(),
   9249                                v8::DEFAULT);
   9250 
   9251   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9252   context0->Enter();
   9253 
   9254   Local<v8::Object> global = context0->Global();
   9255   // Add a normal property that shadows 'accessible'
   9256   global->Set(v8_str("accessible"), v8_num(11));
   9257 
   9258   // Enter a new context.
   9259   v8::HandleScope scope1(CcTest::isolate());
   9260   v8::Local<Context> context1 = Context::New(isolate);
   9261   context1->Enter();
   9262 
   9263   v8::Handle<v8::Object> global1 = context1->Global();
   9264   global1->Set(v8_str("other"), global);
   9265 
   9266   // Should return 10, instead of 11
   9267   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
   9268   CHECK(value->IsNumber());
   9269   CHECK_EQ(10, value->Int32Value());
   9270 
   9271   value = v8_compile("other.unreachable")->Run();
   9272   CHECK(value->IsUndefined());
   9273 
   9274   context1->Exit();
   9275   context0->Exit();
   9276 }
   9277 
   9278 
   9279 static int named_access_count = 0;
   9280 static int indexed_access_count = 0;
   9281 
   9282 static bool NamedAccessCounter(Local<v8::Object> global,
   9283                                Local<Value> name,
   9284                                v8::AccessType type,
   9285                                Local<Value> data) {
   9286   named_access_count++;
   9287   return true;
   9288 }
   9289 
   9290 
   9291 static bool IndexedAccessCounter(Local<v8::Object> global,
   9292                                  uint32_t key,
   9293                                  v8::AccessType type,
   9294                                  Local<Value> data) {
   9295   indexed_access_count++;
   9296   return true;
   9297 }
   9298 
   9299 
   9300 // This one is too easily disturbed by other tests.
   9301 TEST(AccessControlIC) {
   9302   named_access_count = 0;
   9303   indexed_access_count = 0;
   9304 
   9305   v8::Isolate* isolate = CcTest::isolate();
   9306   v8::HandleScope handle_scope(isolate);
   9307 
   9308   // Create an environment.
   9309   v8::Local<Context> context0 = Context::New(isolate);
   9310   context0->Enter();
   9311 
   9312   // Create an object that requires access-check functions to be
   9313   // called for cross-domain access.
   9314   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   9315   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   9316                                            IndexedAccessCounter);
   9317   Local<v8::Object> object = object_template->NewInstance();
   9318 
   9319   v8::HandleScope scope1(isolate);
   9320 
   9321   // Create another environment.
   9322   v8::Local<Context> context1 = Context::New(isolate);
   9323   context1->Enter();
   9324 
   9325   // Make easy access to the object from the other environment.
   9326   v8::Handle<v8::Object> global1 = context1->Global();
   9327   global1->Set(v8_str("obj"), object);
   9328 
   9329   v8::Handle<Value> value;
   9330 
   9331   // Check that the named access-control function is called every time.
   9332   CompileRun("function testProp(obj) {"
   9333              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   9334              "  for (var j = 0; j < 10; j++) obj.prop;"
   9335              "  return obj.prop"
   9336              "}");
   9337   value = CompileRun("testProp(obj)");
   9338   CHECK(value->IsNumber());
   9339   CHECK_EQ(1, value->Int32Value());
   9340   CHECK_EQ(21, named_access_count);
   9341 
   9342   // Check that the named access-control function is called every time.
   9343   CompileRun("var p = 'prop';"
   9344              "function testKeyed(obj) {"
   9345              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   9346              "  for (var j = 0; j < 10; j++) obj[p];"
   9347              "  return obj[p];"
   9348              "}");
   9349   // Use obj which requires access checks.  No inline caching is used
   9350   // in that case.
   9351   value = CompileRun("testKeyed(obj)");
   9352   CHECK(value->IsNumber());
   9353   CHECK_EQ(1, value->Int32Value());
   9354   CHECK_EQ(42, named_access_count);
   9355   // Force the inline caches into generic state and try again.
   9356   CompileRun("testKeyed({ a: 0 })");
   9357   CompileRun("testKeyed({ b: 0 })");
   9358   value = CompileRun("testKeyed(obj)");
   9359   CHECK(value->IsNumber());
   9360   CHECK_EQ(1, value->Int32Value());
   9361   CHECK_EQ(63, named_access_count);
   9362 
   9363   // Check that the indexed access-control function is called every time.
   9364   CompileRun("function testIndexed(obj) {"
   9365              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   9366              "  for (var j = 0; j < 10; j++) obj[0];"
   9367              "  return obj[0]"
   9368              "}");
   9369   value = CompileRun("testIndexed(obj)");
   9370   CHECK(value->IsNumber());
   9371   CHECK_EQ(1, value->Int32Value());
   9372   CHECK_EQ(21, indexed_access_count);
   9373   // Force the inline caches into generic state.
   9374   CompileRun("testIndexed(new Array(1))");
   9375   // Test that the indexed access check is called.
   9376   value = CompileRun("testIndexed(obj)");
   9377   CHECK(value->IsNumber());
   9378   CHECK_EQ(1, value->Int32Value());
   9379   CHECK_EQ(42, indexed_access_count);
   9380 
   9381   // Check that the named access check is called when invoking
   9382   // functions on an object that requires access checks.
   9383   CompileRun("obj.f = function() {}");
   9384   CompileRun("function testCallNormal(obj) {"
   9385              "  for (var i = 0; i < 10; i++) obj.f();"
   9386              "}");
   9387   CompileRun("testCallNormal(obj)");
   9388   CHECK_EQ(74, named_access_count);
   9389 
   9390   // Force obj into slow case.
   9391   value = CompileRun("delete obj.prop");
   9392   CHECK(value->BooleanValue());
   9393   // Force inline caches into dictionary probing mode.
   9394   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   9395   // Test that the named access check is called.
   9396   value = CompileRun("testProp(obj);");
   9397   CHECK(value->IsNumber());
   9398   CHECK_EQ(1, value->Int32Value());
   9399   CHECK_EQ(96, named_access_count);
   9400 
   9401   // Force the call inline cache into dictionary probing mode.
   9402   CompileRun("o.f = function() {}; testCallNormal(o)");
   9403   // Test that the named access check is still called for each
   9404   // invocation of the function.
   9405   value = CompileRun("testCallNormal(obj)");
   9406   CHECK_EQ(106, named_access_count);
   9407 
   9408   context1->Exit();
   9409   context0->Exit();
   9410 }
   9411 
   9412 
   9413 static bool NamedAccessFlatten(Local<v8::Object> global,
   9414                                Local<Value> name,
   9415                                v8::AccessType type,
   9416                                Local<Value> data) {
   9417   char buf[100];
   9418   int len;
   9419 
   9420   CHECK(name->IsString());
   9421 
   9422   memset(buf, 0x1, sizeof(buf));
   9423   len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   9424   CHECK_EQ(4, len);
   9425 
   9426   uint16_t buf2[100];
   9427 
   9428   memset(buf, 0x1, sizeof(buf));
   9429   len = name.As<String>()->Write(buf2);
   9430   CHECK_EQ(4, len);
   9431 
   9432   return true;
   9433 }
   9434 
   9435 
   9436 static bool IndexedAccessFlatten(Local<v8::Object> global,
   9437                                  uint32_t key,
   9438                                  v8::AccessType type,
   9439                                  Local<Value> data) {
   9440   return true;
   9441 }
   9442 
   9443 
   9444 // Regression test.  In access checks, operations that may cause
   9445 // garbage collection are not allowed.  It used to be the case that
   9446 // using the Write operation on a string could cause a garbage
   9447 // collection due to flattening of the string.  This is no longer the
   9448 // case.
   9449 THREADED_TEST(AccessControlFlatten) {
   9450   named_access_count = 0;
   9451   indexed_access_count = 0;
   9452 
   9453   v8::Isolate* isolate = CcTest::isolate();
   9454   v8::HandleScope handle_scope(isolate);
   9455 
   9456   // Create an environment.
   9457   v8::Local<Context> context0 = Context::New(isolate);
   9458   context0->Enter();
   9459 
   9460   // Create an object that requires access-check functions to be
   9461   // called for cross-domain access.
   9462   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   9463   object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
   9464                                            IndexedAccessFlatten);
   9465   Local<v8::Object> object = object_template->NewInstance();
   9466 
   9467   v8::HandleScope scope1(isolate);
   9468 
   9469   // Create another environment.
   9470   v8::Local<Context> context1 = Context::New(isolate);
   9471   context1->Enter();
   9472 
   9473   // Make easy access to the object from the other environment.
   9474   v8::Handle<v8::Object> global1 = context1->Global();
   9475   global1->Set(v8_str("obj"), object);
   9476 
   9477   v8::Handle<Value> value;
   9478 
   9479   value = v8_compile("var p = 'as' + 'df';")->Run();
   9480   value = v8_compile("obj[p];")->Run();
   9481 
   9482   context1->Exit();
   9483   context0->Exit();
   9484 }
   9485 
   9486 
   9487 static void AccessControlNamedGetter(
   9488     Local<String>,
   9489     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9490   info.GetReturnValue().Set(42);
   9491 }
   9492 
   9493 
   9494 static void AccessControlNamedSetter(
   9495     Local<String>,
   9496     Local<Value> value,
   9497     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9498   info.GetReturnValue().Set(value);
   9499 }
   9500 
   9501 
   9502 static void AccessControlIndexedGetter(
   9503       uint32_t index,
   9504       const v8::PropertyCallbackInfo<v8::Value>& info) {
   9505   info.GetReturnValue().Set(v8_num(42));
   9506 }
   9507 
   9508 
   9509 static void AccessControlIndexedSetter(
   9510     uint32_t,
   9511     Local<Value> value,
   9512     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9513   info.GetReturnValue().Set(value);
   9514 }
   9515 
   9516 
   9517 THREADED_TEST(AccessControlInterceptorIC) {
   9518   named_access_count = 0;
   9519   indexed_access_count = 0;
   9520 
   9521   v8::Isolate* isolate = CcTest::isolate();
   9522   v8::HandleScope handle_scope(isolate);
   9523 
   9524   // Create an environment.
   9525   v8::Local<Context> context0 = Context::New(isolate);
   9526   context0->Enter();
   9527 
   9528   // Create an object that requires access-check functions to be
   9529   // called for cross-domain access.  The object also has interceptors
   9530   // interceptor.
   9531   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   9532   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   9533                                            IndexedAccessCounter);
   9534   object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
   9535                                            AccessControlNamedSetter);
   9536   object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
   9537                                              AccessControlIndexedSetter);
   9538   Local<v8::Object> object = object_template->NewInstance();
   9539 
   9540   v8::HandleScope scope1(isolate);
   9541 
   9542   // Create another environment.
   9543   v8::Local<Context> context1 = Context::New(isolate);
   9544   context1->Enter();
   9545 
   9546   // Make easy access to the object from the other environment.
   9547   v8::Handle<v8::Object> global1 = context1->Global();
   9548   global1->Set(v8_str("obj"), object);
   9549 
   9550   v8::Handle<Value> value;
   9551 
   9552   // Check that the named access-control function is called every time
   9553   // eventhough there is an interceptor on the object.
   9554   value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
   9555   value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
   9556                      "obj.x")->Run();
   9557   CHECK(value->IsNumber());
   9558   CHECK_EQ(42, value->Int32Value());
   9559   CHECK_EQ(21, named_access_count);
   9560 
   9561   value = v8_compile("var p = 'x';")->Run();
   9562   value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
   9563   value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
   9564                      "obj[p]")->Run();
   9565   CHECK(value->IsNumber());
   9566   CHECK_EQ(42, value->Int32Value());
   9567   CHECK_EQ(42, named_access_count);
   9568 
   9569   // Check that the indexed access-control function is called every
   9570   // time eventhough there is an interceptor on the object.
   9571   value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
   9572   value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
   9573                      "obj[0]")->Run();
   9574   CHECK(value->IsNumber());
   9575   CHECK_EQ(42, value->Int32Value());
   9576   CHECK_EQ(21, indexed_access_count);
   9577 
   9578   context1->Exit();
   9579   context0->Exit();
   9580 }
   9581 
   9582 
   9583 THREADED_TEST(Version) {
   9584   v8::V8::GetVersion();
   9585 }
   9586 
   9587 
   9588 static void InstanceFunctionCallback(
   9589     const v8::FunctionCallbackInfo<v8::Value>& args) {
   9590   ApiTestFuzzer::Fuzz();
   9591   args.GetReturnValue().Set(v8_num(12));
   9592 }
   9593 
   9594 
   9595 THREADED_TEST(InstanceProperties) {
   9596   LocalContext context;
   9597   v8::HandleScope handle_scope(context->GetIsolate());
   9598 
   9599   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9600   Local<ObjectTemplate> instance = t->InstanceTemplate();
   9601 
   9602   instance->Set(v8_str("x"), v8_num(42));
   9603   instance->Set(v8_str("f"),
   9604                 v8::FunctionTemplate::New(InstanceFunctionCallback));
   9605 
   9606   Local<Value> o = t->GetFunction()->NewInstance();
   9607 
   9608   context->Global()->Set(v8_str("i"), o);
   9609   Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
   9610   CHECK_EQ(42, value->Int32Value());
   9611 
   9612   value = Script::Compile(v8_str("i.f()"))->Run();
   9613   CHECK_EQ(12, value->Int32Value());
   9614 }
   9615 
   9616 
   9617 static void GlobalObjectInstancePropertiesGet(
   9618     Local<String> key,
   9619     const v8::PropertyCallbackInfo<v8::Value>&) {
   9620   ApiTestFuzzer::Fuzz();
   9621 }
   9622 
   9623 
   9624 THREADED_TEST(GlobalObjectInstanceProperties) {
   9625   v8::HandleScope handle_scope(CcTest::isolate());
   9626 
   9627   Local<Value> global_object;
   9628 
   9629   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9630   t->InstanceTemplate()->SetNamedPropertyHandler(
   9631       GlobalObjectInstancePropertiesGet);
   9632   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   9633   instance_template->Set(v8_str("x"), v8_num(42));
   9634   instance_template->Set(v8_str("f"),
   9635                          v8::FunctionTemplate::New(InstanceFunctionCallback));
   9636 
   9637   // The script to check how Crankshaft compiles missing global function
   9638   // invocations.  function g is not defined and should throw on call.
   9639   const char* script =
   9640       "function wrapper(call) {"
   9641       "  var x = 0, y = 1;"
   9642       "  for (var i = 0; i < 1000; i++) {"
   9643       "    x += i * 100;"
   9644       "    y += i * 100;"
   9645       "  }"
   9646       "  if (call) g();"
   9647       "}"
   9648       "for (var i = 0; i < 17; i++) wrapper(false);"
   9649       "var thrown = 0;"
   9650       "try { wrapper(true); } catch (e) { thrown = 1; };"
   9651       "thrown";
   9652 
   9653   {
   9654     LocalContext env(NULL, instance_template);
   9655     // Hold on to the global object so it can be used again in another
   9656     // environment initialization.
   9657     global_object = env->Global();
   9658 
   9659     Local<Value> value = Script::Compile(v8_str("x"))->Run();
   9660     CHECK_EQ(42, value->Int32Value());
   9661     value = Script::Compile(v8_str("f()"))->Run();
   9662     CHECK_EQ(12, value->Int32Value());
   9663     value = Script::Compile(v8_str(script))->Run();
   9664     CHECK_EQ(1, value->Int32Value());
   9665   }
   9666 
   9667   {
   9668     // Create new environment reusing the global object.
   9669     LocalContext env(NULL, instance_template, global_object);
   9670     Local<Value> value = Script::Compile(v8_str("x"))->Run();
   9671     CHECK_EQ(42, value->Int32Value());
   9672     value = Script::Compile(v8_str("f()"))->Run();
   9673     CHECK_EQ(12, value->Int32Value());
   9674     value = Script::Compile(v8_str(script))->Run();
   9675     CHECK_EQ(1, value->Int32Value());
   9676   }
   9677 }
   9678 
   9679 
   9680 THREADED_TEST(CallKnownGlobalReceiver) {
   9681   v8::HandleScope handle_scope(CcTest::isolate());
   9682 
   9683   Local<Value> global_object;
   9684 
   9685   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9686   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   9687 
   9688   // The script to check that we leave global object not
   9689   // global object proxy on stack when we deoptimize from inside
   9690   // arguments evaluation.
   9691   // To provoke error we need to both force deoptimization
   9692   // from arguments evaluation and to force CallIC to take
   9693   // CallIC_Miss code path that can't cope with global proxy.
   9694   const char* script =
   9695       "function bar(x, y) { try { } finally { } }"
   9696       "function baz(x) { try { } finally { } }"
   9697       "function bom(x) { try { } finally { } }"
   9698       "function foo(x) { bar([x], bom(2)); }"
   9699       "for (var i = 0; i < 10000; i++) foo(1);"
   9700       "foo";
   9701 
   9702   Local<Value> foo;
   9703   {
   9704     LocalContext env(NULL, instance_template);
   9705     // Hold on to the global object so it can be used again in another
   9706     // environment initialization.
   9707     global_object = env->Global();
   9708     foo = Script::Compile(v8_str(script))->Run();
   9709   }
   9710 
   9711   {
   9712     // Create new environment reusing the global object.
   9713     LocalContext env(NULL, instance_template, global_object);
   9714     env->Global()->Set(v8_str("foo"), foo);
   9715     Script::Compile(v8_str("foo()"))->Run();
   9716   }
   9717 }
   9718 
   9719 
   9720 static void ShadowFunctionCallback(
   9721     const v8::FunctionCallbackInfo<v8::Value>& args) {
   9722   ApiTestFuzzer::Fuzz();
   9723   args.GetReturnValue().Set(v8_num(42));
   9724 }
   9725 
   9726 
   9727 static int shadow_y;
   9728 static int shadow_y_setter_call_count;
   9729 static int shadow_y_getter_call_count;
   9730 
   9731 
   9732 static void ShadowYSetter(Local<String>,
   9733                           Local<Value>,
   9734                           const v8::PropertyCallbackInfo<void>&) {
   9735   shadow_y_setter_call_count++;
   9736   shadow_y = 42;
   9737 }
   9738 
   9739 
   9740 static void ShadowYGetter(Local<String> name,
   9741                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   9742   ApiTestFuzzer::Fuzz();
   9743   shadow_y_getter_call_count++;
   9744   info.GetReturnValue().Set(v8_num(shadow_y));
   9745 }
   9746 
   9747 
   9748 static void ShadowIndexedGet(uint32_t index,
   9749                              const v8::PropertyCallbackInfo<v8::Value>&) {
   9750 }
   9751 
   9752 
   9753 static void ShadowNamedGet(Local<String> key,
   9754                            const v8::PropertyCallbackInfo<v8::Value>&) {
   9755 }
   9756 
   9757 
   9758 THREADED_TEST(ShadowObject) {
   9759   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   9760   v8::HandleScope handle_scope(CcTest::isolate());
   9761 
   9762   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
   9763   LocalContext context(NULL, global_template);
   9764 
   9765   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9766   t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
   9767   t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
   9768   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   9769   Local<ObjectTemplate> instance = t->InstanceTemplate();
   9770 
   9771   proto->Set(v8_str("f"),
   9772              v8::FunctionTemplate::New(ShadowFunctionCallback, Local<Value>()));
   9773   proto->Set(v8_str("x"), v8_num(12));
   9774 
   9775   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   9776 
   9777   Local<Value> o = t->GetFunction()->NewInstance();
   9778   context->Global()->Set(v8_str("__proto__"), o);
   9779 
   9780   Local<Value> value =
   9781       Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
   9782   CHECK(value->IsBoolean());
   9783   CHECK(!value->BooleanValue());
   9784 
   9785   value = Script::Compile(v8_str("x"))->Run();
   9786   CHECK_EQ(12, value->Int32Value());
   9787 
   9788   value = Script::Compile(v8_str("f()"))->Run();
   9789   CHECK_EQ(42, value->Int32Value());
   9790 
   9791   Script::Compile(v8_str("y = 43"))->Run();
   9792   CHECK_EQ(1, shadow_y_setter_call_count);
   9793   value = Script::Compile(v8_str("y"))->Run();
   9794   CHECK_EQ(1, shadow_y_getter_call_count);
   9795   CHECK_EQ(42, value->Int32Value());
   9796 }
   9797 
   9798 
   9799 THREADED_TEST(HiddenPrototype) {
   9800   LocalContext context;
   9801   v8::HandleScope handle_scope(context->GetIsolate());
   9802 
   9803   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
   9804   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   9805   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   9806   t1->SetHiddenPrototype(true);
   9807   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   9808   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   9809   t2->SetHiddenPrototype(true);
   9810   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   9811   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   9812   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   9813 
   9814   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   9815   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   9816   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   9817   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   9818 
   9819   // Setting the prototype on an object skips hidden prototypes.
   9820   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9821   o0->Set(v8_str("__proto__"), o1);
   9822   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9823   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9824   o0->Set(v8_str("__proto__"), o2);
   9825   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9826   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9827   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   9828   o0->Set(v8_str("__proto__"), o3);
   9829   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9830   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9831   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   9832   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   9833 
   9834   // Getting the prototype of o0 should get the first visible one
   9835   // which is o3.  Therefore, z should not be defined on the prototype
   9836   // object.
   9837   Local<Value> proto = o0->Get(v8_str("__proto__"));
   9838   CHECK(proto->IsObject());
   9839   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
   9840 }
   9841 
   9842 
   9843 THREADED_TEST(HiddenPrototypeSet) {
   9844   LocalContext context;
   9845   v8::HandleScope handle_scope(context->GetIsolate());
   9846 
   9847   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New();
   9848   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New();
   9849   ht->SetHiddenPrototype(true);
   9850   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New();
   9851   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   9852 
   9853   Local<v8::Object> o = ot->GetFunction()->NewInstance();
   9854   Local<v8::Object> h = ht->GetFunction()->NewInstance();
   9855   Local<v8::Object> p = pt->GetFunction()->NewInstance();
   9856   o->Set(v8_str("__proto__"), h);
   9857   h->Set(v8_str("__proto__"), p);
   9858 
   9859   // Setting a property that exists on the hidden prototype goes there.
   9860   o->Set(v8_str("x"), v8_num(7));
   9861   CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
   9862   CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
   9863   CHECK(p->Get(v8_str("x"))->IsUndefined());
   9864 
   9865   // Setting a new property should not be forwarded to the hidden prototype.
   9866   o->Set(v8_str("y"), v8_num(6));
   9867   CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
   9868   CHECK(h->Get(v8_str("y"))->IsUndefined());
   9869   CHECK(p->Get(v8_str("y"))->IsUndefined());
   9870 
   9871   // Setting a property that only exists on a prototype of the hidden prototype
   9872   // is treated normally again.
   9873   p->Set(v8_str("z"), v8_num(8));
   9874   CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
   9875   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
   9876   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
   9877   o->Set(v8_str("z"), v8_num(9));
   9878   CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
   9879   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
   9880   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
   9881 }
   9882 
   9883 
   9884 // Regression test for issue 2457.
   9885 THREADED_TEST(HiddenPrototypeIdentityHash) {
   9886   LocalContext context;
   9887   v8::HandleScope handle_scope(context->GetIsolate());
   9888 
   9889   Handle<FunctionTemplate> t = FunctionTemplate::New();
   9890   t->SetHiddenPrototype(true);
   9891   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
   9892   Handle<Object> p = t->GetFunction()->NewInstance();
   9893   Handle<Object> o = Object::New();
   9894   o->SetPrototype(p);
   9895 
   9896   int hash = o->GetIdentityHash();
   9897   USE(hash);
   9898   o->Set(v8_str("foo"), v8_num(42));
   9899   ASSERT_EQ(hash, o->GetIdentityHash());
   9900 }
   9901 
   9902 
   9903 THREADED_TEST(SetPrototype) {
   9904   LocalContext context;
   9905   v8::HandleScope handle_scope(context->GetIsolate());
   9906 
   9907   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
   9908   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   9909   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   9910   t1->SetHiddenPrototype(true);
   9911   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   9912   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   9913   t2->SetHiddenPrototype(true);
   9914   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   9915   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   9916   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   9917 
   9918   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   9919   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   9920   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   9921   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   9922 
   9923   // Setting the prototype on an object does not skip hidden prototypes.
   9924   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9925   CHECK(o0->SetPrototype(o1));
   9926   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9927   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9928   CHECK(o1->SetPrototype(o2));
   9929   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9930   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9931   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   9932   CHECK(o2->SetPrototype(o3));
   9933   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9934   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9935   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   9936   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   9937 
   9938   // Getting the prototype of o0 should get the first visible one
   9939   // which is o3.  Therefore, z should not be defined on the prototype
   9940   // object.
   9941   Local<Value> proto = o0->Get(v8_str("__proto__"));
   9942   CHECK(proto->IsObject());
   9943   CHECK_EQ(proto.As<v8::Object>(), o3);
   9944 
   9945   // However, Object::GetPrototype ignores hidden prototype.
   9946   Local<Value> proto0 = o0->GetPrototype();
   9947   CHECK(proto0->IsObject());
   9948   CHECK_EQ(proto0.As<v8::Object>(), o1);
   9949 
   9950   Local<Value> proto1 = o1->GetPrototype();
   9951   CHECK(proto1->IsObject());
   9952   CHECK_EQ(proto1.As<v8::Object>(), o2);
   9953 
   9954   Local<Value> proto2 = o2->GetPrototype();
   9955   CHECK(proto2->IsObject());
   9956   CHECK_EQ(proto2.As<v8::Object>(), o3);
   9957 }
   9958 
   9959 
   9960 // Getting property names of an object with a prototype chain that
   9961 // triggers dictionary elements in GetLocalPropertyNames() shouldn't
   9962 // crash the runtime.
   9963 THREADED_TEST(Regress91517) {
   9964   i::FLAG_allow_natives_syntax = true;
   9965   LocalContext context;
   9966   v8::HandleScope handle_scope(context->GetIsolate());
   9967 
   9968   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   9969   t1->SetHiddenPrototype(true);
   9970   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   9971   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   9972   t2->SetHiddenPrototype(true);
   9973   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   9974   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New());
   9975   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   9976   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   9977   t3->SetHiddenPrototype(true);
   9978   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   9979   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
   9980   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   9981 
   9982   // Force dictionary-based properties.
   9983   i::ScopedVector<char> name_buf(1024);
   9984   for (int i = 1; i <= 1000; i++) {
   9985     i::OS::SNPrintF(name_buf, "sdf%d", i);
   9986     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   9987   }
   9988 
   9989   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   9990   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   9991   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   9992   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
   9993 
   9994   // Create prototype chain of hidden prototypes.
   9995   CHECK(o4->SetPrototype(o3));
   9996   CHECK(o3->SetPrototype(o2));
   9997   CHECK(o2->SetPrototype(o1));
   9998 
   9999   // Call the runtime version of GetLocalPropertyNames() on the natively
   10000   // created object through JavaScript.
   10001   context->Global()->Set(v8_str("obj"), o4);
   10002   CompileRun("var names = %GetLocalPropertyNames(obj, true);");
   10003 
   10004   ExpectInt32("names.length", 1006);
   10005   ExpectTrue("names.indexOf(\"baz\") >= 0");
   10006   ExpectTrue("names.indexOf(\"boo\") >= 0");
   10007   ExpectTrue("names.indexOf(\"foo\") >= 0");
   10008   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
   10009   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   10010   ExpectFalse("names[1005] == undefined");
   10011 }
   10012 
   10013 
   10014 THREADED_TEST(FunctionReadOnlyPrototype) {
   10015   LocalContext context;
   10016   v8::HandleScope handle_scope(context->GetIsolate());
   10017 
   10018   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   10019   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
   10020   t1->ReadOnlyPrototype();
   10021   context->Global()->Set(v8_str("func1"), t1->GetFunction());
   10022   // Configured value of ReadOnly flag.
   10023   CHECK(CompileRun(
   10024       "(function() {"
   10025       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   10026       "  return (descriptor['writable'] == false);"
   10027       "})()")->BooleanValue());
   10028   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
   10029   CHECK_EQ(42,
   10030            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
   10031 
   10032   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   10033   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
   10034   context->Global()->Set(v8_str("func2"), t2->GetFunction());
   10035   // Default value of ReadOnly flag.
   10036   CHECK(CompileRun(
   10037       "(function() {"
   10038       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   10039       "  return (descriptor['writable'] == true);"
   10040       "})()")->BooleanValue());
   10041   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
   10042 }
   10043 
   10044 
   10045 THREADED_TEST(SetPrototypeThrows) {
   10046   LocalContext context;
   10047   v8::HandleScope handle_scope(context->GetIsolate());
   10048 
   10049   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   10050 
   10051   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
   10052   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
   10053 
   10054   CHECK(o0->SetPrototype(o1));
   10055   // If setting the prototype leads to the cycle, SetPrototype should
   10056   // return false and keep VM in sane state.
   10057   v8::TryCatch try_catch;
   10058   CHECK(!o1->SetPrototype(o0));
   10059   CHECK(!try_catch.HasCaught());
   10060   ASSERT(!CcTest::i_isolate()->has_pending_exception());
   10061 
   10062   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
   10063 }
   10064 
   10065 
   10066 THREADED_TEST(FunctionRemovePrototype) {
   10067   LocalContext context;
   10068   v8::HandleScope handle_scope(context->GetIsolate());
   10069 
   10070   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   10071   t1->RemovePrototype();
   10072   Local<v8::Function> fun = t1->GetFunction();
   10073   context->Global()->Set(v8_str("fun"), fun);
   10074   CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
   10075 
   10076   v8::TryCatch try_catch;
   10077   CompileRun("new fun()");
   10078   CHECK(try_catch.HasCaught());
   10079 
   10080   try_catch.Reset();
   10081   fun->NewInstance();
   10082   CHECK(try_catch.HasCaught());
   10083 }
   10084 
   10085 
   10086 THREADED_TEST(GetterSetterExceptions) {
   10087   LocalContext context;
   10088   v8::HandleScope handle_scope(context->GetIsolate());
   10089   CompileRun(
   10090     "function Foo() { };"
   10091     "function Throw() { throw 5; };"
   10092     "var x = { };"
   10093     "x.__defineSetter__('set', Throw);"
   10094     "x.__defineGetter__('get', Throw);");
   10095   Local<v8::Object> x =
   10096       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
   10097   v8::TryCatch try_catch;
   10098   x->Set(v8_str("set"), v8::Integer::New(8));
   10099   x->Get(v8_str("get"));
   10100   x->Set(v8_str("set"), v8::Integer::New(8));
   10101   x->Get(v8_str("get"));
   10102   x->Set(v8_str("set"), v8::Integer::New(8));
   10103   x->Get(v8_str("get"));
   10104   x->Set(v8_str("set"), v8::Integer::New(8));
   10105   x->Get(v8_str("get"));
   10106 }
   10107 
   10108 
   10109 THREADED_TEST(Constructor) {
   10110   LocalContext context;
   10111   v8::HandleScope handle_scope(context->GetIsolate());
   10112   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   10113   templ->SetClassName(v8_str("Fun"));
   10114   Local<Function> cons = templ->GetFunction();
   10115   context->Global()->Set(v8_str("Fun"), cons);
   10116   Local<v8::Object> inst = cons->NewInstance();
   10117   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
   10118   CHECK(obj->IsJSObject());
   10119   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   10120   CHECK(value->BooleanValue());
   10121 }
   10122 
   10123 
   10124 static void ConstructorCallback(
   10125     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10126   ApiTestFuzzer::Fuzz();
   10127   Local<Object> This;
   10128 
   10129   if (args.IsConstructCall()) {
   10130     Local<Object> Holder = args.Holder();
   10131     This = Object::New();
   10132     Local<Value> proto = Holder->GetPrototype();
   10133     if (proto->IsObject()) {
   10134       This->SetPrototype(proto);
   10135     }
   10136   } else {
   10137     This = args.This();
   10138   }
   10139 
   10140   This->Set(v8_str("a"), args[0]);
   10141   args.GetReturnValue().Set(This);
   10142 }
   10143 
   10144 
   10145 static void FakeConstructorCallback(
   10146     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10147   ApiTestFuzzer::Fuzz();
   10148   args.GetReturnValue().Set(args[0]);
   10149 }
   10150 
   10151 
   10152 THREADED_TEST(ConstructorForObject) {
   10153   LocalContext context;
   10154   v8::Isolate* isolate = context->GetIsolate();
   10155   v8::HandleScope handle_scope(isolate);
   10156 
   10157   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   10158     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
   10159     Local<Object> instance = instance_template->NewInstance();
   10160     context->Global()->Set(v8_str("obj"), instance);
   10161     v8::TryCatch try_catch;
   10162     Local<Value> value;
   10163     CHECK(!try_catch.HasCaught());
   10164 
   10165     // Call the Object's constructor with a 32-bit signed integer.
   10166     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
   10167     CHECK(!try_catch.HasCaught());
   10168     CHECK(value->IsInt32());
   10169     CHECK_EQ(28, value->Int32Value());
   10170 
   10171     Local<Value> args1[] = { v8_num(28) };
   10172     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
   10173     CHECK(value_obj1->IsObject());
   10174     Local<Object> object1 = Local<Object>::Cast(value_obj1);
   10175     value = object1->Get(v8_str("a"));
   10176     CHECK(value->IsInt32());
   10177     CHECK(!try_catch.HasCaught());
   10178     CHECK_EQ(28, value->Int32Value());
   10179 
   10180     // Call the Object's constructor with a String.
   10181     value = CompileRun(
   10182         "(function() { var o = new obj('tipli'); return o.a; })()");
   10183     CHECK(!try_catch.HasCaught());
   10184     CHECK(value->IsString());
   10185     String::Utf8Value string_value1(value->ToString());
   10186     CHECK_EQ("tipli", *string_value1);
   10187 
   10188     Local<Value> args2[] = { v8_str("tipli") };
   10189     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
   10190     CHECK(value_obj2->IsObject());
   10191     Local<Object> object2 = Local<Object>::Cast(value_obj2);
   10192     value = object2->Get(v8_str("a"));
   10193     CHECK(!try_catch.HasCaught());
   10194     CHECK(value->IsString());
   10195     String::Utf8Value string_value2(value->ToString());
   10196     CHECK_EQ("tipli", *string_value2);
   10197 
   10198     // Call the Object's constructor with a Boolean.
   10199     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
   10200     CHECK(!try_catch.HasCaught());
   10201     CHECK(value->IsBoolean());
   10202     CHECK_EQ(true, value->BooleanValue());
   10203 
   10204     Handle<Value> args3[] = { v8::True(isolate) };
   10205     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
   10206     CHECK(value_obj3->IsObject());
   10207     Local<Object> object3 = Local<Object>::Cast(value_obj3);
   10208     value = object3->Get(v8_str("a"));
   10209     CHECK(!try_catch.HasCaught());
   10210     CHECK(value->IsBoolean());
   10211     CHECK_EQ(true, value->BooleanValue());
   10212 
   10213     // Call the Object's constructor with undefined.
   10214     Handle<Value> args4[] = { v8::Undefined(isolate) };
   10215     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
   10216     CHECK(value_obj4->IsObject());
   10217     Local<Object> object4 = Local<Object>::Cast(value_obj4);
   10218     value = object4->Get(v8_str("a"));
   10219     CHECK(!try_catch.HasCaught());
   10220     CHECK(value->IsUndefined());
   10221 
   10222     // Call the Object's constructor with null.
   10223     Handle<Value> args5[] = { v8::Null(isolate) };
   10224     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
   10225     CHECK(value_obj5->IsObject());
   10226     Local<Object> object5 = Local<Object>::Cast(value_obj5);
   10227     value = object5->Get(v8_str("a"));
   10228     CHECK(!try_catch.HasCaught());
   10229     CHECK(value->IsNull());
   10230   }
   10231 
   10232   // Check exception handling when there is no constructor set for the Object.
   10233   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   10234     Local<Object> instance = instance_template->NewInstance();
   10235     context->Global()->Set(v8_str("obj2"), instance);
   10236     v8::TryCatch try_catch;
   10237     Local<Value> value;
   10238     CHECK(!try_catch.HasCaught());
   10239 
   10240     value = CompileRun("new obj2(28)");
   10241     CHECK(try_catch.HasCaught());
   10242     String::Utf8Value exception_value1(try_catch.Exception());
   10243     CHECK_EQ("TypeError: object is not a function", *exception_value1);
   10244     try_catch.Reset();
   10245 
   10246     Local<Value> args[] = { v8_num(29) };
   10247     value = instance->CallAsConstructor(1, args);
   10248     CHECK(try_catch.HasCaught());
   10249     String::Utf8Value exception_value2(try_catch.Exception());
   10250     CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
   10251     try_catch.Reset();
   10252   }
   10253 
   10254   // Check the case when constructor throws exception.
   10255   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   10256     instance_template->SetCallAsFunctionHandler(ThrowValue);
   10257     Local<Object> instance = instance_template->NewInstance();
   10258     context->Global()->Set(v8_str("obj3"), instance);
   10259     v8::TryCatch try_catch;
   10260     Local<Value> value;
   10261     CHECK(!try_catch.HasCaught());
   10262 
   10263     value = CompileRun("new obj3(22)");
   10264     CHECK(try_catch.HasCaught());
   10265     String::Utf8Value exception_value1(try_catch.Exception());
   10266     CHECK_EQ("22", *exception_value1);
   10267     try_catch.Reset();
   10268 
   10269     Local<Value> args[] = { v8_num(23) };
   10270     value = instance->CallAsConstructor(1, args);
   10271     CHECK(try_catch.HasCaught());
   10272     String::Utf8Value exception_value2(try_catch.Exception());
   10273     CHECK_EQ("23", *exception_value2);
   10274     try_catch.Reset();
   10275   }
   10276 
   10277   // Check whether constructor returns with an object or non-object.
   10278   { Local<FunctionTemplate> function_template =
   10279         FunctionTemplate::New(FakeConstructorCallback);
   10280     Local<Function> function = function_template->GetFunction();
   10281     Local<Object> instance1 = function;
   10282     context->Global()->Set(v8_str("obj4"), instance1);
   10283     v8::TryCatch try_catch;
   10284     Local<Value> value;
   10285     CHECK(!try_catch.HasCaught());
   10286 
   10287     CHECK(instance1->IsObject());
   10288     CHECK(instance1->IsFunction());
   10289 
   10290     value = CompileRun("new obj4(28)");
   10291     CHECK(!try_catch.HasCaught());
   10292     CHECK(value->IsObject());
   10293 
   10294     Local<Value> args1[] = { v8_num(28) };
   10295     value = instance1->CallAsConstructor(1, args1);
   10296     CHECK(!try_catch.HasCaught());
   10297     CHECK(value->IsObject());
   10298 
   10299     Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   10300     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
   10301     Local<Object> instance2 = instance_template->NewInstance();
   10302     context->Global()->Set(v8_str("obj5"), instance2);
   10303     CHECK(!try_catch.HasCaught());
   10304 
   10305     CHECK(instance2->IsObject());
   10306     CHECK(!instance2->IsFunction());
   10307 
   10308     value = CompileRun("new obj5(28)");
   10309     CHECK(!try_catch.HasCaught());
   10310     CHECK(!value->IsObject());
   10311 
   10312     Local<Value> args2[] = { v8_num(28) };
   10313     value = instance2->CallAsConstructor(1, args2);
   10314     CHECK(!try_catch.HasCaught());
   10315     CHECK(!value->IsObject());
   10316   }
   10317 }
   10318 
   10319 
   10320 THREADED_TEST(FunctionDescriptorException) {
   10321   LocalContext context;
   10322   v8::HandleScope handle_scope(context->GetIsolate());
   10323   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   10324   templ->SetClassName(v8_str("Fun"));
   10325   Local<Function> cons = templ->GetFunction();
   10326   context->Global()->Set(v8_str("Fun"), cons);
   10327   Local<Value> value = CompileRun(
   10328     "function test() {"
   10329     "  try {"
   10330     "    (new Fun()).blah()"
   10331     "  } catch (e) {"
   10332     "    var str = String(e);"
   10333     "    if (str.indexOf('TypeError') == -1) return 1;"
   10334     "    if (str.indexOf('[object Fun]') != -1) return 2;"
   10335     "    if (str.indexOf('#<Fun>') == -1) return 3;"
   10336     "    return 0;"
   10337     "  }"
   10338     "  return 4;"
   10339     "}"
   10340     "test();");
   10341   CHECK_EQ(0, value->Int32Value());
   10342 }
   10343 
   10344 
   10345 THREADED_TEST(EvalAliasedDynamic) {
   10346   LocalContext current;
   10347   v8::HandleScope scope(current->GetIsolate());
   10348 
   10349   // Tests where aliased eval can only be resolved dynamically.
   10350   Local<Script> script =
   10351       Script::Compile(v8_str("function f(x) { "
   10352                              "  var foo = 2;"
   10353                              "  with (x) { return eval('foo'); }"
   10354                              "}"
   10355                              "foo = 0;"
   10356                              "result1 = f(new Object());"
   10357                              "result2 = f(this);"
   10358                              "var x = new Object();"
   10359                              "x.eval = function(x) { return 1; };"
   10360                              "result3 = f(x);"));
   10361   script->Run();
   10362   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
   10363   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
   10364   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
   10365 
   10366   v8::TryCatch try_catch;
   10367   script =
   10368     Script::Compile(v8_str("function f(x) { "
   10369                            "  var bar = 2;"
   10370                            "  with (x) { return eval('bar'); }"
   10371                            "}"
   10372                            "result4 = f(this)"));
   10373   script->Run();
   10374   CHECK(!try_catch.HasCaught());
   10375   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
   10376 
   10377   try_catch.Reset();
   10378 }
   10379 
   10380 
   10381 THREADED_TEST(CrossEval) {
   10382   v8::HandleScope scope(CcTest::isolate());
   10383   LocalContext other;
   10384   LocalContext current;
   10385 
   10386   Local<String> token = v8_str("<security token>");
   10387   other->SetSecurityToken(token);
   10388   current->SetSecurityToken(token);
   10389 
   10390   // Set up reference from current to other.
   10391   current->Global()->Set(v8_str("other"), other->Global());
   10392 
   10393   // Check that new variables are introduced in other context.
   10394   Local<Script> script =
   10395       Script::Compile(v8_str("other.eval('var foo = 1234')"));
   10396   script->Run();
   10397   Local<Value> foo = other->Global()->Get(v8_str("foo"));
   10398   CHECK_EQ(1234, foo->Int32Value());
   10399   CHECK(!current->Global()->Has(v8_str("foo")));
   10400 
   10401   // Check that writing to non-existing properties introduces them in
   10402   // the other context.
   10403   script =
   10404       Script::Compile(v8_str("other.eval('na = 1234')"));
   10405   script->Run();
   10406   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
   10407   CHECK(!current->Global()->Has(v8_str("na")));
   10408 
   10409   // Check that global variables in current context are not visible in other
   10410   // context.
   10411   v8::TryCatch try_catch;
   10412   script =
   10413       Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
   10414   Local<Value> result = script->Run();
   10415   CHECK(try_catch.HasCaught());
   10416   try_catch.Reset();
   10417 
   10418   // Check that local variables in current context are not visible in other
   10419   // context.
   10420   script =
   10421       Script::Compile(v8_str("(function() { "
   10422                              "  var baz = 87;"
   10423                              "  return other.eval('baz');"
   10424                              "})();"));
   10425   result = script->Run();
   10426   CHECK(try_catch.HasCaught());
   10427   try_catch.Reset();
   10428 
   10429   // Check that global variables in the other environment are visible
   10430   // when evaluting code.
   10431   other->Global()->Set(v8_str("bis"), v8_num(1234));
   10432   script = Script::Compile(v8_str("other.eval('bis')"));
   10433   CHECK_EQ(1234, script->Run()->Int32Value());
   10434   CHECK(!try_catch.HasCaught());
   10435 
   10436   // Check that the 'this' pointer points to the global object evaluating
   10437   // code.
   10438   other->Global()->Set(v8_str("t"), other->Global());
   10439   script = Script::Compile(v8_str("other.eval('this == t')"));
   10440   result = script->Run();
   10441   CHECK(result->IsTrue());
   10442   CHECK(!try_catch.HasCaught());
   10443 
   10444   // Check that variables introduced in with-statement are not visible in
   10445   // other context.
   10446   script =
   10447       Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
   10448   result = script->Run();
   10449   CHECK(try_catch.HasCaught());
   10450   try_catch.Reset();
   10451 
   10452   // Check that you cannot use 'eval.call' with another object than the
   10453   // current global object.
   10454   script =
   10455       Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
   10456   result = script->Run();
   10457   CHECK(try_catch.HasCaught());
   10458 }
   10459 
   10460 
   10461 // Test that calling eval in a context which has been detached from
   10462 // its global throws an exception.  This behavior is consistent with
   10463 // other JavaScript implementations.
   10464 THREADED_TEST(EvalInDetachedGlobal) {
   10465   v8::Isolate* isolate = CcTest::isolate();
   10466   v8::HandleScope scope(isolate);
   10467 
   10468   v8::Local<Context> context0 = Context::New(isolate);
   10469   v8::Local<Context> context1 = Context::New(isolate);
   10470 
   10471   // Set up function in context0 that uses eval from context0.
   10472   context0->Enter();
   10473   v8::Handle<v8::Value> fun =
   10474       CompileRun("var x = 42;"
   10475                  "(function() {"
   10476                  "  var e = eval;"
   10477                  "  return function(s) { return e(s); }"
   10478                  "})()");
   10479   context0->Exit();
   10480 
   10481   // Put the function into context1 and call it before and after
   10482   // detaching the global.  Before detaching, the call succeeds and
   10483   // after detaching and exception is thrown.
   10484   context1->Enter();
   10485   context1->Global()->Set(v8_str("fun"), fun);
   10486   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
   10487   CHECK_EQ(42, x_value->Int32Value());
   10488   context0->DetachGlobal();
   10489   v8::TryCatch catcher;
   10490   x_value = CompileRun("fun('x')");
   10491   CHECK(x_value.IsEmpty());
   10492   CHECK(catcher.HasCaught());
   10493   context1->Exit();
   10494 }
   10495 
   10496 
   10497 THREADED_TEST(CrossLazyLoad) {
   10498   v8::HandleScope scope(CcTest::isolate());
   10499   LocalContext other;
   10500   LocalContext current;
   10501 
   10502   Local<String> token = v8_str("<security token>");
   10503   other->SetSecurityToken(token);
   10504   current->SetSecurityToken(token);
   10505 
   10506   // Set up reference from current to other.
   10507   current->Global()->Set(v8_str("other"), other->Global());
   10508 
   10509   // Trigger lazy loading in other context.
   10510   Local<Script> script =
   10511       Script::Compile(v8_str("other.eval('new Date(42)')"));
   10512   Local<Value> value = script->Run();
   10513   CHECK_EQ(42.0, value->NumberValue());
   10514 }
   10515 
   10516 
   10517 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   10518   ApiTestFuzzer::Fuzz();
   10519   if (args.IsConstructCall()) {
   10520     if (args[0]->IsInt32()) {
   10521       args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
   10522       return;
   10523     }
   10524   }
   10525 
   10526   args.GetReturnValue().Set(args[0]);
   10527 }
   10528 
   10529 
   10530 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   10531   args.GetReturnValue().Set(args.This());
   10532 }
   10533 
   10534 
   10535 // Test that a call handler can be set for objects which will allow
   10536 // non-function objects created through the API to be called as
   10537 // functions.
   10538 THREADED_TEST(CallAsFunction) {
   10539   LocalContext context;
   10540   v8::HandleScope scope(context->GetIsolate());
   10541 
   10542   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   10543     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10544     instance_template->SetCallAsFunctionHandler(call_as_function);
   10545     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   10546     context->Global()->Set(v8_str("obj"), instance);
   10547     v8::TryCatch try_catch;
   10548     Local<Value> value;
   10549     CHECK(!try_catch.HasCaught());
   10550 
   10551     value = CompileRun("obj(42)");
   10552     CHECK(!try_catch.HasCaught());
   10553     CHECK_EQ(42, value->Int32Value());
   10554 
   10555     value = CompileRun("(function(o){return o(49)})(obj)");
   10556     CHECK(!try_catch.HasCaught());
   10557     CHECK_EQ(49, value->Int32Value());
   10558 
   10559     // test special case of call as function
   10560     value = CompileRun("[obj]['0'](45)");
   10561     CHECK(!try_catch.HasCaught());
   10562     CHECK_EQ(45, value->Int32Value());
   10563 
   10564     value = CompileRun("obj.call = Function.prototype.call;"
   10565                        "obj.call(null, 87)");
   10566     CHECK(!try_catch.HasCaught());
   10567     CHECK_EQ(87, value->Int32Value());
   10568 
   10569     // Regression tests for bug #1116356: Calling call through call/apply
   10570     // must work for non-function receivers.
   10571     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   10572     value = CompileRun(apply_99);
   10573     CHECK(!try_catch.HasCaught());
   10574     CHECK_EQ(99, value->Int32Value());
   10575 
   10576     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   10577     value = CompileRun(call_17);
   10578     CHECK(!try_catch.HasCaught());
   10579     CHECK_EQ(17, value->Int32Value());
   10580 
   10581     // Check that the call-as-function handler can be called through
   10582     // new.
   10583     value = CompileRun("new obj(43)");
   10584     CHECK(!try_catch.HasCaught());
   10585     CHECK_EQ(-43, value->Int32Value());
   10586 
   10587     // Check that the call-as-function handler can be called through
   10588     // the API.
   10589     v8::Handle<Value> args[] = { v8_num(28) };
   10590     value = instance->CallAsFunction(instance, 1, args);
   10591     CHECK(!try_catch.HasCaught());
   10592     CHECK_EQ(28, value->Int32Value());
   10593   }
   10594 
   10595   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   10596     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   10597     USE(instance_template);
   10598     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   10599     context->Global()->Set(v8_str("obj2"), instance);
   10600     v8::TryCatch try_catch;
   10601     Local<Value> value;
   10602     CHECK(!try_catch.HasCaught());
   10603 
   10604     // Call an object without call-as-function handler through the JS
   10605     value = CompileRun("obj2(28)");
   10606     CHECK(value.IsEmpty());
   10607     CHECK(try_catch.HasCaught());
   10608     String::Utf8Value exception_value1(try_catch.Exception());
   10609     CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
   10610              *exception_value1);
   10611     try_catch.Reset();
   10612 
   10613     // Call an object without call-as-function handler through the API
   10614     value = CompileRun("obj2(28)");
   10615     v8::Handle<Value> args[] = { v8_num(28) };
   10616     value = instance->CallAsFunction(instance, 1, args);
   10617     CHECK(value.IsEmpty());
   10618     CHECK(try_catch.HasCaught());
   10619     String::Utf8Value exception_value2(try_catch.Exception());
   10620     CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
   10621     try_catch.Reset();
   10622   }
   10623 
   10624   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   10625     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10626     instance_template->SetCallAsFunctionHandler(ThrowValue);
   10627     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   10628     context->Global()->Set(v8_str("obj3"), instance);
   10629     v8::TryCatch try_catch;
   10630     Local<Value> value;
   10631     CHECK(!try_catch.HasCaught());
   10632 
   10633     // Catch the exception which is thrown by call-as-function handler
   10634     value = CompileRun("obj3(22)");
   10635     CHECK(try_catch.HasCaught());
   10636     String::Utf8Value exception_value1(try_catch.Exception());
   10637     CHECK_EQ("22", *exception_value1);
   10638     try_catch.Reset();
   10639 
   10640     v8::Handle<Value> args[] = { v8_num(23) };
   10641     value = instance->CallAsFunction(instance, 1, args);
   10642     CHECK(try_catch.HasCaught());
   10643     String::Utf8Value exception_value2(try_catch.Exception());
   10644     CHECK_EQ("23", *exception_value2);
   10645     try_catch.Reset();
   10646   }
   10647 
   10648   { v8::Isolate* isolate = context->GetIsolate();
   10649     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   10650     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10651     instance_template->SetCallAsFunctionHandler(ReturnThis);
   10652     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   10653 
   10654     Local<v8::Value> a1 =
   10655         instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
   10656     CHECK(a1->StrictEquals(instance));
   10657     Local<v8::Value> a2 =
   10658         instance->CallAsFunction(v8::Null(isolate), 0, NULL);
   10659     CHECK(a2->StrictEquals(instance));
   10660     Local<v8::Value> a3 =
   10661         instance->CallAsFunction(v8_num(42), 0, NULL);
   10662     CHECK(a3->StrictEquals(instance));
   10663     Local<v8::Value> a4 =
   10664         instance->CallAsFunction(v8_str("hello"), 0, NULL);
   10665     CHECK(a4->StrictEquals(instance));
   10666     Local<v8::Value> a5 =
   10667         instance->CallAsFunction(v8::True(isolate), 0, NULL);
   10668     CHECK(a5->StrictEquals(instance));
   10669   }
   10670 
   10671   { v8::Isolate* isolate = context->GetIsolate();
   10672     CompileRun(
   10673       "function ReturnThisSloppy() {"
   10674       "  return this;"
   10675       "}"
   10676       "function ReturnThisStrict() {"
   10677       "  'use strict';"
   10678       "  return this;"
   10679       "}");
   10680     Local<Function> ReturnThisSloppy =
   10681         Local<Function>::Cast(
   10682             context->Global()->Get(v8_str("ReturnThisSloppy")));
   10683     Local<Function> ReturnThisStrict =
   10684         Local<Function>::Cast(
   10685             context->Global()->Get(v8_str("ReturnThisStrict")));
   10686 
   10687     Local<v8::Value> a1 =
   10688         ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
   10689     CHECK(a1->StrictEquals(context->Global()));
   10690     Local<v8::Value> a2 =
   10691         ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
   10692     CHECK(a2->StrictEquals(context->Global()));
   10693     Local<v8::Value> a3 =
   10694         ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
   10695     CHECK(a3->IsNumberObject());
   10696     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
   10697     Local<v8::Value> a4 =
   10698         ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
   10699     CHECK(a4->IsStringObject());
   10700     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   10701     Local<v8::Value> a5 =
   10702         ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
   10703     CHECK(a5->IsBooleanObject());
   10704     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
   10705 
   10706     Local<v8::Value> a6 =
   10707         ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
   10708     CHECK(a6->IsUndefined());
   10709     Local<v8::Value> a7 =
   10710         ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
   10711     CHECK(a7->IsNull());
   10712     Local<v8::Value> a8 =
   10713         ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
   10714     CHECK(a8->StrictEquals(v8_num(42)));
   10715     Local<v8::Value> a9 =
   10716         ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
   10717     CHECK(a9->StrictEquals(v8_str("hello")));
   10718     Local<v8::Value> a10 =
   10719         ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
   10720     CHECK(a10->StrictEquals(v8::True(isolate)));
   10721   }
   10722 }
   10723 
   10724 
   10725 // Check whether a non-function object is callable.
   10726 THREADED_TEST(CallableObject) {
   10727   LocalContext context;
   10728   v8::HandleScope scope(context->GetIsolate());
   10729 
   10730   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   10731     instance_template->SetCallAsFunctionHandler(call_as_function);
   10732     Local<Object> instance = instance_template->NewInstance();
   10733     v8::TryCatch try_catch;
   10734 
   10735     CHECK(instance->IsCallable());
   10736     CHECK(!try_catch.HasCaught());
   10737   }
   10738 
   10739   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   10740     Local<Object> instance = instance_template->NewInstance();
   10741     v8::TryCatch try_catch;
   10742 
   10743     CHECK(!instance->IsCallable());
   10744     CHECK(!try_catch.HasCaught());
   10745   }
   10746 
   10747   { Local<FunctionTemplate> function_template =
   10748         FunctionTemplate::New(call_as_function);
   10749     Local<Function> function = function_template->GetFunction();
   10750     Local<Object> instance = function;
   10751     v8::TryCatch try_catch;
   10752 
   10753     CHECK(instance->IsCallable());
   10754     CHECK(!try_catch.HasCaught());
   10755   }
   10756 
   10757   { Local<FunctionTemplate> function_template = FunctionTemplate::New();
   10758     Local<Function> function = function_template->GetFunction();
   10759     Local<Object> instance = function;
   10760     v8::TryCatch try_catch;
   10761 
   10762     CHECK(instance->IsCallable());
   10763     CHECK(!try_catch.HasCaught());
   10764   }
   10765 }
   10766 
   10767 
   10768 static int CountHandles() {
   10769   return v8::HandleScope::NumberOfHandles();
   10770 }
   10771 
   10772 
   10773 static int Recurse(int depth, int iterations) {
   10774   v8::HandleScope scope(CcTest::isolate());
   10775   if (depth == 0) return CountHandles();
   10776   for (int i = 0; i < iterations; i++) {
   10777     Local<v8::Number> n(v8::Integer::New(42));
   10778   }
   10779   return Recurse(depth - 1, iterations);
   10780 }
   10781 
   10782 
   10783 THREADED_TEST(HandleIteration) {
   10784   static const int kIterations = 500;
   10785   static const int kNesting = 200;
   10786   CHECK_EQ(0, CountHandles());
   10787   {
   10788     v8::HandleScope scope1(CcTest::isolate());
   10789     CHECK_EQ(0, CountHandles());
   10790     for (int i = 0; i < kIterations; i++) {
   10791       Local<v8::Number> n(v8::Integer::New(42));
   10792       CHECK_EQ(i + 1, CountHandles());
   10793     }
   10794 
   10795     CHECK_EQ(kIterations, CountHandles());
   10796     {
   10797       v8::HandleScope scope2(CcTest::isolate());
   10798       for (int j = 0; j < kIterations; j++) {
   10799         Local<v8::Number> n(v8::Integer::New(42));
   10800         CHECK_EQ(j + 1 + kIterations, CountHandles());
   10801       }
   10802     }
   10803     CHECK_EQ(kIterations, CountHandles());
   10804   }
   10805   CHECK_EQ(0, CountHandles());
   10806   CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
   10807 }
   10808 
   10809 
   10810 static void InterceptorHasOwnPropertyGetter(
   10811     Local<String> name,
   10812     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10813   ApiTestFuzzer::Fuzz();
   10814 }
   10815 
   10816 
   10817 THREADED_TEST(InterceptorHasOwnProperty) {
   10818   LocalContext context;
   10819   v8::HandleScope scope(context->GetIsolate());
   10820   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   10821   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   10822   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
   10823   Local<Function> function = fun_templ->GetFunction();
   10824   context->Global()->Set(v8_str("constructor"), function);
   10825   v8::Handle<Value> value = CompileRun(
   10826       "var o = new constructor();"
   10827       "o.hasOwnProperty('ostehaps');");
   10828   CHECK_EQ(false, value->BooleanValue());
   10829   value = CompileRun(
   10830       "o.ostehaps = 42;"
   10831       "o.hasOwnProperty('ostehaps');");
   10832   CHECK_EQ(true, value->BooleanValue());
   10833   value = CompileRun(
   10834       "var p = new constructor();"
   10835       "p.hasOwnProperty('ostehaps');");
   10836   CHECK_EQ(false, value->BooleanValue());
   10837 }
   10838 
   10839 
   10840 static void InterceptorHasOwnPropertyGetterGC(
   10841     Local<String> name,
   10842     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10843   ApiTestFuzzer::Fuzz();
   10844   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   10845 }
   10846 
   10847 
   10848 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
   10849   LocalContext context;
   10850   v8::HandleScope scope(context->GetIsolate());
   10851   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   10852   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   10853   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
   10854   Local<Function> function = fun_templ->GetFunction();
   10855   context->Global()->Set(v8_str("constructor"), function);
   10856   // Let's first make some stuff so we can be sure to get a good GC.
   10857   CompileRun(
   10858       "function makestr(size) {"
   10859       "  switch (size) {"
   10860       "    case 1: return 'f';"
   10861       "    case 2: return 'fo';"
   10862       "    case 3: return 'foo';"
   10863       "  }"
   10864       "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
   10865       "}"
   10866       "var x = makestr(12345);"
   10867       "x = makestr(31415);"
   10868       "x = makestr(23456);");
   10869   v8::Handle<Value> value = CompileRun(
   10870       "var o = new constructor();"
   10871       "o.__proto__ = new String(x);"
   10872       "o.hasOwnProperty('ostehaps');");
   10873   CHECK_EQ(false, value->BooleanValue());
   10874 }
   10875 
   10876 
   10877 typedef void (*NamedPropertyGetter)(
   10878     Local<String> property,
   10879     const v8::PropertyCallbackInfo<v8::Value>& info);
   10880 
   10881 
   10882 static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
   10883                                    const char* source,
   10884                                    int expected) {
   10885   v8::HandleScope scope(CcTest::isolate());
   10886   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10887   templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
   10888   LocalContext context;
   10889   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10890   v8::Handle<Value> value = CompileRun(source);
   10891   CHECK_EQ(expected, value->Int32Value());
   10892 }
   10893 
   10894 
   10895 static void InterceptorLoadICGetter(
   10896     Local<String> name,
   10897     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10898   ApiTestFuzzer::Fuzz();
   10899   v8::Isolate* isolate = CcTest::isolate();
   10900   CHECK_EQ(isolate, info.GetIsolate());
   10901   CHECK_EQ(v8_str("data"), info.Data());
   10902   CHECK_EQ(v8_str("x"), name);
   10903   info.GetReturnValue().Set(v8::Integer::New(42));
   10904 }
   10905 
   10906 
   10907 // This test should hit the load IC for the interceptor case.
   10908 THREADED_TEST(InterceptorLoadIC) {
   10909   CheckInterceptorLoadIC(InterceptorLoadICGetter,
   10910     "var result = 0;"
   10911     "for (var i = 0; i < 1000; i++) {"
   10912     "  result = o.x;"
   10913     "}",
   10914     42);
   10915 }
   10916 
   10917 
   10918 // Below go several tests which verify that JITing for various
   10919 // configurations of interceptor and explicit fields works fine
   10920 // (those cases are special cased to get better performance).
   10921 
   10922 static void InterceptorLoadXICGetter(
   10923     Local<String> name,
   10924     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10925   ApiTestFuzzer::Fuzz();
   10926   info.GetReturnValue().Set(
   10927       v8_str("x")->Equals(name) ?
   10928           v8::Handle<v8::Value>(v8::Integer::New(42)) :
   10929           v8::Handle<v8::Value>());
   10930 }
   10931 
   10932 
   10933 THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
   10934   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10935     "var result = 0;"
   10936     "o.y = 239;"
   10937     "for (var i = 0; i < 1000; i++) {"
   10938     "  result = o.y;"
   10939     "}",
   10940     239);
   10941 }
   10942 
   10943 
   10944 THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
   10945   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10946     "var result = 0;"
   10947     "o.__proto__ = { 'y': 239 };"
   10948     "for (var i = 0; i < 1000; i++) {"
   10949     "  result = o.y + o.x;"
   10950     "}",
   10951     239 + 42);
   10952 }
   10953 
   10954 
   10955 THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
   10956   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10957     "var result = 0;"
   10958     "o.__proto__.y = 239;"
   10959     "for (var i = 0; i < 1000; i++) {"
   10960     "  result = o.y + o.x;"
   10961     "}",
   10962     239 + 42);
   10963 }
   10964 
   10965 
   10966 THREADED_TEST(InterceptorLoadICUndefined) {
   10967   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10968     "var result = 0;"
   10969     "for (var i = 0; i < 1000; i++) {"
   10970     "  result = (o.y == undefined) ? 239 : 42;"
   10971     "}",
   10972     239);
   10973 }
   10974 
   10975 
   10976 THREADED_TEST(InterceptorLoadICWithOverride) {
   10977   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10978     "fst = new Object();  fst.__proto__ = o;"
   10979     "snd = new Object();  snd.__proto__ = fst;"
   10980     "var result1 = 0;"
   10981     "for (var i = 0; i < 1000;  i++) {"
   10982     "  result1 = snd.x;"
   10983     "}"
   10984     "fst.x = 239;"
   10985     "var result = 0;"
   10986     "for (var i = 0; i < 1000; i++) {"
   10987     "  result = snd.x;"
   10988     "}"
   10989     "result + result1",
   10990     239 + 42);
   10991 }
   10992 
   10993 
   10994 // Test the case when we stored field into
   10995 // a stub, but interceptor produced value on its own.
   10996 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
   10997   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10998     "proto = new Object();"
   10999     "o.__proto__ = proto;"
   11000     "proto.x = 239;"
   11001     "for (var i = 0; i < 1000; i++) {"
   11002     "  o.x;"
   11003     // Now it should be ICed and keep a reference to x defined on proto
   11004     "}"
   11005     "var result = 0;"
   11006     "for (var i = 0; i < 1000; i++) {"
   11007     "  result += o.x;"
   11008     "}"
   11009     "result;",
   11010     42 * 1000);
   11011 }
   11012 
   11013 
   11014 // Test the case when we stored field into
   11015 // a stub, but it got invalidated later on.
   11016 THREADED_TEST(InterceptorLoadICInvalidatedField) {
   11017   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11018     "proto1 = new Object();"
   11019     "proto2 = new Object();"
   11020     "o.__proto__ = proto1;"
   11021     "proto1.__proto__ = proto2;"
   11022     "proto2.y = 239;"
   11023     "for (var i = 0; i < 1000; i++) {"
   11024     "  o.y;"
   11025     // Now it should be ICed and keep a reference to y defined on proto2
   11026     "}"
   11027     "proto1.y = 42;"
   11028     "var result = 0;"
   11029     "for (var i = 0; i < 1000; i++) {"
   11030     "  result += o.y;"
   11031     "}"
   11032     "result;",
   11033     42 * 1000);
   11034 }
   11035 
   11036 
   11037 static int interceptor_load_not_handled_calls = 0;
   11038 static void InterceptorLoadNotHandled(
   11039     Local<String> name,
   11040     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11041   ++interceptor_load_not_handled_calls;
   11042 }
   11043 
   11044 
   11045 // Test how post-interceptor lookups are done in the non-cacheable
   11046 // case: the interceptor should not be invoked during this lookup.
   11047 THREADED_TEST(InterceptorLoadICPostInterceptor) {
   11048   interceptor_load_not_handled_calls = 0;
   11049   CheckInterceptorLoadIC(InterceptorLoadNotHandled,
   11050     "receiver = new Object();"
   11051     "receiver.__proto__ = o;"
   11052     "proto = new Object();"
   11053     "/* Make proto a slow-case object. */"
   11054     "for (var i = 0; i < 1000; i++) {"
   11055     "  proto[\"xxxxxxxx\" + i] = [];"
   11056     "}"
   11057     "proto.x = 17;"
   11058     "o.__proto__ = proto;"
   11059     "var result = 0;"
   11060     "for (var i = 0; i < 1000; i++) {"
   11061     "  result += receiver.x;"
   11062     "}"
   11063     "result;",
   11064     17 * 1000);
   11065   CHECK_EQ(1000, interceptor_load_not_handled_calls);
   11066 }
   11067 
   11068 
   11069 // Test the case when we stored field into
   11070 // a stub, but it got invalidated later on due to override on
   11071 // global object which is between interceptor and fields' holders.
   11072 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
   11073   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11074     "o.__proto__ = this;"  // set a global to be a proto of o.
   11075     "this.__proto__.y = 239;"
   11076     "for (var i = 0; i < 10; i++) {"
   11077     "  if (o.y != 239) throw 'oops: ' + o.y;"
   11078     // Now it should be ICed and keep a reference to y defined on field_holder.
   11079     "}"
   11080     "this.y = 42;"  // Assign on a global.
   11081     "var result = 0;"
   11082     "for (var i = 0; i < 10; i++) {"
   11083     "  result += o.y;"
   11084     "}"
   11085     "result;",
   11086     42 * 10);
   11087 }
   11088 
   11089 
   11090 static void SetOnThis(Local<String> name,
   11091                       Local<Value> value,
   11092                       const v8::PropertyCallbackInfo<void>& info) {
   11093   info.This()->ForceSet(name, value);
   11094 }
   11095 
   11096 
   11097 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
   11098   v8::HandleScope scope(CcTest::isolate());
   11099   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11100   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11101   templ->SetAccessor(v8_str("y"), Return239Callback);
   11102   LocalContext context;
   11103   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11104 
   11105   // Check the case when receiver and interceptor's holder
   11106   // are the same objects.
   11107   v8::Handle<Value> value = CompileRun(
   11108       "var result = 0;"
   11109       "for (var i = 0; i < 7; i++) {"
   11110       "  result = o.y;"
   11111       "}");
   11112   CHECK_EQ(239, value->Int32Value());
   11113 
   11114   // Check the case when interceptor's holder is in proto chain
   11115   // of receiver.
   11116   value = CompileRun(
   11117       "r = { __proto__: o };"
   11118       "var result = 0;"
   11119       "for (var i = 0; i < 7; i++) {"
   11120       "  result = r.y;"
   11121       "}");
   11122   CHECK_EQ(239, value->Int32Value());
   11123 }
   11124 
   11125 
   11126 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
   11127   v8::HandleScope scope(CcTest::isolate());
   11128   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   11129   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11130   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   11131   templ_p->SetAccessor(v8_str("y"), Return239Callback);
   11132 
   11133   LocalContext context;
   11134   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11135   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   11136 
   11137   // Check the case when receiver and interceptor's holder
   11138   // are the same objects.
   11139   v8::Handle<Value> value = CompileRun(
   11140       "o.__proto__ = p;"
   11141       "var result = 0;"
   11142       "for (var i = 0; i < 7; i++) {"
   11143       "  result = o.x + o.y;"
   11144       "}");
   11145   CHECK_EQ(239 + 42, value->Int32Value());
   11146 
   11147   // Check the case when interceptor's holder is in proto chain
   11148   // of receiver.
   11149   value = CompileRun(
   11150       "r = { __proto__: o };"
   11151       "var result = 0;"
   11152       "for (var i = 0; i < 7; i++) {"
   11153       "  result = r.x + r.y;"
   11154       "}");
   11155   CHECK_EQ(239 + 42, value->Int32Value());
   11156 }
   11157 
   11158 
   11159 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
   11160   v8::HandleScope scope(CcTest::isolate());
   11161   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11162   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11163   templ->SetAccessor(v8_str("y"), Return239Callback);
   11164 
   11165   LocalContext context;
   11166   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11167 
   11168   v8::Handle<Value> value = CompileRun(
   11169     "fst = new Object();  fst.__proto__ = o;"
   11170     "snd = new Object();  snd.__proto__ = fst;"
   11171     "var result1 = 0;"
   11172     "for (var i = 0; i < 7;  i++) {"
   11173     "  result1 = snd.x;"
   11174     "}"
   11175     "fst.x = 239;"
   11176     "var result = 0;"
   11177     "for (var i = 0; i < 7; i++) {"
   11178     "  result = snd.x;"
   11179     "}"
   11180     "result + result1");
   11181   CHECK_EQ(239 + 42, value->Int32Value());
   11182 }
   11183 
   11184 
   11185 // Test the case when we stored callback into
   11186 // a stub, but interceptor produced value on its own.
   11187 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
   11188   v8::HandleScope scope(CcTest::isolate());
   11189   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   11190   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11191   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   11192   templ_p->SetAccessor(v8_str("y"), Return239Callback);
   11193 
   11194   LocalContext context;
   11195   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11196   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   11197 
   11198   v8::Handle<Value> value = CompileRun(
   11199     "o.__proto__ = p;"
   11200     "for (var i = 0; i < 7; i++) {"
   11201     "  o.x;"
   11202     // Now it should be ICed and keep a reference to x defined on p
   11203     "}"
   11204     "var result = 0;"
   11205     "for (var i = 0; i < 7; i++) {"
   11206     "  result += o.x;"
   11207     "}"
   11208     "result");
   11209   CHECK_EQ(42 * 7, value->Int32Value());
   11210 }
   11211 
   11212 
   11213 // Test the case when we stored callback into
   11214 // a stub, but it got invalidated later on.
   11215 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
   11216   v8::HandleScope scope(CcTest::isolate());
   11217   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   11218   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11219   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   11220   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
   11221 
   11222   LocalContext context;
   11223   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11224   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   11225 
   11226   v8::Handle<Value> value = CompileRun(
   11227     "inbetween = new Object();"
   11228     "o.__proto__ = inbetween;"
   11229     "inbetween.__proto__ = p;"
   11230     "for (var i = 0; i < 10; i++) {"
   11231     "  o.y;"
   11232     // Now it should be ICed and keep a reference to y defined on p
   11233     "}"
   11234     "inbetween.y = 42;"
   11235     "var result = 0;"
   11236     "for (var i = 0; i < 10; i++) {"
   11237     "  result += o.y;"
   11238     "}"
   11239     "result");
   11240   CHECK_EQ(42 * 10, value->Int32Value());
   11241 }
   11242 
   11243 
   11244 // Test the case when we stored callback into
   11245 // a stub, but it got invalidated later on due to override on
   11246 // global object which is between interceptor and callbacks' holders.
   11247 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
   11248   v8::HandleScope scope(CcTest::isolate());
   11249   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   11250   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11251   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   11252   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
   11253 
   11254   LocalContext context;
   11255   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11256   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   11257 
   11258   v8::Handle<Value> value = CompileRun(
   11259     "o.__proto__ = this;"
   11260     "this.__proto__ = p;"
   11261     "for (var i = 0; i < 10; i++) {"
   11262     "  if (o.y != 239) throw 'oops: ' + o.y;"
   11263     // Now it should be ICed and keep a reference to y defined on p
   11264     "}"
   11265     "this.y = 42;"
   11266     "var result = 0;"
   11267     "for (var i = 0; i < 10; i++) {"
   11268     "  result += o.y;"
   11269     "}"
   11270     "result");
   11271   CHECK_EQ(42 * 10, value->Int32Value());
   11272 }
   11273 
   11274 
   11275 static void InterceptorLoadICGetter0(
   11276     Local<String> name,
   11277     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11278   ApiTestFuzzer::Fuzz();
   11279   CHECK(v8_str("x")->Equals(name));
   11280   info.GetReturnValue().Set(v8::Integer::New(0));
   11281 }
   11282 
   11283 
   11284 THREADED_TEST(InterceptorReturningZero) {
   11285   CheckInterceptorLoadIC(InterceptorLoadICGetter0,
   11286      "o.x == undefined ? 1 : 0",
   11287      0);
   11288 }
   11289 
   11290 
   11291 static void InterceptorStoreICSetter(
   11292     Local<String> key,
   11293     Local<Value> value,
   11294     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11295   CHECK(v8_str("x")->Equals(key));
   11296   CHECK_EQ(42, value->Int32Value());
   11297   info.GetReturnValue().Set(value);
   11298 }
   11299 
   11300 
   11301 // This test should hit the store IC for the interceptor case.
   11302 THREADED_TEST(InterceptorStoreIC) {
   11303   v8::HandleScope scope(CcTest::isolate());
   11304   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11305   templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
   11306                                  InterceptorStoreICSetter,
   11307                                  0, 0, 0, v8_str("data"));
   11308   LocalContext context;
   11309   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11310   CompileRun(
   11311       "for (var i = 0; i < 1000; i++) {"
   11312       "  o.x = 42;"
   11313       "}");
   11314 }
   11315 
   11316 
   11317 THREADED_TEST(InterceptorStoreICWithNoSetter) {
   11318   v8::HandleScope scope(CcTest::isolate());
   11319   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11320   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11321   LocalContext context;
   11322   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11323   v8::Handle<Value> value = CompileRun(
   11324     "for (var i = 0; i < 1000; i++) {"
   11325     "  o.y = 239;"
   11326     "}"
   11327     "42 + o.y");
   11328   CHECK_EQ(239 + 42, value->Int32Value());
   11329 }
   11330 
   11331 
   11332 
   11333 
   11334 v8::Handle<Value> call_ic_function;
   11335 v8::Handle<Value> call_ic_function2;
   11336 v8::Handle<Value> call_ic_function3;
   11337 
   11338 static void InterceptorCallICGetter(
   11339     Local<String> name,
   11340     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11341   ApiTestFuzzer::Fuzz();
   11342   CHECK(v8_str("x")->Equals(name));
   11343   info.GetReturnValue().Set(call_ic_function);
   11344 }
   11345 
   11346 
   11347 // This test should hit the call IC for the interceptor case.
   11348 THREADED_TEST(InterceptorCallIC) {
   11349   v8::HandleScope scope(CcTest::isolate());
   11350   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11351   templ->SetNamedPropertyHandler(InterceptorCallICGetter);
   11352   LocalContext context;
   11353   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11354   call_ic_function =
   11355       v8_compile("function f(x) { return x + 1; }; f")->Run();
   11356   v8::Handle<Value> value = CompileRun(
   11357     "var result = 0;"
   11358     "for (var i = 0; i < 1000; i++) {"
   11359     "  result = o.x(41);"
   11360     "}");
   11361   CHECK_EQ(42, value->Int32Value());
   11362 }
   11363 
   11364 
   11365 // This test checks that if interceptor doesn't provide
   11366 // a value, we can fetch regular value.
   11367 THREADED_TEST(InterceptorCallICSeesOthers) {
   11368   v8::HandleScope scope(CcTest::isolate());
   11369   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11370   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11371   LocalContext context;
   11372   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11373   v8::Handle<Value> value = CompileRun(
   11374     "o.x = function f(x) { return x + 1; };"
   11375     "var result = 0;"
   11376     "for (var i = 0; i < 7; i++) {"
   11377     "  result = o.x(41);"
   11378     "}");
   11379   CHECK_EQ(42, value->Int32Value());
   11380 }
   11381 
   11382 
   11383 static v8::Handle<Value> call_ic_function4;
   11384 static void InterceptorCallICGetter4(
   11385     Local<String> name,
   11386     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11387   ApiTestFuzzer::Fuzz();
   11388   CHECK(v8_str("x")->Equals(name));
   11389   info.GetReturnValue().Set(call_ic_function4);
   11390 }
   11391 
   11392 
   11393 // This test checks that if interceptor provides a function,
   11394 // even if we cached shadowed variant, interceptor's function
   11395 // is invoked
   11396 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
   11397   v8::HandleScope scope(CcTest::isolate());
   11398   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11399   templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
   11400   LocalContext context;
   11401   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11402   call_ic_function4 =
   11403       v8_compile("function f(x) { return x - 1; }; f")->Run();
   11404   v8::Handle<Value> value = CompileRun(
   11405     "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
   11406     "var result = 0;"
   11407     "for (var i = 0; i < 1000; i++) {"
   11408     "  result = o.x(42);"
   11409     "}");
   11410   CHECK_EQ(41, value->Int32Value());
   11411 }
   11412 
   11413 
   11414 // Test the case when we stored cacheable lookup into
   11415 // a stub, but it got invalidated later on
   11416 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
   11417   v8::HandleScope scope(CcTest::isolate());
   11418   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11419   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11420   LocalContext context;
   11421   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11422   v8::Handle<Value> value = CompileRun(
   11423     "proto1 = new Object();"
   11424     "proto2 = new Object();"
   11425     "o.__proto__ = proto1;"
   11426     "proto1.__proto__ = proto2;"
   11427     "proto2.y = function(x) { return x + 1; };"
   11428     // Invoke it many times to compile a stub
   11429     "for (var i = 0; i < 7; i++) {"
   11430     "  o.y(42);"
   11431     "}"
   11432     "proto1.y = function(x) { return x - 1; };"
   11433     "var result = 0;"
   11434     "for (var i = 0; i < 7; i++) {"
   11435     "  result += o.y(42);"
   11436     "}");
   11437   CHECK_EQ(41 * 7, value->Int32Value());
   11438 }
   11439 
   11440 
   11441 // This test checks that if interceptor doesn't provide a function,
   11442 // cached constant function is used
   11443 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
   11444   v8::HandleScope scope(CcTest::isolate());
   11445   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11446   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11447   LocalContext context;
   11448   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11449   v8::Handle<Value> value = CompileRun(
   11450     "function inc(x) { return x + 1; };"
   11451     "inc(1);"
   11452     "o.x = inc;"
   11453     "var result = 0;"
   11454     "for (var i = 0; i < 1000; i++) {"
   11455     "  result = o.x(42);"
   11456     "}");
   11457   CHECK_EQ(43, value->Int32Value());
   11458 }
   11459 
   11460 
   11461 static v8::Handle<Value> call_ic_function5;
   11462 static void InterceptorCallICGetter5(
   11463     Local<String> name,
   11464     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11465   ApiTestFuzzer::Fuzz();
   11466   if (v8_str("x")->Equals(name))
   11467     info.GetReturnValue().Set(call_ic_function5);
   11468 }
   11469 
   11470 
   11471 // This test checks that if interceptor provides a function,
   11472 // even if we cached constant function, interceptor's function
   11473 // is invoked
   11474 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
   11475   v8::HandleScope scope(CcTest::isolate());
   11476   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11477   templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
   11478   LocalContext context;
   11479   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11480   call_ic_function5 =
   11481       v8_compile("function f(x) { return x - 1; }; f")->Run();
   11482   v8::Handle<Value> value = CompileRun(
   11483     "function inc(x) { return x + 1; };"
   11484     "inc(1);"
   11485     "o.x = inc;"
   11486     "var result = 0;"
   11487     "for (var i = 0; i < 1000; i++) {"
   11488     "  result = o.x(42);"
   11489     "}");
   11490   CHECK_EQ(41, value->Int32Value());
   11491 }
   11492 
   11493 
   11494 static v8::Handle<Value> call_ic_function6;
   11495 static void InterceptorCallICGetter6(
   11496     Local<String> name,
   11497     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11498   ApiTestFuzzer::Fuzz();
   11499   if (v8_str("x")->Equals(name))
   11500     info.GetReturnValue().Set(call_ic_function6);
   11501 }
   11502 
   11503 
   11504 // Same test as above, except the code is wrapped in a function
   11505 // to test the optimized compiler.
   11506 THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
   11507   i::FLAG_allow_natives_syntax = true;
   11508   v8::HandleScope scope(CcTest::isolate());
   11509   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11510   templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
   11511   LocalContext context;
   11512   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11513   call_ic_function6 =
   11514       v8_compile("function f(x) { return x - 1; }; f")->Run();
   11515   v8::Handle<Value> value = CompileRun(
   11516     "function inc(x) { return x + 1; };"
   11517     "inc(1);"
   11518     "o.x = inc;"
   11519     "function test() {"
   11520     "  var result = 0;"
   11521     "  for (var i = 0; i < 1000; i++) {"
   11522     "    result = o.x(42);"
   11523     "  }"
   11524     "  return result;"
   11525     "};"
   11526     "test();"
   11527     "test();"
   11528     "test();"
   11529     "%OptimizeFunctionOnNextCall(test);"
   11530     "test()");
   11531   CHECK_EQ(41, value->Int32Value());
   11532 }
   11533 
   11534 
   11535 // Test the case when we stored constant function into
   11536 // a stub, but it got invalidated later on
   11537 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
   11538   v8::HandleScope scope(CcTest::isolate());
   11539   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11540   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11541   LocalContext context;
   11542   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11543   v8::Handle<Value> value = CompileRun(
   11544     "function inc(x) { return x + 1; };"
   11545     "inc(1);"
   11546     "proto1 = new Object();"
   11547     "proto2 = new Object();"
   11548     "o.__proto__ = proto1;"
   11549     "proto1.__proto__ = proto2;"
   11550     "proto2.y = inc;"
   11551     // Invoke it many times to compile a stub
   11552     "for (var i = 0; i < 7; i++) {"
   11553     "  o.y(42);"
   11554     "}"
   11555     "proto1.y = function(x) { return x - 1; };"
   11556     "var result = 0;"
   11557     "for (var i = 0; i < 7; i++) {"
   11558     "  result += o.y(42);"
   11559     "}");
   11560   CHECK_EQ(41 * 7, value->Int32Value());
   11561 }
   11562 
   11563 
   11564 // Test the case when we stored constant function into
   11565 // a stub, but it got invalidated later on due to override on
   11566 // global object which is between interceptor and constant function' holders.
   11567 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
   11568   v8::HandleScope scope(CcTest::isolate());
   11569   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11570   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11571   LocalContext context;
   11572   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11573   v8::Handle<Value> value = CompileRun(
   11574     "function inc(x) { return x + 1; };"
   11575     "inc(1);"
   11576     "o.__proto__ = this;"
   11577     "this.__proto__.y = inc;"
   11578     // Invoke it many times to compile a stub
   11579     "for (var i = 0; i < 7; i++) {"
   11580     "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
   11581     "}"
   11582     "this.y = function(x) { return x - 1; };"
   11583     "var result = 0;"
   11584     "for (var i = 0; i < 7; i++) {"
   11585     "  result += o.y(42);"
   11586     "}");
   11587   CHECK_EQ(41 * 7, value->Int32Value());
   11588 }
   11589 
   11590 
   11591 // Test the case when actual function to call sits on global object.
   11592 THREADED_TEST(InterceptorCallICCachedFromGlobal) {
   11593   v8::HandleScope scope(CcTest::isolate());
   11594   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   11595   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   11596 
   11597   LocalContext context;
   11598   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11599 
   11600   v8::Handle<Value> value = CompileRun(
   11601     "try {"
   11602     "  o.__proto__ = this;"
   11603     "  for (var i = 0; i < 10; i++) {"
   11604     "    var v = o.parseFloat('239');"
   11605     "    if (v != 239) throw v;"
   11606       // Now it should be ICed and keep a reference to parseFloat.
   11607     "  }"
   11608     "  var result = 0;"
   11609     "  for (var i = 0; i < 10; i++) {"
   11610     "    result += o.parseFloat('239');"
   11611     "  }"
   11612     "  result"
   11613     "} catch(e) {"
   11614     "  e"
   11615     "};");
   11616   CHECK_EQ(239 * 10, value->Int32Value());
   11617 }
   11618 
   11619 static void InterceptorCallICFastApi(
   11620     Local<String> name,
   11621     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11622   ApiTestFuzzer::Fuzz();
   11623   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   11624   int* call_count =
   11625       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   11626   ++(*call_count);
   11627   if ((*call_count) % 20 == 0) {
   11628     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   11629   }
   11630 }
   11631 
   11632 static void FastApiCallback_TrivialSignature(
   11633     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11634   ApiTestFuzzer::Fuzz();
   11635   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   11636   v8::Isolate* isolate = CcTest::isolate();
   11637   CHECK_EQ(isolate, args.GetIsolate());
   11638   CHECK_EQ(args.This(), args.Holder());
   11639   CHECK(args.Data()->Equals(v8_str("method_data")));
   11640   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
   11641 }
   11642 
   11643 static void FastApiCallback_SimpleSignature(
   11644     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11645   ApiTestFuzzer::Fuzz();
   11646   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   11647   v8::Isolate* isolate = CcTest::isolate();
   11648   CHECK_EQ(isolate, args.GetIsolate());
   11649   CHECK_EQ(args.This()->GetPrototype(), args.Holder());
   11650   CHECK(args.Data()->Equals(v8_str("method_data")));
   11651   // Note, we're using HasRealNamedProperty instead of Has to avoid
   11652   // invoking the interceptor again.
   11653   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
   11654   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
   11655 }
   11656 
   11657 
   11658 // Helper to maximize the odds of object moving.
   11659 static void GenerateSomeGarbage() {
   11660   CompileRun(
   11661       "var garbage;"
   11662       "for (var i = 0; i < 1000; i++) {"
   11663       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   11664       "}"
   11665       "garbage = undefined;");
   11666 }
   11667 
   11668 
   11669 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11670   static int count = 0;
   11671   if (count++ % 3 == 0) {
   11672     CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   11673         // This should move the stub
   11674     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   11675   }
   11676 }
   11677 
   11678 
   11679 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   11680   LocalContext context;
   11681   v8::HandleScope scope(context->GetIsolate());
   11682   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
   11683   nativeobject_templ->Set(context->GetIsolate(), "callback",
   11684                           v8::FunctionTemplate::New(DirectApiCallback));
   11685   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   11686   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   11687   // call the api function multiple times to ensure direct call stub creation.
   11688   CompileRun(
   11689         "function f() {"
   11690         "  for (var i = 1; i <= 30; i++) {"
   11691         "    nativeobject.callback();"
   11692         "  }"
   11693         "}"
   11694         "f();");
   11695 }
   11696 
   11697 
   11698 void ThrowingDirectApiCallback(
   11699     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11700   args.GetIsolate()->ThrowException(v8_str("g"));
   11701 }
   11702 
   11703 
   11704 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   11705   LocalContext context;
   11706   v8::HandleScope scope(context->GetIsolate());
   11707   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
   11708   nativeobject_templ->Set(context->GetIsolate(), "callback",
   11709                           v8::FunctionTemplate::New(ThrowingDirectApiCallback));
   11710   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   11711   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   11712   // call the api function multiple times to ensure direct call stub creation.
   11713   v8::Handle<Value> result = CompileRun(
   11714       "var result = '';"
   11715       "function f() {"
   11716       "  for (var i = 1; i <= 5; i++) {"
   11717       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   11718       "  }"
   11719       "}"
   11720       "f(); result;");
   11721   CHECK_EQ(v8_str("ggggg"), result);
   11722 }
   11723 
   11724 
   11725 static Handle<Value> DoDirectGetter() {
   11726   if (++p_getter_count % 3 == 0) {
   11727     CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   11728     GenerateSomeGarbage();
   11729   }
   11730   return v8_str("Direct Getter Result");
   11731 }
   11732 
   11733 static void DirectGetterCallback(
   11734     Local<String> name,
   11735     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11736   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   11737   info.GetReturnValue().Set(DoDirectGetter());
   11738 }
   11739 
   11740 
   11741 template<typename Accessor>
   11742 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   11743   LocalContext context;
   11744   v8::HandleScope scope(context->GetIsolate());
   11745   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
   11746   obj->SetAccessor(v8_str("p1"), accessor);
   11747   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   11748   p_getter_count = 0;
   11749   v8::Handle<v8::Value> result = CompileRun(
   11750       "function f() {"
   11751       "  for (var i = 0; i < 30; i++) o1.p1;"
   11752       "  return o1.p1"
   11753       "}"
   11754       "f();");
   11755   CHECK_EQ(v8_str("Direct Getter Result"), result);
   11756   CHECK_EQ(31, p_getter_count);
   11757 }
   11758 
   11759 
   11760 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   11761   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   11762 }
   11763 
   11764 
   11765 void ThrowingDirectGetterCallback(
   11766     Local<String> name,
   11767     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11768   info.GetIsolate()->ThrowException(v8_str("g"));
   11769 }
   11770 
   11771 
   11772 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   11773   LocalContext context;
   11774   v8::HandleScope scope(context->GetIsolate());
   11775   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
   11776   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   11777   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   11778   v8::Handle<Value> result = CompileRun(
   11779       "var result = '';"
   11780       "for (var i = 0; i < 5; i++) {"
   11781       "    try { o1.p1; } catch (e) { result += e; }"
   11782       "}"
   11783       "result;");
   11784   CHECK_EQ(v8_str("ggggg"), result);
   11785 }
   11786 
   11787 
   11788 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   11789   int interceptor_call_count = 0;
   11790   v8::HandleScope scope(CcTest::isolate());
   11791   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11792   v8::Handle<v8::FunctionTemplate> method_templ =
   11793       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
   11794                                 v8_str("method_data"),
   11795                                 v8::Handle<v8::Signature>());
   11796   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11797   proto_templ->Set(v8_str("method"), method_templ);
   11798   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11799   templ->SetNamedPropertyHandler(
   11800       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   11801       v8::External::New(CcTest::isolate(), &interceptor_call_count));
   11802   LocalContext context;
   11803   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11804   GenerateSomeGarbage();
   11805   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11806   CompileRun(
   11807       "var result = 0;"
   11808       "for (var i = 0; i < 100; i++) {"
   11809       "  result = o.method(41);"
   11810       "}");
   11811   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   11812   CHECK_EQ(100, interceptor_call_count);
   11813 }
   11814 
   11815 
   11816 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   11817   int interceptor_call_count = 0;
   11818   v8::HandleScope scope(CcTest::isolate());
   11819   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11820   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   11821       FastApiCallback_SimpleSignature, v8_str("method_data"),
   11822       v8::Signature::New(CcTest::isolate(), fun_templ));
   11823   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11824   proto_templ->Set(v8_str("method"), method_templ);
   11825   fun_templ->SetHiddenPrototype(true);
   11826   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11827   templ->SetNamedPropertyHandler(
   11828       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   11829       v8::External::New(CcTest::isolate(), &interceptor_call_count));
   11830   LocalContext context;
   11831   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11832   GenerateSomeGarbage();
   11833   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11834   CompileRun(
   11835       "o.foo = 17;"
   11836       "var receiver = {};"
   11837       "receiver.__proto__ = o;"
   11838       "var result = 0;"
   11839       "for (var i = 0; i < 100; i++) {"
   11840       "  result = receiver.method(41);"
   11841       "}");
   11842   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   11843   CHECK_EQ(100, interceptor_call_count);
   11844 }
   11845 
   11846 
   11847 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   11848   int interceptor_call_count = 0;
   11849   v8::HandleScope scope(CcTest::isolate());
   11850   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11851   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   11852       FastApiCallback_SimpleSignature, v8_str("method_data"),
   11853       v8::Signature::New(CcTest::isolate(), fun_templ));
   11854   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11855   proto_templ->Set(v8_str("method"), method_templ);
   11856   fun_templ->SetHiddenPrototype(true);
   11857   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11858   templ->SetNamedPropertyHandler(
   11859       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   11860       v8::External::New(CcTest::isolate(), &interceptor_call_count));
   11861   LocalContext context;
   11862   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11863   GenerateSomeGarbage();
   11864   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11865   CompileRun(
   11866       "o.foo = 17;"
   11867       "var receiver = {};"
   11868       "receiver.__proto__ = o;"
   11869       "var result = 0;"
   11870       "var saved_result = 0;"
   11871       "for (var i = 0; i < 100; i++) {"
   11872       "  result = receiver.method(41);"
   11873       "  if (i == 50) {"
   11874       "    saved_result = result;"
   11875       "    receiver = {method: function(x) { return x - 1 }};"
   11876       "  }"
   11877       "}");
   11878   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   11879   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11880   CHECK_GE(interceptor_call_count, 50);
   11881 }
   11882 
   11883 
   11884 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   11885   int interceptor_call_count = 0;
   11886   v8::HandleScope scope(CcTest::isolate());
   11887   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11888   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   11889       FastApiCallback_SimpleSignature, v8_str("method_data"),
   11890       v8::Signature::New(CcTest::isolate(), fun_templ));
   11891   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11892   proto_templ->Set(v8_str("method"), method_templ);
   11893   fun_templ->SetHiddenPrototype(true);
   11894   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11895   templ->SetNamedPropertyHandler(
   11896       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   11897       v8::External::New(CcTest::isolate(), &interceptor_call_count));
   11898   LocalContext context;
   11899   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11900   GenerateSomeGarbage();
   11901   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11902   CompileRun(
   11903       "o.foo = 17;"
   11904       "var receiver = {};"
   11905       "receiver.__proto__ = o;"
   11906       "var result = 0;"
   11907       "var saved_result = 0;"
   11908       "for (var i = 0; i < 100; i++) {"
   11909       "  result = receiver.method(41);"
   11910       "  if (i == 50) {"
   11911       "    saved_result = result;"
   11912       "    o.method = function(x) { return x - 1 };"
   11913       "  }"
   11914       "}");
   11915   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   11916   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11917   CHECK_GE(interceptor_call_count, 50);
   11918 }
   11919 
   11920 
   11921 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   11922   int interceptor_call_count = 0;
   11923   v8::HandleScope scope(CcTest::isolate());
   11924   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11925   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   11926       FastApiCallback_SimpleSignature, v8_str("method_data"),
   11927       v8::Signature::New(CcTest::isolate(), fun_templ));
   11928   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11929   proto_templ->Set(v8_str("method"), method_templ);
   11930   fun_templ->SetHiddenPrototype(true);
   11931   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11932   templ->SetNamedPropertyHandler(
   11933       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   11934       v8::External::New(CcTest::isolate(), &interceptor_call_count));
   11935   LocalContext context;
   11936   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11937   GenerateSomeGarbage();
   11938   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11939   v8::TryCatch try_catch;
   11940   CompileRun(
   11941       "o.foo = 17;"
   11942       "var receiver = {};"
   11943       "receiver.__proto__ = o;"
   11944       "var result = 0;"
   11945       "var saved_result = 0;"
   11946       "for (var i = 0; i < 100; i++) {"
   11947       "  result = receiver.method(41);"
   11948       "  if (i == 50) {"
   11949       "    saved_result = result;"
   11950       "    receiver = 333;"
   11951       "  }"
   11952       "}");
   11953   CHECK(try_catch.HasCaught());
   11954   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
   11955            try_catch.Exception()->ToString());
   11956   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11957   CHECK_GE(interceptor_call_count, 50);
   11958 }
   11959 
   11960 
   11961 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   11962   int interceptor_call_count = 0;
   11963   v8::HandleScope scope(CcTest::isolate());
   11964   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11965   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   11966       FastApiCallback_SimpleSignature, v8_str("method_data"),
   11967       v8::Signature::New(CcTest::isolate(), fun_templ));
   11968   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11969   proto_templ->Set(v8_str("method"), method_templ);
   11970   fun_templ->SetHiddenPrototype(true);
   11971   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11972   templ->SetNamedPropertyHandler(
   11973       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   11974       v8::External::New(CcTest::isolate(), &interceptor_call_count));
   11975   LocalContext context;
   11976   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11977   GenerateSomeGarbage();
   11978   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11979   v8::TryCatch try_catch;
   11980   CompileRun(
   11981       "o.foo = 17;"
   11982       "var receiver = {};"
   11983       "receiver.__proto__ = o;"
   11984       "var result = 0;"
   11985       "var saved_result = 0;"
   11986       "for (var i = 0; i < 100; i++) {"
   11987       "  result = receiver.method(41);"
   11988       "  if (i == 50) {"
   11989       "    saved_result = result;"
   11990       "    receiver = {method: receiver.method};"
   11991       "  }"
   11992       "}");
   11993   CHECK(try_catch.HasCaught());
   11994   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
   11995            try_catch.Exception()->ToString());
   11996   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11997   CHECK_GE(interceptor_call_count, 50);
   11998 }
   11999 
   12000 
   12001 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   12002   v8::HandleScope scope(CcTest::isolate());
   12003   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   12004   v8::Handle<v8::FunctionTemplate> method_templ =
   12005       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
   12006                                 v8_str("method_data"),
   12007                                 v8::Handle<v8::Signature>());
   12008   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12009   proto_templ->Set(v8_str("method"), method_templ);
   12010   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12011   USE(templ);
   12012   LocalContext context;
   12013   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12014   GenerateSomeGarbage();
   12015   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12016   CompileRun(
   12017       "var result = 0;"
   12018       "for (var i = 0; i < 100; i++) {"
   12019       "  result = o.method(41);"
   12020       "}");
   12021 
   12022   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   12023 }
   12024 
   12025 
   12026 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
   12027   v8::HandleScope scope(CcTest::isolate());
   12028   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   12029   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12030       FastApiCallback_SimpleSignature, v8_str("method_data"),
   12031       v8::Signature::New(CcTest::isolate(), fun_templ));
   12032   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12033   proto_templ->Set(v8_str("method"), method_templ);
   12034   fun_templ->SetHiddenPrototype(true);
   12035   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12036   CHECK(!templ.IsEmpty());
   12037   LocalContext context;
   12038   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12039   GenerateSomeGarbage();
   12040   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12041   CompileRun(
   12042       "o.foo = 17;"
   12043       "var receiver = {};"
   12044       "receiver.__proto__ = o;"
   12045       "var result = 0;"
   12046       "for (var i = 0; i < 100; i++) {"
   12047       "  result = receiver.method(41);"
   12048       "}");
   12049 
   12050   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   12051 }
   12052 
   12053 
   12054 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   12055   v8::HandleScope scope(CcTest::isolate());
   12056   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   12057   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12058       FastApiCallback_SimpleSignature, v8_str("method_data"),
   12059       v8::Signature::New(CcTest::isolate(), fun_templ));
   12060   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12061   proto_templ->Set(v8_str("method"), method_templ);
   12062   fun_templ->SetHiddenPrototype(true);
   12063   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12064   CHECK(!templ.IsEmpty());
   12065   LocalContext context;
   12066   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12067   GenerateSomeGarbage();
   12068   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12069   CompileRun(
   12070       "o.foo = 17;"
   12071       "var receiver = {};"
   12072       "receiver.__proto__ = o;"
   12073       "var result = 0;"
   12074       "var saved_result = 0;"
   12075       "for (var i = 0; i < 100; i++) {"
   12076       "  result = receiver.method(41);"
   12077       "  if (i == 50) {"
   12078       "    saved_result = result;"
   12079       "    receiver = {method: function(x) { return x - 1 }};"
   12080       "  }"
   12081       "}");
   12082   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   12083   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12084 }
   12085 
   12086 
   12087 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   12088   v8::HandleScope scope(CcTest::isolate());
   12089   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   12090   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12091       FastApiCallback_SimpleSignature, v8_str("method_data"),
   12092       v8::Signature::New(CcTest::isolate(), fun_templ));
   12093   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12094   proto_templ->Set(v8_str("method"), method_templ);
   12095   fun_templ->SetHiddenPrototype(true);
   12096   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12097   CHECK(!templ.IsEmpty());
   12098   LocalContext context;
   12099   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12100   GenerateSomeGarbage();
   12101   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12102   v8::TryCatch try_catch;
   12103   CompileRun(
   12104       "o.foo = 17;"
   12105       "var receiver = {};"
   12106       "receiver.__proto__ = o;"
   12107       "var result = 0;"
   12108       "var saved_result = 0;"
   12109       "for (var i = 0; i < 100; i++) {"
   12110       "  result = receiver.method(41);"
   12111       "  if (i == 50) {"
   12112       "    saved_result = result;"
   12113       "    receiver = 333;"
   12114       "  }"
   12115       "}");
   12116   CHECK(try_catch.HasCaught());
   12117   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
   12118            try_catch.Exception()->ToString());
   12119   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12120 }
   12121 
   12122 
   12123 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
   12124   v8::HandleScope scope(CcTest::isolate());
   12125   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   12126   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12127       FastApiCallback_SimpleSignature, v8_str("method_data"),
   12128       v8::Signature::New(CcTest::isolate(), fun_templ));
   12129   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12130   proto_templ->Set(v8_str("method"), method_templ);
   12131   fun_templ->SetHiddenPrototype(true);
   12132   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12133   CHECK(!templ.IsEmpty());
   12134   LocalContext context;
   12135   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12136   GenerateSomeGarbage();
   12137   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12138   v8::TryCatch try_catch;
   12139   CompileRun(
   12140       "o.foo = 17;"
   12141       "var receiver = {};"
   12142       "receiver.__proto__ = o;"
   12143       "var result = 0;"
   12144       "var saved_result = 0;"
   12145       "for (var i = 0; i < 100; i++) {"
   12146       "  result = receiver.method(41);"
   12147       "  if (i == 50) {"
   12148       "    saved_result = result;"
   12149       "    receiver = Object.create(receiver);"
   12150       "  }"
   12151       "}");
   12152   CHECK(try_catch.HasCaught());
   12153   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
   12154            try_catch.Exception()->ToString());
   12155   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12156 }
   12157 
   12158 
   12159 v8::Handle<Value> keyed_call_ic_function;
   12160 
   12161 static void InterceptorKeyedCallICGetter(
   12162     Local<String> name,
   12163     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12164   ApiTestFuzzer::Fuzz();
   12165   if (v8_str("x")->Equals(name)) {
   12166     info.GetReturnValue().Set(keyed_call_ic_function);
   12167   }
   12168 }
   12169 
   12170 
   12171 // Test the case when we stored cacheable lookup into
   12172 // a stub, but the function name changed (to another cacheable function).
   12173 THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
   12174   v8::HandleScope scope(CcTest::isolate());
   12175   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   12176   templ->SetNamedPropertyHandler(NoBlockGetterX);
   12177   LocalContext context;
   12178   context->Global()->Set(v8_str("o"), templ->NewInstance());
   12179   CompileRun(
   12180     "proto = new Object();"
   12181     "proto.y = function(x) { return x + 1; };"
   12182     "proto.z = function(x) { return x - 1; };"
   12183     "o.__proto__ = proto;"
   12184     "var result = 0;"
   12185     "var method = 'y';"
   12186     "for (var i = 0; i < 10; i++) {"
   12187     "  if (i == 5) { method = 'z'; };"
   12188     "  result += o[method](41);"
   12189     "}");
   12190   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12191 }
   12192 
   12193 
   12194 // Test the case when we stored cacheable lookup into
   12195 // a stub, but the function name changed (and the new function is present
   12196 // both before and after the interceptor in the prototype chain).
   12197 THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
   12198   v8::HandleScope scope(CcTest::isolate());
   12199   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   12200   templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
   12201   LocalContext context;
   12202   context->Global()->Set(v8_str("proto1"), templ->NewInstance());
   12203   keyed_call_ic_function =
   12204       v8_compile("function f(x) { return x - 1; }; f")->Run();
   12205   CompileRun(
   12206     "o = new Object();"
   12207     "proto2 = new Object();"
   12208     "o.y = function(x) { return x + 1; };"
   12209     "proto2.y = function(x) { return x + 2; };"
   12210     "o.__proto__ = proto1;"
   12211     "proto1.__proto__ = proto2;"
   12212     "var result = 0;"
   12213     "var method = 'x';"
   12214     "for (var i = 0; i < 10; i++) {"
   12215     "  if (i == 5) { method = 'y'; };"
   12216     "  result += o[method](41);"
   12217     "}");
   12218   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12219 }
   12220 
   12221 
   12222 // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
   12223 // on the global object.
   12224 THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
   12225   v8::HandleScope scope(CcTest::isolate());
   12226   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   12227   templ->SetNamedPropertyHandler(NoBlockGetterX);
   12228   LocalContext context;
   12229   context->Global()->Set(v8_str("o"), templ->NewInstance());
   12230   CompileRun(
   12231     "function inc(x) { return x + 1; };"
   12232     "inc(1);"
   12233     "function dec(x) { return x - 1; };"
   12234     "dec(1);"
   12235     "o.__proto__ = this;"
   12236     "this.__proto__.x = inc;"
   12237     "this.__proto__.y = dec;"
   12238     "var result = 0;"
   12239     "var method = 'x';"
   12240     "for (var i = 0; i < 10; i++) {"
   12241     "  if (i == 5) { method = 'y'; };"
   12242     "  result += o[method](41);"
   12243     "}");
   12244   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12245 }
   12246 
   12247 
   12248 // Test the case when actual function to call sits on global object.
   12249 THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
   12250   v8::HandleScope scope(CcTest::isolate());
   12251   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   12252   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   12253   LocalContext context;
   12254   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   12255 
   12256   CompileRun(
   12257     "function len(x) { return x.length; };"
   12258     "o.__proto__ = this;"
   12259     "var m = 'parseFloat';"
   12260     "var result = 0;"
   12261     "for (var i = 0; i < 10; i++) {"
   12262     "  if (i == 5) {"
   12263     "    m = 'len';"
   12264     "    saved_result = result;"
   12265     "  };"
   12266     "  result = o[m]('239');"
   12267     "}");
   12268   CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
   12269   CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12270 }
   12271 
   12272 
   12273 // Test the map transition before the interceptor.
   12274 THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
   12275   v8::HandleScope scope(CcTest::isolate());
   12276   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   12277   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   12278   LocalContext context;
   12279   context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
   12280 
   12281   CompileRun(
   12282     "var o = new Object();"
   12283     "o.__proto__ = proto;"
   12284     "o.method = function(x) { return x + 1; };"
   12285     "var m = 'method';"
   12286     "var result = 0;"
   12287     "for (var i = 0; i < 10; i++) {"
   12288     "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
   12289     "  result += o[m](41);"
   12290     "}");
   12291   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12292 }
   12293 
   12294 
   12295 // Test the map transition after the interceptor.
   12296 THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
   12297   v8::HandleScope scope(CcTest::isolate());
   12298   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   12299   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   12300   LocalContext context;
   12301   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   12302 
   12303   CompileRun(
   12304     "var proto = new Object();"
   12305     "o.__proto__ = proto;"
   12306     "proto.method = function(x) { return x + 1; };"
   12307     "var m = 'method';"
   12308     "var result = 0;"
   12309     "for (var i = 0; i < 10; i++) {"
   12310     "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
   12311     "  result += o[m](41);"
   12312     "}");
   12313   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12314 }
   12315 
   12316 
   12317 static int interceptor_call_count = 0;
   12318 
   12319 static void InterceptorICRefErrorGetter(
   12320     Local<String> name,
   12321     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12322   ApiTestFuzzer::Fuzz();
   12323   if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
   12324     info.GetReturnValue().Set(call_ic_function2);
   12325   }
   12326 }
   12327 
   12328 
   12329 // This test should hit load and call ICs for the interceptor case.
   12330 // Once in a while, the interceptor will reply that a property was not
   12331 // found in which case we should get a reference error.
   12332 THREADED_TEST(InterceptorICReferenceErrors) {
   12333   v8::HandleScope scope(CcTest::isolate());
   12334   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   12335   templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
   12336   LocalContext context(0, templ, v8::Handle<Value>());
   12337   call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
   12338   v8::Handle<Value> value = CompileRun(
   12339     "function f() {"
   12340     "  for (var i = 0; i < 1000; i++) {"
   12341     "    try { x; } catch(e) { return true; }"
   12342     "  }"
   12343     "  return false;"
   12344     "};"
   12345     "f();");
   12346   CHECK_EQ(true, value->BooleanValue());
   12347   interceptor_call_count = 0;
   12348   value = CompileRun(
   12349     "function g() {"
   12350     "  for (var i = 0; i < 1000; i++) {"
   12351     "    try { x(42); } catch(e) { return true; }"
   12352     "  }"
   12353     "  return false;"
   12354     "};"
   12355     "g();");
   12356   CHECK_EQ(true, value->BooleanValue());
   12357 }
   12358 
   12359 
   12360 static int interceptor_ic_exception_get_count = 0;
   12361 
   12362 static void InterceptorICExceptionGetter(
   12363     Local<String> name,
   12364     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12365   ApiTestFuzzer::Fuzz();
   12366   if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
   12367     info.GetReturnValue().Set(call_ic_function3);
   12368   }
   12369   if (interceptor_ic_exception_get_count == 20) {
   12370     info.GetIsolate()->ThrowException(v8_num(42));
   12371     return;
   12372   }
   12373 }
   12374 
   12375 
   12376 // Test interceptor load/call IC where the interceptor throws an
   12377 // exception once in a while.
   12378 THREADED_TEST(InterceptorICGetterExceptions) {
   12379   interceptor_ic_exception_get_count = 0;
   12380   v8::HandleScope scope(CcTest::isolate());
   12381   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   12382   templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
   12383   LocalContext context(0, templ, v8::Handle<Value>());
   12384   call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
   12385   v8::Handle<Value> value = CompileRun(
   12386     "function f() {"
   12387     "  for (var i = 0; i < 100; i++) {"
   12388     "    try { x; } catch(e) { return true; }"
   12389     "  }"
   12390     "  return false;"
   12391     "};"
   12392     "f();");
   12393   CHECK_EQ(true, value->BooleanValue());
   12394   interceptor_ic_exception_get_count = 0;
   12395   value = CompileRun(
   12396     "function f() {"
   12397     "  for (var i = 0; i < 100; i++) {"
   12398     "    try { x(42); } catch(e) { return true; }"
   12399     "  }"
   12400     "  return false;"
   12401     "};"
   12402     "f();");
   12403   CHECK_EQ(true, value->BooleanValue());
   12404 }
   12405 
   12406 
   12407 static int interceptor_ic_exception_set_count = 0;
   12408 
   12409 static void InterceptorICExceptionSetter(
   12410       Local<String> key,
   12411       Local<Value> value,
   12412       const v8::PropertyCallbackInfo<v8::Value>& info) {
   12413   ApiTestFuzzer::Fuzz();
   12414   if (++interceptor_ic_exception_set_count > 20) {
   12415     info.GetIsolate()->ThrowException(v8_num(42));
   12416   }
   12417 }
   12418 
   12419 
   12420 // Test interceptor store IC where the interceptor throws an exception
   12421 // once in a while.
   12422 THREADED_TEST(InterceptorICSetterExceptions) {
   12423   interceptor_ic_exception_set_count = 0;
   12424   v8::HandleScope scope(CcTest::isolate());
   12425   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   12426   templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
   12427   LocalContext context(0, templ, v8::Handle<Value>());
   12428   v8::Handle<Value> value = CompileRun(
   12429     "function f() {"
   12430     "  for (var i = 0; i < 100; i++) {"
   12431     "    try { x = 42; } catch(e) { return true; }"
   12432     "  }"
   12433     "  return false;"
   12434     "};"
   12435     "f();");
   12436   CHECK_EQ(true, value->BooleanValue());
   12437 }
   12438 
   12439 
   12440 // Test that we ignore null interceptors.
   12441 THREADED_TEST(NullNamedInterceptor) {
   12442   v8::HandleScope scope(CcTest::isolate());
   12443   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   12444   templ->SetNamedPropertyHandler(
   12445       static_cast<v8::NamedPropertyGetterCallback>(0));
   12446   LocalContext context;
   12447   templ->Set(CcTest::isolate(), "x", v8_num(42));
   12448   v8::Handle<v8::Object> obj = templ->NewInstance();
   12449   context->Global()->Set(v8_str("obj"), obj);
   12450   v8::Handle<Value> value = CompileRun("obj.x");
   12451   CHECK(value->IsInt32());
   12452   CHECK_EQ(42, value->Int32Value());
   12453 }
   12454 
   12455 
   12456 // Test that we ignore null interceptors.
   12457 THREADED_TEST(NullIndexedInterceptor) {
   12458   v8::HandleScope scope(CcTest::isolate());
   12459   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   12460   templ->SetIndexedPropertyHandler(
   12461       static_cast<v8::IndexedPropertyGetterCallback>(0));
   12462   LocalContext context;
   12463   templ->Set(CcTest::isolate(), "42", v8_num(42));
   12464   v8::Handle<v8::Object> obj = templ->NewInstance();
   12465   context->Global()->Set(v8_str("obj"), obj);
   12466   v8::Handle<Value> value = CompileRun("obj[42]");
   12467   CHECK(value->IsInt32());
   12468   CHECK_EQ(42, value->Int32Value());
   12469 }
   12470 
   12471 
   12472 THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
   12473   v8::HandleScope scope(CcTest::isolate());
   12474   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   12475   templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   12476   LocalContext env;
   12477   env->Global()->Set(v8_str("obj"),
   12478                      templ->GetFunction()->NewInstance());
   12479   ExpectTrue("obj.x === 42");
   12480   ExpectTrue("!obj.propertyIsEnumerable('x')");
   12481 }
   12482 
   12483 
   12484 static void ThrowingGetter(Local<String> name,
   12485                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   12486   ApiTestFuzzer::Fuzz();
   12487   info.GetIsolate()->ThrowException(Handle<Value>());
   12488   info.GetReturnValue().SetUndefined();
   12489 }
   12490 
   12491 
   12492 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   12493   LocalContext context;
   12494   HandleScope scope(context->GetIsolate());
   12495 
   12496   Local<FunctionTemplate> templ = FunctionTemplate::New();
   12497   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12498   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   12499 
   12500   Local<Object> instance = templ->GetFunction()->NewInstance();
   12501 
   12502   Local<Object> another = Object::New();
   12503   another->SetPrototype(instance);
   12504 
   12505   Local<Object> with_js_getter = CompileRun(
   12506       "o = {};\n"
   12507       "o.__defineGetter__('f', function() { throw undefined; });\n"
   12508       "o\n").As<Object>();
   12509   CHECK(!with_js_getter.IsEmpty());
   12510 
   12511   TryCatch try_catch;
   12512 
   12513   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
   12514   CHECK(try_catch.HasCaught());
   12515   try_catch.Reset();
   12516   CHECK(result.IsEmpty());
   12517 
   12518   result = another->GetRealNamedProperty(v8_str("f"));
   12519   CHECK(try_catch.HasCaught());
   12520   try_catch.Reset();
   12521   CHECK(result.IsEmpty());
   12522 
   12523   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
   12524   CHECK(try_catch.HasCaught());
   12525   try_catch.Reset();
   12526   CHECK(result.IsEmpty());
   12527 
   12528   result = another->Get(v8_str("f"));
   12529   CHECK(try_catch.HasCaught());
   12530   try_catch.Reset();
   12531   CHECK(result.IsEmpty());
   12532 
   12533   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
   12534   CHECK(try_catch.HasCaught());
   12535   try_catch.Reset();
   12536   CHECK(result.IsEmpty());
   12537 
   12538   result = with_js_getter->Get(v8_str("f"));
   12539   CHECK(try_catch.HasCaught());
   12540   try_catch.Reset();
   12541   CHECK(result.IsEmpty());
   12542 }
   12543 
   12544 
   12545 static void ThrowingCallbackWithTryCatch(
   12546     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12547   TryCatch try_catch;
   12548   // Verboseness is important: it triggers message delivery which can call into
   12549   // external code.
   12550   try_catch.SetVerbose(true);
   12551   CompileRun("throw 'from JS';");
   12552   CHECK(try_catch.HasCaught());
   12553   CHECK(!CcTest::i_isolate()->has_pending_exception());
   12554   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   12555 }
   12556 
   12557 
   12558 static int call_depth;
   12559 
   12560 
   12561 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
   12562   TryCatch try_catch;
   12563 }
   12564 
   12565 
   12566 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
   12567   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   12568 }
   12569 
   12570 
   12571 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
   12572   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
   12573 }
   12574 
   12575 
   12576 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
   12577   Handle<String> errorMessageString = message->Get();
   12578   CHECK(!errorMessageString.IsEmpty());
   12579   message->GetStackTrace();
   12580   message->GetScriptResourceName();
   12581 }
   12582 
   12583 
   12584 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   12585   LocalContext context;
   12586   HandleScope scope(context->GetIsolate());
   12587 
   12588   Local<Function> func =
   12589       FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction();
   12590   context->Global()->Set(v8_str("func"), func);
   12591 
   12592   MessageCallback callbacks[] =
   12593       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
   12594   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   12595     MessageCallback callback = callbacks[i];
   12596     if (callback != NULL) {
   12597       V8::AddMessageListener(callback);
   12598     }
   12599     // Some small number to control number of times message handler should
   12600     // throw an exception.
   12601     call_depth = 5;
   12602     ExpectFalse(
   12603         "var thrown = false;\n"
   12604         "try { func(); } catch(e) { thrown = true; }\n"
   12605         "thrown\n");
   12606     if (callback != NULL) {
   12607       V8::RemoveMessageListeners(callback);
   12608     }
   12609   }
   12610 }
   12611 
   12612 
   12613 static void ParentGetter(Local<String> name,
   12614                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   12615   ApiTestFuzzer::Fuzz();
   12616   info.GetReturnValue().Set(v8_num(1));
   12617 }
   12618 
   12619 
   12620 static void ChildGetter(Local<String> name,
   12621                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   12622   ApiTestFuzzer::Fuzz();
   12623   info.GetReturnValue().Set(v8_num(42));
   12624 }
   12625 
   12626 
   12627 THREADED_TEST(Overriding) {
   12628   i::FLAG_es5_readonly = true;
   12629   LocalContext context;
   12630   v8::HandleScope scope(context->GetIsolate());
   12631 
   12632   // Parent template.
   12633   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
   12634   Local<ObjectTemplate> parent_instance_templ =
   12635       parent_templ->InstanceTemplate();
   12636   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   12637 
   12638   // Template that inherits from the parent template.
   12639   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
   12640   Local<ObjectTemplate> child_instance_templ =
   12641       child_templ->InstanceTemplate();
   12642   child_templ->Inherit(parent_templ);
   12643   // Override 'f'.  The child version of 'f' should get called for child
   12644   // instances.
   12645   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   12646   // Add 'g' twice.  The 'g' added last should get called for instances.
   12647   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   12648   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   12649 
   12650   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   12651   // so 'h' can be shadowed on the instance object.
   12652   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   12653   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
   12654       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   12655 
   12656   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   12657   // but the attribute does not have effect because it is duplicated with
   12658   // NULL setter.
   12659   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
   12660       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   12661 
   12662 
   12663 
   12664   // Instantiate the child template.
   12665   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
   12666 
   12667   // Check that the child function overrides the parent one.
   12668   context->Global()->Set(v8_str("o"), instance);
   12669   Local<Value> value = v8_compile("o.f")->Run();
   12670   // Check that the 'g' that was added last is hit.
   12671   CHECK_EQ(42, value->Int32Value());
   12672   value = v8_compile("o.g")->Run();
   12673   CHECK_EQ(42, value->Int32Value());
   12674 
   12675   // Check that 'h' cannot be shadowed.
   12676   value = v8_compile("o.h = 3; o.h")->Run();
   12677   CHECK_EQ(1, value->Int32Value());
   12678 
   12679   // Check that 'i' cannot be shadowed or changed.
   12680   value = v8_compile("o.i = 3; o.i")->Run();
   12681   CHECK_EQ(42, value->Int32Value());
   12682 }
   12683 
   12684 
   12685 static void IsConstructHandler(
   12686     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12687   ApiTestFuzzer::Fuzz();
   12688   args.GetReturnValue().Set(args.IsConstructCall());
   12689 }
   12690 
   12691 
   12692 THREADED_TEST(IsConstructCall) {
   12693   v8::HandleScope scope(CcTest::isolate());
   12694 
   12695   // Function template with call handler.
   12696   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   12697   templ->SetCallHandler(IsConstructHandler);
   12698 
   12699   LocalContext context;
   12700 
   12701   context->Global()->Set(v8_str("f"), templ->GetFunction());
   12702   Local<Value> value = v8_compile("f()")->Run();
   12703   CHECK(!value->BooleanValue());
   12704   value = v8_compile("new f()")->Run();
   12705   CHECK(value->BooleanValue());
   12706 }
   12707 
   12708 
   12709 THREADED_TEST(ObjectProtoToString) {
   12710   v8::HandleScope scope(CcTest::isolate());
   12711   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   12712   templ->SetClassName(v8_str("MyClass"));
   12713 
   12714   LocalContext context;
   12715 
   12716   Local<String> customized_tostring = v8_str("customized toString");
   12717 
   12718   // Replace Object.prototype.toString
   12719   v8_compile("Object.prototype.toString = function() {"
   12720                   "  return 'customized toString';"
   12721                   "}")->Run();
   12722 
   12723   // Normal ToString call should call replaced Object.prototype.toString
   12724   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
   12725   Local<String> value = instance->ToString();
   12726   CHECK(value->IsString() && value->Equals(customized_tostring));
   12727 
   12728   // ObjectProtoToString should not call replace toString function.
   12729   value = instance->ObjectProtoToString();
   12730   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
   12731 
   12732   // Check global
   12733   value = context->Global()->ObjectProtoToString();
   12734   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
   12735 
   12736   // Check ordinary object
   12737   Local<Value> object = v8_compile("new Object()")->Run();
   12738   value = object.As<v8::Object>()->ObjectProtoToString();
   12739   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
   12740 }
   12741 
   12742 
   12743 THREADED_TEST(ObjectGetConstructorName) {
   12744   LocalContext context;
   12745   v8::HandleScope scope(context->GetIsolate());
   12746   v8_compile("function Parent() {};"
   12747              "function Child() {};"
   12748              "Child.prototype = new Parent();"
   12749              "var outer = { inner: function() { } };"
   12750              "var p = new Parent();"
   12751              "var c = new Child();"
   12752              "var x = new outer.inner();")->Run();
   12753 
   12754   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
   12755   CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
   12756       v8_str("Parent")));
   12757 
   12758   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
   12759   CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
   12760       v8_str("Child")));
   12761 
   12762   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
   12763   CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
   12764       v8_str("outer.inner")));
   12765 }
   12766 
   12767 
   12768 bool ApiTestFuzzer::fuzzing_ = false;
   12769 i::Semaphore ApiTestFuzzer::all_tests_done_(0);
   12770 int ApiTestFuzzer::active_tests_;
   12771 int ApiTestFuzzer::tests_being_run_;
   12772 int ApiTestFuzzer::current_;
   12773 
   12774 
   12775 // We are in a callback and want to switch to another thread (if we
   12776 // are currently running the thread fuzzing test).
   12777 void ApiTestFuzzer::Fuzz() {
   12778   if (!fuzzing_) return;
   12779   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   12780   test->ContextSwitch();
   12781 }
   12782 
   12783 
   12784 // Let the next thread go.  Since it is also waiting on the V8 lock it may
   12785 // not start immediately.
   12786 bool ApiTestFuzzer::NextThread() {
   12787   int test_position = GetNextTestNumber();
   12788   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   12789   if (test_position == current_) {
   12790     if (kLogThreading)
   12791       printf("Stay with %s\n", test_name);
   12792     return false;
   12793   }
   12794   if (kLogThreading) {
   12795     printf("Switch from %s to %s\n",
   12796            test_name,
   12797            RegisterThreadedTest::nth(test_position)->name());
   12798   }
   12799   current_ = test_position;
   12800   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
   12801   return true;
   12802 }
   12803 
   12804 
   12805 void ApiTestFuzzer::Run() {
   12806   // When it is our turn...
   12807   gate_.Wait();
   12808   {
   12809     // ... get the V8 lock and start running the test.
   12810     v8::Locker locker(CcTest::isolate());
   12811     CallTest();
   12812   }
   12813   // This test finished.
   12814   active_ = false;
   12815   active_tests_--;
   12816   // If it was the last then signal that fact.
   12817   if (active_tests_ == 0) {
   12818     all_tests_done_.Signal();
   12819   } else {
   12820     // Otherwise select a new test and start that.
   12821     NextThread();
   12822   }
   12823 }
   12824 
   12825 
   12826 static unsigned linear_congruential_generator;
   12827 
   12828 
   12829 void ApiTestFuzzer::SetUp(PartOfTest part) {
   12830   linear_congruential_generator = i::FLAG_testing_prng_seed;
   12831   fuzzing_ = true;
   12832   int count = RegisterThreadedTest::count();
   12833   int start =  count * part / (LAST_PART + 1);
   12834   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   12835   active_tests_ = tests_being_run_ = end - start + 1;
   12836   for (int i = 0; i < tests_being_run_; i++) {
   12837     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   12838   }
   12839   for (int i = 0; i < active_tests_; i++) {
   12840     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   12841   }
   12842 }
   12843 
   12844 
   12845 static void CallTestNumber(int test_number) {
   12846   (RegisterThreadedTest::nth(test_number)->callback())();
   12847 }
   12848 
   12849 
   12850 void ApiTestFuzzer::RunAllTests() {
   12851   // Set off the first test.
   12852   current_ = -1;
   12853   NextThread();
   12854   // Wait till they are all done.
   12855   all_tests_done_.Wait();
   12856 }
   12857 
   12858 
   12859 int ApiTestFuzzer::GetNextTestNumber() {
   12860   int next_test;
   12861   do {
   12862     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   12863     linear_congruential_generator *= 1664525u;
   12864     linear_congruential_generator += 1013904223u;
   12865   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   12866   return next_test;
   12867 }
   12868 
   12869 
   12870 void ApiTestFuzzer::ContextSwitch() {
   12871   // If the new thread is the same as the current thread there is nothing to do.
   12872   if (NextThread()) {
   12873     // Now it can start.
   12874     v8::Unlocker unlocker(CcTest::isolate());
   12875     // Wait till someone starts us again.
   12876     gate_.Wait();
   12877     // And we're off.
   12878   }
   12879 }
   12880 
   12881 
   12882 void ApiTestFuzzer::TearDown() {
   12883   fuzzing_ = false;
   12884   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   12885     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   12886     if (fuzzer != NULL) fuzzer->Join();
   12887   }
   12888 }
   12889 
   12890 
   12891 // Lets not be needlessly self-referential.
   12892 TEST(Threading1) {
   12893   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
   12894   ApiTestFuzzer::RunAllTests();
   12895   ApiTestFuzzer::TearDown();
   12896 }
   12897 
   12898 
   12899 TEST(Threading2) {
   12900   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
   12901   ApiTestFuzzer::RunAllTests();
   12902   ApiTestFuzzer::TearDown();
   12903 }
   12904 
   12905 
   12906 TEST(Threading3) {
   12907   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
   12908   ApiTestFuzzer::RunAllTests();
   12909   ApiTestFuzzer::TearDown();
   12910 }
   12911 
   12912 
   12913 TEST(Threading4) {
   12914   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
   12915   ApiTestFuzzer::RunAllTests();
   12916   ApiTestFuzzer::TearDown();
   12917 }
   12918 
   12919 
   12920 void ApiTestFuzzer::CallTest() {
   12921   v8::Isolate::Scope scope(CcTest::isolate());
   12922   if (kLogThreading)
   12923     printf("Start test %d\n", test_number_);
   12924   CallTestNumber(test_number_);
   12925   if (kLogThreading)
   12926     printf("End test %d\n", test_number_);
   12927 }
   12928 
   12929 
   12930 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12931   v8::Isolate* isolate = args.GetIsolate();
   12932   CHECK(v8::Locker::IsLocked(isolate));
   12933   ApiTestFuzzer::Fuzz();
   12934   v8::Unlocker unlocker(isolate);
   12935   const char* code = "throw 7;";
   12936   {
   12937     v8::Locker nested_locker(isolate);
   12938     v8::HandleScope scope(isolate);
   12939     v8::Handle<Value> exception;
   12940     { v8::TryCatch try_catch;
   12941       v8::Handle<Value> value = CompileRun(code);
   12942       CHECK(value.IsEmpty());
   12943       CHECK(try_catch.HasCaught());
   12944       // Make sure to wrap the exception in a new handle because
   12945       // the handle returned from the TryCatch is destroyed
   12946       // when the TryCatch is destroyed.
   12947       exception = Local<Value>::New(isolate, try_catch.Exception());
   12948     }
   12949     args.GetIsolate()->ThrowException(exception);
   12950   }
   12951 }
   12952 
   12953 
   12954 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12955   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   12956   ApiTestFuzzer::Fuzz();
   12957   v8::Unlocker unlocker(CcTest::isolate());
   12958   const char* code = "throw 7;";
   12959   {
   12960     v8::Locker nested_locker(CcTest::isolate());
   12961     v8::HandleScope scope(args.GetIsolate());
   12962     v8::Handle<Value> value = CompileRun(code);
   12963     CHECK(value.IsEmpty());
   12964     args.GetReturnValue().Set(v8_str("foo"));
   12965   }
   12966 }
   12967 
   12968 
   12969 // These are locking tests that don't need to be run again
   12970 // as part of the locking aggregation tests.
   12971 TEST(NestedLockers) {
   12972   v8::Locker locker(CcTest::isolate());
   12973   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   12974   LocalContext env;
   12975   v8::HandleScope scope(env->GetIsolate());
   12976   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
   12977   Local<Function> fun = fun_templ->GetFunction();
   12978   env->Global()->Set(v8_str("throw_in_js"), fun);
   12979   Local<Script> script = v8_compile("(function () {"
   12980                                     "  try {"
   12981                                     "    throw_in_js();"
   12982                                     "    return 42;"
   12983                                     "  } catch (e) {"
   12984                                     "    return e * 13;"
   12985                                     "  }"
   12986                                     "})();");
   12987   CHECK_EQ(91, script->Run()->Int32Value());
   12988 }
   12989 
   12990 
   12991 // These are locking tests that don't need to be run again
   12992 // as part of the locking aggregation tests.
   12993 TEST(NestedLockersNoTryCatch) {
   12994   v8::Locker locker(CcTest::isolate());
   12995   LocalContext env;
   12996   v8::HandleScope scope(env->GetIsolate());
   12997   Local<v8::FunctionTemplate> fun_templ =
   12998       v8::FunctionTemplate::New(ThrowInJSNoCatch);
   12999   Local<Function> fun = fun_templ->GetFunction();
   13000   env->Global()->Set(v8_str("throw_in_js"), fun);
   13001   Local<Script> script = v8_compile("(function () {"
   13002                                     "  try {"
   13003                                     "    throw_in_js();"
   13004                                     "    return 42;"
   13005                                     "  } catch (e) {"
   13006                                     "    return e * 13;"
   13007                                     "  }"
   13008                                     "})();");
   13009   CHECK_EQ(91, script->Run()->Int32Value());
   13010 }
   13011 
   13012 
   13013 THREADED_TEST(RecursiveLocking) {
   13014   v8::Locker locker(CcTest::isolate());
   13015   {
   13016     v8::Locker locker2(CcTest::isolate());
   13017     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13018   }
   13019 }
   13020 
   13021 
   13022 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13023   ApiTestFuzzer::Fuzz();
   13024   v8::Unlocker unlocker(CcTest::isolate());
   13025 }
   13026 
   13027 
   13028 THREADED_TEST(LockUnlockLock) {
   13029   {
   13030     v8::Locker locker(CcTest::isolate());
   13031     v8::HandleScope scope(CcTest::isolate());
   13032     LocalContext env;
   13033     Local<v8::FunctionTemplate> fun_templ =
   13034         v8::FunctionTemplate::New(UnlockForAMoment);
   13035     Local<Function> fun = fun_templ->GetFunction();
   13036     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   13037     Local<Script> script = v8_compile("(function () {"
   13038                                       "  unlock_for_a_moment();"
   13039                                       "  return 42;"
   13040                                       "})();");
   13041     CHECK_EQ(42, script->Run()->Int32Value());
   13042   }
   13043   {
   13044     v8::Locker locker(CcTest::isolate());
   13045     v8::HandleScope scope(CcTest::isolate());
   13046     LocalContext env;
   13047     Local<v8::FunctionTemplate> fun_templ =
   13048         v8::FunctionTemplate::New(UnlockForAMoment);
   13049     Local<Function> fun = fun_templ->GetFunction();
   13050     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   13051     Local<Script> script = v8_compile("(function () {"
   13052                                       "  unlock_for_a_moment();"
   13053                                       "  return 42;"
   13054                                       "})();");
   13055     CHECK_EQ(42, script->Run()->Int32Value());
   13056   }
   13057 }
   13058 
   13059 
   13060 static int GetGlobalObjectsCount() {
   13061   CcTest::heap()->EnsureHeapIsIterable();
   13062   int count = 0;
   13063   i::HeapIterator it(CcTest::heap());
   13064   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
   13065     if (object->IsJSGlobalObject()) count++;
   13066   return count;
   13067 }
   13068 
   13069 
   13070 static void CheckSurvivingGlobalObjectsCount(int expected) {
   13071   // We need to collect all garbage twice to be sure that everything
   13072   // has been collected.  This is because inline caches are cleared in
   13073   // the first garbage collection but some of the maps have already
   13074   // been marked at that point.  Therefore some of the maps are not
   13075   // collected until the second garbage collection.
   13076   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   13077   CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
   13078   int count = GetGlobalObjectsCount();
   13079 #ifdef DEBUG
   13080   if (count != expected) CcTest::heap()->TracePathToGlobal();
   13081 #endif
   13082   CHECK_EQ(expected, count);
   13083 }
   13084 
   13085 
   13086 TEST(DontLeakGlobalObjects) {
   13087   // Regression test for issues 1139850 and 1174891.
   13088 
   13089   v8::V8::Initialize();
   13090 
   13091   for (int i = 0; i < 5; i++) {
   13092     { v8::HandleScope scope(CcTest::isolate());
   13093       LocalContext context;
   13094     }
   13095     v8::V8::ContextDisposedNotification();
   13096     CheckSurvivingGlobalObjectsCount(0);
   13097 
   13098     { v8::HandleScope scope(CcTest::isolate());
   13099       LocalContext context;
   13100       v8_compile("Date")->Run();
   13101     }
   13102     v8::V8::ContextDisposedNotification();
   13103     CheckSurvivingGlobalObjectsCount(0);
   13104 
   13105     { v8::HandleScope scope(CcTest::isolate());
   13106       LocalContext context;
   13107       v8_compile("/aaa/")->Run();
   13108     }
   13109     v8::V8::ContextDisposedNotification();
   13110     CheckSurvivingGlobalObjectsCount(0);
   13111 
   13112     { v8::HandleScope scope(CcTest::isolate());
   13113       const char* extension_list[] = { "v8/gc" };
   13114       v8::ExtensionConfiguration extensions(1, extension_list);
   13115       LocalContext context(&extensions);
   13116       v8_compile("gc();")->Run();
   13117     }
   13118     v8::V8::ContextDisposedNotification();
   13119     CheckSurvivingGlobalObjectsCount(0);
   13120   }
   13121 }
   13122 
   13123 
   13124 TEST(CopyablePersistent) {
   13125   LocalContext context;
   13126   v8::Isolate* isolate = context->GetIsolate();
   13127   i::GlobalHandles* globals =
   13128       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13129   int initial_handles = globals->global_handles_count();
   13130   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
   13131       CopyableObject;
   13132   {
   13133     CopyableObject handle1;
   13134     {
   13135       v8::HandleScope scope(isolate);
   13136       handle1.Reset(isolate, v8::Object::New());
   13137     }
   13138     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
   13139     CopyableObject  handle2;
   13140     handle2 = handle1;
   13141     CHECK(handle1 == handle2);
   13142     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
   13143     CopyableObject handle3(handle2);
   13144     CHECK(handle1 == handle3);
   13145     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
   13146   }
   13147   // Verify autodispose
   13148   CHECK_EQ(initial_handles, globals->global_handles_count());
   13149 }
   13150 
   13151 
   13152 static void WeakApiCallback(
   13153     const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
   13154   Local<Value> value = data.GetValue()->Get(v8_str("key"));
   13155   CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
   13156   data.GetParameter()->Reset();
   13157   delete data.GetParameter();
   13158 }
   13159 
   13160 
   13161 TEST(WeakCallbackApi) {
   13162   LocalContext context;
   13163   v8::Isolate* isolate = context->GetIsolate();
   13164   i::GlobalHandles* globals =
   13165       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13166   int initial_handles = globals->global_handles_count();
   13167   {
   13168     v8::HandleScope scope(isolate);
   13169     v8::Local<v8::Object> obj = v8::Object::New();
   13170     obj->Set(v8_str("key"), v8::Integer::New(231, isolate));
   13171     v8::Persistent<v8::Object>* handle =
   13172         new v8::Persistent<v8::Object>(isolate, obj);
   13173     handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
   13174                                                              WeakApiCallback);
   13175   }
   13176   reinterpret_cast<i::Isolate*>(isolate)->heap()->
   13177       CollectAllGarbage(i::Heap::kNoGCFlags);
   13178   // Verify disposed.
   13179   CHECK_EQ(initial_handles, globals->global_handles_count());
   13180 }
   13181 
   13182 
   13183 v8::Persistent<v8::Object> some_object;
   13184 v8::Persistent<v8::Object> bad_handle;
   13185 
   13186 void NewPersistentHandleCallback(
   13187     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
   13188   v8::HandleScope scope(data.GetIsolate());
   13189   bad_handle.Reset(data.GetIsolate(), some_object);
   13190   data.GetParameter()->Reset();
   13191 }
   13192 
   13193 
   13194 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   13195   LocalContext context;
   13196   v8::Isolate* isolate = context->GetIsolate();
   13197 
   13198   v8::Persistent<v8::Object> handle1, handle2;
   13199   {
   13200     v8::HandleScope scope(isolate);
   13201     some_object.Reset(isolate, v8::Object::New());
   13202     handle1.Reset(isolate, v8::Object::New());
   13203     handle2.Reset(isolate, v8::Object::New());
   13204   }
   13205   // Note: order is implementation dependent alas: currently
   13206   // global handle nodes are processed by PostGarbageCollectionProcessing
   13207   // in reverse allocation order, so if second allocated handle is deleted,
   13208   // weak callback of the first handle would be able to 'reallocate' it.
   13209   handle1.SetWeak(&handle1, NewPersistentHandleCallback);
   13210   handle2.Reset();
   13211   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   13212 }
   13213 
   13214 
   13215 v8::Persistent<v8::Object> to_be_disposed;
   13216 
   13217 void DisposeAndForceGcCallback(
   13218     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
   13219   to_be_disposed.Reset();
   13220   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   13221   data.GetParameter()->Reset();
   13222 }
   13223 
   13224 
   13225 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   13226   LocalContext context;
   13227   v8::Isolate* isolate = context->GetIsolate();
   13228 
   13229   v8::Persistent<v8::Object> handle1, handle2;
   13230   {
   13231     v8::HandleScope scope(isolate);
   13232     handle1.Reset(isolate, v8::Object::New());
   13233     handle2.Reset(isolate, v8::Object::New());
   13234   }
   13235   handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
   13236   to_be_disposed.Reset(isolate, handle2);
   13237   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   13238 }
   13239 
   13240 void DisposingCallback(
   13241     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
   13242   data.GetParameter()->Reset();
   13243 }
   13244 
   13245 void HandleCreatingCallback(
   13246     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
   13247   v8::HandleScope scope(data.GetIsolate());
   13248   v8::Persistent<v8::Object>(data.GetIsolate(), v8::Object::New());
   13249   data.GetParameter()->Reset();
   13250 }
   13251 
   13252 
   13253 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   13254   LocalContext context;
   13255   v8::Isolate* isolate = context->GetIsolate();
   13256 
   13257   v8::Persistent<v8::Object> handle1, handle2, handle3;
   13258   {
   13259     v8::HandleScope scope(isolate);
   13260     handle3.Reset(isolate, v8::Object::New());
   13261     handle2.Reset(isolate, v8::Object::New());
   13262     handle1.Reset(isolate, v8::Object::New());
   13263   }
   13264   handle2.SetWeak(&handle2, DisposingCallback);
   13265   handle3.SetWeak(&handle3, HandleCreatingCallback);
   13266   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   13267 }
   13268 
   13269 
   13270 THREADED_TEST(CheckForCrossContextObjectLiterals) {
   13271   v8::V8::Initialize();
   13272 
   13273   const int nof = 2;
   13274   const char* sources[nof] = {
   13275     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   13276     "Object()"
   13277   };
   13278 
   13279   for (int i = 0; i < nof; i++) {
   13280     const char* source = sources[i];
   13281     { v8::HandleScope scope(CcTest::isolate());
   13282       LocalContext context;
   13283       CompileRun(source);
   13284     }
   13285     { v8::HandleScope scope(CcTest::isolate());
   13286       LocalContext context;
   13287       CompileRun(source);
   13288     }
   13289   }
   13290 }
   13291 
   13292 
   13293 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
   13294   v8::HandleScope inner(env->GetIsolate());
   13295   env->Enter();
   13296   v8::Handle<Value> three = v8_num(3);
   13297   v8::Handle<Value> value = inner.Close(three);
   13298   env->Exit();
   13299   return value;
   13300 }
   13301 
   13302 
   13303 THREADED_TEST(NestedHandleScopeAndContexts) {
   13304   v8::Isolate* isolate = CcTest::isolate();
   13305   v8::HandleScope outer(isolate);
   13306   v8::Local<Context> env = Context::New(isolate);
   13307   env->Enter();
   13308   v8::Handle<Value> value = NestedScope(env);
   13309   v8::Handle<String> str(value->ToString());
   13310   CHECK(!str.IsEmpty());
   13311   env->Exit();
   13312 }
   13313 
   13314 
   13315 static bool MatchPointers(void* key1, void* key2) {
   13316   return key1 == key2;
   13317 }
   13318 
   13319 
   13320 struct SymbolInfo {
   13321   size_t id;
   13322   size_t size;
   13323   std::string name;
   13324 };
   13325 
   13326 
   13327 class SetFunctionEntryHookTest {
   13328  public:
   13329   SetFunctionEntryHookTest() {
   13330     CHECK(instance_ == NULL);
   13331     instance_ = this;
   13332   }
   13333   ~SetFunctionEntryHookTest() {
   13334     CHECK(instance_ == this);
   13335     instance_ = NULL;
   13336   }
   13337   void Reset() {
   13338     symbols_.clear();
   13339     symbol_locations_.clear();
   13340     invocations_.clear();
   13341   }
   13342   void RunTest();
   13343   void OnJitEvent(const v8::JitCodeEvent* event);
   13344   static void JitEvent(const v8::JitCodeEvent* event) {
   13345     CHECK(instance_ != NULL);
   13346     instance_->OnJitEvent(event);
   13347   }
   13348 
   13349   void OnEntryHook(uintptr_t function,
   13350                    uintptr_t return_addr_location);
   13351   static void EntryHook(uintptr_t function,
   13352                         uintptr_t return_addr_location) {
   13353     CHECK(instance_ != NULL);
   13354     instance_->OnEntryHook(function, return_addr_location);
   13355   }
   13356 
   13357   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13358     CHECK(instance_ != NULL);
   13359     args.GetReturnValue().Set(v8_num(42));
   13360   }
   13361   void RunLoopInNewEnv(v8::Isolate* isolate);
   13362 
   13363   // Records addr as location of symbol.
   13364   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
   13365 
   13366   // Finds the symbol containing addr
   13367   SymbolInfo* FindSymbolForAddr(i::Address addr);
   13368   // Returns the number of invocations where the caller name contains
   13369   // \p caller_name and the function name contains \p function_name.
   13370   int CountInvocations(const char* caller_name,
   13371                        const char* function_name);
   13372 
   13373   i::Handle<i::JSFunction> foo_func_;
   13374   i::Handle<i::JSFunction> bar_func_;
   13375 
   13376   typedef std::map<size_t, SymbolInfo> SymbolMap;
   13377   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
   13378   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
   13379   SymbolMap symbols_;
   13380   SymbolLocationMap symbol_locations_;
   13381   InvocationMap invocations_;
   13382 
   13383   static SetFunctionEntryHookTest* instance_;
   13384 };
   13385 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
   13386 
   13387 
   13388 // Returns true if addr is in the range [start, start+len).
   13389 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
   13390   if (start <= addr && start + len > addr)
   13391     return true;
   13392 
   13393   return false;
   13394 }
   13395 
   13396 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
   13397                                               SymbolInfo* symbol) {
   13398   // Insert the symbol at the new location.
   13399   SymbolLocationMap::iterator it =
   13400       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
   13401   // Now erase symbols to the left and right that overlap this one.
   13402   while (it != symbol_locations_.begin()) {
   13403     SymbolLocationMap::iterator left = it;
   13404     --left;
   13405     if (!Overlaps(left->first, left->second->size, addr))
   13406       break;
   13407     symbol_locations_.erase(left);
   13408   }
   13409 
   13410   // Now erase symbols to the left and right that overlap this one.
   13411   while (true) {
   13412     SymbolLocationMap::iterator right = it;
   13413     ++right;
   13414     if (right == symbol_locations_.end())
   13415         break;
   13416     if (!Overlaps(addr, symbol->size, right->first))
   13417       break;
   13418     symbol_locations_.erase(right);
   13419   }
   13420 }
   13421 
   13422 
   13423 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
   13424   switch (event->type) {
   13425     case v8::JitCodeEvent::CODE_ADDED: {
   13426         CHECK(event->code_start != NULL);
   13427         CHECK_NE(0, static_cast<int>(event->code_len));
   13428         CHECK(event->name.str != NULL);
   13429         size_t symbol_id = symbols_.size();
   13430 
   13431         // Record the new symbol.
   13432         SymbolInfo& info = symbols_[symbol_id];
   13433         info.id = symbol_id;
   13434         info.size = event->code_len;
   13435         info.name.assign(event->name.str, event->name.str + event->name.len);
   13436 
   13437         // And record it's location.
   13438         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
   13439       }
   13440       break;
   13441 
   13442     case v8::JitCodeEvent::CODE_MOVED: {
   13443         // We would like to never see code move that we haven't seen before,
   13444         // but the code creation event does not happen until the line endings
   13445         // have been calculated (this is so that we can report the line in the
   13446         // script at which the function source is found, see
   13447         // Compiler::RecordFunctionCompilation) and the line endings
   13448         // calculations can cause a GC, which can move the newly created code
   13449         // before its existence can be logged.
   13450         SymbolLocationMap::iterator it(
   13451             symbol_locations_.find(
   13452                 reinterpret_cast<i::Address>(event->code_start)));
   13453         if (it != symbol_locations_.end()) {
   13454           // Found a symbol at this location, move it.
   13455           SymbolInfo* info = it->second;
   13456           symbol_locations_.erase(it);
   13457           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
   13458                          info);
   13459         }
   13460       }
   13461     default:
   13462       break;
   13463   }
   13464 }
   13465 
   13466 void SetFunctionEntryHookTest::OnEntryHook(
   13467     uintptr_t function, uintptr_t return_addr_location) {
   13468   // Get the function's code object.
   13469   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
   13470       reinterpret_cast<i::Address>(function));
   13471   CHECK(function_code != NULL);
   13472 
   13473   // Then try and look up the caller's code object.
   13474   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
   13475 
   13476   // Count the invocation.
   13477   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
   13478   SymbolInfo* function_symbol =
   13479       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
   13480   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
   13481 
   13482   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
   13483     // Check that we have a symbol for the "bar" function at the right location.
   13484     SymbolLocationMap::iterator it(
   13485         symbol_locations_.find(function_code->instruction_start()));
   13486     CHECK(it != symbol_locations_.end());
   13487   }
   13488 
   13489   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
   13490     // Check that we have a symbol for "foo" at the right location.
   13491     SymbolLocationMap::iterator it(
   13492         symbol_locations_.find(function_code->instruction_start()));
   13493     CHECK(it != symbol_locations_.end());
   13494   }
   13495 }
   13496 
   13497 
   13498 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
   13499   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
   13500   // Do we have a direct hit on a symbol?
   13501   if (it != symbol_locations_.end()) {
   13502     if (it->first == addr)
   13503       return it->second;
   13504   }
   13505 
   13506   // If not a direct hit, it'll have to be the previous symbol.
   13507   if (it == symbol_locations_.begin())
   13508     return NULL;
   13509 
   13510   --it;
   13511   size_t offs = addr - it->first;
   13512   if (offs < it->second->size)
   13513     return it->second;
   13514 
   13515   return NULL;
   13516 }
   13517 
   13518 
   13519 int SetFunctionEntryHookTest::CountInvocations(
   13520     const char* caller_name, const char* function_name) {
   13521   InvocationMap::iterator it(invocations_.begin());
   13522   int invocations = 0;
   13523   for (; it != invocations_.end(); ++it) {
   13524     SymbolInfo* caller = it->first.first;
   13525     SymbolInfo* function = it->first.second;
   13526 
   13527     // Filter out non-matching functions.
   13528     if (function_name != NULL) {
   13529       if (function->name.find(function_name) == std::string::npos)
   13530         continue;
   13531     }
   13532 
   13533     // Filter out non-matching callers.
   13534     if (caller_name != NULL) {
   13535       if (caller == NULL)
   13536         continue;
   13537       if (caller->name.find(caller_name) == std::string::npos)
   13538         continue;
   13539     }
   13540 
   13541     // It matches add the invocation count to the tally.
   13542     invocations += it->second;
   13543   }
   13544 
   13545   return invocations;
   13546 }
   13547 
   13548 
   13549 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
   13550   v8::HandleScope outer(isolate);
   13551   v8::Local<Context> env = Context::New(isolate);
   13552   env->Enter();
   13553 
   13554   Local<ObjectTemplate> t = ObjectTemplate::New();
   13555   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(RuntimeCallback));
   13556   env->Global()->Set(v8_str("obj"), t->NewInstance());
   13557 
   13558   const char* script =
   13559       "function bar() {\n"
   13560       "  var sum = 0;\n"
   13561       "  for (i = 0; i < 100; ++i)\n"
   13562       "    sum = foo(i);\n"
   13563       "  return sum;\n"
   13564       "}\n"
   13565       "function foo(i) { return i * i; }\n"
   13566       "// Invoke on the runtime function.\n"
   13567       "obj.asdf()";
   13568   CompileRun(script);
   13569   bar_func_ = i::Handle<i::JSFunction>::cast(
   13570           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
   13571   ASSERT(!bar_func_.is_null());
   13572 
   13573   foo_func_ =
   13574       i::Handle<i::JSFunction>::cast(
   13575            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
   13576   ASSERT(!foo_func_.is_null());
   13577 
   13578   v8::Handle<v8::Value> value = CompileRun("bar();");
   13579   CHECK(value->IsNumber());
   13580   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   13581 
   13582   // Test the optimized codegen path.
   13583   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
   13584                      "bar();");
   13585   CHECK(value->IsNumber());
   13586   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   13587 
   13588   env->Exit();
   13589 }
   13590 
   13591 
   13592 void SetFunctionEntryHookTest::RunTest() {
   13593   // Work in a new isolate throughout.
   13594   v8::Isolate* isolate = v8::Isolate::New();
   13595 
   13596   // Test setting the entry hook on the new isolate.
   13597   CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
   13598 
   13599   // Replacing the hook, once set should fail.
   13600   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
   13601 
   13602   {
   13603     v8::Isolate::Scope scope(isolate);
   13604 
   13605     v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
   13606 
   13607     RunLoopInNewEnv(isolate);
   13608 
   13609     // Check the exepected invocation counts.
   13610     CHECK_EQ(2, CountInvocations(NULL, "bar"));
   13611     CHECK_EQ(200, CountInvocations("bar", "foo"));
   13612     CHECK_EQ(200, CountInvocations(NULL, "foo"));
   13613 
   13614     // Verify that we have an entry hook on some specific stubs.
   13615     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
   13616     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
   13617     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
   13618   }
   13619   isolate->Dispose();
   13620 
   13621   Reset();
   13622 
   13623   // Make sure a second isolate is unaffected by the previous entry hook.
   13624   isolate = v8::Isolate::New();
   13625   {
   13626     v8::Isolate::Scope scope(isolate);
   13627 
   13628     // Reset the entry count to zero and set the entry hook.
   13629     RunLoopInNewEnv(isolate);
   13630 
   13631     // We should record no invocations in this isolate.
   13632     CHECK_EQ(0, static_cast<int>(invocations_.size()));
   13633   }
   13634   // Since the isolate has been used, we shouldn't be able to set an entry
   13635   // hook anymore.
   13636   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
   13637 
   13638   isolate->Dispose();
   13639 }
   13640 
   13641 
   13642 TEST(SetFunctionEntryHook) {
   13643   // FunctionEntryHook does not work well with experimental natives.
   13644   // Experimental natives are compiled during snapshot deserialization.
   13645   // This test breaks because InstallGetter (function from snapshot that
   13646   // only gets called from experimental natives) is compiled with entry hooks.
   13647   i::FLAG_allow_natives_syntax = true;
   13648   i::FLAG_use_inlining = false;
   13649 
   13650   SetFunctionEntryHookTest test;
   13651   test.RunTest();
   13652 }
   13653 
   13654 
   13655 static i::HashMap* code_map = NULL;
   13656 static i::HashMap* jitcode_line_info = NULL;
   13657 static int saw_bar = 0;
   13658 static int move_events = 0;
   13659 
   13660 
   13661 static bool FunctionNameIs(const char* expected,
   13662                            const v8::JitCodeEvent* event) {
   13663   // Log lines for functions are of the general form:
   13664   // "LazyCompile:<type><function_name>", where the type is one of
   13665   // "*", "~" or "".
   13666   static const char kPreamble[] = "LazyCompile:";
   13667   static size_t kPreambleLen = sizeof(kPreamble) - 1;
   13668 
   13669   if (event->name.len < sizeof(kPreamble) - 1 ||
   13670       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   13671     return false;
   13672   }
   13673 
   13674   const char* tail = event->name.str + kPreambleLen;
   13675   size_t tail_len = event->name.len - kPreambleLen;
   13676   size_t expected_len = strlen(expected);
   13677   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   13678     --tail_len;
   13679     ++tail;
   13680   }
   13681 
   13682   // Check for tails like 'bar :1'.
   13683   if (tail_len > expected_len + 2 &&
   13684       tail[expected_len] == ' ' &&
   13685       tail[expected_len + 1] == ':' &&
   13686       tail[expected_len + 2] &&
   13687       !strncmp(tail, expected, expected_len)) {
   13688     return true;
   13689   }
   13690 
   13691   if (tail_len != expected_len)
   13692     return false;
   13693 
   13694   return strncmp(tail, expected, expected_len) == 0;
   13695 }
   13696 
   13697 
   13698 static void event_handler(const v8::JitCodeEvent* event) {
   13699   CHECK(event != NULL);
   13700   CHECK(code_map != NULL);
   13701   CHECK(jitcode_line_info != NULL);
   13702 
   13703   class DummyJitCodeLineInfo {
   13704   };
   13705 
   13706   switch (event->type) {
   13707     case v8::JitCodeEvent::CODE_ADDED: {
   13708         CHECK(event->code_start != NULL);
   13709         CHECK_NE(0, static_cast<int>(event->code_len));
   13710         CHECK(event->name.str != NULL);
   13711         i::HashMap::Entry* entry =
   13712             code_map->Lookup(event->code_start,
   13713                              i::ComputePointerHash(event->code_start),
   13714                              true);
   13715         entry->value = reinterpret_cast<void*>(event->code_len);
   13716 
   13717         if (FunctionNameIs("bar", event)) {
   13718           ++saw_bar;
   13719         }
   13720       }
   13721       break;
   13722 
   13723     case v8::JitCodeEvent::CODE_MOVED: {
   13724         uint32_t hash = i::ComputePointerHash(event->code_start);
   13725         // We would like to never see code move that we haven't seen before,
   13726         // but the code creation event does not happen until the line endings
   13727         // have been calculated (this is so that we can report the line in the
   13728         // script at which the function source is found, see
   13729         // Compiler::RecordFunctionCompilation) and the line endings
   13730         // calculations can cause a GC, which can move the newly created code
   13731         // before its existence can be logged.
   13732         i::HashMap::Entry* entry =
   13733             code_map->Lookup(event->code_start, hash, false);
   13734         if (entry != NULL) {
   13735           ++move_events;
   13736 
   13737           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   13738           code_map->Remove(event->code_start, hash);
   13739 
   13740           entry = code_map->Lookup(event->new_code_start,
   13741                                    i::ComputePointerHash(event->new_code_start),
   13742                                    true);
   13743           CHECK(entry != NULL);
   13744           entry->value = reinterpret_cast<void*>(event->code_len);
   13745         }
   13746       }
   13747       break;
   13748 
   13749     case v8::JitCodeEvent::CODE_REMOVED:
   13750       // Object/code removal events are currently not dispatched from the GC.
   13751       CHECK(false);
   13752       break;
   13753 
   13754     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   13755     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   13756     // record it in jitcode_line_info.
   13757     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   13758         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   13759         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   13760         temp_event->user_data = line_info;
   13761         i::HashMap::Entry* entry =
   13762             jitcode_line_info->Lookup(line_info,
   13763                                       i::ComputePointerHash(line_info),
   13764                                       true);
   13765         entry->value = reinterpret_cast<void*>(line_info);
   13766       }
   13767       break;
   13768     // For these two events, we will check whether the event->user_data
   13769     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   13770     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   13771     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   13772         CHECK(event->user_data != NULL);
   13773         uint32_t hash = i::ComputePointerHash(event->user_data);
   13774         i::HashMap::Entry* entry =
   13775             jitcode_line_info->Lookup(event->user_data, hash, false);
   13776         CHECK(entry != NULL);
   13777         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   13778       }
   13779       break;
   13780 
   13781     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   13782         CHECK(event->user_data != NULL);
   13783         uint32_t hash = i::ComputePointerHash(event->user_data);
   13784         i::HashMap::Entry* entry =
   13785             jitcode_line_info->Lookup(event->user_data, hash, false);
   13786         CHECK(entry != NULL);
   13787       }
   13788       break;
   13789 
   13790     default:
   13791       // Impossible event.
   13792       CHECK(false);
   13793       break;
   13794   }
   13795 }
   13796 
   13797 
   13798 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
   13799   i::FLAG_stress_compaction = true;
   13800   i::FLAG_incremental_marking = false;
   13801   const char* script =
   13802     "function bar() {"
   13803     "  var sum = 0;"
   13804     "  for (i = 0; i < 100; ++i)"
   13805     "    sum = foo(i);"
   13806     "  return sum;"
   13807     "}"
   13808     "function foo(i) { return i * i; };"
   13809     "bar();";
   13810 
   13811   // Run this test in a new isolate to make sure we don't
   13812   // have remnants of state from other code.
   13813   v8::Isolate* isolate = v8::Isolate::New();
   13814   isolate->Enter();
   13815   i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
   13816 
   13817   {
   13818     v8::HandleScope scope(isolate);
   13819     i::HashMap code(MatchPointers);
   13820     code_map = &code;
   13821 
   13822     i::HashMap lineinfo(MatchPointers);
   13823     jitcode_line_info = &lineinfo;
   13824 
   13825     saw_bar = 0;
   13826     move_events = 0;
   13827 
   13828     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   13829 
   13830     // Generate new code objects sparsely distributed across several
   13831     // different fragmented code-space pages.
   13832     const int kIterations = 10;
   13833     for (int i = 0; i < kIterations; ++i) {
   13834       LocalContext env(isolate);
   13835       i::AlwaysAllocateScope always_allocate;
   13836       SimulateFullSpace(heap->code_space());
   13837       CompileRun(script);
   13838 
   13839       // Keep a strong reference to the code object in the handle scope.
   13840       i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
   13841           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
   13842       i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
   13843           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
   13844 
   13845       // Clear the compilation cache to get more wastage.
   13846       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
   13847     }
   13848 
   13849     // Force code movement.
   13850     heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
   13851 
   13852     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   13853 
   13854     CHECK_LE(kIterations, saw_bar);
   13855     CHECK_LT(0, move_events);
   13856 
   13857     code_map = NULL;
   13858     jitcode_line_info = NULL;
   13859   }
   13860 
   13861   isolate->Exit();
   13862   isolate->Dispose();
   13863 
   13864   // Do this in a new isolate.
   13865   isolate = v8::Isolate::New();
   13866   isolate->Enter();
   13867 
   13868   // Verify that we get callbacks for existing code objects when we
   13869   // request enumeration of existing code.
   13870   {
   13871     v8::HandleScope scope(isolate);
   13872     LocalContext env(isolate);
   13873     CompileRun(script);
   13874 
   13875     // Now get code through initial iteration.
   13876     i::HashMap code(MatchPointers);
   13877     code_map = &code;
   13878 
   13879     i::HashMap lineinfo(MatchPointers);
   13880     jitcode_line_info = &lineinfo;
   13881 
   13882     V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
   13883     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   13884 
   13885     jitcode_line_info = NULL;
   13886     // We expect that we got some events. Note that if we could get code removal
   13887     // notifications, we could compare two collections, one created by listening
   13888     // from the time of creation of an isolate, and the other by subscribing
   13889     // with EnumExisting.
   13890     CHECK_LT(0, code.occupancy());
   13891 
   13892     code_map = NULL;
   13893   }
   13894 
   13895   isolate->Exit();
   13896   isolate->Dispose();
   13897 }
   13898 
   13899 
   13900 THREADED_TEST(ExternalAllocatedMemory) {
   13901   v8::Isolate* isolate = CcTest::isolate();
   13902   v8::HandleScope outer(isolate);
   13903   v8::Local<Context> env(Context::New(isolate));
   13904   CHECK(!env.IsEmpty());
   13905   const int64_t kSize = 1024*1024;
   13906   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
   13907   CHECK_EQ(baseline + kSize,
   13908            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   13909   CHECK_EQ(baseline,
   13910            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
   13911 }
   13912 
   13913 
   13914 // Regression test for issue 54, object templates with internal fields
   13915 // but no accessors or interceptors did not get their internal field
   13916 // count set on instances.
   13917 THREADED_TEST(Regress54) {
   13918   LocalContext context;
   13919   v8::Isolate* isolate = context->GetIsolate();
   13920   v8::HandleScope outer(isolate);
   13921   static v8::Persistent<v8::ObjectTemplate> templ;
   13922   if (templ.IsEmpty()) {
   13923     v8::HandleScope inner(isolate);
   13924     v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
   13925     local->SetInternalFieldCount(1);
   13926     templ.Reset(isolate, inner.Close(local));
   13927   }
   13928   v8::Handle<v8::Object> result =
   13929       v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
   13930   CHECK_EQ(1, result->InternalFieldCount());
   13931 }
   13932 
   13933 
   13934 // If part of the threaded tests, this test makes ThreadingTest fail
   13935 // on mac.
   13936 TEST(CatchStackOverflow) {
   13937   LocalContext context;
   13938   v8::HandleScope scope(context->GetIsolate());
   13939   v8::TryCatch try_catch;
   13940   v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(
   13941     context->GetIsolate(),
   13942     "function f() {"
   13943     "  return f();"
   13944     "}"
   13945     ""
   13946     "f();"));
   13947   v8::Handle<v8::Value> result = script->Run();
   13948   CHECK(result.IsEmpty());
   13949 }
   13950 
   13951 
   13952 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
   13953                                     const char* resource_name,
   13954                                     int line_offset) {
   13955   v8::HandleScope scope(CcTest::isolate());
   13956   v8::TryCatch try_catch;
   13957   v8::Handle<v8::Value> result = script->Run();
   13958   CHECK(result.IsEmpty());
   13959   CHECK(try_catch.HasCaught());
   13960   v8::Handle<v8::Message> message = try_catch.Message();
   13961   CHECK(!message.IsEmpty());
   13962   CHECK_EQ(10 + line_offset, message->GetLineNumber());
   13963   CHECK_EQ(91, message->GetStartPosition());
   13964   CHECK_EQ(92, message->GetEndPosition());
   13965   CHECK_EQ(2, message->GetStartColumn());
   13966   CHECK_EQ(3, message->GetEndColumn());
   13967   v8::String::Utf8Value line(message->GetSourceLine());
   13968   CHECK_EQ("  throw 'nirk';", *line);
   13969   v8::String::Utf8Value name(message->GetScriptResourceName());
   13970   CHECK_EQ(resource_name, *name);
   13971 }
   13972 
   13973 
   13974 THREADED_TEST(TryCatchSourceInfo) {
   13975   LocalContext context;
   13976   v8::HandleScope scope(context->GetIsolate());
   13977   v8::Handle<v8::String> source = v8::String::NewFromUtf8(
   13978       context->GetIsolate(),
   13979       "function Foo() {\n"
   13980       "  return Bar();\n"
   13981       "}\n"
   13982       "\n"
   13983       "function Bar() {\n"
   13984       "  return Baz();\n"
   13985       "}\n"
   13986       "\n"
   13987       "function Baz() {\n"
   13988       "  throw 'nirk';\n"
   13989       "}\n"
   13990       "\n"
   13991       "Foo();\n");
   13992 
   13993   const char* resource_name;
   13994   v8::Handle<v8::Script> script;
   13995   resource_name = "test.js";
   13996   script = v8::Script::Compile(
   13997       source, v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
   13998   CheckTryCatchSourceInfo(script, resource_name, 0);
   13999 
   14000   resource_name = "test1.js";
   14001   v8::ScriptOrigin origin1(
   14002       v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
   14003   script = v8::Script::Compile(source, &origin1);
   14004   CheckTryCatchSourceInfo(script, resource_name, 0);
   14005 
   14006   resource_name = "test2.js";
   14007   v8::ScriptOrigin origin2(
   14008       v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
   14009       v8::Integer::New(7));
   14010   script = v8::Script::Compile(source, &origin2);
   14011   CheckTryCatchSourceInfo(script, resource_name, 7);
   14012 }
   14013 
   14014 
   14015 THREADED_TEST(CompilationCache) {
   14016   LocalContext context;
   14017   v8::HandleScope scope(context->GetIsolate());
   14018   v8::Handle<v8::String> source0 =
   14019       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
   14020   v8::Handle<v8::String> source1 =
   14021       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
   14022   v8::Handle<v8::Script> script0 = v8::Script::Compile(
   14023       source0, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
   14024   v8::Handle<v8::Script> script1 = v8::Script::Compile(
   14025       source1, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
   14026   v8::Handle<v8::Script> script2 =
   14027       v8::Script::Compile(source0);  // different origin
   14028   CHECK_EQ(1234, script0->Run()->Int32Value());
   14029   CHECK_EQ(1234, script1->Run()->Int32Value());
   14030   CHECK_EQ(1234, script2->Run()->Int32Value());
   14031 }
   14032 
   14033 
   14034 static void FunctionNameCallback(
   14035     const v8::FunctionCallbackInfo<v8::Value>& args) {
   14036   ApiTestFuzzer::Fuzz();
   14037   args.GetReturnValue().Set(v8_num(42));
   14038 }
   14039 
   14040 
   14041 THREADED_TEST(CallbackFunctionName) {
   14042   LocalContext context;
   14043   v8::HandleScope scope(context->GetIsolate());
   14044   Local<ObjectTemplate> t = ObjectTemplate::New();
   14045   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
   14046   context->Global()->Set(v8_str("obj"), t->NewInstance());
   14047   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
   14048   CHECK(value->IsString());
   14049   v8::String::Utf8Value name(value);
   14050   CHECK_EQ("asdf", *name);
   14051 }
   14052 
   14053 
   14054 THREADED_TEST(DateAccess) {
   14055   LocalContext context;
   14056   v8::HandleScope scope(context->GetIsolate());
   14057   v8::Handle<v8::Value> date =
   14058       v8::Date::New(context->GetIsolate(), 1224744689038.0);
   14059   CHECK(date->IsDate());
   14060   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   14061 }
   14062 
   14063 
   14064 void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
   14065   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   14066   v8::Handle<v8::Array> props = obj->GetPropertyNames();
   14067   CHECK_EQ(elmc, props->Length());
   14068   for (int i = 0; i < elmc; i++) {
   14069     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
   14070     CHECK_EQ(elmv[i], *elm);
   14071   }
   14072 }
   14073 
   14074 
   14075 void CheckOwnProperties(v8::Handle<v8::Value> val,
   14076                         int elmc,
   14077                         const char* elmv[]) {
   14078   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   14079   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
   14080   CHECK_EQ(elmc, props->Length());
   14081   for (int i = 0; i < elmc; i++) {
   14082     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
   14083     CHECK_EQ(elmv[i], *elm);
   14084   }
   14085 }
   14086 
   14087 
   14088 THREADED_TEST(PropertyEnumeration) {
   14089   LocalContext context;
   14090   v8::HandleScope scope(context->GetIsolate());
   14091   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
   14092       context->GetIsolate(),
   14093       "var result = [];"
   14094       "result[0] = {};"
   14095       "result[1] = {a: 1, b: 2};"
   14096       "result[2] = [1, 2, 3];"
   14097       "var proto = {x: 1, y: 2, z: 3};"
   14098       "var x = { __proto__: proto, w: 0, z: 1 };"
   14099       "result[3] = x;"
   14100       "result;"))->Run();
   14101   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   14102   CHECK_EQ(4, elms->Length());
   14103   int elmc0 = 0;
   14104   const char** elmv0 = NULL;
   14105   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   14106   CheckOwnProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   14107   int elmc1 = 2;
   14108   const char* elmv1[] = {"a", "b"};
   14109   CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
   14110   CheckOwnProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
   14111   int elmc2 = 3;
   14112   const char* elmv2[] = {"0", "1", "2"};
   14113   CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
   14114   CheckOwnProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
   14115   int elmc3 = 4;
   14116   const char* elmv3[] = {"w", "z", "x", "y"};
   14117   CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
   14118   int elmc4 = 2;
   14119   const char* elmv4[] = {"w", "z"};
   14120   CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4);
   14121 }
   14122 
   14123 
   14124 THREADED_TEST(PropertyEnumeration2) {
   14125   LocalContext context;
   14126   v8::HandleScope scope(context->GetIsolate());
   14127   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
   14128       context->GetIsolate(),
   14129       "var result = [];"
   14130       "result[0] = {};"
   14131       "result[1] = {a: 1, b: 2};"
   14132       "result[2] = [1, 2, 3];"
   14133       "var proto = {x: 1, y: 2, z: 3};"
   14134       "var x = { __proto__: proto, w: 0, z: 1 };"
   14135       "result[3] = x;"
   14136       "result;"))->Run();
   14137   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   14138   CHECK_EQ(4, elms->Length());
   14139   int elmc0 = 0;
   14140   const char** elmv0 = NULL;
   14141   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   14142 
   14143   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
   14144   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
   14145   CHECK_EQ(0, props->Length());
   14146   for (uint32_t i = 0; i < props->Length(); i++) {
   14147     printf("p[%d]\n", i);
   14148   }
   14149 }
   14150 
   14151 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
   14152                                   Local<Value> name,
   14153                                   v8::AccessType type,
   14154                                   Local<Value> data) {
   14155   return type != v8::ACCESS_SET;
   14156 }
   14157 
   14158 
   14159 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
   14160                                     uint32_t key,
   14161                                     v8::AccessType type,
   14162                                     Local<Value> data) {
   14163   return type != v8::ACCESS_SET;
   14164 }
   14165 
   14166 
   14167 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
   14168   LocalContext context;
   14169   v8::Isolate* isolate = context->GetIsolate();
   14170   v8::HandleScope scope(isolate);
   14171   Local<ObjectTemplate> templ = ObjectTemplate::New();
   14172   templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   14173                                  IndexedSetAccessBlocker);
   14174   templ->Set(v8_str("x"), v8::True(isolate));
   14175   Local<v8::Object> instance = templ->NewInstance();
   14176   context->Global()->Set(v8_str("obj"), instance);
   14177   Local<Value> value = CompileRun("obj.x");
   14178   CHECK(value->BooleanValue());
   14179 }
   14180 
   14181 
   14182 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
   14183                                   Local<Value> name,
   14184                                   v8::AccessType type,
   14185                                   Local<Value> data) {
   14186   return false;
   14187 }
   14188 
   14189 
   14190 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
   14191                                     uint32_t key,
   14192                                     v8::AccessType type,
   14193                                     Local<Value> data) {
   14194   return false;
   14195 }
   14196 
   14197 
   14198 
   14199 THREADED_TEST(AccessChecksReenabledCorrectly) {
   14200   LocalContext context;
   14201   v8::HandleScope scope(context->GetIsolate());
   14202   Local<ObjectTemplate> templ = ObjectTemplate::New();
   14203   templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   14204                                  IndexedGetAccessBlocker);
   14205   templ->Set(v8_str("a"), v8_str("a"));
   14206   // Add more than 8 (see kMaxFastProperties) properties
   14207   // so that the constructor will force copying map.
   14208   // Cannot sprintf, gcc complains unsafety.
   14209   char buf[4];
   14210   for (char i = '0'; i <= '9' ; i++) {
   14211     buf[0] = i;
   14212     for (char j = '0'; j <= '9'; j++) {
   14213       buf[1] = j;
   14214       for (char k = '0'; k <= '9'; k++) {
   14215         buf[2] = k;
   14216         buf[3] = 0;
   14217         templ->Set(v8_str(buf), v8::Number::New(k));
   14218       }
   14219     }
   14220   }
   14221 
   14222   Local<v8::Object> instance_1 = templ->NewInstance();
   14223   context->Global()->Set(v8_str("obj_1"), instance_1);
   14224 
   14225   Local<Value> value_1 = CompileRun("obj_1.a");
   14226   CHECK(value_1->IsUndefined());
   14227 
   14228   Local<v8::Object> instance_2 = templ->NewInstance();
   14229   context->Global()->Set(v8_str("obj_2"), instance_2);
   14230 
   14231   Local<Value> value_2 = CompileRun("obj_2.a");
   14232   CHECK(value_2->IsUndefined());
   14233 }
   14234 
   14235 
   14236 // This tests that access check information remains on the global
   14237 // object template when creating contexts.
   14238 THREADED_TEST(AccessControlRepeatedContextCreation) {
   14239   v8::Isolate* isolate = CcTest::isolate();
   14240   v8::HandleScope handle_scope(isolate);
   14241   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   14242   global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   14243                                            IndexedSetAccessBlocker);
   14244   i::Handle<i::ObjectTemplateInfo> internal_template =
   14245       v8::Utils::OpenHandle(*global_template);
   14246   CHECK(!internal_template->constructor()->IsUndefined());
   14247   i::Handle<i::FunctionTemplateInfo> constructor(
   14248       i::FunctionTemplateInfo::cast(internal_template->constructor()));
   14249   CHECK(!constructor->access_check_info()->IsUndefined());
   14250   v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
   14251   CHECK(!context0.IsEmpty());
   14252   CHECK(!constructor->access_check_info()->IsUndefined());
   14253 }
   14254 
   14255 
   14256 THREADED_TEST(TurnOnAccessCheck) {
   14257   v8::Isolate* isolate = CcTest::isolate();
   14258   v8::HandleScope handle_scope(isolate);
   14259 
   14260   // Create an environment with access check to the global object disabled by
   14261   // default.
   14262   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   14263   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   14264                                            IndexedGetAccessBlocker,
   14265                                            v8::Handle<v8::Value>(),
   14266                                            false);
   14267   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
   14268   Context::Scope context_scope(context);
   14269 
   14270   // Set up a property and a number of functions.
   14271   context->Global()->Set(v8_str("a"), v8_num(1));
   14272   CompileRun("function f1() {return a;}"
   14273              "function f2() {return a;}"
   14274              "function g1() {return h();}"
   14275              "function g2() {return h();}"
   14276              "function h() {return 1;}");
   14277   Local<Function> f1 =
   14278       Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   14279   Local<Function> f2 =
   14280       Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   14281   Local<Function> g1 =
   14282       Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   14283   Local<Function> g2 =
   14284       Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   14285   Local<Function> h =
   14286       Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   14287 
   14288   // Get the global object.
   14289   v8::Handle<v8::Object> global = context->Global();
   14290 
   14291   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   14292   // uses the runtime system to retreive property a whereas f2 uses global load
   14293   // inline cache.
   14294   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   14295   for (int i = 0; i < 4; i++) {
   14296     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   14297   }
   14298 
   14299   // Same for g1 and g2.
   14300   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   14301   for (int i = 0; i < 4; i++) {
   14302     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   14303   }
   14304 
   14305   // Detach the global and turn on access check.
   14306   Local<Object> hidden_global = Local<Object>::Cast(
   14307       context->Global()->GetPrototype());
   14308   context->DetachGlobal();
   14309   hidden_global->TurnOnAccessCheck();
   14310 
   14311   // Failing access check to property get results in undefined.
   14312   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   14313   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   14314 
   14315   // Failing access check to function call results in exception.
   14316   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   14317   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   14318 
   14319   // No failing access check when just returning a constant.
   14320   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   14321 }
   14322 
   14323 
   14324 static const char* kPropertyA = "a";
   14325 static const char* kPropertyH = "h";
   14326 
   14327 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
   14328                                        Local<Value> name,
   14329                                        v8::AccessType type,
   14330                                        Local<Value> data) {
   14331   if (!name->IsString()) return false;
   14332   i::Handle<i::String> name_handle =
   14333       v8::Utils::OpenHandle(String::Cast(*name));
   14334   return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
   14335       && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
   14336 }
   14337 
   14338 
   14339 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
   14340   v8::Isolate* isolate = CcTest::isolate();
   14341   v8::HandleScope handle_scope(isolate);
   14342 
   14343   // Create an environment with access check to the global object disabled by
   14344   // default. When the registered access checker will block access to properties
   14345   // a and h.
   14346   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   14347   global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
   14348                                            IndexedGetAccessBlocker,
   14349                                            v8::Handle<v8::Value>(),
   14350                                            false);
   14351   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
   14352   Context::Scope context_scope(context);
   14353 
   14354   // Set up a property and a number of functions.
   14355   context->Global()->Set(v8_str("a"), v8_num(1));
   14356   static const char* source = "function f1() {return a;}"
   14357                               "function f2() {return a;}"
   14358                               "function g1() {return h();}"
   14359                               "function g2() {return h();}"
   14360                               "function h() {return 1;}";
   14361 
   14362   CompileRun(source);
   14363   Local<Function> f1;
   14364   Local<Function> f2;
   14365   Local<Function> g1;
   14366   Local<Function> g2;
   14367   Local<Function> h;
   14368   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   14369   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   14370   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   14371   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   14372   h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   14373 
   14374   // Get the global object.
   14375   v8::Handle<v8::Object> global = context->Global();
   14376 
   14377   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   14378   // uses the runtime system to retreive property a whereas f2 uses global load
   14379   // inline cache.
   14380   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   14381   for (int i = 0; i < 4; i++) {
   14382     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   14383   }
   14384 
   14385   // Same for g1 and g2.
   14386   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   14387   for (int i = 0; i < 4; i++) {
   14388     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   14389   }
   14390 
   14391   // Detach the global and turn on access check now blocking access to property
   14392   // a and function h.
   14393   Local<Object> hidden_global = Local<Object>::Cast(
   14394       context->Global()->GetPrototype());
   14395   context->DetachGlobal();
   14396   hidden_global->TurnOnAccessCheck();
   14397 
   14398   // Failing access check to property get results in undefined.
   14399   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   14400   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   14401 
   14402   // Failing access check to function call results in exception.
   14403   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   14404   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   14405 
   14406   // No failing access check when just returning a constant.
   14407   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   14408 
   14409   // Now compile the source again. And get the newly compiled functions, except
   14410   // for h for which access is blocked.
   14411   CompileRun(source);
   14412   f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
   14413   f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
   14414   g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
   14415   g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
   14416   CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
   14417 
   14418   // Failing access check to property get results in undefined.
   14419   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   14420   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   14421 
   14422   // Failing access check to function call results in exception.
   14423   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   14424   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   14425 }
   14426 
   14427 
   14428 // This test verifies that pre-compilation (aka preparsing) can be called
   14429 // without initializing the whole VM. Thus we cannot run this test in a
   14430 // multi-threaded setup.
   14431 TEST(PreCompile) {
   14432   // TODO(155): This test would break without the initialization of V8. This is
   14433   // a workaround for now to make this test not fail.
   14434   v8::V8::Initialize();
   14435   v8::Isolate* isolate = CcTest::isolate();
   14436   const char* script = "function foo(a) { return a+1; }";
   14437   v8::ScriptData* sd =
   14438       v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
   14439   CHECK_NE(sd->Length(), 0);
   14440   CHECK_NE(sd->Data(), NULL);
   14441   CHECK(!sd->HasError());
   14442   delete sd;
   14443 }
   14444 
   14445 
   14446 TEST(PreCompileWithError) {
   14447   v8::V8::Initialize();
   14448   v8::Isolate* isolate = CcTest::isolate();
   14449   const char* script = "function foo(a) { return 1 * * 2; }";
   14450   v8::ScriptData* sd =
   14451       v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
   14452   CHECK(sd->HasError());
   14453   delete sd;
   14454 }
   14455 
   14456 
   14457 TEST(Regress31661) {
   14458   v8::V8::Initialize();
   14459   v8::Isolate* isolate = CcTest::isolate();
   14460   const char* script = " The Definintive Guide";
   14461   v8::ScriptData* sd =
   14462       v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
   14463   CHECK(sd->HasError());
   14464   delete sd;
   14465 }
   14466 
   14467 
   14468 // Tests that ScriptData can be serialized and deserialized.
   14469 TEST(PreCompileSerialization) {
   14470   v8::V8::Initialize();
   14471   v8::Isolate* isolate = CcTest::isolate();
   14472   const char* script = "function foo(a) { return a+1; }";
   14473   v8::ScriptData* sd =
   14474       v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
   14475 
   14476   // Serialize.
   14477   int serialized_data_length = sd->Length();
   14478   char* serialized_data = i::NewArray<char>(serialized_data_length);
   14479   i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
   14480 
   14481   // Deserialize.
   14482   v8::ScriptData* deserialized_sd =
   14483       v8::ScriptData::New(serialized_data, serialized_data_length);
   14484 
   14485   // Verify that the original is the same as the deserialized.
   14486   CHECK_EQ(sd->Length(), deserialized_sd->Length());
   14487   CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
   14488   CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
   14489 
   14490   delete sd;
   14491   delete deserialized_sd;
   14492 }
   14493 
   14494 
   14495 // Attempts to deserialize bad data.
   14496 TEST(PreCompileDeserializationError) {
   14497   v8::V8::Initialize();
   14498   const char* data = "DONT CARE";
   14499   int invalid_size = 3;
   14500   v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
   14501 
   14502   CHECK_EQ(0, sd->Length());
   14503 
   14504   delete sd;
   14505 }
   14506 
   14507 
   14508 // Attempts to deserialize bad data.
   14509 TEST(PreCompileInvalidPreparseDataError) {
   14510   v8::V8::Initialize();
   14511   v8::Isolate* isolate = CcTest::isolate();
   14512   LocalContext context;
   14513   v8::HandleScope scope(context->GetIsolate());
   14514 
   14515   const char* script = "function foo(){ return 5;}\n"
   14516       "function bar(){ return 6 + 7;}  foo();";
   14517   v8::ScriptData* sd =
   14518       v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
   14519   CHECK(!sd->HasError());
   14520   // ScriptDataImpl private implementation details
   14521   const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
   14522   const int kFunctionEntrySize = i::FunctionEntry::kSize;
   14523   const int kFunctionEntryStartOffset = 0;
   14524   const int kFunctionEntryEndOffset = 1;
   14525   unsigned* sd_data =
   14526       reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   14527 
   14528   // Overwrite function bar's end position with 0.
   14529   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
   14530   v8::TryCatch try_catch;
   14531 
   14532   Local<String> source = String::NewFromUtf8(isolate, script);
   14533   Local<Script> compiled_script = Script::New(source, NULL, sd);
   14534   CHECK(try_catch.HasCaught());
   14535   String::Utf8Value exception_value(try_catch.Message()->Get());
   14536   CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
   14537            *exception_value);
   14538 
   14539   try_catch.Reset();
   14540 
   14541   // Overwrite function bar's start position with 200.  The function entry
   14542   // will not be found when searching for it by position and we should fall
   14543   // back on eager compilation.
   14544   sd = v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
   14545   sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   14546   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
   14547       200;
   14548   compiled_script = Script::New(source, NULL, sd);
   14549   CHECK(!try_catch.HasCaught());
   14550 
   14551   delete sd;
   14552 }
   14553 
   14554 
   14555 // Verifies that the Handle<String> and const char* versions of the API produce
   14556 // the same results (at least for one trivial case).
   14557 TEST(PreCompileAPIVariationsAreSame) {
   14558   v8::V8::Initialize();
   14559   v8::Isolate* isolate = CcTest::isolate();
   14560   v8::HandleScope scope(isolate);
   14561 
   14562   const char* cstring = "function foo(a) { return a+1; }";
   14563 
   14564   v8::ScriptData* sd_from_cstring =
   14565       v8::ScriptData::PreCompile(isolate, cstring, i::StrLength(cstring));
   14566 
   14567   TestAsciiResource* resource = new TestAsciiResource(cstring);
   14568   v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
   14569       v8::String::NewExternal(isolate, resource));
   14570 
   14571   v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
   14572       v8::String::NewFromUtf8(isolate, cstring));
   14573 
   14574   CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
   14575   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
   14576                      sd_from_external_string->Data(),
   14577                      sd_from_cstring->Length()));
   14578 
   14579   CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
   14580   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
   14581                      sd_from_string->Data(),
   14582                      sd_from_cstring->Length()));
   14583 
   14584 
   14585   delete sd_from_cstring;
   14586   delete sd_from_external_string;
   14587   delete sd_from_string;
   14588 }
   14589 
   14590 
   14591 // This tests that we do not allow dictionary load/call inline caches
   14592 // to use functions that have not yet been compiled.  The potential
   14593 // problem of loading a function that has not yet been compiled can
   14594 // arise because we share code between contexts via the compilation
   14595 // cache.
   14596 THREADED_TEST(DictionaryICLoadedFunction) {
   14597   v8::HandleScope scope(CcTest::isolate());
   14598   // Test LoadIC.
   14599   for (int i = 0; i < 2; i++) {
   14600     LocalContext context;
   14601     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
   14602     context->Global()->Delete(v8_str("tmp"));
   14603     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   14604   }
   14605   // Test CallIC.
   14606   for (int i = 0; i < 2; i++) {
   14607     LocalContext context;
   14608     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
   14609     context->Global()->Delete(v8_str("tmp"));
   14610     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   14611   }
   14612 }
   14613 
   14614 
   14615 // Test that cross-context new calls use the context of the callee to
   14616 // create the new JavaScript object.
   14617 THREADED_TEST(CrossContextNew) {
   14618   v8::Isolate* isolate = CcTest::isolate();
   14619   v8::HandleScope scope(isolate);
   14620   v8::Local<Context> context0 = Context::New(isolate);
   14621   v8::Local<Context> context1 = Context::New(isolate);
   14622 
   14623   // Allow cross-domain access.
   14624   Local<String> token = v8_str("<security token>");
   14625   context0->SetSecurityToken(token);
   14626   context1->SetSecurityToken(token);
   14627 
   14628   // Set an 'x' property on the Object prototype and define a
   14629   // constructor function in context0.
   14630   context0->Enter();
   14631   CompileRun("Object.prototype.x = 42; function C() {};");
   14632   context0->Exit();
   14633 
   14634   // Call the constructor function from context0 and check that the
   14635   // result has the 'x' property.
   14636   context1->Enter();
   14637   context1->Global()->Set(v8_str("other"), context0->Global());
   14638   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   14639   CHECK(value->IsInt32());
   14640   CHECK_EQ(42, value->Int32Value());
   14641   context1->Exit();
   14642 }
   14643 
   14644 
   14645 // Verify that we can clone an object
   14646 TEST(ObjectClone) {
   14647   LocalContext env;
   14648   v8::HandleScope scope(env->GetIsolate());
   14649 
   14650   const char* sample =
   14651     "var rv = {};"      \
   14652     "rv.alpha = 'hello';" \
   14653     "rv.beta = 123;"     \
   14654     "rv;";
   14655 
   14656   // Create an object, verify basics.
   14657   Local<Value> val = CompileRun(sample);
   14658   CHECK(val->IsObject());
   14659   Local<v8::Object> obj = val.As<v8::Object>();
   14660   obj->Set(v8_str("gamma"), v8_str("cloneme"));
   14661 
   14662   CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
   14663   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
   14664   CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
   14665 
   14666   // Clone it.
   14667   Local<v8::Object> clone = obj->Clone();
   14668   CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
   14669   CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
   14670   CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
   14671 
   14672   // Set a property on the clone, verify each object.
   14673   clone->Set(v8_str("beta"), v8::Integer::New(456));
   14674   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
   14675   CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
   14676 }
   14677 
   14678 
   14679 class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
   14680  public:
   14681   explicit AsciiVectorResource(i::Vector<const char> vector)
   14682       : data_(vector) {}
   14683   virtual ~AsciiVectorResource() {}
   14684   virtual size_t length() const { return data_.length(); }
   14685   virtual const char* data() const { return data_.start(); }
   14686  private:
   14687   i::Vector<const char> data_;
   14688 };
   14689 
   14690 
   14691 class UC16VectorResource : public v8::String::ExternalStringResource {
   14692  public:
   14693   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   14694       : data_(vector) {}
   14695   virtual ~UC16VectorResource() {}
   14696   virtual size_t length() const { return data_.length(); }
   14697   virtual const i::uc16* data() const { return data_.start(); }
   14698  private:
   14699   i::Vector<const i::uc16> data_;
   14700 };
   14701 
   14702 
   14703 static void MorphAString(i::String* string,
   14704                          AsciiVectorResource* ascii_resource,
   14705                          UC16VectorResource* uc16_resource) {
   14706   CHECK(i::StringShape(string).IsExternal());
   14707   if (string->IsOneByteRepresentation()) {
   14708     // Check old map is not internalized or long.
   14709     CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
   14710     // Morph external string to be TwoByte string.
   14711     string->set_map(CcTest::heap()->external_string_map());
   14712     i::ExternalTwoByteString* morphed =
   14713          i::ExternalTwoByteString::cast(string);
   14714     morphed->set_resource(uc16_resource);
   14715   } else {
   14716     // Check old map is not internalized or long.
   14717     CHECK(string->map() == CcTest::heap()->external_string_map());
   14718     // Morph external string to be ASCII string.
   14719     string->set_map(CcTest::heap()->external_ascii_string_map());
   14720     i::ExternalAsciiString* morphed =
   14721          i::ExternalAsciiString::cast(string);
   14722     morphed->set_resource(ascii_resource);
   14723   }
   14724 }
   14725 
   14726 
   14727 // Test that we can still flatten a string if the components it is built up
   14728 // from have been turned into 16 bit strings in the mean time.
   14729 THREADED_TEST(MorphCompositeStringTest) {
   14730   char utf_buffer[129];
   14731   const char* c_string = "Now is the time for all good men"
   14732                          " to come to the aid of the party";
   14733   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   14734   {
   14735     LocalContext env;
   14736     i::Factory* factory = CcTest::i_isolate()->factory();
   14737     v8::HandleScope scope(env->GetIsolate());
   14738     AsciiVectorResource ascii_resource(
   14739         i::Vector<const char>(c_string, i::StrLength(c_string)));
   14740     UC16VectorResource uc16_resource(
   14741         i::Vector<const uint16_t>(two_byte_string,
   14742                                   i::StrLength(c_string)));
   14743 
   14744     Local<String> lhs(v8::Utils::ToLocal(
   14745         factory->NewExternalStringFromAscii(&ascii_resource)));
   14746     Local<String> rhs(v8::Utils::ToLocal(
   14747         factory->NewExternalStringFromAscii(&ascii_resource)));
   14748 
   14749     env->Global()->Set(v8_str("lhs"), lhs);
   14750     env->Global()->Set(v8_str("rhs"), rhs);
   14751 
   14752     CompileRun(
   14753         "var cons = lhs + rhs;"
   14754         "var slice = lhs.substring(1, lhs.length - 1);"
   14755         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   14756 
   14757     CHECK(lhs->IsOneByte());
   14758     CHECK(rhs->IsOneByte());
   14759 
   14760     MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
   14761     MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
   14762 
   14763     // This should UTF-8 without flattening, since everything is ASCII.
   14764     Handle<String> cons = v8_compile("cons")->Run().As<String>();
   14765     CHECK_EQ(128, cons->Utf8Length());
   14766     int nchars = -1;
   14767     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
   14768     CHECK_EQ(128, nchars);
   14769     CHECK_EQ(0, strcmp(
   14770         utf_buffer,
   14771         "Now is the time for all good men to come to the aid of the party"
   14772         "Now is the time for all good men to come to the aid of the party"));
   14773 
   14774     // Now do some stuff to make sure the strings are flattened, etc.
   14775     CompileRun(
   14776         "/[^a-z]/.test(cons);"
   14777         "/[^a-z]/.test(slice);"
   14778         "/[^a-z]/.test(slice_on_cons);");
   14779     const char* expected_cons =
   14780         "Now is the time for all good men to come to the aid of the party"
   14781         "Now is the time for all good men to come to the aid of the party";
   14782     const char* expected_slice =
   14783         "ow is the time for all good men to come to the aid of the part";
   14784     const char* expected_slice_on_cons =
   14785         "ow is the time for all good men to come to the aid of the party"
   14786         "Now is the time for all good men to come to the aid of the part";
   14787     CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
   14788              env->Global()->Get(v8_str("cons")));
   14789     CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
   14790              env->Global()->Get(v8_str("slice")));
   14791     CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
   14792              env->Global()->Get(v8_str("slice_on_cons")));
   14793   }
   14794   i::DeleteArray(two_byte_string);
   14795 }
   14796 
   14797 
   14798 TEST(CompileExternalTwoByteSource) {
   14799   LocalContext context;
   14800   v8::HandleScope scope(context->GetIsolate());
   14801 
   14802   // This is a very short list of sources, which currently is to check for a
   14803   // regression caused by r2703.
   14804   const char* ascii_sources[] = {
   14805     "0.5",
   14806     "-0.5",   // This mainly testes PushBack in the Scanner.
   14807     "--0.5",  // This mainly testes PushBack in the Scanner.
   14808     NULL
   14809   };
   14810 
   14811   // Compile the sources as external two byte strings.
   14812   for (int i = 0; ascii_sources[i] != NULL; i++) {
   14813     uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
   14814     UC16VectorResource uc16_resource(
   14815         i::Vector<const uint16_t>(two_byte_string,
   14816                                   i::StrLength(ascii_sources[i])));
   14817     v8::Local<v8::String> source =
   14818         v8::String::NewExternal(context->GetIsolate(), &uc16_resource);
   14819     v8::Script::Compile(source);
   14820     i::DeleteArray(two_byte_string);
   14821   }
   14822 }
   14823 
   14824 
   14825 #ifndef V8_INTERPRETED_REGEXP
   14826 
   14827 struct RegExpInterruptionData {
   14828   int loop_count;
   14829   UC16VectorResource* string_resource;
   14830   v8::Persistent<v8::String> string;
   14831 } regexp_interruption_data;
   14832 
   14833 
   14834 class RegExpInterruptionThread : public i::Thread {
   14835  public:
   14836   explicit RegExpInterruptionThread(v8::Isolate* isolate)
   14837       : Thread("TimeoutThread"), isolate_(isolate) {}
   14838 
   14839   virtual void Run() {
   14840     for (regexp_interruption_data.loop_count = 0;
   14841          regexp_interruption_data.loop_count < 7;
   14842          regexp_interruption_data.loop_count++) {
   14843       i::OS::Sleep(50);  // Wait a bit before requesting GC.
   14844       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
   14845     }
   14846     i::OS::Sleep(50);  // Wait a bit before terminating.
   14847     v8::V8::TerminateExecution(isolate_);
   14848   }
   14849 
   14850  private:
   14851   v8::Isolate* isolate_;
   14852 };
   14853 
   14854 
   14855 void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
   14856   if (regexp_interruption_data.loop_count != 2) return;
   14857   v8::HandleScope scope(CcTest::isolate());
   14858   v8::Local<v8::String> string = v8::Local<v8::String>::New(
   14859       CcTest::isolate(), regexp_interruption_data.string);
   14860   string->MakeExternal(regexp_interruption_data.string_resource);
   14861 }
   14862 
   14863 
   14864 // Test that RegExp execution can be interrupted.  Specifically, we test
   14865 // * interrupting with GC
   14866 // * turn the subject string from one-byte internal to two-byte external string
   14867 // * force termination
   14868 TEST(RegExpInterruption) {
   14869   v8::HandleScope scope(CcTest::isolate());
   14870   LocalContext env;
   14871 
   14872   RegExpInterruptionThread timeout_thread(CcTest::isolate());
   14873 
   14874   v8::V8::AddGCPrologueCallback(RunBeforeGC);
   14875   static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
   14876   i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
   14877   v8::Local<v8::String> string = v8_str(ascii_content);
   14878 
   14879   CcTest::global()->Set(v8_str("a"), string);
   14880   regexp_interruption_data.string.Reset(CcTest::isolate(), string);
   14881   regexp_interruption_data.string_resource = new UC16VectorResource(
   14882       i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
   14883 
   14884   v8::TryCatch try_catch;
   14885   timeout_thread.Start();
   14886 
   14887   CompileRun("/((a*)*)*b/.exec(a)");
   14888   CHECK(try_catch.HasTerminated());
   14889 
   14890   timeout_thread.Join();
   14891 
   14892   delete regexp_interruption_data.string_resource;
   14893   regexp_interruption_data.string.Reset();
   14894 }
   14895 
   14896 #endif  // V8_INTERPRETED_REGEXP
   14897 
   14898 
   14899 // Test that we cannot set a property on the global object if there
   14900 // is a read-only property in the prototype chain.
   14901 TEST(ReadOnlyPropertyInGlobalProto) {
   14902   i::FLAG_es5_readonly = true;
   14903   v8::HandleScope scope(CcTest::isolate());
   14904   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   14905   LocalContext context(0, templ);
   14906   v8::Handle<v8::Object> global = context->Global();
   14907   v8::Handle<v8::Object> global_proto =
   14908       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
   14909   global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
   14910   global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
   14911   // Check without 'eval' or 'with'.
   14912   v8::Handle<v8::Value> res =
   14913       CompileRun("function f() { x = 42; return x; }; f()");
   14914   CHECK_EQ(v8::Integer::New(0), res);
   14915   // Check with 'eval'.
   14916   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   14917   CHECK_EQ(v8::Integer::New(0), res);
   14918   // Check with 'with'.
   14919   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   14920   CHECK_EQ(v8::Integer::New(0), res);
   14921 }
   14922 
   14923 static int force_set_set_count = 0;
   14924 static int force_set_get_count = 0;
   14925 bool pass_on_get = false;
   14926 
   14927 static void ForceSetGetter(v8::Local<v8::String> name,
   14928                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   14929   force_set_get_count++;
   14930   if (pass_on_get) {
   14931     return;
   14932   }
   14933   info.GetReturnValue().Set(3);
   14934 }
   14935 
   14936 static void ForceSetSetter(v8::Local<v8::String> name,
   14937                            v8::Local<v8::Value> value,
   14938                            const v8::PropertyCallbackInfo<void>& info) {
   14939   force_set_set_count++;
   14940 }
   14941 
   14942 static void ForceSetInterceptSetter(
   14943     v8::Local<v8::String> name,
   14944     v8::Local<v8::Value> value,
   14945     const v8::PropertyCallbackInfo<v8::Value>& info) {
   14946   force_set_set_count++;
   14947   info.GetReturnValue().SetUndefined();
   14948 }
   14949 
   14950 
   14951 TEST(ForceSet) {
   14952   force_set_get_count = 0;
   14953   force_set_set_count = 0;
   14954   pass_on_get = false;
   14955 
   14956   v8::HandleScope scope(CcTest::isolate());
   14957   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   14958   v8::Handle<v8::String> access_property =
   14959       v8::String::NewFromUtf8(CcTest::isolate(), "a");
   14960   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
   14961   LocalContext context(NULL, templ);
   14962   v8::Handle<v8::Object> global = context->Global();
   14963 
   14964   // Ordinary properties
   14965   v8::Handle<v8::String> simple_property =
   14966       v8::String::NewFromUtf8(CcTest::isolate(), "p");
   14967   global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
   14968   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   14969   // This should fail because the property is read-only
   14970   global->Set(simple_property, v8::Int32::New(5));
   14971   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   14972   // This should succeed even though the property is read-only
   14973   global->ForceSet(simple_property, v8::Int32::New(6));
   14974   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
   14975 
   14976   // Accessors
   14977   CHECK_EQ(0, force_set_set_count);
   14978   CHECK_EQ(0, force_set_get_count);
   14979   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   14980   // CHECK_EQ the property shouldn't override it, just call the setter
   14981   // which in this case does nothing.
   14982   global->Set(access_property, v8::Int32::New(7));
   14983   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   14984   CHECK_EQ(1, force_set_set_count);
   14985   CHECK_EQ(2, force_set_get_count);
   14986   // Forcing the property to be set should override the accessor without
   14987   // calling it
   14988   global->ForceSet(access_property, v8::Int32::New(8));
   14989   CHECK_EQ(8, global->Get(access_property)->Int32Value());
   14990   CHECK_EQ(1, force_set_set_count);
   14991   CHECK_EQ(2, force_set_get_count);
   14992 }
   14993 
   14994 
   14995 TEST(ForceSetWithInterceptor) {
   14996   force_set_get_count = 0;
   14997   force_set_set_count = 0;
   14998   pass_on_get = false;
   14999 
   15000   v8::HandleScope scope(CcTest::isolate());
   15001   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   15002   templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
   15003   LocalContext context(NULL, templ);
   15004   v8::Handle<v8::Object> global = context->Global();
   15005 
   15006   v8::Handle<v8::String> some_property =
   15007       v8::String::NewFromUtf8(CcTest::isolate(), "a");
   15008   CHECK_EQ(0, force_set_set_count);
   15009   CHECK_EQ(0, force_set_get_count);
   15010   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   15011   // Setting the property shouldn't override it, just call the setter
   15012   // which in this case does nothing.
   15013   global->Set(some_property, v8::Int32::New(7));
   15014   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   15015   CHECK_EQ(1, force_set_set_count);
   15016   CHECK_EQ(2, force_set_get_count);
   15017   // Getting the property when the interceptor returns an empty handle
   15018   // should yield undefined, since the property isn't present on the
   15019   // object itself yet.
   15020   pass_on_get = true;
   15021   CHECK(global->Get(some_property)->IsUndefined());
   15022   CHECK_EQ(1, force_set_set_count);
   15023   CHECK_EQ(3, force_set_get_count);
   15024   // Forcing the property to be set should cause the value to be
   15025   // set locally without calling the interceptor.
   15026   global->ForceSet(some_property, v8::Int32::New(8));
   15027   CHECK_EQ(8, global->Get(some_property)->Int32Value());
   15028   CHECK_EQ(1, force_set_set_count);
   15029   CHECK_EQ(4, force_set_get_count);
   15030   // Reenabling the interceptor should cause it to take precedence over
   15031   // the property
   15032   pass_on_get = false;
   15033   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   15034   CHECK_EQ(1, force_set_set_count);
   15035   CHECK_EQ(5, force_set_get_count);
   15036   // The interceptor should also work for other properties
   15037   CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(CcTest::isolate(), "b"))
   15038                   ->Int32Value());
   15039   CHECK_EQ(1, force_set_set_count);
   15040   CHECK_EQ(6, force_set_get_count);
   15041 }
   15042 
   15043 
   15044 THREADED_TEST(ForceDelete) {
   15045   v8::HandleScope scope(CcTest::isolate());
   15046   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   15047   LocalContext context(NULL, templ);
   15048   v8::Handle<v8::Object> global = context->Global();
   15049 
   15050   // Ordinary properties
   15051   v8::Handle<v8::String> simple_property =
   15052       v8::String::NewFromUtf8(CcTest::isolate(), "p");
   15053   global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
   15054   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   15055   // This should fail because the property is dont-delete.
   15056   CHECK(!global->Delete(simple_property));
   15057   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   15058   // This should succeed even though the property is dont-delete.
   15059   CHECK(global->ForceDelete(simple_property));
   15060   CHECK(global->Get(simple_property)->IsUndefined());
   15061 }
   15062 
   15063 
   15064 static int force_delete_interceptor_count = 0;
   15065 static bool pass_on_delete = false;
   15066 
   15067 
   15068 static void ForceDeleteDeleter(
   15069     v8::Local<v8::String> name,
   15070     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   15071   force_delete_interceptor_count++;
   15072   if (pass_on_delete) return;
   15073   info.GetReturnValue().Set(true);
   15074 }
   15075 
   15076 
   15077 THREADED_TEST(ForceDeleteWithInterceptor) {
   15078   force_delete_interceptor_count = 0;
   15079   pass_on_delete = false;
   15080 
   15081   v8::HandleScope scope(CcTest::isolate());
   15082   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   15083   templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
   15084   LocalContext context(NULL, templ);
   15085   v8::Handle<v8::Object> global = context->Global();
   15086 
   15087   v8::Handle<v8::String> some_property =
   15088       v8::String::NewFromUtf8(CcTest::isolate(), "a");
   15089   global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
   15090 
   15091   // Deleting a property should get intercepted and nothing should
   15092   // happen.
   15093   CHECK_EQ(0, force_delete_interceptor_count);
   15094   CHECK(global->Delete(some_property));
   15095   CHECK_EQ(1, force_delete_interceptor_count);
   15096   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   15097   // Deleting the property when the interceptor returns an empty
   15098   // handle should not delete the property since it is DontDelete.
   15099   pass_on_delete = true;
   15100   CHECK(!global->Delete(some_property));
   15101   CHECK_EQ(2, force_delete_interceptor_count);
   15102   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   15103   // Forcing the property to be deleted should delete the value
   15104   // without calling the interceptor.
   15105   CHECK(global->ForceDelete(some_property));
   15106   CHECK(global->Get(some_property)->IsUndefined());
   15107   CHECK_EQ(2, force_delete_interceptor_count);
   15108 }
   15109 
   15110 
   15111 // Make sure that forcing a delete invalidates any IC stubs, so we
   15112 // don't read the hole value.
   15113 THREADED_TEST(ForceDeleteIC) {
   15114   LocalContext context;
   15115   v8::HandleScope scope(context->GetIsolate());
   15116   // Create a DontDelete variable on the global object.
   15117   CompileRun("this.__proto__ = { foo: 'horse' };"
   15118              "var foo = 'fish';"
   15119              "function f() { return foo.length; }");
   15120   // Initialize the IC for foo in f.
   15121   CompileRun("for (var i = 0; i < 4; i++) f();");
   15122   // Make sure the value of foo is correct before the deletion.
   15123   CHECK_EQ(4, CompileRun("f()")->Int32Value());
   15124   // Force the deletion of foo.
   15125   CHECK(context->Global()->ForceDelete(v8_str("foo")));
   15126   // Make sure the value for foo is read from the prototype, and that
   15127   // we don't get in trouble with reading the deleted cell value
   15128   // sentinel.
   15129   CHECK_EQ(5, CompileRun("f()")->Int32Value());
   15130 }
   15131 
   15132 
   15133 TEST(InlinedFunctionAcrossContexts) {
   15134   i::FLAG_allow_natives_syntax = true;
   15135   v8::Isolate* isolate = CcTest::isolate();
   15136   v8::HandleScope outer_scope(isolate);
   15137   v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
   15138   v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
   15139   ctx1->Enter();
   15140 
   15141   {
   15142     v8::HandleScope inner_scope(CcTest::isolate());
   15143     CompileRun("var G = 42; function foo() { return G; }");
   15144     v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
   15145     ctx2->Enter();
   15146     ctx2->Global()->Set(v8_str("o"), foo);
   15147     v8::Local<v8::Value> res = CompileRun(
   15148         "function f() { return o(); }"
   15149         "for (var i = 0; i < 10; ++i) f();"
   15150         "%OptimizeFunctionOnNextCall(f);"
   15151         "f();");
   15152     CHECK_EQ(42, res->Int32Value());
   15153     ctx2->Exit();
   15154     v8::Handle<v8::String> G_property =
   15155         v8::String::NewFromUtf8(CcTest::isolate(), "G");
   15156     CHECK(ctx1->Global()->ForceDelete(G_property));
   15157     ctx2->Enter();
   15158     ExpectString(
   15159         "(function() {"
   15160         "  try {"
   15161         "    return f();"
   15162         "  } catch(e) {"
   15163         "    return e.toString();"
   15164         "  }"
   15165         " })()",
   15166         "ReferenceError: G is not defined");
   15167     ctx2->Exit();
   15168     ctx1->Exit();
   15169   }
   15170 }
   15171 
   15172 
   15173 static v8::Local<Context> calling_context0;
   15174 static v8::Local<Context> calling_context1;
   15175 static v8::Local<Context> calling_context2;
   15176 
   15177 
   15178 // Check that the call to the callback is initiated in
   15179 // calling_context2, the directly calling context is calling_context1
   15180 // and the callback itself is in calling_context0.
   15181 static void GetCallingContextCallback(
   15182     const v8::FunctionCallbackInfo<v8::Value>& args) {
   15183   ApiTestFuzzer::Fuzz();
   15184   CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
   15185   CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
   15186   CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
   15187   args.GetReturnValue().Set(42);
   15188 }
   15189 
   15190 
   15191 THREADED_TEST(GetCurrentContextWhenNotInContext) {
   15192   i::Isolate* isolate = CcTest::i_isolate();
   15193   CHECK(isolate != NULL);
   15194   CHECK(isolate->context() == NULL);
   15195   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   15196   v8::HandleScope scope(v8_isolate);
   15197   // The following should not crash, but return an empty handle.
   15198   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   15199   CHECK(current.IsEmpty());
   15200 }
   15201 
   15202 
   15203 THREADED_TEST(GetCallingContext) {
   15204   v8::Isolate* isolate = CcTest::isolate();
   15205   v8::HandleScope scope(isolate);
   15206 
   15207   Local<Context> calling_context0(Context::New(isolate));
   15208   Local<Context> calling_context1(Context::New(isolate));
   15209   Local<Context> calling_context2(Context::New(isolate));
   15210   ::calling_context0 = calling_context0;
   15211   ::calling_context1 = calling_context1;
   15212   ::calling_context2 = calling_context2;
   15213 
   15214   // Allow cross-domain access.
   15215   Local<String> token = v8_str("<security token>");
   15216   calling_context0->SetSecurityToken(token);
   15217   calling_context1->SetSecurityToken(token);
   15218   calling_context2->SetSecurityToken(token);
   15219 
   15220   // Create an object with a C++ callback in context0.
   15221   calling_context0->Enter();
   15222   Local<v8::FunctionTemplate> callback_templ =
   15223       v8::FunctionTemplate::New(GetCallingContextCallback);
   15224   calling_context0->Global()->Set(v8_str("callback"),
   15225                                   callback_templ->GetFunction());
   15226   calling_context0->Exit();
   15227 
   15228   // Expose context0 in context1 and set up a function that calls the
   15229   // callback function.
   15230   calling_context1->Enter();
   15231   calling_context1->Global()->Set(v8_str("context0"),
   15232                                   calling_context0->Global());
   15233   CompileRun("function f() { context0.callback() }");
   15234   calling_context1->Exit();
   15235 
   15236   // Expose context1 in context2 and call the callback function in
   15237   // context0 indirectly through f in context1.
   15238   calling_context2->Enter();
   15239   calling_context2->Global()->Set(v8_str("context1"),
   15240                                   calling_context1->Global());
   15241   CompileRun("context1.f()");
   15242   calling_context2->Exit();
   15243   ::calling_context0.Clear();
   15244   ::calling_context1.Clear();
   15245   ::calling_context2.Clear();
   15246 }
   15247 
   15248 
   15249 // Check that a variable declaration with no explicit initialization
   15250 // value does shadow an existing property in the prototype chain.
   15251 THREADED_TEST(InitGlobalVarInProtoChain) {
   15252   i::FLAG_es52_globals = true;
   15253   LocalContext context;
   15254   v8::HandleScope scope(context->GetIsolate());
   15255   // Introduce a variable in the prototype chain.
   15256   CompileRun("__proto__.x = 42");
   15257   v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
   15258   CHECK(!result->IsUndefined());
   15259   CHECK_EQ(43, result->Int32Value());
   15260 }
   15261 
   15262 
   15263 // Regression test for issue 398.
   15264 // If a function is added to an object, creating a constant function
   15265 // field, and the result is cloned, replacing the constant function on the
   15266 // original should not affect the clone.
   15267 // See http://code.google.com/p/v8/issues/detail?id=398
   15268 THREADED_TEST(ReplaceConstantFunction) {
   15269   LocalContext context;
   15270   v8::HandleScope scope(context->GetIsolate());
   15271   v8::Handle<v8::Object> obj = v8::Object::New();
   15272   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
   15273   v8::Handle<v8::String> foo_string =
   15274       v8::String::NewFromUtf8(context->GetIsolate(), "foo");
   15275   obj->Set(foo_string, func_templ->GetFunction());
   15276   v8::Handle<v8::Object> obj_clone = obj->Clone();
   15277   obj_clone->Set(foo_string,
   15278                  v8::String::NewFromUtf8(context->GetIsolate(), "Hello"));
   15279   CHECK(!obj->Get(foo_string)->IsUndefined());
   15280 }
   15281 
   15282 
   15283 static void CheckElementValue(i::Isolate* isolate,
   15284                               int expected,
   15285                               i::Handle<i::Object> obj,
   15286                               int offset) {
   15287   i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
   15288   CHECK_EQ(expected, i::Smi::cast(element)->value());
   15289 }
   15290 
   15291 
   15292 THREADED_TEST(PixelArray) {
   15293   LocalContext context;
   15294   i::Isolate* isolate = CcTest::i_isolate();
   15295   i::Factory* factory = isolate->factory();
   15296   v8::HandleScope scope(context->GetIsolate());
   15297   const int kElementCount = 260;
   15298   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   15299   i::Handle<i::ExternalPixelArray> pixels =
   15300       i::Handle<i::ExternalPixelArray>::cast(
   15301           factory->NewExternalArray(kElementCount,
   15302                                     v8::kExternalPixelArray,
   15303                                     pixel_data));
   15304   // Force GC to trigger verification.
   15305   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   15306   for (int i = 0; i < kElementCount; i++) {
   15307     pixels->set(i, i % 256);
   15308   }
   15309   // Force GC to trigger verification.
   15310   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   15311   for (int i = 0; i < kElementCount; i++) {
   15312     CHECK_EQ(i % 256, pixels->get_scalar(i));
   15313     CHECK_EQ(i % 256, pixel_data[i]);
   15314   }
   15315 
   15316   v8::Handle<v8::Object> obj = v8::Object::New();
   15317   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   15318   // Set the elements to be the pixels.
   15319   // jsobj->set_elements(*pixels);
   15320   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   15321   CheckElementValue(isolate, 1, jsobj, 1);
   15322   obj->Set(v8_str("field"), v8::Int32::New(1503));
   15323   context->Global()->Set(v8_str("pixels"), obj);
   15324   v8::Handle<v8::Value> result = CompileRun("pixels.field");
   15325   CHECK_EQ(1503, result->Int32Value());
   15326   result = CompileRun("pixels[1]");
   15327   CHECK_EQ(1, result->Int32Value());
   15328 
   15329   result = CompileRun("var sum = 0;"
   15330                       "for (var i = 0; i < 8; i++) {"
   15331                       "  sum += pixels[i] = pixels[i] = -i;"
   15332                       "}"
   15333                       "sum;");
   15334   CHECK_EQ(-28, result->Int32Value());
   15335 
   15336   result = CompileRun("var sum = 0;"
   15337                       "for (var i = 0; i < 8; i++) {"
   15338                       "  sum += pixels[i] = pixels[i] = 0;"
   15339                       "}"
   15340                       "sum;");
   15341   CHECK_EQ(0, result->Int32Value());
   15342 
   15343   result = CompileRun("var sum = 0;"
   15344                       "for (var i = 0; i < 8; i++) {"
   15345                       "  sum += pixels[i] = pixels[i] = 255;"
   15346                       "}"
   15347                       "sum;");
   15348   CHECK_EQ(8 * 255, result->Int32Value());
   15349 
   15350   result = CompileRun("var sum = 0;"
   15351                       "for (var i = 0; i < 8; i++) {"
   15352                       "  sum += pixels[i] = pixels[i] = 256 + i;"
   15353                       "}"
   15354                       "sum;");
   15355   CHECK_EQ(2076, result->Int32Value());
   15356 
   15357   result = CompileRun("var sum = 0;"
   15358                       "for (var i = 0; i < 8; i++) {"
   15359                       "  sum += pixels[i] = pixels[i] = i;"
   15360                       "}"
   15361                       "sum;");
   15362   CHECK_EQ(28, result->Int32Value());
   15363 
   15364   result = CompileRun("var sum = 0;"
   15365                       "for (var i = 0; i < 8; i++) {"
   15366                       "  sum += pixels[i];"
   15367                       "}"
   15368                       "sum;");
   15369   CHECK_EQ(28, result->Int32Value());
   15370 
   15371   i::Handle<i::Smi> value(i::Smi::FromInt(2),
   15372                           reinterpret_cast<i::Isolate*>(context->GetIsolate()));
   15373   i::Handle<i::Object> no_failure;
   15374   no_failure =
   15375       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   15376   ASSERT(!no_failure.is_null());
   15377   i::USE(no_failure);
   15378   CheckElementValue(isolate, 2, jsobj, 1);
   15379   *value.location() = i::Smi::FromInt(256);
   15380   no_failure =
   15381       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   15382   ASSERT(!no_failure.is_null());
   15383   i::USE(no_failure);
   15384   CheckElementValue(isolate, 255, jsobj, 1);
   15385   *value.location() = i::Smi::FromInt(-1);
   15386   no_failure =
   15387       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   15388   ASSERT(!no_failure.is_null());
   15389   i::USE(no_failure);
   15390   CheckElementValue(isolate, 0, jsobj, 1);
   15391 
   15392   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15393                       "  pixels[i] = (i * 65) - 109;"
   15394                       "}"
   15395                       "pixels[1] + pixels[6];");
   15396   CHECK_EQ(255, result->Int32Value());
   15397   CheckElementValue(isolate, 0, jsobj, 0);
   15398   CheckElementValue(isolate, 0, jsobj, 1);
   15399   CheckElementValue(isolate, 21, jsobj, 2);
   15400   CheckElementValue(isolate, 86, jsobj, 3);
   15401   CheckElementValue(isolate, 151, jsobj, 4);
   15402   CheckElementValue(isolate, 216, jsobj, 5);
   15403   CheckElementValue(isolate, 255, jsobj, 6);
   15404   CheckElementValue(isolate, 255, jsobj, 7);
   15405   result = CompileRun("var sum = 0;"
   15406                       "for (var i = 0; i < 8; i++) {"
   15407                       "  sum += pixels[i];"
   15408                       "}"
   15409                       "sum;");
   15410   CHECK_EQ(984, result->Int32Value());
   15411 
   15412   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15413                       "  pixels[i] = (i * 1.1);"
   15414                       "}"
   15415                       "pixels[1] + pixels[6];");
   15416   CHECK_EQ(8, result->Int32Value());
   15417   CheckElementValue(isolate, 0, jsobj, 0);
   15418   CheckElementValue(isolate, 1, jsobj, 1);
   15419   CheckElementValue(isolate, 2, jsobj, 2);
   15420   CheckElementValue(isolate, 3, jsobj, 3);
   15421   CheckElementValue(isolate, 4, jsobj, 4);
   15422   CheckElementValue(isolate, 6, jsobj, 5);
   15423   CheckElementValue(isolate, 7, jsobj, 6);
   15424   CheckElementValue(isolate, 8, jsobj, 7);
   15425 
   15426   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15427                       "  pixels[7] = undefined;"
   15428                       "}"
   15429                       "pixels[7];");
   15430   CHECK_EQ(0, result->Int32Value());
   15431   CheckElementValue(isolate, 0, jsobj, 7);
   15432 
   15433   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15434                       "  pixels[6] = '2.3';"
   15435                       "}"
   15436                       "pixels[6];");
   15437   CHECK_EQ(2, result->Int32Value());
   15438   CheckElementValue(isolate, 2, jsobj, 6);
   15439 
   15440   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15441                       "  pixels[5] = NaN;"
   15442                       "}"
   15443                       "pixels[5];");
   15444   CHECK_EQ(0, result->Int32Value());
   15445   CheckElementValue(isolate, 0, jsobj, 5);
   15446 
   15447   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15448                       "  pixels[8] = Infinity;"
   15449                       "}"
   15450                       "pixels[8];");
   15451   CHECK_EQ(255, result->Int32Value());
   15452   CheckElementValue(isolate, 255, jsobj, 8);
   15453 
   15454   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15455                       "  pixels[9] = -Infinity;"
   15456                       "}"
   15457                       "pixels[9];");
   15458   CHECK_EQ(0, result->Int32Value());
   15459   CheckElementValue(isolate, 0, jsobj, 9);
   15460 
   15461   result = CompileRun("pixels[3] = 33;"
   15462                       "delete pixels[3];"
   15463                       "pixels[3];");
   15464   CHECK_EQ(33, result->Int32Value());
   15465 
   15466   result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
   15467                       "pixels[2] = 12; pixels[3] = 13;"
   15468                       "pixels.__defineGetter__('2',"
   15469                       "function() { return 120; });"
   15470                       "pixels[2];");
   15471   CHECK_EQ(12, result->Int32Value());
   15472 
   15473   result = CompileRun("var js_array = new Array(40);"
   15474                       "js_array[0] = 77;"
   15475                       "js_array;");
   15476   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   15477 
   15478   result = CompileRun("pixels[1] = 23;"
   15479                       "pixels.__proto__ = [];"
   15480                       "js_array.__proto__ = pixels;"
   15481                       "js_array.concat(pixels);");
   15482   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   15483   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   15484 
   15485   result = CompileRun("pixels[1] = 23;");
   15486   CHECK_EQ(23, result->Int32Value());
   15487 
   15488   // Test for index greater than 255.  Regression test for:
   15489   // http://code.google.com/p/chromium/issues/detail?id=26337.
   15490   result = CompileRun("pixels[256] = 255;");
   15491   CHECK_EQ(255, result->Int32Value());
   15492   result = CompileRun("var i = 0;"
   15493                       "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
   15494                       "i");
   15495   CHECK_EQ(255, result->Int32Value());
   15496 
   15497   // Make sure that pixel array ICs recognize when a non-pixel array
   15498   // is passed to it.
   15499   result = CompileRun("function pa_load(p) {"
   15500                       "  var sum = 0;"
   15501                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   15502                       "  return sum;"
   15503                       "}"
   15504                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15505                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   15506                       "just_ints = new Object();"
   15507                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15508                       "for (var i = 0; i < 10; ++i) {"
   15509                       "  result = pa_load(just_ints);"
   15510                       "}"
   15511                       "result");
   15512   CHECK_EQ(32640, result->Int32Value());
   15513 
   15514   // Make sure that pixel array ICs recognize out-of-bound accesses.
   15515   result = CompileRun("function pa_load(p, start) {"
   15516                       "  var sum = 0;"
   15517                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   15518                       "  return sum;"
   15519                       "}"
   15520                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15521                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   15522                       "for (var i = 0; i < 10; ++i) {"
   15523                       "  result = pa_load(pixels,-10);"
   15524                       "}"
   15525                       "result");
   15526   CHECK_EQ(0, result->Int32Value());
   15527 
   15528   // Make sure that generic ICs properly handles a pixel array.
   15529   result = CompileRun("function pa_load(p) {"
   15530                       "  var sum = 0;"
   15531                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   15532                       "  return sum;"
   15533                       "}"
   15534                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15535                       "just_ints = new Object();"
   15536                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15537                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   15538                       "for (var i = 0; i < 10; ++i) {"
   15539                       "  result = pa_load(pixels);"
   15540                       "}"
   15541                       "result");
   15542   CHECK_EQ(32640, result->Int32Value());
   15543 
   15544   // Make sure that generic load ICs recognize out-of-bound accesses in
   15545   // pixel arrays.
   15546   result = CompileRun("function pa_load(p, start) {"
   15547                       "  var sum = 0;"
   15548                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   15549                       "  return sum;"
   15550                       "}"
   15551                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15552                       "just_ints = new Object();"
   15553                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15554                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
   15555                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   15556                       "for (var i = 0; i < 10; ++i) {"
   15557                       "  result = pa_load(pixels,-10);"
   15558                       "}"
   15559                       "result");
   15560   CHECK_EQ(0, result->Int32Value());
   15561 
   15562   // Make sure that generic ICs properly handles other types than pixel
   15563   // arrays (that the inlined fast pixel array test leaves the right information
   15564   // in the right registers).
   15565   result = CompileRun("function pa_load(p) {"
   15566                       "  var sum = 0;"
   15567                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   15568                       "  return sum;"
   15569                       "}"
   15570                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15571                       "just_ints = new Object();"
   15572                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15573                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   15574                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   15575                       "sparse_array = new Object();"
   15576                       "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
   15577                       "sparse_array[1000000] = 3;"
   15578                       "for (var i = 0; i < 10; ++i) {"
   15579                       "  result = pa_load(sparse_array);"
   15580                       "}"
   15581                       "result");
   15582   CHECK_EQ(32640, result->Int32Value());
   15583 
   15584   // Make sure that pixel array store ICs clamp values correctly.
   15585   result = CompileRun("function pa_store(p) {"
   15586                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   15587                       "}"
   15588                       "pa_store(pixels);"
   15589                       "var sum = 0;"
   15590                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   15591                       "sum");
   15592   CHECK_EQ(48896, result->Int32Value());
   15593 
   15594   // Make sure that pixel array stores correctly handle accesses outside
   15595   // of the pixel array..
   15596   result = CompileRun("function pa_store(p,start) {"
   15597                       "  for (var j = 0; j < 256; j++) {"
   15598                       "    p[j+start] = j * 2;"
   15599                       "  }"
   15600                       "}"
   15601                       "pa_store(pixels,0);"
   15602                       "pa_store(pixels,-128);"
   15603                       "var sum = 0;"
   15604                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   15605                       "sum");
   15606   CHECK_EQ(65280, result->Int32Value());
   15607 
   15608   // Make sure that the generic store stub correctly handle accesses outside
   15609   // of the pixel array..
   15610   result = CompileRun("function pa_store(p,start) {"
   15611                       "  for (var j = 0; j < 256; j++) {"
   15612                       "    p[j+start] = j * 2;"
   15613                       "  }"
   15614                       "}"
   15615                       "pa_store(pixels,0);"
   15616                       "just_ints = new Object();"
   15617                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15618                       "pa_store(just_ints, 0);"
   15619                       "pa_store(pixels,-128);"
   15620                       "var sum = 0;"
   15621                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   15622                       "sum");
   15623   CHECK_EQ(65280, result->Int32Value());
   15624 
   15625   // Make sure that the generic keyed store stub clamps pixel array values
   15626   // correctly.
   15627   result = CompileRun("function pa_store(p) {"
   15628                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   15629                       "}"
   15630                       "pa_store(pixels);"
   15631                       "just_ints = new Object();"
   15632                       "pa_store(just_ints);"
   15633                       "pa_store(pixels);"
   15634                       "var sum = 0;"
   15635                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   15636                       "sum");
   15637   CHECK_EQ(48896, result->Int32Value());
   15638 
   15639   // Make sure that pixel array loads are optimized by crankshaft.
   15640   result = CompileRun("function pa_load(p) {"
   15641                       "  var sum = 0;"
   15642                       "  for (var i=0; i<256; ++i) {"
   15643                       "    sum += p[i];"
   15644                       "  }"
   15645                       "  return sum; "
   15646                       "}"
   15647                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15648                       "for (var i = 0; i < 5000; ++i) {"
   15649                       "  result = pa_load(pixels);"
   15650                       "}"
   15651                       "result");
   15652   CHECK_EQ(32640, result->Int32Value());
   15653 
   15654   // Make sure that pixel array stores are optimized by crankshaft.
   15655   result = CompileRun("function pa_init(p) {"
   15656                       "for (var i = 0; i < 256; ++i) { p[i] = i; }"
   15657                       "}"
   15658                       "function pa_load(p) {"
   15659                       "  var sum = 0;"
   15660                       "  for (var i=0; i<256; ++i) {"
   15661                       "    sum += p[i];"
   15662                       "  }"
   15663                       "  return sum; "
   15664                       "}"
   15665                       "for (var i = 0; i < 5000; ++i) {"
   15666                       "  pa_init(pixels);"
   15667                       "}"
   15668                       "result = pa_load(pixels);"
   15669                       "result");
   15670   CHECK_EQ(32640, result->Int32Value());
   15671 
   15672   free(pixel_data);
   15673 }
   15674 
   15675 
   15676 THREADED_TEST(PixelArrayInfo) {
   15677   LocalContext context;
   15678   v8::HandleScope scope(context->GetIsolate());
   15679   for (int size = 0; size < 100; size += 10) {
   15680     uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
   15681     v8::Handle<v8::Object> obj = v8::Object::New();
   15682     obj->SetIndexedPropertiesToPixelData(pixel_data, size);
   15683     CHECK(obj->HasIndexedPropertiesInPixelData());
   15684     CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
   15685     CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
   15686     free(pixel_data);
   15687   }
   15688 }
   15689 
   15690 
   15691 static void NotHandledIndexedPropertyGetter(
   15692     uint32_t index,
   15693     const v8::PropertyCallbackInfo<v8::Value>& info) {
   15694   ApiTestFuzzer::Fuzz();
   15695 }
   15696 
   15697 
   15698 static void NotHandledIndexedPropertySetter(
   15699     uint32_t index,
   15700     Local<Value> value,
   15701     const v8::PropertyCallbackInfo<v8::Value>& info) {
   15702   ApiTestFuzzer::Fuzz();
   15703 }
   15704 
   15705 
   15706 THREADED_TEST(PixelArrayWithInterceptor) {
   15707   LocalContext context;
   15708   i::Factory* factory = CcTest::i_isolate()->factory();
   15709   v8::HandleScope scope(context->GetIsolate());
   15710   const int kElementCount = 260;
   15711   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   15712   i::Handle<i::ExternalPixelArray> pixels =
   15713       i::Handle<i::ExternalPixelArray>::cast(
   15714           factory->NewExternalArray(kElementCount,
   15715                                     v8::kExternalPixelArray,
   15716                                     pixel_data));
   15717   for (int i = 0; i < kElementCount; i++) {
   15718     pixels->set(i, i % 256);
   15719   }
   15720   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   15721   templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
   15722                                    NotHandledIndexedPropertySetter);
   15723   v8::Handle<v8::Object> obj = templ->NewInstance();
   15724   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   15725   context->Global()->Set(v8_str("pixels"), obj);
   15726   v8::Handle<v8::Value> result = CompileRun("pixels[1]");
   15727   CHECK_EQ(1, result->Int32Value());
   15728   result = CompileRun("var sum = 0;"
   15729                       "for (var i = 0; i < 8; i++) {"
   15730                       "  sum += pixels[i] = pixels[i] = -i;"
   15731                       "}"
   15732                       "sum;");
   15733   CHECK_EQ(-28, result->Int32Value());
   15734   result = CompileRun("pixels.hasOwnProperty('1')");
   15735   CHECK(result->BooleanValue());
   15736   free(pixel_data);
   15737 }
   15738 
   15739 
   15740 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
   15741   switch (array_type) {
   15742     case v8::kExternalByteArray:
   15743     case v8::kExternalUnsignedByteArray:
   15744     case v8::kExternalPixelArray:
   15745       return 1;
   15746       break;
   15747     case v8::kExternalShortArray:
   15748     case v8::kExternalUnsignedShortArray:
   15749       return 2;
   15750       break;
   15751     case v8::kExternalIntArray:
   15752     case v8::kExternalUnsignedIntArray:
   15753     case v8::kExternalFloatArray:
   15754       return 4;
   15755       break;
   15756     case v8::kExternalDoubleArray:
   15757       return 8;
   15758       break;
   15759     default:
   15760       UNREACHABLE();
   15761       return -1;
   15762   }
   15763   UNREACHABLE();
   15764   return -1;
   15765 }
   15766 
   15767 
   15768 template <class ExternalArrayClass, class ElementType>
   15769 static void ObjectWithExternalArrayTestHelper(
   15770     Handle<Context> context,
   15771     v8::Handle<Object> obj,
   15772     int element_count,
   15773     v8::ExternalArrayType array_type,
   15774     int64_t low, int64_t high) {
   15775   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   15776   i::Isolate* isolate = jsobj->GetIsolate();
   15777   obj->Set(v8_str("field"), v8::Int32::New(1503));
   15778   context->Global()->Set(v8_str("ext_array"), obj);
   15779   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
   15780   CHECK_EQ(1503, result->Int32Value());
   15781   result = CompileRun("ext_array[1]");
   15782   CHECK_EQ(1, result->Int32Value());
   15783 
   15784   // Check pass through of assigned smis
   15785   result = CompileRun("var sum = 0;"
   15786                       "for (var i = 0; i < 8; i++) {"
   15787                       "  sum += ext_array[i] = ext_array[i] = -i;"
   15788                       "}"
   15789                       "sum;");
   15790   CHECK_EQ(-28, result->Int32Value());
   15791 
   15792   // Check assigned smis
   15793   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15794                       "  ext_array[i] = i;"
   15795                       "}"
   15796                       "var sum = 0;"
   15797                       "for (var i = 0; i < 8; i++) {"
   15798                       "  sum += ext_array[i];"
   15799                       "}"
   15800                       "sum;");
   15801   CHECK_EQ(28, result->Int32Value());
   15802 
   15803   // Check assigned smis in reverse order
   15804   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   15805                       "  ext_array[i] = i;"
   15806                       "}"
   15807                       "var sum = 0;"
   15808                       "for (var i = 0; i < 8; i++) {"
   15809                       "  sum += ext_array[i];"
   15810                       "}"
   15811                       "sum;");
   15812   CHECK_EQ(28, result->Int32Value());
   15813 
   15814   // Check pass through of assigned HeapNumbers
   15815   result = CompileRun("var sum = 0;"
   15816                       "for (var i = 0; i < 16; i+=2) {"
   15817                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   15818                       "}"
   15819                       "sum;");
   15820   CHECK_EQ(-28, result->Int32Value());
   15821 
   15822   // Check assigned HeapNumbers
   15823   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   15824                       "  ext_array[i] = (i * 0.5);"
   15825                       "}"
   15826                       "var sum = 0;"
   15827                       "for (var i = 0; i < 16; i+=2) {"
   15828                       "  sum += ext_array[i];"
   15829                       "}"
   15830                       "sum;");
   15831   CHECK_EQ(28, result->Int32Value());
   15832 
   15833   // Check assigned HeapNumbers in reverse order
   15834   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   15835                       "  ext_array[i] = (i * 0.5);"
   15836                       "}"
   15837                       "var sum = 0;"
   15838                       "for (var i = 0; i < 16; i+=2) {"
   15839                       "  sum += ext_array[i];"
   15840                       "}"
   15841                       "sum;");
   15842   CHECK_EQ(28, result->Int32Value());
   15843 
   15844   i::ScopedVector<char> test_buf(1024);
   15845 
   15846   // Check legal boundary conditions.
   15847   // The repeated loads and stores ensure the ICs are exercised.
   15848   const char* boundary_program =
   15849       "var res = 0;"
   15850       "for (var i = 0; i < 16; i++) {"
   15851       "  ext_array[i] = %lld;"
   15852       "  if (i > 8) {"
   15853       "    res = ext_array[i];"
   15854       "  }"
   15855       "}"
   15856       "res;";
   15857   i::OS::SNPrintF(test_buf,
   15858                   boundary_program,
   15859                   low);
   15860   result = CompileRun(test_buf.start());
   15861   CHECK_EQ(low, result->IntegerValue());
   15862 
   15863   i::OS::SNPrintF(test_buf,
   15864                   boundary_program,
   15865                   high);
   15866   result = CompileRun(test_buf.start());
   15867   CHECK_EQ(high, result->IntegerValue());
   15868 
   15869   // Check misprediction of type in IC.
   15870   result = CompileRun("var tmp_array = ext_array;"
   15871                       "var sum = 0;"
   15872                       "for (var i = 0; i < 8; i++) {"
   15873                       "  tmp_array[i] = i;"
   15874                       "  sum += tmp_array[i];"
   15875                       "  if (i == 4) {"
   15876                       "    tmp_array = {};"
   15877                       "  }"
   15878                       "}"
   15879                       "sum;");
   15880   // Force GC to trigger verification.
   15881   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   15882   CHECK_EQ(28, result->Int32Value());
   15883 
   15884   // Make sure out-of-range loads do not throw.
   15885   i::OS::SNPrintF(test_buf,
   15886                   "var caught_exception = false;"
   15887                   "try {"
   15888                   "  ext_array[%d];"
   15889                   "} catch (e) {"
   15890                   "  caught_exception = true;"
   15891                   "}"
   15892                   "caught_exception;",
   15893                   element_count);
   15894   result = CompileRun(test_buf.start());
   15895   CHECK_EQ(false, result->BooleanValue());
   15896 
   15897   // Make sure out-of-range stores do not throw.
   15898   i::OS::SNPrintF(test_buf,
   15899                   "var caught_exception = false;"
   15900                   "try {"
   15901                   "  ext_array[%d] = 1;"
   15902                   "} catch (e) {"
   15903                   "  caught_exception = true;"
   15904                   "}"
   15905                   "caught_exception;",
   15906                   element_count);
   15907   result = CompileRun(test_buf.start());
   15908   CHECK_EQ(false, result->BooleanValue());
   15909 
   15910   // Check other boundary conditions, values and operations.
   15911   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15912                       "  ext_array[7] = undefined;"
   15913                       "}"
   15914                       "ext_array[7];");
   15915   CHECK_EQ(0, result->Int32Value());
   15916   if (array_type == v8::kExternalDoubleArray ||
   15917       array_type == v8::kExternalFloatArray) {
   15918     CHECK_EQ(static_cast<int>(i::OS::nan_value()),
   15919              static_cast<int>(
   15920                  jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
   15921   } else {
   15922     CheckElementValue(isolate, 0, jsobj, 7);
   15923   }
   15924 
   15925   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15926                       "  ext_array[6] = '2.3';"
   15927                       "}"
   15928                       "ext_array[6];");
   15929   CHECK_EQ(2, result->Int32Value());
   15930   CHECK_EQ(2,
   15931            static_cast<int>(
   15932                jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
   15933 
   15934   if (array_type != v8::kExternalFloatArray &&
   15935       array_type != v8::kExternalDoubleArray) {
   15936     // Though the specification doesn't state it, be explicit about
   15937     // converting NaNs and +/-Infinity to zero.
   15938     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15939                         "  ext_array[i] = 5;"
   15940                         "}"
   15941                         "for (var i = 0; i < 8; i++) {"
   15942                         "  ext_array[i] = NaN;"
   15943                         "}"
   15944                         "ext_array[5];");
   15945     CHECK_EQ(0, result->Int32Value());
   15946     CheckElementValue(isolate, 0, jsobj, 5);
   15947 
   15948     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15949                         "  ext_array[i] = 5;"
   15950                         "}"
   15951                         "for (var i = 0; i < 8; i++) {"
   15952                         "  ext_array[i] = Infinity;"
   15953                         "}"
   15954                         "ext_array[5];");
   15955     int expected_value =
   15956         (array_type == v8::kExternalPixelArray) ? 255 : 0;
   15957     CHECK_EQ(expected_value, result->Int32Value());
   15958     CheckElementValue(isolate, expected_value, jsobj, 5);
   15959 
   15960     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15961                         "  ext_array[i] = 5;"
   15962                         "}"
   15963                         "for (var i = 0; i < 8; i++) {"
   15964                         "  ext_array[i] = -Infinity;"
   15965                         "}"
   15966                         "ext_array[5];");
   15967     CHECK_EQ(0, result->Int32Value());
   15968     CheckElementValue(isolate, 0, jsobj, 5);
   15969 
   15970     // Check truncation behavior of integral arrays.
   15971     const char* unsigned_data =
   15972         "var source_data = [0.6, 10.6];"
   15973         "var expected_results = [0, 10];";
   15974     const char* signed_data =
   15975         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   15976         "var expected_results = [0, 10, 0, -10];";
   15977     const char* pixel_data =
   15978         "var source_data = [0.6, 10.6];"
   15979         "var expected_results = [1, 11];";
   15980     bool is_unsigned =
   15981         (array_type == v8::kExternalUnsignedByteArray ||
   15982          array_type == v8::kExternalUnsignedShortArray ||
   15983          array_type == v8::kExternalUnsignedIntArray);
   15984     bool is_pixel_data = array_type == v8::kExternalPixelArray;
   15985 
   15986     i::OS::SNPrintF(test_buf,
   15987                     "%s"
   15988                     "var all_passed = true;"
   15989                     "for (var i = 0; i < source_data.length; i++) {"
   15990                     "  for (var j = 0; j < 8; j++) {"
   15991                     "    ext_array[j] = source_data[i];"
   15992                     "  }"
   15993                     "  all_passed = all_passed &&"
   15994                     "               (ext_array[5] == expected_results[i]);"
   15995                     "}"
   15996                     "all_passed;",
   15997                     (is_unsigned ?
   15998                          unsigned_data :
   15999                          (is_pixel_data ? pixel_data : signed_data)));
   16000     result = CompileRun(test_buf.start());
   16001     CHECK_EQ(true, result->BooleanValue());
   16002   }
   16003 
   16004   i::Handle<ExternalArrayClass> array(
   16005       ExternalArrayClass::cast(jsobj->elements()));
   16006   for (int i = 0; i < element_count; i++) {
   16007     array->set(i, static_cast<ElementType>(i));
   16008   }
   16009 
   16010   // Test complex assignments
   16011   result = CompileRun("function ee_op_test_complex_func(sum) {"
   16012                       " for (var i = 0; i < 40; ++i) {"
   16013                       "   sum += (ext_array[i] += 1);"
   16014                       "   sum += (ext_array[i] -= 1);"
   16015                       " } "
   16016                       " return sum;"
   16017                       "}"
   16018                       "sum=0;"
   16019                       "for (var i=0;i<10000;++i) {"
   16020                       "  sum=ee_op_test_complex_func(sum);"
   16021                       "}"
   16022                       "sum;");
   16023   CHECK_EQ(16000000, result->Int32Value());
   16024 
   16025   // Test count operations
   16026   result = CompileRun("function ee_op_test_count_func(sum) {"
   16027                       " for (var i = 0; i < 40; ++i) {"
   16028                       "   sum += (++ext_array[i]);"
   16029                       "   sum += (--ext_array[i]);"
   16030                       " } "
   16031                       " return sum;"
   16032                       "}"
   16033                       "sum=0;"
   16034                       "for (var i=0;i<10000;++i) {"
   16035                       "  sum=ee_op_test_count_func(sum);"
   16036                       "}"
   16037                       "sum;");
   16038   CHECK_EQ(16000000, result->Int32Value());
   16039 
   16040   result = CompileRun("ext_array[3] = 33;"
   16041                       "delete ext_array[3];"
   16042                       "ext_array[3];");
   16043   CHECK_EQ(33, result->Int32Value());
   16044 
   16045   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
   16046                       "ext_array[2] = 12; ext_array[3] = 13;"
   16047                       "ext_array.__defineGetter__('2',"
   16048                       "function() { return 120; });"
   16049                       "ext_array[2];");
   16050   CHECK_EQ(12, result->Int32Value());
   16051 
   16052   result = CompileRun("var js_array = new Array(40);"
   16053                       "js_array[0] = 77;"
   16054                       "js_array;");
   16055   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   16056 
   16057   result = CompileRun("ext_array[1] = 23;"
   16058                       "ext_array.__proto__ = [];"
   16059                       "js_array.__proto__ = ext_array;"
   16060                       "js_array.concat(ext_array);");
   16061   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   16062   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   16063 
   16064   result = CompileRun("ext_array[1] = 23;");
   16065   CHECK_EQ(23, result->Int32Value());
   16066 }
   16067 
   16068 
   16069 template <class ExternalArrayClass, class ElementType>
   16070 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
   16071                                     int64_t low,
   16072                                     int64_t high) {
   16073   LocalContext context;
   16074   i::Isolate* isolate = CcTest::i_isolate();
   16075   i::Factory* factory = isolate->factory();
   16076   v8::HandleScope scope(context->GetIsolate());
   16077   const int kElementCount = 40;
   16078   int element_size = ExternalArrayElementSize(array_type);
   16079   ElementType* array_data =
   16080       static_cast<ElementType*>(malloc(kElementCount * element_size));
   16081   i::Handle<ExternalArrayClass> array =
   16082       i::Handle<ExternalArrayClass>::cast(
   16083           factory->NewExternalArray(kElementCount, array_type, array_data));
   16084   // Force GC to trigger verification.
   16085   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   16086   for (int i = 0; i < kElementCount; i++) {
   16087     array->set(i, static_cast<ElementType>(i));
   16088   }
   16089   // Force GC to trigger verification.
   16090   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   16091   for (int i = 0; i < kElementCount; i++) {
   16092     CHECK_EQ(static_cast<int64_t>(i),
   16093              static_cast<int64_t>(array->get_scalar(i)));
   16094     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
   16095   }
   16096 
   16097   v8::Handle<v8::Object> obj = v8::Object::New();
   16098   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   16099   // Set the elements to be the external array.
   16100   obj->SetIndexedPropertiesToExternalArrayData(array_data,
   16101                                                array_type,
   16102                                                kElementCount);
   16103   CHECK_EQ(1,
   16104            static_cast<int>(
   16105                jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
   16106 
   16107   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16108       context.local(), obj, kElementCount, array_type, low, high);
   16109 
   16110   v8::Handle<v8::Value> result;
   16111 
   16112   // Test more complex manipulations which cause eax to contain values
   16113   // that won't be completely overwritten by loads from the arrays.
   16114   // This catches bugs in the instructions used for the KeyedLoadIC
   16115   // for byte and word types.
   16116   {
   16117     const int kXSize = 300;
   16118     const int kYSize = 300;
   16119     const int kLargeElementCount = kXSize * kYSize * 4;
   16120     ElementType* large_array_data =
   16121         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
   16122     v8::Handle<v8::Object> large_obj = v8::Object::New();
   16123     // Set the elements to be the external array.
   16124     large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
   16125                                                        array_type,
   16126                                                        kLargeElementCount);
   16127     context->Global()->Set(v8_str("large_array"), large_obj);
   16128     // Initialize contents of a few rows.
   16129     for (int x = 0; x < 300; x++) {
   16130       int row = 0;
   16131       int offset = row * 300 * 4;
   16132       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   16133       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   16134       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   16135       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   16136       row = 150;
   16137       offset = row * 300 * 4;
   16138       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   16139       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   16140       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   16141       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   16142       row = 298;
   16143       offset = row * 300 * 4;
   16144       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   16145       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   16146       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   16147       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   16148     }
   16149     // The goal of the code below is to make "offset" large enough
   16150     // that the computation of the index (which goes into eax) has
   16151     // high bits set which will not be overwritten by a byte or short
   16152     // load.
   16153     result = CompileRun("var failed = false;"
   16154                         "var offset = 0;"
   16155                         "for (var i = 0; i < 300; i++) {"
   16156                         "  if (large_array[4 * i] != 127 ||"
   16157                         "      large_array[4 * i + 1] != 0 ||"
   16158                         "      large_array[4 * i + 2] != 0 ||"
   16159                         "      large_array[4 * i + 3] != 127) {"
   16160                         "    failed = true;"
   16161                         "  }"
   16162                         "}"
   16163                         "offset = 150 * 300 * 4;"
   16164                         "for (var i = 0; i < 300; i++) {"
   16165                         "  if (large_array[offset + 4 * i] != 127 ||"
   16166                         "      large_array[offset + 4 * i + 1] != 0 ||"
   16167                         "      large_array[offset + 4 * i + 2] != 0 ||"
   16168                         "      large_array[offset + 4 * i + 3] != 127) {"
   16169                         "    failed = true;"
   16170                         "  }"
   16171                         "}"
   16172                         "offset = 298 * 300 * 4;"
   16173                         "for (var i = 0; i < 300; i++) {"
   16174                         "  if (large_array[offset + 4 * i] != 127 ||"
   16175                         "      large_array[offset + 4 * i + 1] != 0 ||"
   16176                         "      large_array[offset + 4 * i + 2] != 0 ||"
   16177                         "      large_array[offset + 4 * i + 3] != 127) {"
   16178                         "    failed = true;"
   16179                         "  }"
   16180                         "}"
   16181                         "!failed;");
   16182     CHECK_EQ(true, result->BooleanValue());
   16183     free(large_array_data);
   16184   }
   16185 
   16186   // The "" property descriptor is overloaded to store information about
   16187   // the external array. Ensure that setting and accessing the "" property
   16188   // works (it should overwrite the information cached about the external
   16189   // array in the DescriptorArray) in various situations.
   16190   result = CompileRun("ext_array[''] = 23; ext_array['']");
   16191   CHECK_EQ(23, result->Int32Value());
   16192 
   16193   // Property "" set after the external array is associated with the object.
   16194   {
   16195     v8::Handle<v8::Object> obj2 = v8::Object::New();
   16196     obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
   16197     obj2->Set(v8_str(""), v8::Int32::New(1503));
   16198     // Set the elements to be the external array.
   16199     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   16200                                                   array_type,
   16201                                                   kElementCount);
   16202     context->Global()->Set(v8_str("ext_array"), obj2);
   16203     result = CompileRun("ext_array['']");
   16204     CHECK_EQ(1503, result->Int32Value());
   16205   }
   16206 
   16207   // Property "" set after the external array is associated with the object.
   16208   {
   16209     v8::Handle<v8::Object> obj2 = v8::Object::New();
   16210     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
   16211     // Set the elements to be the external array.
   16212     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   16213                                                   array_type,
   16214                                                   kElementCount);
   16215     obj2->Set(v8_str(""), v8::Int32::New(1503));
   16216     context->Global()->Set(v8_str("ext_array"), obj2);
   16217     result = CompileRun("ext_array['']");
   16218     CHECK_EQ(1503, result->Int32Value());
   16219   }
   16220 
   16221   // Should reuse the map from previous test.
   16222   {
   16223     v8::Handle<v8::Object> obj2 = v8::Object::New();
   16224     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
   16225     // Set the elements to be the external array. Should re-use the map
   16226     // from previous test.
   16227     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   16228                                                   array_type,
   16229                                                   kElementCount);
   16230     context->Global()->Set(v8_str("ext_array"), obj2);
   16231     result = CompileRun("ext_array['']");
   16232   }
   16233 
   16234   // Property "" is a constant function that shouldn't not be interfered with
   16235   // when an external array is set.
   16236   {
   16237     v8::Handle<v8::Object> obj2 = v8::Object::New();
   16238     // Start
   16239     obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
   16240 
   16241     // Add a constant function to an object.
   16242     context->Global()->Set(v8_str("ext_array"), obj2);
   16243     result = CompileRun("ext_array[''] = function() {return 1503;};"
   16244                         "ext_array['']();");
   16245 
   16246     // Add an external array transition to the same map that
   16247     // has the constant transition.
   16248     v8::Handle<v8::Object> obj3 = v8::Object::New();
   16249     obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
   16250     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   16251                                                   array_type,
   16252                                                   kElementCount);
   16253     context->Global()->Set(v8_str("ext_array"), obj3);
   16254   }
   16255 
   16256   // If a external array transition is in the map, it should get clobbered
   16257   // by a constant function.
   16258   {
   16259     // Add an external array transition.
   16260     v8::Handle<v8::Object> obj3 = v8::Object::New();
   16261     obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
   16262     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   16263                                                   array_type,
   16264                                                   kElementCount);
   16265 
   16266     // Add a constant function to the same map that just got an external array
   16267     // transition.
   16268     v8::Handle<v8::Object> obj2 = v8::Object::New();
   16269     obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
   16270     context->Global()->Set(v8_str("ext_array"), obj2);
   16271     result = CompileRun("ext_array[''] = function() {return 1503;};"
   16272                         "ext_array['']();");
   16273   }
   16274 
   16275   free(array_data);
   16276 }
   16277 
   16278 
   16279 THREADED_TEST(ExternalByteArray) {
   16280   ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
   16281       v8::kExternalByteArray,
   16282       -128,
   16283       127);
   16284 }
   16285 
   16286 
   16287 THREADED_TEST(ExternalUnsignedByteArray) {
   16288   ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
   16289       v8::kExternalUnsignedByteArray,
   16290       0,
   16291       255);
   16292 }
   16293 
   16294 
   16295 THREADED_TEST(ExternalPixelArray) {
   16296   ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
   16297       v8::kExternalPixelArray,
   16298       0,
   16299       255);
   16300 }
   16301 
   16302 
   16303 THREADED_TEST(ExternalShortArray) {
   16304   ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
   16305       v8::kExternalShortArray,
   16306       -32768,
   16307       32767);
   16308 }
   16309 
   16310 
   16311 THREADED_TEST(ExternalUnsignedShortArray) {
   16312   ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
   16313       v8::kExternalUnsignedShortArray,
   16314       0,
   16315       65535);
   16316 }
   16317 
   16318 
   16319 THREADED_TEST(ExternalIntArray) {
   16320   ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
   16321       v8::kExternalIntArray,
   16322       INT_MIN,   // -2147483648
   16323       INT_MAX);  //  2147483647
   16324 }
   16325 
   16326 
   16327 THREADED_TEST(ExternalUnsignedIntArray) {
   16328   ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
   16329       v8::kExternalUnsignedIntArray,
   16330       0,
   16331       UINT_MAX);  // 4294967295
   16332 }
   16333 
   16334 
   16335 THREADED_TEST(ExternalFloatArray) {
   16336   ExternalArrayTestHelper<i::ExternalFloatArray, float>(
   16337       v8::kExternalFloatArray,
   16338       -500,
   16339       500);
   16340 }
   16341 
   16342 
   16343 THREADED_TEST(ExternalDoubleArray) {
   16344   ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
   16345       v8::kExternalDoubleArray,
   16346       -500,
   16347       500);
   16348 }
   16349 
   16350 
   16351 THREADED_TEST(ExternalArrays) {
   16352   TestExternalByteArray();
   16353   TestExternalUnsignedByteArray();
   16354   TestExternalShortArray();
   16355   TestExternalUnsignedShortArray();
   16356   TestExternalIntArray();
   16357   TestExternalUnsignedIntArray();
   16358   TestExternalFloatArray();
   16359 }
   16360 
   16361 
   16362 void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
   16363   LocalContext context;
   16364   v8::HandleScope scope(context->GetIsolate());
   16365   for (int size = 0; size < 100; size += 10) {
   16366     int element_size = ExternalArrayElementSize(array_type);
   16367     void* external_data = malloc(size * element_size);
   16368     v8::Handle<v8::Object> obj = v8::Object::New();
   16369     obj->SetIndexedPropertiesToExternalArrayData(
   16370         external_data, array_type, size);
   16371     CHECK(obj->HasIndexedPropertiesInExternalArrayData());
   16372     CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
   16373     CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
   16374     CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
   16375     free(external_data);
   16376   }
   16377 }
   16378 
   16379 
   16380 THREADED_TEST(ExternalArrayInfo) {
   16381   ExternalArrayInfoTestHelper(v8::kExternalByteArray);
   16382   ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
   16383   ExternalArrayInfoTestHelper(v8::kExternalShortArray);
   16384   ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
   16385   ExternalArrayInfoTestHelper(v8::kExternalIntArray);
   16386   ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
   16387   ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
   16388   ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
   16389   ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
   16390 }
   16391 
   16392 
   16393 void ExternalArrayLimitTestHelper(v8::ExternalArrayType array_type, int size) {
   16394   v8::Handle<v8::Object> obj = v8::Object::New();
   16395   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   16396   last_location = last_message = NULL;
   16397   obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
   16398   CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
   16399   CHECK_NE(NULL, last_location);
   16400   CHECK_NE(NULL, last_message);
   16401 }
   16402 
   16403 
   16404 TEST(ExternalArrayLimits) {
   16405   LocalContext context;
   16406   v8::HandleScope scope(context->GetIsolate());
   16407   ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0x40000000);
   16408   ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0xffffffff);
   16409   ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0x40000000);
   16410   ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0xffffffff);
   16411   ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0x40000000);
   16412   ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0xffffffff);
   16413   ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0x40000000);
   16414   ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0xffffffff);
   16415   ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0x40000000);
   16416   ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0xffffffff);
   16417   ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0x40000000);
   16418   ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0xffffffff);
   16419   ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0x40000000);
   16420   ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0xffffffff);
   16421   ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0x40000000);
   16422   ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0xffffffff);
   16423   ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0x40000000);
   16424   ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0xffffffff);
   16425 }
   16426 
   16427 
   16428 template <typename ElementType, typename TypedArray,
   16429           class ExternalArrayClass>
   16430 void TypedArrayTestHelper(v8::ExternalArrayType array_type,
   16431                           int64_t low, int64_t high) {
   16432   const int kElementCount = 50;
   16433 
   16434   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   16435 
   16436   LocalContext env;
   16437   v8::Isolate* isolate = env->GetIsolate();
   16438   v8::HandleScope handle_scope(isolate);
   16439 
   16440   Local<v8::ArrayBuffer> ab =
   16441       v8::ArrayBuffer::New(isolate, backing_store.start(),
   16442                            (kElementCount + 2) * sizeof(ElementType));
   16443   Local<TypedArray> ta =
   16444       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   16445   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   16446   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   16447   CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
   16448   CHECK_EQ(kElementCount*sizeof(ElementType),
   16449            static_cast<int>(ta->ByteLength()));
   16450   CHECK_EQ(ab, ta->Buffer());
   16451 
   16452   ElementType* data = backing_store.start() + 2;
   16453   for (int i = 0; i < kElementCount; i++) {
   16454     data[i] = static_cast<ElementType>(i);
   16455   }
   16456 
   16457   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16458       env.local(), ta, kElementCount, array_type, low, high);
   16459 }
   16460 
   16461 
   16462 THREADED_TEST(Uint8Array) {
   16463   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUnsignedByteArray>(
   16464       v8::kExternalUnsignedByteArray, 0, 0xFF);
   16465 }
   16466 
   16467 
   16468 THREADED_TEST(Int8Array) {
   16469   TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalByteArray>(
   16470       v8::kExternalByteArray, -0x80, 0x7F);
   16471 }
   16472 
   16473 
   16474 THREADED_TEST(Uint16Array) {
   16475   TypedArrayTestHelper<uint16_t,
   16476                        v8::Uint16Array,
   16477                        i::ExternalUnsignedShortArray>(
   16478       v8::kExternalUnsignedShortArray, 0, 0xFFFF);
   16479 }
   16480 
   16481 
   16482 THREADED_TEST(Int16Array) {
   16483   TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalShortArray>(
   16484       v8::kExternalShortArray, -0x8000, 0x7FFF);
   16485 }
   16486 
   16487 
   16488 THREADED_TEST(Uint32Array) {
   16489   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUnsignedIntArray>(
   16490       v8::kExternalUnsignedIntArray, 0, UINT_MAX);
   16491 }
   16492 
   16493 
   16494 THREADED_TEST(Int32Array) {
   16495   TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalIntArray>(
   16496       v8::kExternalIntArray, INT_MIN, INT_MAX);
   16497 }
   16498 
   16499 
   16500 THREADED_TEST(Float32Array) {
   16501   TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloatArray>(
   16502       v8::kExternalFloatArray, -500, 500);
   16503 }
   16504 
   16505 
   16506 THREADED_TEST(Float64Array) {
   16507   TypedArrayTestHelper<double, v8::Float64Array, i::ExternalDoubleArray>(
   16508       v8::kExternalDoubleArray, -500, 500);
   16509 }
   16510 
   16511 
   16512 THREADED_TEST(Uint8ClampedArray) {
   16513   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, i::ExternalPixelArray>(
   16514       v8::kExternalPixelArray, 0, 0xFF);
   16515 }
   16516 
   16517 
   16518 THREADED_TEST(DataView) {
   16519   const int kSize = 50;
   16520 
   16521   i::ScopedVector<uint8_t> backing_store(kSize+2);
   16522 
   16523   LocalContext env;
   16524   v8::Isolate* isolate = env->GetIsolate();
   16525   v8::HandleScope handle_scope(isolate);
   16526 
   16527   Local<v8::ArrayBuffer> ab =
   16528       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16529   Local<v8::DataView> dv =
   16530       v8::DataView::New(ab, 2, kSize);
   16531   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16532   CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
   16533   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16534   CHECK_EQ(ab, dv->Buffer());
   16535 }
   16536 
   16537 
   16538 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
   16539   THREADED_TEST(Is##View) {                                                   \
   16540     LocalContext env;                                                         \
   16541     v8::Isolate* isolate = env->GetIsolate();                                 \
   16542     v8::HandleScope handle_scope(isolate);                                    \
   16543                                                                               \
   16544     Handle<Value> result = CompileRun(                                        \
   16545         "var ab = new ArrayBuffer(128);"                                      \
   16546         "new " #View "(ab)");                                                 \
   16547     CHECK(result->IsArrayBufferView());                                       \
   16548     CHECK(result->Is##View());                                                \
   16549     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
   16550   }
   16551 
   16552 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   16553 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   16554 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   16555 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   16556 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   16557 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   16558 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   16559 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   16560 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   16561 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   16562 
   16563 #undef IS_ARRAY_BUFFER_VIEW_TEST
   16564 
   16565 
   16566 
   16567 THREADED_TEST(ScriptContextDependence) {
   16568   LocalContext c1;
   16569   v8::HandleScope scope(c1->GetIsolate());
   16570   const char *source = "foo";
   16571   v8::Handle<v8::Script> dep =
   16572       v8::Script::Compile(v8::String::NewFromUtf8(c1->GetIsolate(), source));
   16573   v8::Handle<v8::Script> indep =
   16574       v8::Script::New(v8::String::NewFromUtf8(c1->GetIsolate(), source));
   16575   c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
   16576                     v8::Integer::New(100));
   16577   CHECK_EQ(dep->Run()->Int32Value(), 100);
   16578   CHECK_EQ(indep->Run()->Int32Value(), 100);
   16579   LocalContext c2;
   16580   c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
   16581                     v8::Integer::New(101));
   16582   CHECK_EQ(dep->Run()->Int32Value(), 100);
   16583   CHECK_EQ(indep->Run()->Int32Value(), 101);
   16584 }
   16585 
   16586 
   16587 THREADED_TEST(StackTrace) {
   16588   LocalContext context;
   16589   v8::HandleScope scope(context->GetIsolate());
   16590   v8::TryCatch try_catch;
   16591   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   16592   v8::Handle<v8::String> src =
   16593       v8::String::NewFromUtf8(context->GetIsolate(), source);
   16594   v8::Handle<v8::String> origin =
   16595       v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
   16596   v8::Script::New(src, origin)->Run();
   16597   CHECK(try_catch.HasCaught());
   16598   v8::String::Utf8Value stack(try_catch.StackTrace());
   16599   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
   16600 }
   16601 
   16602 
   16603 // Checks that a StackFrame has certain expected values.
   16604 void checkStackFrame(const char* expected_script_name,
   16605     const char* expected_func_name, int expected_line_number,
   16606     int expected_column, bool is_eval, bool is_constructor,
   16607     v8::Handle<v8::StackFrame> frame) {
   16608   v8::HandleScope scope(CcTest::isolate());
   16609   v8::String::Utf8Value func_name(frame->GetFunctionName());
   16610   v8::String::Utf8Value script_name(frame->GetScriptName());
   16611   if (*script_name == NULL) {
   16612     // The situation where there is no associated script, like for evals.
   16613     CHECK(expected_script_name == NULL);
   16614   } else {
   16615     CHECK(strstr(*script_name, expected_script_name) != NULL);
   16616   }
   16617   CHECK(strstr(*func_name, expected_func_name) != NULL);
   16618   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   16619   CHECK_EQ(expected_column, frame->GetColumn());
   16620   CHECK_EQ(is_eval, frame->IsEval());
   16621   CHECK_EQ(is_constructor, frame->IsConstructor());
   16622 }
   16623 
   16624 
   16625 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   16626   v8::HandleScope scope(args.GetIsolate());
   16627   const char* origin = "capture-stack-trace-test";
   16628   const int kOverviewTest = 1;
   16629   const int kDetailedTest = 2;
   16630 
   16631   ASSERT(args.Length() == 1);
   16632 
   16633   int testGroup = args[0]->Int32Value();
   16634   if (testGroup == kOverviewTest) {
   16635     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16636         args.GetIsolate(), 10, v8::StackTrace::kOverview);
   16637     CHECK_EQ(4, stackTrace->GetFrameCount());
   16638     checkStackFrame(origin, "bar", 2, 10, false, false,
   16639                     stackTrace->GetFrame(0));
   16640     checkStackFrame(origin, "foo", 6, 3, false, false,
   16641                     stackTrace->GetFrame(1));
   16642     // This is the source string inside the eval which has the call to foo.
   16643     checkStackFrame(NULL, "", 1, 5, false, false,
   16644                     stackTrace->GetFrame(2));
   16645     // The last frame is an anonymous function which has the initial eval call.
   16646     checkStackFrame(origin, "", 8, 7, false, false,
   16647                     stackTrace->GetFrame(3));
   16648 
   16649     CHECK(stackTrace->AsArray()->IsArray());
   16650   } else if (testGroup == kDetailedTest) {
   16651     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16652         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   16653     CHECK_EQ(4, stackTrace->GetFrameCount());
   16654     checkStackFrame(origin, "bat", 4, 22, false, false,
   16655                     stackTrace->GetFrame(0));
   16656     checkStackFrame(origin, "baz", 8, 3, false, true,
   16657                     stackTrace->GetFrame(1));
   16658 #ifdef ENABLE_DEBUGGER_SUPPORT
   16659     bool is_eval = true;
   16660 #else  // ENABLE_DEBUGGER_SUPPORT
   16661     bool is_eval = false;
   16662 #endif  // ENABLE_DEBUGGER_SUPPORT
   16663 
   16664     // This is the source string inside the eval which has the call to baz.
   16665     checkStackFrame(NULL, "", 1, 5, is_eval, false,
   16666                     stackTrace->GetFrame(2));
   16667     // The last frame is an anonymous function which has the initial eval call.
   16668     checkStackFrame(origin, "", 10, 1, false, false,
   16669                     stackTrace->GetFrame(3));
   16670 
   16671     CHECK(stackTrace->AsArray()->IsArray());
   16672   }
   16673 }
   16674 
   16675 
   16676 // Tests the C++ StackTrace API.
   16677 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   16678 // THREADED_TEST(CaptureStackTrace) {
   16679 TEST(CaptureStackTrace) {
   16680   v8::HandleScope scope(CcTest::isolate());
   16681   v8::Handle<v8::String> origin =
   16682       v8::String::NewFromUtf8(CcTest::isolate(), "capture-stack-trace-test");
   16683   Local<ObjectTemplate> templ = ObjectTemplate::New();
   16684   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   16685              v8::FunctionTemplate::New(AnalyzeStackInNativeCode));
   16686   LocalContext context(0, templ);
   16687 
   16688   // Test getting OVERVIEW information. Should ignore information that is not
   16689   // script name, function name, line number, and column offset.
   16690   const char *overview_source =
   16691     "function bar() {\n"
   16692     "  var y; AnalyzeStackInNativeCode(1);\n"
   16693     "}\n"
   16694     "function foo() {\n"
   16695     "\n"
   16696     "  bar();\n"
   16697     "}\n"
   16698     "var x;eval('new foo();');";
   16699   v8::Handle<v8::String> overview_src =
   16700       v8::String::NewFromUtf8(CcTest::isolate(), overview_source);
   16701   v8::Handle<Value> overview_result(
   16702       v8::Script::New(overview_src, origin)->Run());
   16703   CHECK(!overview_result.IsEmpty());
   16704   CHECK(overview_result->IsObject());
   16705 
   16706   // Test getting DETAILED information.
   16707   const char *detailed_source =
   16708     "function bat() {AnalyzeStackInNativeCode(2);\n"
   16709     "}\n"
   16710     "\n"
   16711     "function baz() {\n"
   16712     "  bat();\n"
   16713     "}\n"
   16714     "eval('new baz();');";
   16715   v8::Handle<v8::String> detailed_src =
   16716       v8::String::NewFromUtf8(CcTest::isolate(), detailed_source);
   16717   // Make the script using a non-zero line and column offset.
   16718   v8::Handle<v8::Integer> line_offset = v8::Integer::New(3);
   16719   v8::Handle<v8::Integer> column_offset = v8::Integer::New(5);
   16720   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   16721   v8::Handle<v8::Script> detailed_script(
   16722       v8::Script::New(detailed_src, &detailed_origin));
   16723   v8::Handle<Value> detailed_result(detailed_script->Run());
   16724   CHECK(!detailed_result.IsEmpty());
   16725   CHECK(detailed_result->IsObject());
   16726 }
   16727 
   16728 
   16729 static void StackTraceForUncaughtExceptionListener(
   16730     v8::Handle<v8::Message> message,
   16731     v8::Handle<Value>) {
   16732   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16733   CHECK_EQ(2, stack_trace->GetFrameCount());
   16734   checkStackFrame("origin", "foo", 2, 3, false, false,
   16735                   stack_trace->GetFrame(0));
   16736   checkStackFrame("origin", "bar", 5, 3, false, false,
   16737                   stack_trace->GetFrame(1));
   16738 }
   16739 
   16740 
   16741 TEST(CaptureStackTraceForUncaughtException) {
   16742   report_count = 0;
   16743   LocalContext env;
   16744   v8::HandleScope scope(env->GetIsolate());
   16745   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
   16746   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16747 
   16748   Script::Compile(v8_str("function foo() {\n"
   16749                          "  throw 1;\n"
   16750                          "};\n"
   16751                          "function bar() {\n"
   16752                          "  foo();\n"
   16753                          "};"),
   16754                   v8_str("origin"))->Run();
   16755   v8::Local<v8::Object> global = env->Global();
   16756   Local<Value> trouble = global->Get(v8_str("bar"));
   16757   CHECK(trouble->IsFunction());
   16758   Function::Cast(*trouble)->Call(global, 0, NULL);
   16759   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16760   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   16761 }
   16762 
   16763 
   16764 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   16765   LocalContext env;
   16766   v8::HandleScope scope(env->GetIsolate());
   16767   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
   16768                                                     1024,
   16769                                                     v8::StackTrace::kDetailed);
   16770 
   16771   CompileRun(
   16772       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   16773       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   16774       "    'isConstructor'];\n"
   16775       "for (var i = 0; i < setters.length; i++) {\n"
   16776       "  var prop = setters[i];\n"
   16777       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   16778       "}\n");
   16779   CompileRun("throw 'exception';");
   16780   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16781 }
   16782 
   16783 
   16784 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
   16785                                      v8::Handle<v8::Value> data) {
   16786   // Use the frame where JavaScript is called from.
   16787   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16788   CHECK(!stack_trace.IsEmpty());
   16789   int frame_count = stack_trace->GetFrameCount();
   16790   CHECK_EQ(3, frame_count);
   16791   int line_number[] = {1, 2, 5};
   16792   for (int i = 0; i < frame_count; i++) {
   16793     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   16794   }
   16795 }
   16796 
   16797 
   16798 // Test that we only return the stack trace at the site where the exception
   16799 // is first thrown (not where it is rethrown).
   16800 TEST(RethrowStackTrace) {
   16801   LocalContext env;
   16802   v8::HandleScope scope(env->GetIsolate());
   16803   // We make sure that
   16804   // - the stack trace of the ReferenceError in g() is reported.
   16805   // - the stack trace is not overwritten when e1 is rethrown by t().
   16806   // - the stack trace of e2 does not overwrite that of e1.
   16807   const char* source =
   16808       "function g() { error; }          \n"
   16809       "function f() { g(); }            \n"
   16810       "function t(e) { throw e; }       \n"
   16811       "try {                            \n"
   16812       "  f();                           \n"
   16813       "} catch (e1) {                   \n"
   16814       "  try {                          \n"
   16815       "    error;                       \n"
   16816       "  } catch (e2) {                 \n"
   16817       "    t(e1);                       \n"
   16818       "  }                              \n"
   16819       "}                                \n";
   16820   v8::V8::AddMessageListener(RethrowStackTraceHandler);
   16821   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16822   CompileRun(source);
   16823   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16824   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
   16825 }
   16826 
   16827 
   16828 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
   16829                                               v8::Handle<v8::Value> data) {
   16830   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16831   CHECK(!stack_trace.IsEmpty());
   16832   int frame_count = stack_trace->GetFrameCount();
   16833   CHECK_EQ(2, frame_count);
   16834   int line_number[] = {3, 7};
   16835   for (int i = 0; i < frame_count; i++) {
   16836     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   16837   }
   16838 }
   16839 
   16840 
   16841 // Test that we do not recognize identity for primitive exceptions.
   16842 TEST(RethrowPrimitiveStackTrace) {
   16843   LocalContext env;
   16844   v8::HandleScope scope(env->GetIsolate());
   16845   // We do not capture stack trace for non Error objects on creation time.
   16846   // Instead, we capture the stack trace on last throw.
   16847   const char* source =
   16848       "function g() { throw 404; }      \n"
   16849       "function f() { g(); }            \n"
   16850       "function t(e) { throw e; }       \n"
   16851       "try {                            \n"
   16852       "  f();                           \n"
   16853       "} catch (e1) {                   \n"
   16854       "  t(e1)                          \n"
   16855       "}                                \n";
   16856   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
   16857   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16858   CompileRun(source);
   16859   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16860   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   16861 }
   16862 
   16863 
   16864 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
   16865                                               v8::Handle<v8::Value> data) {
   16866   // Use the frame where JavaScript is called from.
   16867   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16868   CHECK(!stack_trace.IsEmpty());
   16869   CHECK_EQ(1, stack_trace->GetFrameCount());
   16870   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
   16871 }
   16872 
   16873 
   16874 // Test that the stack trace is captured when the error object is created and
   16875 // not where it is thrown.
   16876 TEST(RethrowExistingStackTrace) {
   16877   LocalContext env;
   16878   v8::HandleScope scope(env->GetIsolate());
   16879   const char* source =
   16880       "var e = new Error();           \n"
   16881       "throw e;                       \n";
   16882   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
   16883   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16884   CompileRun(source);
   16885   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16886   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
   16887 }
   16888 
   16889 
   16890 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
   16891                                                v8::Handle<v8::Value> data) {
   16892   // Use the frame where JavaScript is called from.
   16893   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16894   CHECK(!stack_trace.IsEmpty());
   16895   CHECK_EQ(1, stack_trace->GetFrameCount());
   16896   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
   16897 }
   16898 
   16899 
   16900 // Test that the stack trace is captured where the bogus Error object is thrown.
   16901 TEST(RethrowBogusErrorStackTrace) {
   16902   LocalContext env;
   16903   v8::HandleScope scope(env->GetIsolate());
   16904   const char* source =
   16905       "var e = {__proto__: new Error()} \n"
   16906       "throw e;                         \n";
   16907   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
   16908   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16909   CompileRun(source);
   16910   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16911   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   16912 }
   16913 
   16914 
   16915 void AnalyzeStackOfEvalWithSourceURL(
   16916     const v8::FunctionCallbackInfo<v8::Value>& args) {
   16917   v8::HandleScope scope(args.GetIsolate());
   16918   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16919       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   16920   CHECK_EQ(5, stackTrace->GetFrameCount());
   16921   v8::Handle<v8::String> url = v8_str("eval_url");
   16922   for (int i = 0; i < 3; i++) {
   16923     v8::Handle<v8::String> name =
   16924         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   16925     CHECK(!name.IsEmpty());
   16926     CHECK_EQ(url, name);
   16927   }
   16928 }
   16929 
   16930 
   16931 TEST(SourceURLInStackTrace) {
   16932   v8::HandleScope scope(CcTest::isolate());
   16933   Local<ObjectTemplate> templ = ObjectTemplate::New();
   16934   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   16935              v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
   16936   LocalContext context(0, templ);
   16937 
   16938   const char *source =
   16939     "function outer() {\n"
   16940     "function bar() {\n"
   16941     "  AnalyzeStackOfEvalWithSourceURL();\n"
   16942     "}\n"
   16943     "function foo() {\n"
   16944     "\n"
   16945     "  bar();\n"
   16946     "}\n"
   16947     "foo();\n"
   16948     "}\n"
   16949     "eval('(' + outer +')()%s');";
   16950 
   16951   i::ScopedVector<char> code(1024);
   16952   i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
   16953   CHECK(CompileRun(code.start())->IsUndefined());
   16954   i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
   16955   CHECK(CompileRun(code.start())->IsUndefined());
   16956 }
   16957 
   16958 
   16959 static int scriptIdInStack[2];
   16960 
   16961 void AnalyzeScriptIdInStack(
   16962     const v8::FunctionCallbackInfo<v8::Value>& args) {
   16963   v8::HandleScope scope(args.GetIsolate());
   16964   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16965       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
   16966   CHECK_EQ(2, stackTrace->GetFrameCount());
   16967   for (int i = 0; i < 2; i++) {
   16968     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
   16969   }
   16970 }
   16971 
   16972 
   16973 TEST(ScriptIdInStackTrace) {
   16974   v8::HandleScope scope(CcTest::isolate());
   16975   Local<ObjectTemplate> templ = ObjectTemplate::New();
   16976   templ->Set(v8_str("AnalyzeScriptIdInStack"),
   16977              v8::FunctionTemplate::New(AnalyzeScriptIdInStack));
   16978   LocalContext context(0, templ);
   16979 
   16980   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
   16981     CcTest::isolate(),
   16982     "function foo() {\n"
   16983     "  AnalyzeScriptIdInStack();"
   16984     "}\n"
   16985     "foo();\n");
   16986   v8::ScriptOrigin origin =
   16987       v8::ScriptOrigin(v8::String::NewFromUtf8(CcTest::isolate(), "test"));
   16988   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
   16989   script->Run();
   16990   for (int i = 0; i < 2; i++) {
   16991     CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
   16992     CHECK_EQ(scriptIdInStack[i], script->GetId());
   16993   }
   16994 }
   16995 
   16996 
   16997 void AnalyzeStackOfInlineScriptWithSourceURL(
   16998     const v8::FunctionCallbackInfo<v8::Value>& args) {
   16999   v8::HandleScope scope(args.GetIsolate());
   17000   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17001       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17002   CHECK_EQ(4, stackTrace->GetFrameCount());
   17003   v8::Handle<v8::String> url = v8_str("url");
   17004   for (int i = 0; i < 3; i++) {
   17005     v8::Handle<v8::String> name =
   17006         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17007     CHECK(!name.IsEmpty());
   17008     CHECK_EQ(url, name);
   17009   }
   17010 }
   17011 
   17012 
   17013 TEST(InlineScriptWithSourceURLInStackTrace) {
   17014   v8::HandleScope scope(CcTest::isolate());
   17015   Local<ObjectTemplate> templ = ObjectTemplate::New();
   17016   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   17017              v8::FunctionTemplate::New(
   17018                  AnalyzeStackOfInlineScriptWithSourceURL));
   17019   LocalContext context(0, templ);
   17020 
   17021   const char *source =
   17022     "function outer() {\n"
   17023     "function bar() {\n"
   17024     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   17025     "}\n"
   17026     "function foo() {\n"
   17027     "\n"
   17028     "  bar();\n"
   17029     "}\n"
   17030     "foo();\n"
   17031     "}\n"
   17032     "outer()\n%s";
   17033 
   17034   i::ScopedVector<char> code(1024);
   17035   i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
   17036   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17037   i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
   17038   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17039 }
   17040 
   17041 
   17042 void AnalyzeStackOfDynamicScriptWithSourceURL(
   17043     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17044   v8::HandleScope scope(args.GetIsolate());
   17045   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17046       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17047   CHECK_EQ(4, stackTrace->GetFrameCount());
   17048   v8::Handle<v8::String> url = v8_str("source_url");
   17049   for (int i = 0; i < 3; i++) {
   17050     v8::Handle<v8::String> name =
   17051         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17052     CHECK(!name.IsEmpty());
   17053     CHECK_EQ(url, name);
   17054   }
   17055 }
   17056 
   17057 
   17058 TEST(DynamicWithSourceURLInStackTrace) {
   17059   v8::HandleScope scope(CcTest::isolate());
   17060   Local<ObjectTemplate> templ = ObjectTemplate::New();
   17061   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   17062              v8::FunctionTemplate::New(
   17063                  AnalyzeStackOfDynamicScriptWithSourceURL));
   17064   LocalContext context(0, templ);
   17065 
   17066   const char *source =
   17067     "function outer() {\n"
   17068     "function bar() {\n"
   17069     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   17070     "}\n"
   17071     "function foo() {\n"
   17072     "\n"
   17073     "  bar();\n"
   17074     "}\n"
   17075     "foo();\n"
   17076     "}\n"
   17077     "outer()\n%s";
   17078 
   17079   i::ScopedVector<char> code(1024);
   17080   i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
   17081   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   17082   i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
   17083   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   17084 }
   17085 
   17086 
   17087 static void CreateGarbageInOldSpace() {
   17088   i::Factory* factory = CcTest::i_isolate()->factory();
   17089   v8::HandleScope scope(CcTest::isolate());
   17090   i::AlwaysAllocateScope always_allocate;
   17091   for (int i = 0; i < 1000; i++) {
   17092     factory->NewFixedArray(1000, i::TENURED);
   17093   }
   17094 }
   17095 
   17096 
   17097 // Test that idle notification can be handled and eventually returns true.
   17098 TEST(IdleNotification) {
   17099   const intptr_t MB = 1024 * 1024;
   17100   LocalContext env;
   17101   v8::HandleScope scope(env->GetIsolate());
   17102   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17103   CreateGarbageInOldSpace();
   17104   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17105   CHECK_GT(size_with_garbage, initial_size + MB);
   17106   bool finished = false;
   17107   for (int i = 0; i < 200 && !finished; i++) {
   17108     finished = v8::V8::IdleNotification();
   17109   }
   17110   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17111   CHECK(finished);
   17112   CHECK_LT(final_size, initial_size + 1);
   17113 }
   17114 
   17115 
   17116 // Test that idle notification can be handled and eventually collects garbage.
   17117 TEST(IdleNotificationWithSmallHint) {
   17118   const intptr_t MB = 1024 * 1024;
   17119   const int IdlePauseInMs = 900;
   17120   LocalContext env;
   17121   v8::HandleScope scope(env->GetIsolate());
   17122   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17123   CreateGarbageInOldSpace();
   17124   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17125   CHECK_GT(size_with_garbage, initial_size + MB);
   17126   bool finished = false;
   17127   for (int i = 0; i < 200 && !finished; i++) {
   17128     finished = v8::V8::IdleNotification(IdlePauseInMs);
   17129   }
   17130   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17131   CHECK(finished);
   17132   CHECK_LT(final_size, initial_size + 1);
   17133 }
   17134 
   17135 
   17136 // Test that idle notification can be handled and eventually collects garbage.
   17137 TEST(IdleNotificationWithLargeHint) {
   17138   const intptr_t MB = 1024 * 1024;
   17139   const int IdlePauseInMs = 900;
   17140   LocalContext env;
   17141   v8::HandleScope scope(env->GetIsolate());
   17142   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17143   CreateGarbageInOldSpace();
   17144   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17145   CHECK_GT(size_with_garbage, initial_size + MB);
   17146   bool finished = false;
   17147   for (int i = 0; i < 200 && !finished; i++) {
   17148     finished = v8::V8::IdleNotification(IdlePauseInMs);
   17149   }
   17150   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17151   CHECK(finished);
   17152   CHECK_LT(final_size, initial_size + 1);
   17153 }
   17154 
   17155 
   17156 TEST(Regress2107) {
   17157   const intptr_t MB = 1024 * 1024;
   17158   const int kShortIdlePauseInMs = 100;
   17159   const int kLongIdlePauseInMs = 1000;
   17160   LocalContext env;
   17161   v8::Isolate* isolate = env->GetIsolate();
   17162   v8::HandleScope scope(env->GetIsolate());
   17163   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17164   // Send idle notification to start a round of incremental GCs.
   17165   v8::V8::IdleNotification(kShortIdlePauseInMs);
   17166   // Emulate 7 page reloads.
   17167   for (int i = 0; i < 7; i++) {
   17168     {
   17169       v8::HandleScope inner_scope(env->GetIsolate());
   17170       v8::Local<v8::Context> ctx = v8::Context::New(isolate);
   17171       ctx->Enter();
   17172       CreateGarbageInOldSpace();
   17173       ctx->Exit();
   17174     }
   17175     v8::V8::ContextDisposedNotification();
   17176     v8::V8::IdleNotification(kLongIdlePauseInMs);
   17177   }
   17178   // Create garbage and check that idle notification still collects it.
   17179   CreateGarbageInOldSpace();
   17180   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17181   CHECK_GT(size_with_garbage, initial_size + MB);
   17182   bool finished = false;
   17183   for (int i = 0; i < 200 && !finished; i++) {
   17184     finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
   17185   }
   17186   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17187   CHECK_LT(final_size, initial_size + 1);
   17188 }
   17189 
   17190 
   17191 TEST(Regress2333) {
   17192   LocalContext env;
   17193   for (int i = 0; i < 3; i++) {
   17194     CcTest::heap()->PerformScavenge();
   17195   }
   17196 }
   17197 
   17198 static uint32_t* stack_limit;
   17199 
   17200 static void GetStackLimitCallback(
   17201     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17202   stack_limit = reinterpret_cast<uint32_t*>(
   17203       CcTest::i_isolate()->stack_guard()->real_climit());
   17204 }
   17205 
   17206 
   17207 // Uses the address of a local variable to determine the stack top now.
   17208 // Given a size, returns an address that is that far from the current
   17209 // top of stack.
   17210 static uint32_t* ComputeStackLimit(uint32_t size) {
   17211   uint32_t* answer = &size - (size / sizeof(size));
   17212   // If the size is very large and the stack is very near the bottom of
   17213   // memory then the calculation above may wrap around and give an address
   17214   // that is above the (downwards-growing) stack.  In that case we return
   17215   // a very low address.
   17216   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   17217   return answer;
   17218 }
   17219 
   17220 
   17221 // We need at least 165kB for an x64 debug build with clang and ASAN.
   17222 static const int stack_breathing_room = 256 * i::KB;
   17223 
   17224 
   17225 TEST(SetResourceConstraints) {
   17226   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   17227 
   17228   // Set stack limit.
   17229   v8::ResourceConstraints constraints;
   17230   constraints.set_stack_limit(set_limit);
   17231   CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
   17232 
   17233   // Execute a script.
   17234   LocalContext env;
   17235   v8::HandleScope scope(env->GetIsolate());
   17236   Local<v8::FunctionTemplate> fun_templ =
   17237       v8::FunctionTemplate::New(GetStackLimitCallback);
   17238   Local<Function> fun = fun_templ->GetFunction();
   17239   env->Global()->Set(v8_str("get_stack_limit"), fun);
   17240   CompileRun("get_stack_limit();");
   17241 
   17242   CHECK(stack_limit == set_limit);
   17243 }
   17244 
   17245 
   17246 TEST(SetResourceConstraintsInThread) {
   17247   uint32_t* set_limit;
   17248   {
   17249     v8::Locker locker(CcTest::isolate());
   17250     set_limit = ComputeStackLimit(stack_breathing_room);
   17251 
   17252     // Set stack limit.
   17253     v8::ResourceConstraints constraints;
   17254     constraints.set_stack_limit(set_limit);
   17255     CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
   17256 
   17257     // Execute a script.
   17258     v8::HandleScope scope(CcTest::isolate());
   17259     LocalContext env;
   17260     Local<v8::FunctionTemplate> fun_templ =
   17261         v8::FunctionTemplate::New(GetStackLimitCallback);
   17262     Local<Function> fun = fun_templ->GetFunction();
   17263     env->Global()->Set(v8_str("get_stack_limit"), fun);
   17264     CompileRun("get_stack_limit();");
   17265 
   17266     CHECK(stack_limit == set_limit);
   17267   }
   17268   {
   17269     v8::Locker locker(CcTest::isolate());
   17270     CHECK(stack_limit == set_limit);
   17271   }
   17272 }
   17273 
   17274 
   17275 THREADED_TEST(GetHeapStatistics) {
   17276   LocalContext c1;
   17277   v8::HandleScope scope(c1->GetIsolate());
   17278   v8::HeapStatistics heap_statistics;
   17279   CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
   17280   CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
   17281   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   17282   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   17283   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   17284 }
   17285 
   17286 
   17287 class VisitorImpl : public v8::ExternalResourceVisitor {
   17288  public:
   17289   explicit VisitorImpl(TestResource** resource) {
   17290     for (int i = 0; i < 4; i++) {
   17291       resource_[i] = resource[i];
   17292       found_resource_[i] = false;
   17293     }
   17294   }
   17295   virtual ~VisitorImpl() {}
   17296   virtual void VisitExternalString(v8::Handle<v8::String> string) {
   17297     if (!string->IsExternal()) {
   17298       CHECK(string->IsExternalAscii());
   17299       return;
   17300     }
   17301     v8::String::ExternalStringResource* resource =
   17302         string->GetExternalStringResource();
   17303     CHECK(resource);
   17304     for (int i = 0; i < 4; i++) {
   17305       if (resource_[i] == resource) {
   17306         CHECK(!found_resource_[i]);
   17307         found_resource_[i] = true;
   17308       }
   17309     }
   17310   }
   17311   void CheckVisitedResources() {
   17312     for (int i = 0; i < 4; i++) {
   17313       CHECK(found_resource_[i]);
   17314     }
   17315   }
   17316 
   17317  private:
   17318   v8::String::ExternalStringResource* resource_[4];
   17319   bool found_resource_[4];
   17320 };
   17321 
   17322 
   17323 TEST(VisitExternalStrings) {
   17324   LocalContext env;
   17325   v8::HandleScope scope(env->GetIsolate());
   17326   const char* string = "Some string";
   17327   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   17328   TestResource* resource[4];
   17329   resource[0] = new TestResource(two_byte_string);
   17330   v8::Local<v8::String> string0 =
   17331       v8::String::NewExternal(env->GetIsolate(), resource[0]);
   17332   resource[1] = new TestResource(two_byte_string);
   17333   v8::Local<v8::String> string1 =
   17334       v8::String::NewExternal(env->GetIsolate(), resource[1]);
   17335 
   17336   // Externalized symbol.
   17337   resource[2] = new TestResource(two_byte_string);
   17338   v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
   17339       env->GetIsolate(), string, v8::String::kInternalizedString);
   17340   CHECK(string2->MakeExternal(resource[2]));
   17341 
   17342   // Symbolized External.
   17343   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   17344   v8::Local<v8::String> string3 =
   17345       v8::String::NewExternal(env->GetIsolate(), resource[3]);
   17346   CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
   17347   // Turn into a symbol.
   17348   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   17349   CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
   17350   CHECK(string3_i->IsInternalizedString());
   17351 
   17352   // We need to add usages for string* to avoid warnings in GCC 4.7
   17353   CHECK(string0->IsExternal());
   17354   CHECK(string1->IsExternal());
   17355   CHECK(string2->IsExternal());
   17356   CHECK(string3->IsExternal());
   17357 
   17358   VisitorImpl visitor(resource);
   17359   v8::V8::VisitExternalResources(&visitor);
   17360   visitor.CheckVisitedResources();
   17361 }
   17362 
   17363 
   17364 TEST(ExternalStringCollectedAtTearDown) {
   17365   int destroyed = 0;
   17366   v8::Isolate* isolate = v8::Isolate::New();
   17367   { v8::Isolate::Scope isolate_scope(isolate);
   17368     v8::HandleScope handle_scope(isolate);
   17369     const char* s = "One string to test them all, one string to find them.";
   17370     TestAsciiResource* inscription =
   17371         new TestAsciiResource(i::StrDup(s), &destroyed);
   17372     v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
   17373     // Ring is still alive.  Orcs are roaming freely across our lands.
   17374     CHECK_EQ(0, destroyed);
   17375     USE(ring);
   17376   }
   17377 
   17378   isolate->Dispose();
   17379   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   17380   CHECK_EQ(1, destroyed);
   17381 }
   17382 
   17383 
   17384 static double DoubleFromBits(uint64_t value) {
   17385   double target;
   17386   i::OS::MemCopy(&target, &value, sizeof(target));
   17387   return target;
   17388 }
   17389 
   17390 
   17391 static uint64_t DoubleToBits(double value) {
   17392   uint64_t target;
   17393   i::OS::MemCopy(&target, &value, sizeof(target));
   17394   return target;
   17395 }
   17396 
   17397 
   17398 static double DoubleToDateTime(double input) {
   17399   double date_limit = 864e13;
   17400   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   17401     return i::OS::nan_value();
   17402   }
   17403   return (input < 0) ? -(floor(-input)) : floor(input);
   17404 }
   17405 
   17406 
   17407 // We don't have a consistent way to write 64-bit constants syntactically, so we
   17408 // split them into two 32-bit constants and combine them programmatically.
   17409 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   17410   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   17411 }
   17412 
   17413 
   17414 THREADED_TEST(QuietSignalingNaNs) {
   17415   LocalContext context;
   17416   v8::HandleScope scope(context->GetIsolate());
   17417   v8::TryCatch try_catch;
   17418 
   17419   // Special double values.
   17420   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
   17421   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
   17422   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
   17423   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
   17424   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   17425   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
   17426   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   17427 
   17428   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   17429   // on either side of the epoch.
   17430   double date_limit = 864e13;
   17431 
   17432   double test_values[] = {
   17433       snan,
   17434       qnan,
   17435       infinity,
   17436       max_normal,
   17437       date_limit + 1,
   17438       date_limit,
   17439       min_normal,
   17440       max_denormal,
   17441       min_denormal,
   17442       0,
   17443       -0,
   17444       -min_denormal,
   17445       -max_denormal,
   17446       -min_normal,
   17447       -date_limit,
   17448       -date_limit - 1,
   17449       -max_normal,
   17450       -infinity,
   17451       -qnan,
   17452       -snan
   17453   };
   17454   int num_test_values = 20;
   17455 
   17456   for (int i = 0; i < num_test_values; i++) {
   17457     double test_value = test_values[i];
   17458 
   17459     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   17460     v8::Handle<v8::Value> number = v8::Number::New(test_value);
   17461     double stored_number = number->NumberValue();
   17462     if (!std::isnan(test_value)) {
   17463       CHECK_EQ(test_value, stored_number);
   17464     } else {
   17465       uint64_t stored_bits = DoubleToBits(stored_number);
   17466       // Check if quiet nan (bits 51..62 all set).
   17467 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
   17468       // Most significant fraction bit for quiet nan is set to 0
   17469       // on MIPS architecture. Allowed by IEEE-754.
   17470       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   17471 #else
   17472       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   17473 #endif
   17474     }
   17475 
   17476     // Check that Date::New preserves non-NaNs in the date range and
   17477     // quiets SNaNs.
   17478     v8::Handle<v8::Value> date =
   17479         v8::Date::New(context->GetIsolate(), test_value);
   17480     double expected_stored_date = DoubleToDateTime(test_value);
   17481     double stored_date = date->NumberValue();
   17482     if (!std::isnan(expected_stored_date)) {
   17483       CHECK_EQ(expected_stored_date, stored_date);
   17484     } else {
   17485       uint64_t stored_bits = DoubleToBits(stored_date);
   17486       // Check if quiet nan (bits 51..62 all set).
   17487 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
   17488       // Most significant fraction bit for quiet nan is set to 0
   17489       // on MIPS architecture. Allowed by IEEE-754.
   17490       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   17491 #else
   17492       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   17493 #endif
   17494     }
   17495   }
   17496 }
   17497 
   17498 
   17499 static void SpaghettiIncident(
   17500     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17501   v8::HandleScope scope(args.GetIsolate());
   17502   v8::TryCatch tc;
   17503   v8::Handle<v8::String> str(args[0]->ToString());
   17504   USE(str);
   17505   if (tc.HasCaught())
   17506     tc.ReThrow();
   17507 }
   17508 
   17509 
   17510 // Test that an exception can be propagated down through a spaghetti
   17511 // stack using ReThrow.
   17512 THREADED_TEST(SpaghettiStackReThrow) {
   17513   v8::HandleScope scope(CcTest::isolate());
   17514   LocalContext context;
   17515   context->Global()->Set(
   17516       v8::String::NewFromUtf8(CcTest::isolate(), "s"),
   17517       v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
   17518   v8::TryCatch try_catch;
   17519   CompileRun(
   17520       "var i = 0;"
   17521       "var o = {"
   17522       "  toString: function () {"
   17523       "    if (i == 10) {"
   17524       "      throw 'Hey!';"
   17525       "    } else {"
   17526       "      i++;"
   17527       "      return s(o);"
   17528       "    }"
   17529       "  }"
   17530       "};"
   17531       "s(o);");
   17532   CHECK(try_catch.HasCaught());
   17533   v8::String::Utf8Value value(try_catch.Exception());
   17534   CHECK_EQ(0, strcmp(*value, "Hey!"));
   17535 }
   17536 
   17537 
   17538 TEST(Regress528) {
   17539   v8::V8::Initialize();
   17540   v8::Isolate* isolate = CcTest::isolate();
   17541   v8::HandleScope scope(isolate);
   17542   v8::Local<Context> other_context;
   17543   int gc_count;
   17544 
   17545   // Create a context used to keep the code from aging in the compilation
   17546   // cache.
   17547   other_context = Context::New(isolate);
   17548 
   17549   // Context-dependent context data creates reference from the compilation
   17550   // cache to the global object.
   17551   const char* source_simple = "1";
   17552   {
   17553     v8::HandleScope scope(isolate);
   17554     v8::Local<Context> context = Context::New(isolate);
   17555 
   17556     context->Enter();
   17557     Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
   17558     context->SetEmbedderData(0, obj);
   17559     CompileRun(source_simple);
   17560     context->Exit();
   17561   }
   17562   v8::V8::ContextDisposedNotification();
   17563   for (gc_count = 1; gc_count < 10; gc_count++) {
   17564     other_context->Enter();
   17565     CompileRun(source_simple);
   17566     other_context->Exit();
   17567     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   17568     if (GetGlobalObjectsCount() == 1) break;
   17569   }
   17570   CHECK_GE(2, gc_count);
   17571   CHECK_EQ(1, GetGlobalObjectsCount());
   17572 
   17573   // Eval in a function creates reference from the compilation cache to the
   17574   // global object.
   17575   const char* source_eval = "function f(){eval('1')}; f()";
   17576   {
   17577     v8::HandleScope scope(isolate);
   17578     v8::Local<Context> context = Context::New(isolate);
   17579 
   17580     context->Enter();
   17581     CompileRun(source_eval);
   17582     context->Exit();
   17583   }
   17584   v8::V8::ContextDisposedNotification();
   17585   for (gc_count = 1; gc_count < 10; gc_count++) {
   17586     other_context->Enter();
   17587     CompileRun(source_eval);
   17588     other_context->Exit();
   17589     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   17590     if (GetGlobalObjectsCount() == 1) break;
   17591   }
   17592   CHECK_GE(2, gc_count);
   17593   CHECK_EQ(1, GetGlobalObjectsCount());
   17594 
   17595   // Looking up the line number for an exception creates reference from the
   17596   // compilation cache to the global object.
   17597   const char* source_exception = "function f(){throw 1;} f()";
   17598   {
   17599     v8::HandleScope scope(isolate);
   17600     v8::Local<Context> context = Context::New(isolate);
   17601 
   17602     context->Enter();
   17603     v8::TryCatch try_catch;
   17604     CompileRun(source_exception);
   17605     CHECK(try_catch.HasCaught());
   17606     v8::Handle<v8::Message> message = try_catch.Message();
   17607     CHECK(!message.IsEmpty());
   17608     CHECK_EQ(1, message->GetLineNumber());
   17609     context->Exit();
   17610   }
   17611   v8::V8::ContextDisposedNotification();
   17612   for (gc_count = 1; gc_count < 10; gc_count++) {
   17613     other_context->Enter();
   17614     CompileRun(source_exception);
   17615     other_context->Exit();
   17616     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   17617     if (GetGlobalObjectsCount() == 1) break;
   17618   }
   17619   CHECK_GE(2, gc_count);
   17620   CHECK_EQ(1, GetGlobalObjectsCount());
   17621 
   17622   v8::V8::ContextDisposedNotification();
   17623 }
   17624 
   17625 
   17626 THREADED_TEST(ScriptOrigin) {
   17627   LocalContext env;
   17628   v8::HandleScope scope(env->GetIsolate());
   17629   v8::ScriptOrigin origin =
   17630       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
   17631   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   17632       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
   17633   v8::Script::Compile(script, &origin)->Run();
   17634   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17635       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   17636   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   17637       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
   17638 
   17639   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   17640   CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
   17641   CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
   17642 
   17643   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   17644   CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
   17645   CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
   17646 }
   17647 
   17648 
   17649 THREADED_TEST(FunctionGetInferredName) {
   17650   LocalContext env;
   17651   v8::HandleScope scope(env->GetIsolate());
   17652   v8::ScriptOrigin origin =
   17653       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
   17654   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   17655       env->GetIsolate(),
   17656       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   17657   v8::Script::Compile(script, &origin)->Run();
   17658   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17659       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   17660   CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
   17661 }
   17662 
   17663 
   17664 THREADED_TEST(FunctionGetDisplayName) {
   17665   LocalContext env;
   17666   v8::HandleScope scope(env->GetIsolate());
   17667   const char* code = "var error = false;"
   17668                      "function a() { this.x = 1; };"
   17669                      "a.displayName = 'display_a';"
   17670                      "var b = (function() {"
   17671                      "  var f = function() { this.x = 2; };"
   17672                      "  f.displayName = 'display_b';"
   17673                      "  return f;"
   17674                      "})();"
   17675                      "var c = function() {};"
   17676                      "c.__defineGetter__('displayName', function() {"
   17677                      "  error = true;"
   17678                      "  throw new Error();"
   17679                      "});"
   17680                      "function d() {};"
   17681                      "d.__defineGetter__('displayName', function() {"
   17682                      "  error = true;"
   17683                      "  return 'wrong_display_name';"
   17684                      "});"
   17685                      "function e() {};"
   17686                      "e.displayName = 'wrong_display_name';"
   17687                      "e.__defineSetter__('displayName', function() {"
   17688                      "  error = true;"
   17689                      "  throw new Error();"
   17690                      "});"
   17691                      "function f() {};"
   17692                      "f.displayName = { 'foo': 6, toString: function() {"
   17693                      "  error = true;"
   17694                      "  return 'wrong_display_name';"
   17695                      "}};"
   17696                      "var g = function() {"
   17697                      "  arguments.callee.displayName = 'set_in_runtime';"
   17698                      "}; g();"
   17699                      ;
   17700   v8::ScriptOrigin origin =
   17701       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
   17702   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
   17703       ->Run();
   17704   v8::Local<v8::Value> error =
   17705       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
   17706   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
   17707       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
   17708   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
   17709       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
   17710   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
   17711       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
   17712   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
   17713       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
   17714   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
   17715       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
   17716   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17717       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   17718   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   17719       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
   17720   CHECK_EQ(false, error->BooleanValue());
   17721   CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
   17722   CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
   17723   CHECK(c->GetDisplayName()->IsUndefined());
   17724   CHECK(d->GetDisplayName()->IsUndefined());
   17725   CHECK(e->GetDisplayName()->IsUndefined());
   17726   CHECK(f->GetDisplayName()->IsUndefined());
   17727   CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
   17728 }
   17729 
   17730 
   17731 THREADED_TEST(ScriptLineNumber) {
   17732   LocalContext env;
   17733   v8::HandleScope scope(env->GetIsolate());
   17734   v8::ScriptOrigin origin =
   17735       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
   17736   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   17737       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
   17738   v8::Script::Compile(script, &origin)->Run();
   17739   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17740       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   17741   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   17742       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
   17743   CHECK_EQ(0, f->GetScriptLineNumber());
   17744   CHECK_EQ(2, g->GetScriptLineNumber());
   17745 }
   17746 
   17747 
   17748 THREADED_TEST(ScriptColumnNumber) {
   17749   LocalContext env;
   17750   v8::HandleScope scope(env->GetIsolate());
   17751   v8::ScriptOrigin origin =
   17752       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"),
   17753                        v8::Integer::New(3), v8::Integer::New(2));
   17754   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   17755       env->GetIsolate(), "function foo() {}\n\n     function bar() {}");
   17756   v8::Script::Compile(script, &origin)->Run();
   17757   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   17758       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
   17759   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   17760       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "bar")));
   17761   CHECK_EQ(14, foo->GetScriptColumnNumber());
   17762   CHECK_EQ(17, bar->GetScriptColumnNumber());
   17763 }
   17764 
   17765 
   17766 THREADED_TEST(FunctionIsBuiltin) {
   17767   LocalContext env;
   17768   v8::HandleScope scope(env->GetIsolate());
   17769   v8::Local<v8::Function> f;
   17770   f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
   17771   CHECK(f->IsBuiltin());
   17772   f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
   17773   CHECK(f->IsBuiltin());
   17774   f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
   17775   CHECK(f->IsBuiltin());
   17776   f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
   17777   CHECK(f->IsBuiltin());
   17778   f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
   17779   CHECK(!f->IsBuiltin());
   17780 }
   17781 
   17782 
   17783 THREADED_TEST(FunctionGetScriptId) {
   17784   LocalContext env;
   17785   v8::HandleScope scope(env->GetIsolate());
   17786   v8::ScriptOrigin origin =
   17787       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"),
   17788                        v8::Integer::New(3), v8::Integer::New(2));
   17789   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
   17790       env->GetIsolate(), "function foo() {}\n\n     function bar() {}");
   17791   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
   17792   script->Run();
   17793   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   17794       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
   17795   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   17796       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "bar")));
   17797   CHECK_EQ(script->GetId(), foo->ScriptId());
   17798   CHECK_EQ(script->GetId(), bar->ScriptId());
   17799 }
   17800 
   17801 
   17802 static void GetterWhichReturns42(
   17803     Local<String> name,
   17804     const v8::PropertyCallbackInfo<v8::Value>& info) {
   17805   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   17806   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   17807   info.GetReturnValue().Set(v8_num(42));
   17808 }
   17809 
   17810 
   17811 static void SetterWhichSetsYOnThisTo23(
   17812     Local<String> name,
   17813     Local<Value> value,
   17814     const v8::PropertyCallbackInfo<void>& info) {
   17815   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   17816   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   17817   info.This()->Set(v8_str("y"), v8_num(23));
   17818 }
   17819 
   17820 
   17821 void FooGetInterceptor(Local<String> name,
   17822                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   17823   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   17824   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   17825   if (!name->Equals(v8_str("foo"))) return;
   17826   info.GetReturnValue().Set(v8_num(42));
   17827 }
   17828 
   17829 
   17830 void FooSetInterceptor(Local<String> name,
   17831                        Local<Value> value,
   17832                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   17833   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   17834   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   17835   if (!name->Equals(v8_str("foo"))) return;
   17836   info.This()->Set(v8_str("y"), v8_num(23));
   17837   info.GetReturnValue().Set(v8_num(23));
   17838 }
   17839 
   17840 
   17841 TEST(SetterOnConstructorPrototype) {
   17842   v8::HandleScope scope(CcTest::isolate());
   17843   Local<ObjectTemplate> templ = ObjectTemplate::New();
   17844   templ->SetAccessor(v8_str("x"),
   17845                      GetterWhichReturns42,
   17846                      SetterWhichSetsYOnThisTo23);
   17847   LocalContext context;
   17848   context->Global()->Set(v8_str("P"), templ->NewInstance());
   17849   CompileRun("function C1() {"
   17850              "  this.x = 23;"
   17851              "};"
   17852              "C1.prototype = P;"
   17853              "function C2() {"
   17854              "  this.x = 23"
   17855              "};"
   17856              "C2.prototype = { };"
   17857              "C2.prototype.__proto__ = P;");
   17858 
   17859   v8::Local<v8::Script> script;
   17860   script = v8::Script::Compile(v8_str("new C1();"));
   17861   for (int i = 0; i < 10; i++) {
   17862     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   17863     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   17864     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   17865   }
   17866 
   17867   script = v8::Script::Compile(v8_str("new C2();"));
   17868   for (int i = 0; i < 10; i++) {
   17869     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   17870     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
   17871     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
   17872   }
   17873 }
   17874 
   17875 
   17876 static void NamedPropertyGetterWhichReturns42(
   17877     Local<String> name,
   17878     const v8::PropertyCallbackInfo<v8::Value>& info) {
   17879   info.GetReturnValue().Set(v8_num(42));
   17880 }
   17881 
   17882 
   17883 static void NamedPropertySetterWhichSetsYOnThisTo23(
   17884     Local<String> name,
   17885     Local<Value> value,
   17886     const v8::PropertyCallbackInfo<v8::Value>& info) {
   17887   if (name->Equals(v8_str("x"))) {
   17888     info.This()->Set(v8_str("y"), v8_num(23));
   17889   }
   17890 }
   17891 
   17892 
   17893 THREADED_TEST(InterceptorOnConstructorPrototype) {
   17894   v8::HandleScope scope(CcTest::isolate());
   17895   Local<ObjectTemplate> templ = ObjectTemplate::New();
   17896   templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
   17897                                  NamedPropertySetterWhichSetsYOnThisTo23);
   17898   LocalContext context;
   17899   context->Global()->Set(v8_str("P"), templ->NewInstance());
   17900   CompileRun("function C1() {"
   17901              "  this.x = 23;"
   17902              "};"
   17903              "C1.prototype = P;"
   17904              "function C2() {"
   17905              "  this.x = 23"
   17906              "};"
   17907              "C2.prototype = { };"
   17908              "C2.prototype.__proto__ = P;");
   17909 
   17910   v8::Local<v8::Script> script;
   17911   script = v8::Script::Compile(v8_str("new C1();"));
   17912   for (int i = 0; i < 10; i++) {
   17913     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   17914     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   17915     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   17916   }
   17917 
   17918   script = v8::Script::Compile(v8_str("new C2();"));
   17919   for (int i = 0; i < 10; i++) {
   17920     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   17921     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
   17922     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
   17923   }
   17924 }
   17925 
   17926 
   17927 TEST(Regress618) {
   17928   const char* source = "function C1() {"
   17929                        "  this.x = 23;"
   17930                        "};"
   17931                        "C1.prototype = P;";
   17932 
   17933   LocalContext context;
   17934   v8::HandleScope scope(context->GetIsolate());
   17935   v8::Local<v8::Script> script;
   17936 
   17937   // Use a simple object as prototype.
   17938   v8::Local<v8::Object> prototype = v8::Object::New();
   17939   prototype->Set(v8_str("y"), v8_num(42));
   17940   context->Global()->Set(v8_str("P"), prototype);
   17941 
   17942   // This compile will add the code to the compilation cache.
   17943   CompileRun(source);
   17944 
   17945   script = v8::Script::Compile(v8_str("new C1();"));
   17946   // Allow enough iterations for the inobject slack tracking logic
   17947   // to finalize instance size and install the fast construct stub.
   17948   for (int i = 0; i < 256; i++) {
   17949     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   17950     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   17951     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   17952   }
   17953 
   17954   // Use an API object with accessors as prototype.
   17955   Local<ObjectTemplate> templ = ObjectTemplate::New();
   17956   templ->SetAccessor(v8_str("x"),
   17957                      GetterWhichReturns42,
   17958                      SetterWhichSetsYOnThisTo23);
   17959   context->Global()->Set(v8_str("P"), templ->NewInstance());
   17960 
   17961   // This compile will get the code from the compilation cache.
   17962   CompileRun(source);
   17963 
   17964   script = v8::Script::Compile(v8_str("new C1();"));
   17965   for (int i = 0; i < 10; i++) {
   17966     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   17967     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   17968     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   17969   }
   17970 }
   17971 
   17972 v8::Isolate* gc_callbacks_isolate = NULL;
   17973 int prologue_call_count = 0;
   17974 int epilogue_call_count = 0;
   17975 int prologue_call_count_second = 0;
   17976 int epilogue_call_count_second = 0;
   17977 
   17978 void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
   17979   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   17980   ++prologue_call_count;
   17981 }
   17982 
   17983 
   17984 void PrologueCallback(v8::Isolate* isolate,
   17985                       v8::GCType,
   17986                       v8::GCCallbackFlags flags) {
   17987   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   17988   CHECK_EQ(gc_callbacks_isolate, isolate);
   17989   ++prologue_call_count;
   17990 }
   17991 
   17992 
   17993 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
   17994   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   17995   ++epilogue_call_count;
   17996 }
   17997 
   17998 
   17999 void EpilogueCallback(v8::Isolate* isolate,
   18000                       v8::GCType,
   18001                       v8::GCCallbackFlags flags) {
   18002   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18003   CHECK_EQ(gc_callbacks_isolate, isolate);
   18004   ++epilogue_call_count;
   18005 }
   18006 
   18007 
   18008 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
   18009   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18010   ++prologue_call_count_second;
   18011 }
   18012 
   18013 
   18014 void PrologueCallbackSecond(v8::Isolate* isolate,
   18015                             v8::GCType,
   18016                             v8::GCCallbackFlags flags) {
   18017   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18018   CHECK_EQ(gc_callbacks_isolate, isolate);
   18019   ++prologue_call_count_second;
   18020 }
   18021 
   18022 
   18023 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
   18024   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18025   ++epilogue_call_count_second;
   18026 }
   18027 
   18028 
   18029 void EpilogueCallbackSecond(v8::Isolate* isolate,
   18030                             v8::GCType,
   18031                             v8::GCCallbackFlags flags) {
   18032   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18033   CHECK_EQ(gc_callbacks_isolate, isolate);
   18034   ++epilogue_call_count_second;
   18035 }
   18036 
   18037 
   18038 TEST(GCCallbacksOld) {
   18039   LocalContext context;
   18040 
   18041   v8::V8::AddGCPrologueCallback(PrologueCallback);
   18042   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
   18043   CHECK_EQ(0, prologue_call_count);
   18044   CHECK_EQ(0, epilogue_call_count);
   18045   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18046   CHECK_EQ(1, prologue_call_count);
   18047   CHECK_EQ(1, epilogue_call_count);
   18048   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
   18049   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
   18050   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18051   CHECK_EQ(2, prologue_call_count);
   18052   CHECK_EQ(2, epilogue_call_count);
   18053   CHECK_EQ(1, prologue_call_count_second);
   18054   CHECK_EQ(1, epilogue_call_count_second);
   18055   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
   18056   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
   18057   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18058   CHECK_EQ(2, prologue_call_count);
   18059   CHECK_EQ(2, epilogue_call_count);
   18060   CHECK_EQ(2, prologue_call_count_second);
   18061   CHECK_EQ(2, epilogue_call_count_second);
   18062   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
   18063   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   18064   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18065   CHECK_EQ(2, prologue_call_count);
   18066   CHECK_EQ(2, epilogue_call_count);
   18067   CHECK_EQ(2, prologue_call_count_second);
   18068   CHECK_EQ(2, epilogue_call_count_second);
   18069 }
   18070 
   18071 
   18072 TEST(GCCallbacks) {
   18073   LocalContext context;
   18074   v8::Isolate* isolate = context->GetIsolate();
   18075   gc_callbacks_isolate = isolate;
   18076   isolate->AddGCPrologueCallback(PrologueCallback);
   18077   isolate->AddGCEpilogueCallback(EpilogueCallback);
   18078   CHECK_EQ(0, prologue_call_count);
   18079   CHECK_EQ(0, epilogue_call_count);
   18080   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18081   CHECK_EQ(1, prologue_call_count);
   18082   CHECK_EQ(1, epilogue_call_count);
   18083   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
   18084   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
   18085   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18086   CHECK_EQ(2, prologue_call_count);
   18087   CHECK_EQ(2, epilogue_call_count);
   18088   CHECK_EQ(1, prologue_call_count_second);
   18089   CHECK_EQ(1, epilogue_call_count_second);
   18090   isolate->RemoveGCPrologueCallback(PrologueCallback);
   18091   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
   18092   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18093   CHECK_EQ(2, prologue_call_count);
   18094   CHECK_EQ(2, epilogue_call_count);
   18095   CHECK_EQ(2, prologue_call_count_second);
   18096   CHECK_EQ(2, epilogue_call_count_second);
   18097   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
   18098   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   18099   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18100   CHECK_EQ(2, prologue_call_count);
   18101   CHECK_EQ(2, epilogue_call_count);
   18102   CHECK_EQ(2, prologue_call_count_second);
   18103   CHECK_EQ(2, epilogue_call_count_second);
   18104 }
   18105 
   18106 
   18107 THREADED_TEST(AddToJSFunctionResultCache) {
   18108   i::FLAG_stress_compaction = false;
   18109   i::FLAG_allow_natives_syntax = true;
   18110   v8::HandleScope scope(CcTest::isolate());
   18111 
   18112   LocalContext context;
   18113 
   18114   const char* code =
   18115       "(function() {"
   18116       "  var key0 = 'a';"
   18117       "  var key1 = 'b';"
   18118       "  var r0 = %_GetFromCache(0, key0);"
   18119       "  var r1 = %_GetFromCache(0, key1);"
   18120       "  var r0_ = %_GetFromCache(0, key0);"
   18121       "  if (r0 !== r0_)"
   18122       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
   18123       "  var r1_ = %_GetFromCache(0, key1);"
   18124       "  if (r1 !== r1_)"
   18125       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
   18126       "  return 'PASSED';"
   18127       "})()";
   18128   CcTest::heap()->ClearJSFunctionResultCaches();
   18129   ExpectString(code, "PASSED");
   18130 }
   18131 
   18132 
   18133 static const int k0CacheSize = 16;
   18134 
   18135 THREADED_TEST(FillJSFunctionResultCache) {
   18136   i::FLAG_allow_natives_syntax = true;
   18137   LocalContext context;
   18138   v8::HandleScope scope(context->GetIsolate());
   18139 
   18140   const char* code =
   18141       "(function() {"
   18142       "  var k = 'a';"
   18143       "  var r = %_GetFromCache(0, k);"
   18144       "  for (var i = 0; i < 16; i++) {"
   18145       "    %_GetFromCache(0, 'a' + i);"
   18146       "  };"
   18147       "  if (r === %_GetFromCache(0, k))"
   18148       "    return 'FAILED: k0CacheSize is too small';"
   18149       "  return 'PASSED';"
   18150       "})()";
   18151   CcTest::heap()->ClearJSFunctionResultCaches();
   18152   ExpectString(code, "PASSED");
   18153 }
   18154 
   18155 
   18156 THREADED_TEST(RoundRobinGetFromCache) {
   18157   i::FLAG_allow_natives_syntax = true;
   18158   LocalContext context;
   18159   v8::HandleScope scope(context->GetIsolate());
   18160 
   18161   const char* code =
   18162       "(function() {"
   18163       "  var keys = [];"
   18164       "  for (var i = 0; i < 16; i++) keys.push(i);"
   18165       "  var values = [];"
   18166       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   18167       "  for (var i = 0; i < 16; i++) {"
   18168       "    var v = %_GetFromCache(0, keys[i]);"
   18169       "    if (v.toString() !== values[i].toString())"
   18170       "      return 'Wrong value for ' + "
   18171       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   18172       "  };"
   18173       "  return 'PASSED';"
   18174       "})()";
   18175   CcTest::heap()->ClearJSFunctionResultCaches();
   18176   ExpectString(code, "PASSED");
   18177 }
   18178 
   18179 
   18180 THREADED_TEST(ReverseGetFromCache) {
   18181   i::FLAG_allow_natives_syntax = true;
   18182   LocalContext context;
   18183   v8::HandleScope scope(context->GetIsolate());
   18184 
   18185   const char* code =
   18186       "(function() {"
   18187       "  var keys = [];"
   18188       "  for (var i = 0; i < 16; i++) keys.push(i);"
   18189       "  var values = [];"
   18190       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   18191       "  for (var i = 15; i >= 16; i--) {"
   18192       "    var v = %_GetFromCache(0, keys[i]);"
   18193       "    if (v !== values[i])"
   18194       "      return 'Wrong value for ' + "
   18195       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   18196       "  };"
   18197       "  return 'PASSED';"
   18198       "})()";
   18199   CcTest::heap()->ClearJSFunctionResultCaches();
   18200   ExpectString(code, "PASSED");
   18201 }
   18202 
   18203 
   18204 THREADED_TEST(TestEviction) {
   18205   i::FLAG_allow_natives_syntax = true;
   18206   LocalContext context;
   18207   v8::HandleScope scope(context->GetIsolate());
   18208 
   18209   const char* code =
   18210       "(function() {"
   18211       "  for (var i = 0; i < 2*16; i++) {"
   18212       "    %_GetFromCache(0, 'a' + i);"
   18213       "  };"
   18214       "  return 'PASSED';"
   18215       "})()";
   18216   CcTest::heap()->ClearJSFunctionResultCaches();
   18217   ExpectString(code, "PASSED");
   18218 }
   18219 
   18220 
   18221 THREADED_TEST(TwoByteStringInAsciiCons) {
   18222   // See Chromium issue 47824.
   18223   LocalContext context;
   18224   v8::HandleScope scope(context->GetIsolate());
   18225 
   18226   const char* init_code =
   18227       "var str1 = 'abelspendabel';"
   18228       "var str2 = str1 + str1 + str1;"
   18229       "str2;";
   18230   Local<Value> result = CompileRun(init_code);
   18231 
   18232   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   18233   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   18234 
   18235   CHECK(result->IsString());
   18236   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   18237   int length = string->length();
   18238   CHECK(string->IsOneByteRepresentation());
   18239 
   18240   FlattenString(string);
   18241   i::Handle<i::String> flat_string = FlattenGetString(string);
   18242 
   18243   CHECK(string->IsOneByteRepresentation());
   18244   CHECK(flat_string->IsOneByteRepresentation());
   18245 
   18246   // Create external resource.
   18247   uint16_t* uc16_buffer = new uint16_t[length + 1];
   18248 
   18249   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   18250   uc16_buffer[length] = 0;
   18251 
   18252   TestResource resource(uc16_buffer);
   18253 
   18254   flat_string->MakeExternal(&resource);
   18255 
   18256   CHECK(flat_string->IsTwoByteRepresentation());
   18257 
   18258   // If the cons string has been short-circuited, skip the following checks.
   18259   if (!string.is_identical_to(flat_string)) {
   18260     // At this point, we should have a Cons string which is flat and ASCII,
   18261     // with a first half that is a two-byte string (although it only contains
   18262     // ASCII characters). This is a valid sequence of steps, and it can happen
   18263     // in real pages.
   18264     CHECK(string->IsOneByteRepresentation());
   18265     i::ConsString* cons = i::ConsString::cast(*string);
   18266     CHECK_EQ(0, cons->second()->length());
   18267     CHECK(cons->first()->IsTwoByteRepresentation());
   18268   }
   18269 
   18270   // Check that some string operations work.
   18271 
   18272   // Atom RegExp.
   18273   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   18274   CHECK_EQ(6, reresult->Int32Value());
   18275 
   18276   // Nonatom RegExp.
   18277   reresult = CompileRun("str2.match(/abe./g).length;");
   18278   CHECK_EQ(6, reresult->Int32Value());
   18279 
   18280   reresult = CompileRun("str2.search(/bel/g);");
   18281   CHECK_EQ(1, reresult->Int32Value());
   18282 
   18283   reresult = CompileRun("str2.search(/be./g);");
   18284   CHECK_EQ(1, reresult->Int32Value());
   18285 
   18286   ExpectTrue("/bel/g.test(str2);");
   18287 
   18288   ExpectTrue("/be./g.test(str2);");
   18289 
   18290   reresult = CompileRun("/bel/g.exec(str2);");
   18291   CHECK(!reresult->IsNull());
   18292 
   18293   reresult = CompileRun("/be./g.exec(str2);");
   18294   CHECK(!reresult->IsNull());
   18295 
   18296   ExpectString("str2.substring(2, 10);", "elspenda");
   18297 
   18298   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   18299 
   18300   ExpectString("str2.charAt(2);", "e");
   18301 
   18302   ExpectObject("str2.indexOf('els');", indexof);
   18303 
   18304   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   18305 
   18306   reresult = CompileRun("str2.charCodeAt(2);");
   18307   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
   18308 }
   18309 
   18310 
   18311 TEST(ContainsOnlyOneByte) {
   18312   v8::V8::Initialize();
   18313   v8::Isolate* isolate = CcTest::isolate();
   18314   v8::HandleScope scope(isolate);
   18315   // Make a buffer long enough that it won't automatically be converted.
   18316   const int length = 512;
   18317   // Ensure word aligned assignment.
   18318   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   18319   i::SmartArrayPointer<uintptr_t>
   18320   aligned_contents(new uintptr_t[aligned_length]);
   18321   uint16_t* string_contents = reinterpret_cast<uint16_t*>(*aligned_contents);
   18322   // Set to contain only one byte.
   18323   for (int i = 0; i < length-1; i++) {
   18324     string_contents[i] = 0x41;
   18325   }
   18326   string_contents[length-1] = 0;
   18327   // Simple case.
   18328   Handle<String> string;
   18329   string = String::NewExternal(isolate, new TestResource(string_contents));
   18330   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   18331   // Counter example.
   18332   string = String::NewFromTwoByte(isolate, string_contents);
   18333   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   18334   // Test left right and balanced cons strings.
   18335   Handle<String> base = String::NewFromUtf8(isolate, "a");
   18336   Handle<String> left = base;
   18337   Handle<String> right = base;
   18338   for (int i = 0; i < 1000; i++) {
   18339     left = String::Concat(base, left);
   18340     right = String::Concat(right, base);
   18341   }
   18342   Handle<String> balanced = String::Concat(left, base);
   18343   balanced = String::Concat(balanced, right);
   18344   Handle<String> cons_strings[] = {left, balanced, right};
   18345   Handle<String> two_byte =
   18346       String::NewExternal(isolate, new TestResource(string_contents));
   18347   for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
   18348     // Base assumptions.
   18349     string = cons_strings[i];
   18350     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   18351     // Test left and right concatentation.
   18352     string = String::Concat(two_byte, cons_strings[i]);
   18353     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   18354     string = String::Concat(cons_strings[i], two_byte);
   18355     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   18356   }
   18357   // Set bits in different positions
   18358   // for strings of different lengths and alignments.
   18359   for (int alignment = 0; alignment < 7; alignment++) {
   18360     for (int size = 2; alignment + size < length; size *= 2) {
   18361       int zero_offset = size + alignment;
   18362       string_contents[zero_offset] = 0;
   18363       for (int i = 0; i < size; i++) {
   18364         int shift = 8 + (i % 7);
   18365         string_contents[alignment + i] = 1 << shift;
   18366         string = String::NewExternal(
   18367             isolate, new TestResource(string_contents + alignment));
   18368         CHECK_EQ(size, string->Length());
   18369         CHECK(!string->ContainsOnlyOneByte());
   18370         string_contents[alignment + i] = 0x41;
   18371       }
   18372       string_contents[zero_offset] = 0x41;
   18373     }
   18374   }
   18375 }
   18376 
   18377 
   18378 // Failed access check callback that performs a GC on each invocation.
   18379 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   18380                                  v8::AccessType type,
   18381                                  Local<v8::Value> data) {
   18382   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18383 }
   18384 
   18385 
   18386 TEST(GCInFailedAccessCheckCallback) {
   18387   // Install a failed access check callback that performs a GC on each
   18388   // invocation. Then force the callback to be called from va
   18389 
   18390   v8::V8::Initialize();
   18391   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   18392 
   18393   v8::HandleScope scope(CcTest::isolate());
   18394 
   18395   // Create an ObjectTemplate for global objects and install access
   18396   // check callbacks that will block access.
   18397   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   18398   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   18399                                            IndexedGetAccessBlocker,
   18400                                            v8::Handle<v8::Value>(),
   18401                                            false);
   18402 
   18403   // Create a context and set an x property on it's global object.
   18404   LocalContext context0(NULL, global_template);
   18405   context0->Global()->Set(v8_str("x"), v8_num(42));
   18406   v8::Handle<v8::Object> global0 = context0->Global();
   18407 
   18408   // Create a context with a different security token so that the
   18409   // failed access check callback will be called on each access.
   18410   LocalContext context1(NULL, global_template);
   18411   context1->Global()->Set(v8_str("other"), global0);
   18412 
   18413   // Get property with failed access check.
   18414   ExpectUndefined("other.x");
   18415 
   18416   // Get element with failed access check.
   18417   ExpectUndefined("other[0]");
   18418 
   18419   // Set property with failed access check.
   18420   v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
   18421   CHECK(result->IsObject());
   18422 
   18423   // Set element with failed access check.
   18424   result = CompileRun("other[0] = new Object()");
   18425   CHECK(result->IsObject());
   18426 
   18427   // Get property attribute with failed access check.
   18428   ExpectFalse("\'x\' in other");
   18429 
   18430   // Get property attribute for element with failed access check.
   18431   ExpectFalse("0 in other");
   18432 
   18433   // Delete property.
   18434   ExpectFalse("delete other.x");
   18435 
   18436   // Delete element.
   18437   CHECK_EQ(false, global0->Delete(0));
   18438 
   18439   // DefineAccessor.
   18440   CHECK_EQ(false,
   18441            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
   18442 
   18443   // Define JavaScript accessor.
   18444   ExpectUndefined("Object.prototype.__defineGetter__.call("
   18445                   "    other, \'x\', function() { return 42; })");
   18446 
   18447   // LookupAccessor.
   18448   ExpectUndefined("Object.prototype.__lookupGetter__.call("
   18449                   "    other, \'x\')");
   18450 
   18451   // HasLocalElement.
   18452   ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
   18453 
   18454   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
   18455   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
   18456   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
   18457 
   18458   // Reset the failed access check callback so it does not influence
   18459   // the other tests.
   18460   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
   18461 }
   18462 
   18463 
   18464 TEST(IsolateNewDispose) {
   18465   v8::Isolate* current_isolate = CcTest::isolate();
   18466   v8::Isolate* isolate = v8::Isolate::New();
   18467   CHECK(isolate != NULL);
   18468   CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   18469   CHECK(current_isolate != isolate);
   18470   CHECK(current_isolate == CcTest::isolate());
   18471 
   18472   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   18473   last_location = last_message = NULL;
   18474   isolate->Dispose();
   18475   CHECK_EQ(last_location, NULL);
   18476   CHECK_EQ(last_message, NULL);
   18477 }
   18478 
   18479 
   18480 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   18481   v8::Isolate* isolate = v8::Isolate::New();
   18482   CHECK(isolate);
   18483   isolate->Enter();
   18484   v8::HandleScope scope(isolate);
   18485   LocalContext context(isolate);
   18486   // Run something in this isolate.
   18487   ExpectTrue("true");
   18488   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   18489   last_location = last_message = NULL;
   18490   // Still entered, should fail.
   18491   isolate->Dispose();
   18492   CHECK_NE(last_location, NULL);
   18493   CHECK_NE(last_message, NULL);
   18494 }
   18495 
   18496 
   18497 TEST(RunTwoIsolatesOnSingleThread) {
   18498   // Run isolate 1.
   18499   v8::Isolate* isolate1 = v8::Isolate::New();
   18500   isolate1->Enter();
   18501   v8::Persistent<v8::Context> context1;
   18502   {
   18503     v8::HandleScope scope(isolate1);
   18504     context1.Reset(isolate1, Context::New(isolate1));
   18505   }
   18506 
   18507   {
   18508     v8::HandleScope scope(isolate1);
   18509     v8::Local<v8::Context> context =
   18510         v8::Local<v8::Context>::New(isolate1, context1);
   18511     v8::Context::Scope context_scope(context);
   18512     // Run something in new isolate.
   18513     CompileRun("var foo = 'isolate 1';");
   18514     ExpectString("function f() { return foo; }; f()", "isolate 1");
   18515   }
   18516 
   18517   // Run isolate 2.
   18518   v8::Isolate* isolate2 = v8::Isolate::New();
   18519   v8::Persistent<v8::Context> context2;
   18520 
   18521   {
   18522     v8::Isolate::Scope iscope(isolate2);
   18523     v8::HandleScope scope(isolate2);
   18524     context2.Reset(isolate2, Context::New(isolate2));
   18525     v8::Local<v8::Context> context =
   18526         v8::Local<v8::Context>::New(isolate2, context2);
   18527     v8::Context::Scope context_scope(context);
   18528 
   18529     // Run something in new isolate.
   18530     CompileRun("var foo = 'isolate 2';");
   18531     ExpectString("function f() { return foo; }; f()", "isolate 2");
   18532   }
   18533 
   18534   {
   18535     v8::HandleScope scope(isolate1);
   18536     v8::Local<v8::Context> context =
   18537         v8::Local<v8::Context>::New(isolate1, context1);
   18538     v8::Context::Scope context_scope(context);
   18539     // Now again in isolate 1
   18540     ExpectString("function f() { return foo; }; f()", "isolate 1");
   18541   }
   18542 
   18543   isolate1->Exit();
   18544 
   18545   // Run some stuff in default isolate.
   18546   v8::Persistent<v8::Context> context_default;
   18547   {
   18548     v8::Isolate* isolate = CcTest::isolate();
   18549     v8::Isolate::Scope iscope(isolate);
   18550     v8::HandleScope scope(isolate);
   18551     context_default.Reset(isolate, Context::New(isolate));
   18552   }
   18553 
   18554   {
   18555     v8::HandleScope scope(CcTest::isolate());
   18556     v8::Local<v8::Context> context =
   18557         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   18558     v8::Context::Scope context_scope(context);
   18559     // Variables in other isolates should be not available, verify there
   18560     // is an exception.
   18561     ExpectTrue("function f() {"
   18562                "  try {"
   18563                "    foo;"
   18564                "    return false;"
   18565                "  } catch(e) {"
   18566                "    return true;"
   18567                "  }"
   18568                "};"
   18569                "var isDefaultIsolate = true;"
   18570                "f()");
   18571   }
   18572 
   18573   isolate1->Enter();
   18574 
   18575   {
   18576     v8::Isolate::Scope iscope(isolate2);
   18577     v8::HandleScope scope(isolate2);
   18578     v8::Local<v8::Context> context =
   18579         v8::Local<v8::Context>::New(isolate2, context2);
   18580     v8::Context::Scope context_scope(context);
   18581     ExpectString("function f() { return foo; }; f()", "isolate 2");
   18582   }
   18583 
   18584   {
   18585     v8::HandleScope scope(v8::Isolate::GetCurrent());
   18586     v8::Local<v8::Context> context =
   18587         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   18588     v8::Context::Scope context_scope(context);
   18589     ExpectString("function f() { return foo; }; f()", "isolate 1");
   18590   }
   18591 
   18592   {
   18593     v8::Isolate::Scope iscope(isolate2);
   18594     context2.Reset();
   18595   }
   18596 
   18597   context1.Reset();
   18598   isolate1->Exit();
   18599 
   18600   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   18601   last_location = last_message = NULL;
   18602 
   18603   isolate1->Dispose();
   18604   CHECK_EQ(last_location, NULL);
   18605   CHECK_EQ(last_message, NULL);
   18606 
   18607   isolate2->Dispose();
   18608   CHECK_EQ(last_location, NULL);
   18609   CHECK_EQ(last_message, NULL);
   18610 
   18611   // Check that default isolate still runs.
   18612   {
   18613     v8::HandleScope scope(CcTest::isolate());
   18614     v8::Local<v8::Context> context =
   18615         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   18616     v8::Context::Scope context_scope(context);
   18617     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   18618   }
   18619 }
   18620 
   18621 
   18622 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   18623   v8::Isolate::Scope isolate_scope(isolate);
   18624   v8::HandleScope scope(isolate);
   18625   LocalContext context(isolate);
   18626   i::ScopedVector<char> code(1024);
   18627   i::OS::SNPrintF(code, "function fib(n) {"
   18628                         "  if (n <= 2) return 1;"
   18629                         "  return fib(n-1) + fib(n-2);"
   18630                         "}"
   18631                         "fib(%d)", limit);
   18632   Local<Value> value = CompileRun(code.start());
   18633   CHECK(value->IsNumber());
   18634   return static_cast<int>(value->NumberValue());
   18635 }
   18636 
   18637 class IsolateThread : public v8::internal::Thread {
   18638  public:
   18639   IsolateThread(v8::Isolate* isolate, int fib_limit)
   18640       : Thread("IsolateThread"),
   18641         isolate_(isolate),
   18642         fib_limit_(fib_limit),
   18643         result_(0) { }
   18644 
   18645   void Run() {
   18646     result_ = CalcFibonacci(isolate_, fib_limit_);
   18647   }
   18648 
   18649   int result() { return result_; }
   18650 
   18651  private:
   18652   v8::Isolate* isolate_;
   18653   int fib_limit_;
   18654   int result_;
   18655 };
   18656 
   18657 
   18658 TEST(MultipleIsolatesOnIndividualThreads) {
   18659   v8::Isolate* isolate1 = v8::Isolate::New();
   18660   v8::Isolate* isolate2 = v8::Isolate::New();
   18661 
   18662   IsolateThread thread1(isolate1, 21);
   18663   IsolateThread thread2(isolate2, 12);
   18664 
   18665   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   18666   thread1.Start();
   18667   thread2.Start();
   18668 
   18669   int result1 = CalcFibonacci(CcTest::isolate(), 21);
   18670   int result2 = CalcFibonacci(CcTest::isolate(), 12);
   18671 
   18672   thread1.Join();
   18673   thread2.Join();
   18674 
   18675   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   18676   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   18677   CHECK_EQ(result1, 10946);
   18678   CHECK_EQ(result2, 144);
   18679   CHECK_EQ(result1, thread1.result());
   18680   CHECK_EQ(result2, thread2.result());
   18681 
   18682   isolate1->Dispose();
   18683   isolate2->Dispose();
   18684 }
   18685 
   18686 
   18687 TEST(IsolateDifferentContexts) {
   18688   v8::Isolate* isolate = v8::Isolate::New();
   18689   Local<v8::Context> context;
   18690   {
   18691     v8::Isolate::Scope isolate_scope(isolate);
   18692     v8::HandleScope handle_scope(isolate);
   18693     context = v8::Context::New(isolate);
   18694     v8::Context::Scope context_scope(context);
   18695     Local<Value> v = CompileRun("2");
   18696     CHECK(v->IsNumber());
   18697     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
   18698   }
   18699   {
   18700     v8::Isolate::Scope isolate_scope(isolate);
   18701     v8::HandleScope handle_scope(isolate);
   18702     context = v8::Context::New(isolate);
   18703     v8::Context::Scope context_scope(context);
   18704     Local<Value> v = CompileRun("22");
   18705     CHECK(v->IsNumber());
   18706     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
   18707   }
   18708 }
   18709 
   18710 class InitDefaultIsolateThread : public v8::internal::Thread {
   18711  public:
   18712   enum TestCase {
   18713     IgnoreOOM,
   18714     SetResourceConstraints,
   18715     SetFatalHandler,
   18716     SetCounterFunction,
   18717     SetCreateHistogramFunction,
   18718     SetAddHistogramSampleFunction
   18719   };
   18720 
   18721   explicit InitDefaultIsolateThread(TestCase testCase)
   18722       : Thread("InitDefaultIsolateThread"),
   18723         testCase_(testCase),
   18724         result_(false) { }
   18725 
   18726   void Run() {
   18727     v8::Isolate* isolate = v8::Isolate::New();
   18728     isolate->Enter();
   18729     switch (testCase_) {
   18730     case IgnoreOOM:
   18731       v8::V8::IgnoreOutOfMemoryException();
   18732       break;
   18733 
   18734     case SetResourceConstraints: {
   18735       static const int K = 1024;
   18736       v8::ResourceConstraints constraints;
   18737       constraints.set_max_young_space_size(256 * K);
   18738       constraints.set_max_old_space_size(4 * K * K);
   18739       v8::SetResourceConstraints(CcTest::isolate(), &constraints);
   18740       break;
   18741     }
   18742 
   18743     case SetFatalHandler:
   18744       v8::V8::SetFatalErrorHandler(NULL);
   18745       break;
   18746 
   18747     case SetCounterFunction:
   18748       v8::V8::SetCounterFunction(NULL);
   18749       break;
   18750 
   18751     case SetCreateHistogramFunction:
   18752       v8::V8::SetCreateHistogramFunction(NULL);
   18753       break;
   18754 
   18755     case SetAddHistogramSampleFunction:
   18756       v8::V8::SetAddHistogramSampleFunction(NULL);
   18757       break;
   18758     }
   18759     isolate->Exit();
   18760     isolate->Dispose();
   18761     result_ = true;
   18762   }
   18763 
   18764   bool result() { return result_; }
   18765 
   18766  private:
   18767   TestCase testCase_;
   18768   bool result_;
   18769 };
   18770 
   18771 
   18772 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   18773   InitDefaultIsolateThread thread(testCase);
   18774   thread.Start();
   18775   thread.Join();
   18776   CHECK_EQ(thread.result(), true);
   18777 }
   18778 
   18779 
   18780 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
   18781   InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
   18782 }
   18783 
   18784 
   18785 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
   18786   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
   18787 }
   18788 
   18789 
   18790 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
   18791   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   18792 }
   18793 
   18794 
   18795 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
   18796   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   18797 }
   18798 
   18799 
   18800 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
   18801   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   18802 }
   18803 
   18804 
   18805 TEST(InitializeDefaultIsolateOnSecondaryThread6) {
   18806   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   18807 }
   18808 
   18809 
   18810 TEST(StringCheckMultipleContexts) {
   18811   const char* code =
   18812       "(function() { return \"a\".charAt(0); })()";
   18813 
   18814   {
   18815     // Run the code twice in the first context to initialize the call IC.
   18816     LocalContext context1;
   18817     v8::HandleScope scope(context1->GetIsolate());
   18818     ExpectString(code, "a");
   18819     ExpectString(code, "a");
   18820   }
   18821 
   18822   {
   18823     // Change the String.prototype in the second context and check
   18824     // that the right function gets called.
   18825     LocalContext context2;
   18826     v8::HandleScope scope(context2->GetIsolate());
   18827     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   18828     ExpectString(code, "not a");
   18829   }
   18830 }
   18831 
   18832 
   18833 TEST(NumberCheckMultipleContexts) {
   18834   const char* code =
   18835       "(function() { return (42).toString(); })()";
   18836 
   18837   {
   18838     // Run the code twice in the first context to initialize the call IC.
   18839     LocalContext context1;
   18840     v8::HandleScope scope(context1->GetIsolate());
   18841     ExpectString(code, "42");
   18842     ExpectString(code, "42");
   18843   }
   18844 
   18845   {
   18846     // Change the Number.prototype in the second context and check
   18847     // that the right function gets called.
   18848     LocalContext context2;
   18849     v8::HandleScope scope(context2->GetIsolate());
   18850     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   18851     ExpectString(code, "not 42");
   18852   }
   18853 }
   18854 
   18855 
   18856 TEST(BooleanCheckMultipleContexts) {
   18857   const char* code =
   18858       "(function() { return true.toString(); })()";
   18859 
   18860   {
   18861     // Run the code twice in the first context to initialize the call IC.
   18862     LocalContext context1;
   18863     v8::HandleScope scope(context1->GetIsolate());
   18864     ExpectString(code, "true");
   18865     ExpectString(code, "true");
   18866   }
   18867 
   18868   {
   18869     // Change the Boolean.prototype in the second context and check
   18870     // that the right function gets called.
   18871     LocalContext context2;
   18872     v8::HandleScope scope(context2->GetIsolate());
   18873     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   18874     ExpectString(code, "");
   18875   }
   18876 }
   18877 
   18878 
   18879 TEST(DontDeleteCellLoadIC) {
   18880   const char* function_code =
   18881       "function readCell() { while (true) { return cell; } }";
   18882 
   18883   {
   18884     // Run the code twice in the first context to initialize the load
   18885     // IC for a don't delete cell.
   18886     LocalContext context1;
   18887     v8::HandleScope scope(context1->GetIsolate());
   18888     CompileRun("var cell = \"first\";");
   18889     ExpectBoolean("delete cell", false);
   18890     CompileRun(function_code);
   18891     ExpectString("readCell()", "first");
   18892     ExpectString("readCell()", "first");
   18893   }
   18894 
   18895   {
   18896     // Use a deletable cell in the second context.
   18897     LocalContext context2;
   18898     v8::HandleScope scope(context2->GetIsolate());
   18899     CompileRun("cell = \"second\";");
   18900     CompileRun(function_code);
   18901     ExpectString("readCell()", "second");
   18902     ExpectBoolean("delete cell", true);
   18903     ExpectString("(function() {"
   18904                  "  try {"
   18905                  "    return readCell();"
   18906                  "  } catch(e) {"
   18907                  "    return e.toString();"
   18908                  "  }"
   18909                  "})()",
   18910                  "ReferenceError: cell is not defined");
   18911     CompileRun("cell = \"new_second\";");
   18912     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18913     ExpectString("readCell()", "new_second");
   18914     ExpectString("readCell()", "new_second");
   18915   }
   18916 }
   18917 
   18918 
   18919 TEST(DontDeleteCellLoadICForceDelete) {
   18920   const char* function_code =
   18921       "function readCell() { while (true) { return cell; } }";
   18922 
   18923   // Run the code twice to initialize the load IC for a don't delete
   18924   // cell.
   18925   LocalContext context;
   18926   v8::HandleScope scope(context->GetIsolate());
   18927   CompileRun("var cell = \"value\";");
   18928   ExpectBoolean("delete cell", false);
   18929   CompileRun(function_code);
   18930   ExpectString("readCell()", "value");
   18931   ExpectString("readCell()", "value");
   18932 
   18933   // Delete the cell using the API and check the inlined code works
   18934   // correctly.
   18935   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   18936   ExpectString("(function() {"
   18937                "  try {"
   18938                "    return readCell();"
   18939                "  } catch(e) {"
   18940                "    return e.toString();"
   18941                "  }"
   18942                "})()",
   18943                "ReferenceError: cell is not defined");
   18944 }
   18945 
   18946 
   18947 TEST(DontDeleteCellLoadICAPI) {
   18948   const char* function_code =
   18949       "function readCell() { while (true) { return cell; } }";
   18950 
   18951   // Run the code twice to initialize the load IC for a don't delete
   18952   // cell created using the API.
   18953   LocalContext context;
   18954   v8::HandleScope scope(context->GetIsolate());
   18955   context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
   18956   ExpectBoolean("delete cell", false);
   18957   CompileRun(function_code);
   18958   ExpectString("readCell()", "value");
   18959   ExpectString("readCell()", "value");
   18960 
   18961   // Delete the cell using the API and check the inlined code works
   18962   // correctly.
   18963   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   18964   ExpectString("(function() {"
   18965                "  try {"
   18966                "    return readCell();"
   18967                "  } catch(e) {"
   18968                "    return e.toString();"
   18969                "  }"
   18970                "})()",
   18971                "ReferenceError: cell is not defined");
   18972 }
   18973 
   18974 
   18975 class Visitor42 : public v8::PersistentHandleVisitor {
   18976  public:
   18977   explicit Visitor42(v8::Persistent<v8::Object>* object)
   18978       : counter_(0), object_(object) { }
   18979 
   18980   virtual void VisitPersistentHandle(Persistent<Value>* value,
   18981                                      uint16_t class_id) {
   18982     if (class_id != 42) return;
   18983     CHECK_EQ(42, value->WrapperClassId());
   18984     v8::Isolate* isolate = CcTest::isolate();
   18985     v8::HandleScope handle_scope(isolate);
   18986     v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   18987     v8::Handle<v8::Value> object =
   18988         v8::Local<v8::Object>::New(isolate, *object_);
   18989     CHECK(handle->IsObject());
   18990     CHECK_EQ(Handle<Object>::Cast(handle), object);
   18991     ++counter_;
   18992   }
   18993 
   18994   int counter_;
   18995   v8::Persistent<v8::Object>* object_;
   18996 };
   18997 
   18998 
   18999 TEST(PersistentHandleVisitor) {
   19000   LocalContext context;
   19001   v8::Isolate* isolate = context->GetIsolate();
   19002   v8::HandleScope scope(isolate);
   19003   v8::Persistent<v8::Object> object(isolate, v8::Object::New());
   19004   CHECK_EQ(0, object.WrapperClassId());
   19005   object.SetWrapperClassId(42);
   19006   CHECK_EQ(42, object.WrapperClassId());
   19007 
   19008   Visitor42 visitor(&object);
   19009   v8::V8::VisitHandlesWithClassIds(&visitor);
   19010   CHECK_EQ(1, visitor.counter_);
   19011 
   19012   object.Reset();
   19013 }
   19014 
   19015 
   19016 TEST(WrapperClassId) {
   19017   LocalContext context;
   19018   v8::Isolate* isolate = context->GetIsolate();
   19019   v8::HandleScope scope(isolate);
   19020   v8::Persistent<v8::Object> object(isolate, v8::Object::New());
   19021   CHECK_EQ(0, object.WrapperClassId());
   19022   object.SetWrapperClassId(65535);
   19023   CHECK_EQ(65535, object.WrapperClassId());
   19024   object.Reset();
   19025 }
   19026 
   19027 
   19028 TEST(PersistentHandleInNewSpaceVisitor) {
   19029   LocalContext context;
   19030   v8::Isolate* isolate = context->GetIsolate();
   19031   v8::HandleScope scope(isolate);
   19032   v8::Persistent<v8::Object> object1(isolate, v8::Object::New());
   19033   CHECK_EQ(0, object1.WrapperClassId());
   19034   object1.SetWrapperClassId(42);
   19035   CHECK_EQ(42, object1.WrapperClassId());
   19036 
   19037   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   19038 
   19039   v8::Persistent<v8::Object> object2(isolate, v8::Object::New());
   19040   CHECK_EQ(0, object2.WrapperClassId());
   19041   object2.SetWrapperClassId(42);
   19042   CHECK_EQ(42, object2.WrapperClassId());
   19043 
   19044   Visitor42 visitor(&object2);
   19045   v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
   19046   CHECK_EQ(1, visitor.counter_);
   19047 
   19048   object1.Reset();
   19049   object2.Reset();
   19050 }
   19051 
   19052 
   19053 TEST(RegExp) {
   19054   LocalContext context;
   19055   v8::HandleScope scope(context->GetIsolate());
   19056 
   19057   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
   19058   CHECK(re->IsRegExp());
   19059   CHECK(re->GetSource()->Equals(v8_str("foo")));
   19060   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19061 
   19062   re = v8::RegExp::New(v8_str("bar"),
   19063                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19064                                                       v8::RegExp::kGlobal));
   19065   CHECK(re->IsRegExp());
   19066   CHECK(re->GetSource()->Equals(v8_str("bar")));
   19067   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   19068            static_cast<int>(re->GetFlags()));
   19069 
   19070   re = v8::RegExp::New(v8_str("baz"),
   19071                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19072                                                       v8::RegExp::kMultiline));
   19073   CHECK(re->IsRegExp());
   19074   CHECK(re->GetSource()->Equals(v8_str("baz")));
   19075   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   19076            static_cast<int>(re->GetFlags()));
   19077 
   19078   re = CompileRun("/quux/").As<v8::RegExp>();
   19079   CHECK(re->IsRegExp());
   19080   CHECK(re->GetSource()->Equals(v8_str("quux")));
   19081   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19082 
   19083   re = CompileRun("/quux/gm").As<v8::RegExp>();
   19084   CHECK(re->IsRegExp());
   19085   CHECK(re->GetSource()->Equals(v8_str("quux")));
   19086   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   19087            static_cast<int>(re->GetFlags()));
   19088 
   19089   // Override the RegExp constructor and check the API constructor
   19090   // still works.
   19091   CompileRun("RegExp = function() {}");
   19092 
   19093   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
   19094   CHECK(re->IsRegExp());
   19095   CHECK(re->GetSource()->Equals(v8_str("foobar")));
   19096   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19097 
   19098   re = v8::RegExp::New(v8_str("foobarbaz"),
   19099                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19100                                                       v8::RegExp::kMultiline));
   19101   CHECK(re->IsRegExp());
   19102   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
   19103   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   19104            static_cast<int>(re->GetFlags()));
   19105 
   19106   context->Global()->Set(v8_str("re"), re);
   19107   ExpectTrue("re.test('FoobarbaZ')");
   19108 
   19109   // RegExps are objects on which you can set properties.
   19110   re->Set(v8_str("property"), v8::Integer::New(32));
   19111   v8::Handle<v8::Value> value(CompileRun("re.property"));
   19112   CHECK_EQ(32, value->Int32Value());
   19113 
   19114   v8::TryCatch try_catch;
   19115   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
   19116   CHECK(re.IsEmpty());
   19117   CHECK(try_catch.HasCaught());
   19118   context->Global()->Set(v8_str("ex"), try_catch.Exception());
   19119   ExpectTrue("ex instanceof SyntaxError");
   19120 }
   19121 
   19122 
   19123 THREADED_TEST(Equals) {
   19124   LocalContext localContext;
   19125   v8::HandleScope handleScope(localContext->GetIsolate());
   19126 
   19127   v8::Handle<v8::Object> globalProxy = localContext->Global();
   19128   v8::Handle<Value> global = globalProxy->GetPrototype();
   19129 
   19130   CHECK(global->StrictEquals(global));
   19131   CHECK(!global->StrictEquals(globalProxy));
   19132   CHECK(!globalProxy->StrictEquals(global));
   19133   CHECK(globalProxy->StrictEquals(globalProxy));
   19134 
   19135   CHECK(global->Equals(global));
   19136   CHECK(!global->Equals(globalProxy));
   19137   CHECK(!globalProxy->Equals(global));
   19138   CHECK(globalProxy->Equals(globalProxy));
   19139 }
   19140 
   19141 
   19142 static void Getter(v8::Local<v8::String> property,
   19143                    const v8::PropertyCallbackInfo<v8::Value>& info ) {
   19144   info.GetReturnValue().Set(v8_str("42!"));
   19145 }
   19146 
   19147 
   19148 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   19149   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
   19150   result->Set(0, v8_str("universalAnswer"));
   19151   info.GetReturnValue().Set(result);
   19152 }
   19153 
   19154 
   19155 TEST(NamedEnumeratorAndForIn) {
   19156   LocalContext context;
   19157   v8::HandleScope handle_scope(context->GetIsolate());
   19158   v8::Context::Scope context_scope(context.local());
   19159 
   19160   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
   19161   tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
   19162   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
   19163   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   19164         "var result = []; for (var k in o) result.push(k); result"));
   19165   CHECK_EQ(1, result->Length());
   19166   CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
   19167 }
   19168 
   19169 
   19170 TEST(DefinePropertyPostDetach) {
   19171   LocalContext context;
   19172   v8::HandleScope scope(context->GetIsolate());
   19173   v8::Handle<v8::Object> proxy = context->Global();
   19174   v8::Handle<v8::Function> define_property =
   19175       CompileRun("(function() {"
   19176                  "  Object.defineProperty("
   19177                  "    this,"
   19178                  "    1,"
   19179                  "    { configurable: true, enumerable: true, value: 3 });"
   19180                  "})").As<Function>();
   19181   context->DetachGlobal();
   19182   define_property->Call(proxy, 0, NULL);
   19183 }
   19184 
   19185 
   19186 static void InstallContextId(v8::Handle<Context> context, int id) {
   19187   Context::Scope scope(context);
   19188   CompileRun("Object.prototype").As<Object>()->
   19189       Set(v8_str("context_id"), v8::Integer::New(id));
   19190 }
   19191 
   19192 
   19193 static void CheckContextId(v8::Handle<Object> object, int expected) {
   19194   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
   19195 }
   19196 
   19197 
   19198 THREADED_TEST(CreationContext) {
   19199   HandleScope handle_scope(CcTest::isolate());
   19200   Handle<Context> context1 = Context::New(CcTest::isolate());
   19201   InstallContextId(context1, 1);
   19202   Handle<Context> context2 = Context::New(CcTest::isolate());
   19203   InstallContextId(context2, 2);
   19204   Handle<Context> context3 = Context::New(CcTest::isolate());
   19205   InstallContextId(context3, 3);
   19206 
   19207   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
   19208 
   19209   Local<Object> object1;
   19210   Local<Function> func1;
   19211   {
   19212     Context::Scope scope(context1);
   19213     object1 = Object::New();
   19214     func1 = tmpl->GetFunction();
   19215   }
   19216 
   19217   Local<Object> object2;
   19218   Local<Function> func2;
   19219   {
   19220     Context::Scope scope(context2);
   19221     object2 = Object::New();
   19222     func2 = tmpl->GetFunction();
   19223   }
   19224 
   19225   Local<Object> instance1;
   19226   Local<Object> instance2;
   19227 
   19228   {
   19229     Context::Scope scope(context3);
   19230     instance1 = func1->NewInstance();
   19231     instance2 = func2->NewInstance();
   19232   }
   19233 
   19234   CHECK(object1->CreationContext() == context1);
   19235   CheckContextId(object1, 1);
   19236   CHECK(func1->CreationContext() == context1);
   19237   CheckContextId(func1, 1);
   19238   CHECK(instance1->CreationContext() == context1);
   19239   CheckContextId(instance1, 1);
   19240   CHECK(object2->CreationContext() == context2);
   19241   CheckContextId(object2, 2);
   19242   CHECK(func2->CreationContext() == context2);
   19243   CheckContextId(func2, 2);
   19244   CHECK(instance2->CreationContext() == context2);
   19245   CheckContextId(instance2, 2);
   19246 
   19247   {
   19248     Context::Scope scope(context1);
   19249     CHECK(object1->CreationContext() == context1);
   19250     CheckContextId(object1, 1);
   19251     CHECK(func1->CreationContext() == context1);
   19252     CheckContextId(func1, 1);
   19253     CHECK(instance1->CreationContext() == context1);
   19254     CheckContextId(instance1, 1);
   19255     CHECK(object2->CreationContext() == context2);
   19256     CheckContextId(object2, 2);
   19257     CHECK(func2->CreationContext() == context2);
   19258     CheckContextId(func2, 2);
   19259     CHECK(instance2->CreationContext() == context2);
   19260     CheckContextId(instance2, 2);
   19261   }
   19262 
   19263   {
   19264     Context::Scope scope(context2);
   19265     CHECK(object1->CreationContext() == context1);
   19266     CheckContextId(object1, 1);
   19267     CHECK(func1->CreationContext() == context1);
   19268     CheckContextId(func1, 1);
   19269     CHECK(instance1->CreationContext() == context1);
   19270     CheckContextId(instance1, 1);
   19271     CHECK(object2->CreationContext() == context2);
   19272     CheckContextId(object2, 2);
   19273     CHECK(func2->CreationContext() == context2);
   19274     CheckContextId(func2, 2);
   19275     CHECK(instance2->CreationContext() == context2);
   19276     CheckContextId(instance2, 2);
   19277   }
   19278 }
   19279 
   19280 
   19281 THREADED_TEST(CreationContextOfJsFunction) {
   19282   HandleScope handle_scope(CcTest::isolate());
   19283   Handle<Context> context = Context::New(CcTest::isolate());
   19284   InstallContextId(context, 1);
   19285 
   19286   Local<Object> function;
   19287   {
   19288     Context::Scope scope(context);
   19289     function = CompileRun("function foo() {}; foo").As<Object>();
   19290   }
   19291 
   19292   CHECK(function->CreationContext() == context);
   19293   CheckContextId(function, 1);
   19294 }
   19295 
   19296 
   19297 void HasOwnPropertyIndexedPropertyGetter(
   19298     uint32_t index,
   19299     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19300   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   19301 }
   19302 
   19303 
   19304 void HasOwnPropertyNamedPropertyGetter(
   19305     Local<String> property,
   19306     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19307   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
   19308 }
   19309 
   19310 
   19311 void HasOwnPropertyIndexedPropertyQuery(
   19312     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   19313   if (index == 42) info.GetReturnValue().Set(1);
   19314 }
   19315 
   19316 
   19317 void HasOwnPropertyNamedPropertyQuery(
   19318     Local<String> property,
   19319     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   19320   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
   19321 }
   19322 
   19323 
   19324 void HasOwnPropertyNamedPropertyQuery2(
   19325     Local<String> property,
   19326     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   19327   if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
   19328 }
   19329 
   19330 
   19331 void HasOwnPropertyAccessorGetter(
   19332     Local<String> property,
   19333     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19334   info.GetReturnValue().Set(v8_str("yes"));
   19335 }
   19336 
   19337 
   19338 TEST(HasOwnProperty) {
   19339   LocalContext env;
   19340   v8::HandleScope scope(env->GetIsolate());
   19341   { // Check normal properties and defined getters.
   19342     Handle<Value> value = CompileRun(
   19343         "function Foo() {"
   19344         "    this.foo = 11;"
   19345         "    this.__defineGetter__('baz', function() { return 1; });"
   19346         "};"
   19347         "function Bar() { "
   19348         "    this.bar = 13;"
   19349         "    this.__defineGetter__('bla', function() { return 2; });"
   19350         "};"
   19351         "Bar.prototype = new Foo();"
   19352         "new Bar();");
   19353     CHECK(value->IsObject());
   19354     Handle<Object> object = value->ToObject();
   19355     CHECK(object->Has(v8_str("foo")));
   19356     CHECK(!object->HasOwnProperty(v8_str("foo")));
   19357     CHECK(object->HasOwnProperty(v8_str("bar")));
   19358     CHECK(object->Has(v8_str("baz")));
   19359     CHECK(!object->HasOwnProperty(v8_str("baz")));
   19360     CHECK(object->HasOwnProperty(v8_str("bla")));
   19361   }
   19362   { // Check named getter interceptors.
   19363     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   19364     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
   19365     Handle<Object> instance = templ->NewInstance();
   19366     CHECK(!instance->HasOwnProperty(v8_str("42")));
   19367     CHECK(instance->HasOwnProperty(v8_str("foo")));
   19368     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   19369   }
   19370   { // Check indexed getter interceptors.
   19371     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   19372     templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
   19373     Handle<Object> instance = templ->NewInstance();
   19374     CHECK(instance->HasOwnProperty(v8_str("42")));
   19375     CHECK(!instance->HasOwnProperty(v8_str("43")));
   19376     CHECK(!instance->HasOwnProperty(v8_str("foo")));
   19377   }
   19378   { // Check named query interceptors.
   19379     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   19380     templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
   19381     Handle<Object> instance = templ->NewInstance();
   19382     CHECK(instance->HasOwnProperty(v8_str("foo")));
   19383     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   19384   }
   19385   { // Check indexed query interceptors.
   19386     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   19387     templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
   19388     Handle<Object> instance = templ->NewInstance();
   19389     CHECK(instance->HasOwnProperty(v8_str("42")));
   19390     CHECK(!instance->HasOwnProperty(v8_str("41")));
   19391   }
   19392   { // Check callbacks.
   19393     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   19394     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   19395     Handle<Object> instance = templ->NewInstance();
   19396     CHECK(instance->HasOwnProperty(v8_str("foo")));
   19397     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   19398   }
   19399   { // Check that query wins on disagreement.
   19400     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   19401     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
   19402                                    0,
   19403                                    HasOwnPropertyNamedPropertyQuery2);
   19404     Handle<Object> instance = templ->NewInstance();
   19405     CHECK(!instance->HasOwnProperty(v8_str("foo")));
   19406     CHECK(instance->HasOwnProperty(v8_str("bar")));
   19407   }
   19408 }
   19409 
   19410 
   19411 TEST(IndexedInterceptorWithStringProto) {
   19412   v8::HandleScope scope(CcTest::isolate());
   19413   Handle<ObjectTemplate> templ = ObjectTemplate::New();
   19414   templ->SetIndexedPropertyHandler(NULL,
   19415                                    NULL,
   19416                                    HasOwnPropertyIndexedPropertyQuery);
   19417   LocalContext context;
   19418   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   19419   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   19420   // These should be intercepted.
   19421   CHECK(CompileRun("42 in obj")->BooleanValue());
   19422   CHECK(CompileRun("'42' in obj")->BooleanValue());
   19423   // These should fall through to the String prototype.
   19424   CHECK(CompileRun("0 in obj")->BooleanValue());
   19425   CHECK(CompileRun("'0' in obj")->BooleanValue());
   19426   // And these should both fail.
   19427   CHECK(!CompileRun("32 in obj")->BooleanValue());
   19428   CHECK(!CompileRun("'32' in obj")->BooleanValue());
   19429 }
   19430 
   19431 
   19432 void CheckCodeGenerationAllowed() {
   19433   Handle<Value> result = CompileRun("eval('42')");
   19434   CHECK_EQ(42, result->Int32Value());
   19435   result = CompileRun("(function(e) { return e('42'); })(eval)");
   19436   CHECK_EQ(42, result->Int32Value());
   19437   result = CompileRun("var f = new Function('return 42'); f()");
   19438   CHECK_EQ(42, result->Int32Value());
   19439 }
   19440 
   19441 
   19442 void CheckCodeGenerationDisallowed() {
   19443   TryCatch try_catch;
   19444 
   19445   Handle<Value> result = CompileRun("eval('42')");
   19446   CHECK(result.IsEmpty());
   19447   CHECK(try_catch.HasCaught());
   19448   try_catch.Reset();
   19449 
   19450   result = CompileRun("(function(e) { return e('42'); })(eval)");
   19451   CHECK(result.IsEmpty());
   19452   CHECK(try_catch.HasCaught());
   19453   try_catch.Reset();
   19454 
   19455   result = CompileRun("var f = new Function('return 42'); f()");
   19456   CHECK(result.IsEmpty());
   19457   CHECK(try_catch.HasCaught());
   19458 }
   19459 
   19460 
   19461 bool CodeGenerationAllowed(Local<Context> context) {
   19462   ApiTestFuzzer::Fuzz();
   19463   return true;
   19464 }
   19465 
   19466 
   19467 bool CodeGenerationDisallowed(Local<Context> context) {
   19468   ApiTestFuzzer::Fuzz();
   19469   return false;
   19470 }
   19471 
   19472 
   19473 THREADED_TEST(AllowCodeGenFromStrings) {
   19474   LocalContext context;
   19475   v8::HandleScope scope(context->GetIsolate());
   19476 
   19477   // eval and the Function constructor allowed by default.
   19478   CHECK(context->IsCodeGenerationFromStringsAllowed());
   19479   CheckCodeGenerationAllowed();
   19480 
   19481   // Disallow eval and the Function constructor.
   19482   context->AllowCodeGenerationFromStrings(false);
   19483   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   19484   CheckCodeGenerationDisallowed();
   19485 
   19486   // Allow again.
   19487   context->AllowCodeGenerationFromStrings(true);
   19488   CheckCodeGenerationAllowed();
   19489 
   19490   // Disallow but setting a global callback that will allow the calls.
   19491   context->AllowCodeGenerationFromStrings(false);
   19492   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
   19493   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   19494   CheckCodeGenerationAllowed();
   19495 
   19496   // Set a callback that disallows the code generation.
   19497   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
   19498   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   19499   CheckCodeGenerationDisallowed();
   19500 }
   19501 
   19502 
   19503 TEST(SetErrorMessageForCodeGenFromStrings) {
   19504   LocalContext context;
   19505   v8::HandleScope scope(context->GetIsolate());
   19506   TryCatch try_catch;
   19507 
   19508   Handle<String> message = v8_str("Message") ;
   19509   Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
   19510   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
   19511   context->AllowCodeGenerationFromStrings(false);
   19512   context->SetErrorMessageForCodeGenerationFromStrings(message);
   19513   Handle<Value> result = CompileRun("eval('42')");
   19514   CHECK(result.IsEmpty());
   19515   CHECK(try_catch.HasCaught());
   19516   Handle<String> actual_message = try_catch.Message()->Get();
   19517   CHECK(expected_message->Equals(actual_message));
   19518 }
   19519 
   19520 
   19521 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   19522 }
   19523 
   19524 
   19525 THREADED_TEST(CallAPIFunctionOnNonObject) {
   19526   LocalContext context;
   19527   v8::HandleScope scope(context->GetIsolate());
   19528   Handle<FunctionTemplate> templ = v8::FunctionTemplate::New(NonObjectThis);
   19529   Handle<Function> function = templ->GetFunction();
   19530   context->Global()->Set(v8_str("f"), function);
   19531   TryCatch try_catch;
   19532   CompileRun("f.call(2)");
   19533 }
   19534 
   19535 
   19536 // Regression test for issue 1470.
   19537 THREADED_TEST(ReadOnlyIndexedProperties) {
   19538   v8::HandleScope scope(CcTest::isolate());
   19539   Local<ObjectTemplate> templ = ObjectTemplate::New();
   19540 
   19541   LocalContext context;
   19542   Local<v8::Object> obj = templ->NewInstance();
   19543   context->Global()->Set(v8_str("obj"), obj);
   19544   obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
   19545   obj->Set(v8_str("1"), v8_str("foobar"));
   19546   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
   19547   obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
   19548   obj->Set(v8_num(2), v8_str("foobar"));
   19549   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
   19550 
   19551   // Test non-smi case.
   19552   obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
   19553   obj->Set(v8_str("2000000000"), v8_str("foobar"));
   19554   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
   19555 }
   19556 
   19557 
   19558 THREADED_TEST(Regress1516) {
   19559   LocalContext context;
   19560   v8::HandleScope scope(context->GetIsolate());
   19561 
   19562   { v8::HandleScope temp_scope(context->GetIsolate());
   19563     CompileRun("({'a': 0})");
   19564   }
   19565 
   19566   int elements;
   19567   { i::MapCache* map_cache =
   19568         i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
   19569     elements = map_cache->NumberOfElements();
   19570     CHECK_LE(1, elements);
   19571   }
   19572 
   19573   CcTest::heap()->CollectAllGarbage(
   19574       i::Heap::kAbortIncrementalMarkingMask);
   19575   { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
   19576     if (raw_map_cache != CcTest::heap()->undefined_value()) {
   19577       i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
   19578       CHECK_GT(elements, map_cache->NumberOfElements());
   19579     }
   19580   }
   19581 }
   19582 
   19583 
   19584 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
   19585                                                 Local<Value> name,
   19586                                                 v8::AccessType type,
   19587                                                 Local<Value> data) {
   19588   // Only block read access to __proto__.
   19589   if (type == v8::ACCESS_GET &&
   19590       name->IsString() &&
   19591       name->ToString()->Length() == 9 &&
   19592       name->ToString()->Utf8Length() == 9) {
   19593     char buffer[10];
   19594     CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
   19595     return strncmp(buffer, "__proto__", 9) != 0;
   19596   }
   19597 
   19598   return true;
   19599 }
   19600 
   19601 
   19602 THREADED_TEST(Regress93759) {
   19603   v8::Isolate* isolate = CcTest::isolate();
   19604   HandleScope scope(isolate);
   19605 
   19606   // Template for object with security check.
   19607   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New();
   19608   // We don't do indexing, so any callback can be used for that.
   19609   no_proto_template->SetAccessCheckCallbacks(
   19610       BlockProtoNamedSecurityTestCallback,
   19611       IndexedSecurityTestCallback);
   19612 
   19613   // Templates for objects with hidden prototypes and possibly security check.
   19614   Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New();
   19615   hidden_proto_template->SetHiddenPrototype(true);
   19616 
   19617   Local<FunctionTemplate> protected_hidden_proto_template =
   19618       v8::FunctionTemplate::New();
   19619   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
   19620       BlockProtoNamedSecurityTestCallback,
   19621       IndexedSecurityTestCallback);
   19622   protected_hidden_proto_template->SetHiddenPrototype(true);
   19623 
   19624   // Context for "foreign" objects used in test.
   19625   Local<Context> context = v8::Context::New(isolate);
   19626   context->Enter();
   19627 
   19628   // Plain object, no security check.
   19629   Local<Object> simple_object = Object::New();
   19630 
   19631   // Object with explicit security check.
   19632   Local<Object> protected_object =
   19633       no_proto_template->NewInstance();
   19634 
   19635   // JSGlobalProxy object, always have security check.
   19636   Local<Object> proxy_object =
   19637       context->Global();
   19638 
   19639   // Global object, the  prototype of proxy_object. No security checks.
   19640   Local<Object> global_object =
   19641       proxy_object->GetPrototype()->ToObject();
   19642 
   19643   // Hidden prototype without security check.
   19644   Local<Object> hidden_prototype =
   19645       hidden_proto_template->GetFunction()->NewInstance();
   19646   Local<Object> object_with_hidden =
   19647     Object::New();
   19648   object_with_hidden->SetPrototype(hidden_prototype);
   19649 
   19650   // Hidden prototype with security check on the hidden prototype.
   19651   Local<Object> protected_hidden_prototype =
   19652       protected_hidden_proto_template->GetFunction()->NewInstance();
   19653   Local<Object> object_with_protected_hidden =
   19654     Object::New();
   19655   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
   19656 
   19657   context->Exit();
   19658 
   19659   // Template for object for second context. Values to test are put on it as
   19660   // properties.
   19661   Local<ObjectTemplate> global_template = ObjectTemplate::New();
   19662   global_template->Set(v8_str("simple"), simple_object);
   19663   global_template->Set(v8_str("protected"), protected_object);
   19664   global_template->Set(v8_str("global"), global_object);
   19665   global_template->Set(v8_str("proxy"), proxy_object);
   19666   global_template->Set(v8_str("hidden"), object_with_hidden);
   19667   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
   19668 
   19669   LocalContext context2(NULL, global_template);
   19670 
   19671   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   19672   CHECK(result1->Equals(simple_object->GetPrototype()));
   19673 
   19674   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
   19675   CHECK(result2->Equals(Undefined(isolate)));
   19676 
   19677   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
   19678   CHECK(result3->Equals(global_object->GetPrototype()));
   19679 
   19680   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
   19681   CHECK(result4->Equals(Undefined(isolate)));
   19682 
   19683   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
   19684   CHECK(result5->Equals(
   19685       object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
   19686 
   19687   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
   19688   CHECK(result6->Equals(Undefined(isolate)));
   19689 }
   19690 
   19691 
   19692 THREADED_TEST(Regress125988) {
   19693   v8::HandleScope scope(CcTest::isolate());
   19694   Handle<FunctionTemplate> intercept = FunctionTemplate::New();
   19695   AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
   19696   LocalContext env;
   19697   env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
   19698   CompileRun("var a = new Object();"
   19699              "var b = new Intercept();"
   19700              "var c = new Object();"
   19701              "c.__proto__ = b;"
   19702              "b.__proto__ = a;"
   19703              "a.x = 23;"
   19704              "for (var i = 0; i < 3; i++) c.x;");
   19705   ExpectBoolean("c.hasOwnProperty('x')", false);
   19706   ExpectInt32("c.x", 23);
   19707   CompileRun("a.y = 42;"
   19708              "for (var i = 0; i < 3; i++) c.x;");
   19709   ExpectBoolean("c.hasOwnProperty('x')", false);
   19710   ExpectInt32("c.x", 23);
   19711   ExpectBoolean("c.hasOwnProperty('y')", false);
   19712   ExpectInt32("c.y", 42);
   19713 }
   19714 
   19715 
   19716 static void TestReceiver(Local<Value> expected_result,
   19717                          Local<Value> expected_receiver,
   19718                          const char* code) {
   19719   Local<Value> result = CompileRun(code);
   19720   CHECK(result->IsObject());
   19721   CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
   19722   CHECK(expected_result->Equals(result->ToObject()->Get(0)));
   19723 }
   19724 
   19725 
   19726 THREADED_TEST(ForeignFunctionReceiver) {
   19727   v8::Isolate* isolate = CcTest::isolate();
   19728   HandleScope scope(isolate);
   19729 
   19730   // Create two contexts with different "id" properties ('i' and 'o').
   19731   // Call a function both from its own context and from a the foreign
   19732   // context, and see what "this" is bound to (returning both "this"
   19733   // and "this.id" for comparison).
   19734 
   19735   Local<Context> foreign_context = v8::Context::New(isolate);
   19736   foreign_context->Enter();
   19737   Local<Value> foreign_function =
   19738     CompileRun("function func() { return { 0: this.id, "
   19739                "                           1: this, "
   19740                "                           toString: function() { "
   19741                "                               return this[0];"
   19742                "                           }"
   19743                "                         };"
   19744                "}"
   19745                "var id = 'i';"
   19746                "func;");
   19747   CHECK(foreign_function->IsFunction());
   19748   foreign_context->Exit();
   19749 
   19750   LocalContext context;
   19751 
   19752   Local<String> password = v8_str("Password");
   19753   // Don't get hit by security checks when accessing foreign_context's
   19754   // global receiver (aka. global proxy).
   19755   context->SetSecurityToken(password);
   19756   foreign_context->SetSecurityToken(password);
   19757 
   19758   Local<String> i = v8_str("i");
   19759   Local<String> o = v8_str("o");
   19760   Local<String> id = v8_str("id");
   19761 
   19762   CompileRun("function ownfunc() { return { 0: this.id, "
   19763              "                              1: this, "
   19764              "                              toString: function() { "
   19765              "                                  return this[0];"
   19766              "                              }"
   19767              "                             };"
   19768              "}"
   19769              "var id = 'o';"
   19770              "ownfunc");
   19771   context->Global()->Set(v8_str("func"), foreign_function);
   19772 
   19773   // Sanity check the contexts.
   19774   CHECK(i->Equals(foreign_context->Global()->Get(id)));
   19775   CHECK(o->Equals(context->Global()->Get(id)));
   19776 
   19777   // Checking local function's receiver.
   19778   // Calling function using its call/apply methods.
   19779   TestReceiver(o, context->Global(), "ownfunc.call()");
   19780   TestReceiver(o, context->Global(), "ownfunc.apply()");
   19781   // Making calls through built-in functions.
   19782   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   19783   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
   19784   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
   19785   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
   19786   // Calling with environment record as base.
   19787   TestReceiver(o, context->Global(), "ownfunc()");
   19788   // Calling with no base.
   19789   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   19790 
   19791   // Checking foreign function return value.
   19792   // Calling function using its call/apply methods.
   19793   TestReceiver(i, foreign_context->Global(), "func.call()");
   19794   TestReceiver(i, foreign_context->Global(), "func.apply()");
   19795   // Calling function using another context's call/apply methods.
   19796   TestReceiver(i, foreign_context->Global(),
   19797                "Function.prototype.call.call(func)");
   19798   TestReceiver(i, foreign_context->Global(),
   19799                "Function.prototype.call.apply(func)");
   19800   TestReceiver(i, foreign_context->Global(),
   19801                "Function.prototype.apply.call(func)");
   19802   TestReceiver(i, foreign_context->Global(),
   19803                "Function.prototype.apply.apply(func)");
   19804   // Making calls through built-in functions.
   19805   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   19806   // ToString(func()) is func()[0], i.e., the returned this.id.
   19807   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
   19808   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
   19809   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
   19810 
   19811   // TODO(1547): Make the following also return "i".
   19812   // Calling with environment record as base.
   19813   TestReceiver(o, context->Global(), "func()");
   19814   // Calling with no base.
   19815   TestReceiver(o, context->Global(), "(1,func)()");
   19816 }
   19817 
   19818 
   19819 uint8_t callback_fired = 0;
   19820 
   19821 
   19822 void CallCompletedCallback1() {
   19823   i::OS::Print("Firing callback 1.\n");
   19824   callback_fired ^= 1;  // Toggle first bit.
   19825 }
   19826 
   19827 
   19828 void CallCompletedCallback2() {
   19829   i::OS::Print("Firing callback 2.\n");
   19830   callback_fired ^= 2;  // Toggle second bit.
   19831 }
   19832 
   19833 
   19834 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   19835   int32_t level = args[0]->Int32Value();
   19836   if (level < 3) {
   19837     level++;
   19838     i::OS::Print("Entering recursion level %d.\n", level);
   19839     char script[64];
   19840     i::Vector<char> script_vector(script, sizeof(script));
   19841     i::OS::SNPrintF(script_vector, "recursion(%d)", level);
   19842     CompileRun(script_vector.start());
   19843     i::OS::Print("Leaving recursion level %d.\n", level);
   19844     CHECK_EQ(0, callback_fired);
   19845   } else {
   19846     i::OS::Print("Recursion ends.\n");
   19847     CHECK_EQ(0, callback_fired);
   19848   }
   19849 }
   19850 
   19851 
   19852 TEST(CallCompletedCallback) {
   19853   LocalContext env;
   19854   v8::HandleScope scope(env->GetIsolate());
   19855   v8::Handle<v8::FunctionTemplate> recursive_runtime =
   19856       v8::FunctionTemplate::New(RecursiveCall);
   19857   env->Global()->Set(v8_str("recursion"),
   19858                      recursive_runtime->GetFunction());
   19859   // Adding the same callback a second time has no effect.
   19860   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
   19861   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
   19862   v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
   19863   i::OS::Print("--- Script (1) ---\n");
   19864   Local<Script> script = v8::Script::Compile(
   19865       v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
   19866   script->Run();
   19867   CHECK_EQ(3, callback_fired);
   19868 
   19869   i::OS::Print("\n--- Script (2) ---\n");
   19870   callback_fired = 0;
   19871   v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
   19872   script->Run();
   19873   CHECK_EQ(2, callback_fired);
   19874 
   19875   i::OS::Print("\n--- Function ---\n");
   19876   callback_fired = 0;
   19877   Local<Function> recursive_function =
   19878       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
   19879   v8::Handle<Value> args[] = { v8_num(0) };
   19880   recursive_function->Call(env->Global(), 1, args);
   19881   CHECK_EQ(2, callback_fired);
   19882 }
   19883 
   19884 
   19885 void CallCompletedCallbackNoException() {
   19886   v8::HandleScope scope(CcTest::isolate());
   19887   CompileRun("1+1;");
   19888 }
   19889 
   19890 
   19891 void CallCompletedCallbackException() {
   19892   v8::HandleScope scope(CcTest::isolate());
   19893   CompileRun("throw 'second exception';");
   19894 }
   19895 
   19896 
   19897 TEST(CallCompletedCallbackOneException) {
   19898   LocalContext env;
   19899   v8::HandleScope scope(env->GetIsolate());
   19900   v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
   19901   CompileRun("throw 'exception';");
   19902 }
   19903 
   19904 
   19905 TEST(CallCompletedCallbackTwoExceptions) {
   19906   LocalContext env;
   19907   v8::HandleScope scope(env->GetIsolate());
   19908   v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
   19909   CompileRun("throw 'first exception';");
   19910 }
   19911 
   19912 
   19913 static int probes_counter = 0;
   19914 static int misses_counter = 0;
   19915 static int updates_counter = 0;
   19916 
   19917 
   19918 static int* LookupCounter(const char* name) {
   19919   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
   19920     return &probes_counter;
   19921   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
   19922     return &misses_counter;
   19923   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
   19924     return &updates_counter;
   19925   }
   19926   return NULL;
   19927 }
   19928 
   19929 
   19930 static const char* kMegamorphicTestProgram =
   19931     "function ClassA() { };"
   19932     "function ClassB() { };"
   19933     "ClassA.prototype.foo = function() { };"
   19934     "ClassB.prototype.foo = function() { };"
   19935     "function fooify(obj) { obj.foo(); };"
   19936     "var a = new ClassA();"
   19937     "var b = new ClassB();"
   19938     "for (var i = 0; i < 10000; i++) {"
   19939     "  fooify(a);"
   19940     "  fooify(b);"
   19941     "}";
   19942 
   19943 
   19944 static void StubCacheHelper(bool primary) {
   19945   V8::SetCounterFunction(LookupCounter);
   19946   USE(kMegamorphicTestProgram);
   19947 #ifdef DEBUG
   19948   i::FLAG_native_code_counters = true;
   19949   if (primary) {
   19950     i::FLAG_test_primary_stub_cache = true;
   19951   } else {
   19952     i::FLAG_test_secondary_stub_cache = true;
   19953   }
   19954   i::FLAG_crankshaft = false;
   19955   LocalContext env;
   19956   v8::HandleScope scope(env->GetIsolate());
   19957   int initial_probes = probes_counter;
   19958   int initial_misses = misses_counter;
   19959   int initial_updates = updates_counter;
   19960   CompileRun(kMegamorphicTestProgram);
   19961   int probes = probes_counter - initial_probes;
   19962   int misses = misses_counter - initial_misses;
   19963   int updates = updates_counter - initial_updates;
   19964   CHECK_LT(updates, 10);
   19965   CHECK_LT(misses, 10);
   19966   CHECK_GE(probes, 10000);
   19967 #endif
   19968 }
   19969 
   19970 
   19971 TEST(SecondaryStubCache) {
   19972   StubCacheHelper(true);
   19973 }
   19974 
   19975 
   19976 TEST(PrimaryStubCache) {
   19977   StubCacheHelper(false);
   19978 }
   19979 
   19980 
   19981 static int cow_arrays_created_runtime = 0;
   19982 
   19983 
   19984 static int* LookupCounterCOWArrays(const char* name) {
   19985   if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
   19986     return &cow_arrays_created_runtime;
   19987   }
   19988   return NULL;
   19989 }
   19990 
   19991 
   19992 TEST(CheckCOWArraysCreatedRuntimeCounter) {
   19993   V8::SetCounterFunction(LookupCounterCOWArrays);
   19994 #ifdef DEBUG
   19995   i::FLAG_native_code_counters = true;
   19996   LocalContext env;
   19997   v8::HandleScope scope(env->GetIsolate());
   19998   int initial_cow_arrays = cow_arrays_created_runtime;
   19999   CompileRun("var o = [1, 2, 3];");
   20000   CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
   20001   CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
   20002   CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
   20003   CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
   20004   CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
   20005 #endif
   20006 }
   20007 
   20008 
   20009 TEST(StaticGetters) {
   20010   LocalContext context;
   20011   i::Factory* factory = CcTest::i_isolate()->factory();
   20012   v8::Isolate* isolate = CcTest::isolate();
   20013   v8::HandleScope scope(isolate);
   20014   i::Handle<i::Object> undefined_value = factory->undefined_value();
   20015   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   20016   i::Handle<i::Object> null_value = factory->null_value();
   20017   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   20018   i::Handle<i::Object> true_value = factory->true_value();
   20019   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   20020   i::Handle<i::Object> false_value = factory->false_value();
   20021   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   20022 }
   20023 
   20024 
   20025 UNINITIALIZED_TEST(IsolateEmbedderData) {
   20026   CcTest::DisableAutomaticDispose();
   20027   v8::Isolate* isolate = v8::Isolate::New();
   20028   isolate->Enter();
   20029   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   20030   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20031     CHECK_EQ(NULL, isolate->GetData(slot));
   20032     CHECK_EQ(NULL, i_isolate->GetData(slot));
   20033   }
   20034   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20035     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   20036     isolate->SetData(slot, data);
   20037   }
   20038   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20039     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   20040     CHECK_EQ(data, isolate->GetData(slot));
   20041     CHECK_EQ(data, i_isolate->GetData(slot));
   20042   }
   20043   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20044     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   20045     isolate->SetData(slot, data);
   20046   }
   20047   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20048     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   20049     CHECK_EQ(data, isolate->GetData(slot));
   20050     CHECK_EQ(data, i_isolate->GetData(slot));
   20051   }
   20052   isolate->Exit();
   20053   isolate->Dispose();
   20054 }
   20055 
   20056 
   20057 TEST(StringEmpty) {
   20058   LocalContext context;
   20059   i::Factory* factory = CcTest::i_isolate()->factory();
   20060   v8::Isolate* isolate = CcTest::isolate();
   20061   v8::HandleScope scope(isolate);
   20062   i::Handle<i::Object> empty_string = factory->empty_string();
   20063   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty()) == *empty_string);
   20064   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   20065 }
   20066 
   20067 
   20068 static int instance_checked_getter_count = 0;
   20069 static void InstanceCheckedGetter(
   20070     Local<String> name,
   20071     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20072   CHECK_EQ(name, v8_str("foo"));
   20073   instance_checked_getter_count++;
   20074   info.GetReturnValue().Set(v8_num(11));
   20075 }
   20076 
   20077 
   20078 static int instance_checked_setter_count = 0;
   20079 static void InstanceCheckedSetter(Local<String> name,
   20080                       Local<Value> value,
   20081                       const v8::PropertyCallbackInfo<void>& info) {
   20082   CHECK_EQ(name, v8_str("foo"));
   20083   CHECK_EQ(value, v8_num(23));
   20084   instance_checked_setter_count++;
   20085 }
   20086 
   20087 
   20088 static void CheckInstanceCheckedResult(int getters,
   20089                                        int setters,
   20090                                        bool expects_callbacks,
   20091                                        TryCatch* try_catch) {
   20092   if (expects_callbacks) {
   20093     CHECK(!try_catch->HasCaught());
   20094     CHECK_EQ(getters, instance_checked_getter_count);
   20095     CHECK_EQ(setters, instance_checked_setter_count);
   20096   } else {
   20097     CHECK(try_catch->HasCaught());
   20098     CHECK_EQ(0, instance_checked_getter_count);
   20099     CHECK_EQ(0, instance_checked_setter_count);
   20100   }
   20101   try_catch->Reset();
   20102 }
   20103 
   20104 
   20105 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   20106   instance_checked_getter_count = 0;
   20107   instance_checked_setter_count = 0;
   20108   TryCatch try_catch;
   20109 
   20110   // Test path through generic runtime code.
   20111   CompileRun("obj.foo");
   20112   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   20113   CompileRun("obj.foo = 23");
   20114   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   20115 
   20116   // Test path through generated LoadIC and StoredIC.
   20117   CompileRun("function test_get(o) { o.foo; }"
   20118              "test_get(obj);");
   20119   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   20120   CompileRun("test_get(obj);");
   20121   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   20122   CompileRun("test_get(obj);");
   20123   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   20124   CompileRun("function test_set(o) { o.foo = 23; }"
   20125              "test_set(obj);");
   20126   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   20127   CompileRun("test_set(obj);");
   20128   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   20129   CompileRun("test_set(obj);");
   20130   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   20131 
   20132   // Test path through optimized code.
   20133   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   20134              "test_get(obj);");
   20135   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   20136   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   20137              "test_set(obj);");
   20138   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   20139 
   20140   // Cleanup so that closures start out fresh in next check.
   20141   CompileRun("%DeoptimizeFunction(test_get);"
   20142              "%ClearFunctionTypeFeedback(test_get);"
   20143              "%DeoptimizeFunction(test_set);"
   20144              "%ClearFunctionTypeFeedback(test_set);");
   20145 }
   20146 
   20147 
   20148 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   20149   v8::internal::FLAG_allow_natives_syntax = true;
   20150   LocalContext context;
   20151   v8::HandleScope scope(context->GetIsolate());
   20152 
   20153   Local<FunctionTemplate> templ = FunctionTemplate::New();
   20154   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   20155   inst->SetAccessor(v8_str("foo"),
   20156                     InstanceCheckedGetter, InstanceCheckedSetter,
   20157                     Handle<Value>(),
   20158                     v8::DEFAULT,
   20159                     v8::None,
   20160                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   20161   context->Global()->Set(v8_str("f"), templ->GetFunction());
   20162 
   20163   printf("Testing positive ...\n");
   20164   CompileRun("var obj = new f();");
   20165   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   20166   CheckInstanceCheckedAccessors(true);
   20167 
   20168   printf("Testing negative ...\n");
   20169   CompileRun("var obj = {};"
   20170              "obj.__proto__ = new f();");
   20171   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   20172   CheckInstanceCheckedAccessors(false);
   20173 }
   20174 
   20175 
   20176 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   20177   v8::internal::FLAG_allow_natives_syntax = true;
   20178   LocalContext context;
   20179   v8::HandleScope scope(context->GetIsolate());
   20180 
   20181   Local<FunctionTemplate> templ = FunctionTemplate::New();
   20182   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   20183   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   20184   inst->SetAccessor(v8_str("foo"),
   20185                     InstanceCheckedGetter, InstanceCheckedSetter,
   20186                     Handle<Value>(),
   20187                     v8::DEFAULT,
   20188                     v8::None,
   20189                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   20190   context->Global()->Set(v8_str("f"), templ->GetFunction());
   20191 
   20192   printf("Testing positive ...\n");
   20193   CompileRun("var obj = new f();");
   20194   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   20195   CheckInstanceCheckedAccessors(true);
   20196 
   20197   printf("Testing negative ...\n");
   20198   CompileRun("var obj = {};"
   20199              "obj.__proto__ = new f();");
   20200   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   20201   CheckInstanceCheckedAccessors(false);
   20202 }
   20203 
   20204 
   20205 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   20206   v8::internal::FLAG_allow_natives_syntax = true;
   20207   LocalContext context;
   20208   v8::HandleScope scope(context->GetIsolate());
   20209 
   20210   Local<FunctionTemplate> templ = FunctionTemplate::New();
   20211   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   20212   proto->SetAccessor(v8_str("foo"),
   20213                      InstanceCheckedGetter, InstanceCheckedSetter,
   20214                      Handle<Value>(),
   20215                      v8::DEFAULT,
   20216                      v8::None,
   20217                      v8::AccessorSignature::New(context->GetIsolate(), templ));
   20218   context->Global()->Set(v8_str("f"), templ->GetFunction());
   20219 
   20220   printf("Testing positive ...\n");
   20221   CompileRun("var obj = new f();");
   20222   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   20223   CheckInstanceCheckedAccessors(true);
   20224 
   20225   printf("Testing negative ...\n");
   20226   CompileRun("var obj = {};"
   20227              "obj.__proto__ = new f();");
   20228   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   20229   CheckInstanceCheckedAccessors(false);
   20230 
   20231   printf("Testing positive with modified prototype chain ...\n");
   20232   CompileRun("var obj = new f();"
   20233              "var pro = {};"
   20234              "pro.__proto__ = obj.__proto__;"
   20235              "obj.__proto__ = pro;");
   20236   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   20237   CheckInstanceCheckedAccessors(true);
   20238 }
   20239 
   20240 
   20241 TEST(TryFinallyMessage) {
   20242   LocalContext context;
   20243   v8::HandleScope scope(context->GetIsolate());
   20244   {
   20245     // Test that the original error message is not lost if there is a
   20246     // recursive call into Javascript is done in the finally block, e.g. to
   20247     // initialize an IC. (crbug.com/129171)
   20248     TryCatch try_catch;
   20249     const char* trigger_ic =
   20250         "try {                      \n"
   20251         "  throw new Error('test'); \n"
   20252         "} finally {                \n"
   20253         "  var x = 0;               \n"
   20254         "  x++;                     \n"  // Trigger an IC initialization here.
   20255         "}                          \n";
   20256     CompileRun(trigger_ic);
   20257     CHECK(try_catch.HasCaught());
   20258     Local<Message> message = try_catch.Message();
   20259     CHECK(!message.IsEmpty());
   20260     CHECK_EQ(2, message->GetLineNumber());
   20261   }
   20262 
   20263   {
   20264     // Test that the original exception message is indeed overwritten if
   20265     // a new error is thrown in the finally block.
   20266     TryCatch try_catch;
   20267     const char* throw_again =
   20268         "try {                       \n"
   20269         "  throw new Error('test');  \n"
   20270         "} finally {                 \n"
   20271         "  var x = 0;                \n"
   20272         "  x++;                      \n"
   20273         "  throw new Error('again'); \n"  // This is the new uncaught error.
   20274         "}                           \n";
   20275     CompileRun(throw_again);
   20276     CHECK(try_catch.HasCaught());
   20277     Local<Message> message = try_catch.Message();
   20278     CHECK(!message.IsEmpty());
   20279     CHECK_EQ(6, message->GetLineNumber());
   20280   }
   20281 }
   20282 
   20283 
   20284 static void Helper137002(bool do_store,
   20285                          bool polymorphic,
   20286                          bool remove_accessor,
   20287                          bool interceptor) {
   20288   LocalContext context;
   20289   Local<ObjectTemplate> templ = ObjectTemplate::New();
   20290   if (interceptor) {
   20291     templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
   20292   } else {
   20293     templ->SetAccessor(v8_str("foo"),
   20294                        GetterWhichReturns42,
   20295                        SetterWhichSetsYOnThisTo23);
   20296   }
   20297   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   20298 
   20299   // Turn monomorphic on slow object with native accessor, then turn
   20300   // polymorphic, finally optimize to create negative lookup and fail.
   20301   CompileRun(do_store ?
   20302              "function f(x) { x.foo = void 0; }" :
   20303              "function f(x) { return x.foo; }");
   20304   CompileRun("obj.y = void 0;");
   20305   if (!interceptor) {
   20306     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   20307   }
   20308   CompileRun("obj.__proto__ = null;"
   20309              "f(obj); f(obj); f(obj);");
   20310   if (polymorphic) {
   20311     CompileRun("f({});");
   20312   }
   20313   CompileRun("obj.y = void 0;"
   20314              "%OptimizeFunctionOnNextCall(f);");
   20315   if (remove_accessor) {
   20316     CompileRun("delete obj.foo;");
   20317   }
   20318   CompileRun("var result = f(obj);");
   20319   if (do_store) {
   20320     CompileRun("result = obj.y;");
   20321   }
   20322   if (remove_accessor && !interceptor) {
   20323     CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
   20324   } else {
   20325     CHECK_EQ(do_store ? 23 : 42,
   20326              context->Global()->Get(v8_str("result"))->Int32Value());
   20327   }
   20328 }
   20329 
   20330 
   20331 THREADED_TEST(Regress137002a) {
   20332   i::FLAG_allow_natives_syntax = true;
   20333   i::FLAG_compilation_cache = false;
   20334   v8::HandleScope scope(CcTest::isolate());
   20335   for (int i = 0; i < 16; i++) {
   20336     Helper137002(i & 8, i & 4, i & 2, i & 1);
   20337   }
   20338 }
   20339 
   20340 
   20341 THREADED_TEST(Regress137002b) {
   20342   i::FLAG_allow_natives_syntax = true;
   20343   LocalContext context;
   20344   v8::HandleScope scope(context->GetIsolate());
   20345   Local<ObjectTemplate> templ = ObjectTemplate::New();
   20346   templ->SetAccessor(v8_str("foo"),
   20347                      GetterWhichReturns42,
   20348                      SetterWhichSetsYOnThisTo23);
   20349   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   20350 
   20351   // Turn monomorphic on slow object with native accessor, then just
   20352   // delete the property and fail.
   20353   CompileRun("function load(x) { return x.foo; }"
   20354              "function store(x) { x.foo = void 0; }"
   20355              "function keyed_load(x, key) { return x[key]; }"
   20356              // Second version of function has a different source (add void 0)
   20357              // so that it does not share code with the first version.  This
   20358              // ensures that the ICs are monomorphic.
   20359              "function load2(x) { void 0; return x.foo; }"
   20360              "function store2(x) { void 0; x.foo = void 0; }"
   20361              "function keyed_load2(x, key) { void 0; return x[key]; }"
   20362 
   20363              "obj.y = void 0;"
   20364              "obj.__proto__ = null;"
   20365              "var subobj = {};"
   20366              "subobj.y = void 0;"
   20367              "subobj.__proto__ = obj;"
   20368              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   20369 
   20370              // Make the ICs monomorphic.
   20371              "load(obj); load(obj);"
   20372              "load2(subobj); load2(subobj);"
   20373              "store(obj); store(obj);"
   20374              "store2(subobj); store2(subobj);"
   20375              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   20376              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   20377 
   20378              // Actually test the shiny new ICs and better not crash. This
   20379              // serves as a regression test for issue 142088 as well.
   20380              "load(obj);"
   20381              "load2(subobj);"
   20382              "store(obj);"
   20383              "store2(subobj);"
   20384              "keyed_load(obj, 'foo');"
   20385              "keyed_load2(subobj, 'foo');"
   20386 
   20387              // Delete the accessor.  It better not be called any more now.
   20388              "delete obj.foo;"
   20389              "obj.y = void 0;"
   20390              "subobj.y = void 0;"
   20391 
   20392              "var load_result = load(obj);"
   20393              "var load_result2 = load2(subobj);"
   20394              "var keyed_load_result = keyed_load(obj, 'foo');"
   20395              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   20396              "store(obj);"
   20397              "store2(subobj);"
   20398              "var y_from_obj = obj.y;"
   20399              "var y_from_subobj = subobj.y;");
   20400   CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
   20401   CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
   20402   CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
   20403   CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
   20404   CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
   20405   CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
   20406 }
   20407 
   20408 
   20409 THREADED_TEST(Regress142088) {
   20410   i::FLAG_allow_natives_syntax = true;
   20411   LocalContext context;
   20412   v8::HandleScope scope(context->GetIsolate());
   20413   Local<ObjectTemplate> templ = ObjectTemplate::New();
   20414   templ->SetAccessor(v8_str("foo"),
   20415                      GetterWhichReturns42,
   20416                      SetterWhichSetsYOnThisTo23);
   20417   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   20418 
   20419   CompileRun("function load(x) { return x.foo; }"
   20420              "var o = Object.create(obj);"
   20421              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   20422              "load(o); load(o); load(o); load(o);");
   20423 }
   20424 
   20425 
   20426 THREADED_TEST(Regress137496) {
   20427   i::FLAG_expose_gc = true;
   20428   LocalContext context;
   20429   v8::HandleScope scope(context->GetIsolate());
   20430 
   20431   // Compile a try-finally clause where the finally block causes a GC
   20432   // while there still is a message pending for external reporting.
   20433   TryCatch try_catch;
   20434   try_catch.SetVerbose(true);
   20435   CompileRun("try { throw new Error(); } finally { gc(); }");
   20436   CHECK(try_catch.HasCaught());
   20437 }
   20438 
   20439 
   20440 THREADED_TEST(Regress149912) {
   20441   LocalContext context;
   20442   v8::HandleScope scope(context->GetIsolate());
   20443   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   20444   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   20445   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
   20446   CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
   20447 }
   20448 
   20449 
   20450 THREADED_TEST(Regress157124) {
   20451   LocalContext context;
   20452   v8::HandleScope scope(context->GetIsolate());
   20453   Local<ObjectTemplate> templ = ObjectTemplate::New();
   20454   Local<Object> obj = templ->NewInstance();
   20455   obj->GetIdentityHash();
   20456   obj->DeleteHiddenValue(v8_str("Bug"));
   20457 }
   20458 
   20459 
   20460 THREADED_TEST(Regress2535) {
   20461   i::FLAG_harmony_collections = true;
   20462   LocalContext context;
   20463   v8::HandleScope scope(context->GetIsolate());
   20464   Local<Value> set_value = CompileRun("new Set();");
   20465   Local<Object> set_object(Local<Object>::Cast(set_value));
   20466   CHECK_EQ(0, set_object->InternalFieldCount());
   20467   Local<Value> map_value = CompileRun("new Map();");
   20468   Local<Object> map_object(Local<Object>::Cast(map_value));
   20469   CHECK_EQ(0, map_object->InternalFieldCount());
   20470 }
   20471 
   20472 
   20473 THREADED_TEST(Regress2746) {
   20474   LocalContext context;
   20475   v8::Isolate* isolate = context->GetIsolate();
   20476   v8::HandleScope scope(isolate);
   20477   Local<Object> obj = Object::New();
   20478   Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
   20479   obj->SetHiddenValue(key, v8::Undefined(isolate));
   20480   Local<Value> value = obj->GetHiddenValue(key);
   20481   CHECK(!value.IsEmpty());
   20482   CHECK(value->IsUndefined());
   20483 }
   20484 
   20485 
   20486 THREADED_TEST(Regress260106) {
   20487   LocalContext context;
   20488   v8::HandleScope scope(context->GetIsolate());
   20489   Local<FunctionTemplate> templ = FunctionTemplate::New(DummyCallHandler);
   20490   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   20491   Local<Function> function = templ->GetFunction();
   20492   CHECK(!function.IsEmpty());
   20493   CHECK(function->IsFunction());
   20494 }
   20495 
   20496 
   20497 THREADED_TEST(JSONParseObject) {
   20498   LocalContext context;
   20499   HandleScope scope(context->GetIsolate());
   20500   Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
   20501   Handle<Object> global = context->Global();
   20502   global->Set(v8_str("obj"), obj);
   20503   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   20504 }
   20505 
   20506 
   20507 THREADED_TEST(JSONParseNumber) {
   20508   LocalContext context;
   20509   HandleScope scope(context->GetIsolate());
   20510   Local<Value> obj = v8::JSON::Parse(v8_str("42"));
   20511   Handle<Object> global = context->Global();
   20512   global->Set(v8_str("obj"), obj);
   20513   ExpectString("JSON.stringify(obj)", "42");
   20514 }
   20515 
   20516 
   20517 #if V8_OS_POSIX
   20518 class ThreadInterruptTest {
   20519  public:
   20520   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
   20521   ~ThreadInterruptTest() {}
   20522 
   20523   void RunTest() {
   20524     InterruptThread i_thread(this);
   20525     i_thread.Start();
   20526 
   20527     sem_.Wait();
   20528     CHECK_EQ(kExpectedValue, sem_value_);
   20529   }
   20530 
   20531  private:
   20532   static const int kExpectedValue = 1;
   20533 
   20534   class InterruptThread : public i::Thread {
   20535    public:
   20536     explicit InterruptThread(ThreadInterruptTest* test)
   20537         : Thread("InterruptThread"), test_(test) {}
   20538 
   20539     virtual void Run() {
   20540       struct sigaction action;
   20541 
   20542       // Ensure that we'll enter waiting condition
   20543       i::OS::Sleep(100);
   20544 
   20545       // Setup signal handler
   20546       memset(&action, 0, sizeof(action));
   20547       action.sa_handler = SignalHandler;
   20548       sigaction(SIGCHLD, &action, NULL);
   20549 
   20550       // Send signal
   20551       kill(getpid(), SIGCHLD);
   20552 
   20553       // Ensure that if wait has returned because of error
   20554       i::OS::Sleep(100);
   20555 
   20556       // Set value and signal semaphore
   20557       test_->sem_value_ = 1;
   20558       test_->sem_.Signal();
   20559     }
   20560 
   20561     static void SignalHandler(int signal) {
   20562     }
   20563 
   20564    private:
   20565      ThreadInterruptTest* test_;
   20566   };
   20567 
   20568   i::Semaphore sem_;
   20569   volatile int sem_value_;
   20570 };
   20571 
   20572 
   20573 THREADED_TEST(SemaphoreInterruption) {
   20574   ThreadInterruptTest().RunTest();
   20575 }
   20576 
   20577 
   20578 static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
   20579                                      Local<Value> name,
   20580                                      v8::AccessType type,
   20581                                      Local<Value> data) {
   20582   i::PrintF("Named access blocked.\n");
   20583   return false;
   20584 }
   20585 
   20586 
   20587 static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
   20588                                      uint32_t key,
   20589                                      v8::AccessType type,
   20590                                      Local<Value> data) {
   20591   i::PrintF("Indexed access blocked.\n");
   20592   return false;
   20593 }
   20594 
   20595 
   20596 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20597   CHECK(false);
   20598 }
   20599 
   20600 
   20601 TEST(JSONStringifyAccessCheck) {
   20602   v8::V8::Initialize();
   20603   v8::HandleScope scope(CcTest::isolate());
   20604 
   20605   // Create an ObjectTemplate for global objects and install access
   20606   // check callbacks that will block access.
   20607   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   20608   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
   20609                                            IndexAccessAlwaysBlocked);
   20610 
   20611   // Create a context and set an x property on it's global object.
   20612   LocalContext context0(NULL, global_template);
   20613   v8::Handle<v8::Object> global0 = context0->Global();
   20614   global0->Set(v8_str("x"), v8_num(42));
   20615   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   20616 
   20617   for (int i = 0; i < 2; i++) {
   20618     if (i == 1) {
   20619       // Install a toJSON function on the second run.
   20620       v8::Handle<v8::FunctionTemplate> toJSON =
   20621           v8::FunctionTemplate::New(UnreachableCallback);
   20622 
   20623       global0->Set(v8_str("toJSON"), toJSON->GetFunction());
   20624     }
   20625     // Create a context with a different security token so that the
   20626     // failed access check callback will be called on each access.
   20627     LocalContext context1(NULL, global_template);
   20628     context1->Global()->Set(v8_str("other"), global0);
   20629 
   20630     ExpectString("JSON.stringify(other)", "{}");
   20631     ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
   20632                  "{\"a\":{},\"b\":[\"c\"]}");
   20633     ExpectString("JSON.stringify([other, 'b', 'c'])",
   20634                  "[{},\"b\",\"c\"]");
   20635 
   20636     v8::Handle<v8::Array> array = v8::Array::New(CcTest::isolate(), 2);
   20637     array->Set(0, v8_str("a"));
   20638     array->Set(1, v8_str("b"));
   20639     context1->Global()->Set(v8_str("array"), array);
   20640     ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
   20641     array->TurnOnAccessCheck();
   20642     ExpectString("JSON.stringify(array)", "[]");
   20643     ExpectString("JSON.stringify([array])", "[[]]");
   20644     ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
   20645   }
   20646 }
   20647 
   20648 
   20649 bool access_check_fail_thrown = false;
   20650 bool catch_callback_called = false;
   20651 
   20652 
   20653 // Failed access check callback that performs a GC on each invocation.
   20654 void FailedAccessCheckThrows(Local<v8::Object> target,
   20655                              v8::AccessType type,
   20656                              Local<v8::Value> data) {
   20657   access_check_fail_thrown = true;
   20658   i::PrintF("Access check failed. Error thrown.\n");
   20659   CcTest::isolate()->ThrowException(
   20660       v8::Exception::Error(v8_str("cross context")));
   20661 }
   20662 
   20663 
   20664 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20665   for (int i = 0; i < args.Length(); i++) {
   20666     i::PrintF("%s\n", *String::Utf8Value(args[i]));
   20667   }
   20668   catch_callback_called = true;
   20669 }
   20670 
   20671 
   20672 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20673   args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
   20674 }
   20675 
   20676 
   20677 void CheckCorrectThrow(const char* script) {
   20678   // Test that the script, when wrapped into a try-catch, triggers the catch
   20679   // clause due to failed access check throwing an exception.
   20680   // The subsequent try-catch should run without any exception.
   20681   access_check_fail_thrown = false;
   20682   catch_callback_called = false;
   20683   i::ScopedVector<char> source(1024);
   20684   i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   20685   CompileRun(source.start());
   20686   CHECK(access_check_fail_thrown);
   20687   CHECK(catch_callback_called);
   20688 
   20689   access_check_fail_thrown = false;
   20690   catch_callback_called = false;
   20691   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   20692   CHECK(!access_check_fail_thrown);
   20693   CHECK(!catch_callback_called);
   20694 }
   20695 
   20696 
   20697 TEST(AccessCheckThrows) {
   20698   i::FLAG_allow_natives_syntax = true;
   20699   v8::V8::Initialize();
   20700   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   20701   v8::HandleScope scope(CcTest::isolate());
   20702 
   20703   // Create an ObjectTemplate for global objects and install access
   20704   // check callbacks that will block access.
   20705   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   20706   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
   20707                                            IndexAccessAlwaysBlocked);
   20708 
   20709   // Create a context and set an x property on it's global object.
   20710   LocalContext context0(NULL, global_template);
   20711   context0->Global()->Set(v8_str("x"), v8_num(42));
   20712   v8::Handle<v8::Object> global0 = context0->Global();
   20713 
   20714   // Create a context with a different security token so that the
   20715   // failed access check callback will be called on each access.
   20716   LocalContext context1(NULL, global_template);
   20717   context1->Global()->Set(v8_str("other"), global0);
   20718 
   20719   v8::Handle<v8::FunctionTemplate> catcher_fun =
   20720       v8::FunctionTemplate::New(CatcherCallback);
   20721   context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
   20722 
   20723   v8::Handle<v8::FunctionTemplate> has_own_property_fun =
   20724       v8::FunctionTemplate::New(HasOwnPropertyCallback);
   20725   context1->Global()->Set(v8_str("has_own_property"),
   20726                           has_own_property_fun->GetFunction());
   20727 
   20728   { v8::TryCatch try_catch;
   20729     access_check_fail_thrown = false;
   20730     CompileRun("other.x;");
   20731     CHECK(access_check_fail_thrown);
   20732     CHECK(try_catch.HasCaught());
   20733   }
   20734 
   20735   CheckCorrectThrow("other.x");
   20736   CheckCorrectThrow("other[1]");
   20737   CheckCorrectThrow("JSON.stringify(other)");
   20738   CheckCorrectThrow("has_own_property(other, 'x')");
   20739   CheckCorrectThrow("%GetProperty(other, 'x')");
   20740   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
   20741   CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
   20742   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
   20743   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
   20744   CheckCorrectThrow("%HasLocalProperty(other, 'x')");
   20745   CheckCorrectThrow("%HasProperty(other, 'x')");
   20746   CheckCorrectThrow("%HasElement(other, 1)");
   20747   CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
   20748   CheckCorrectThrow("%GetPropertyNames(other)");
   20749   CheckCorrectThrow("%GetLocalPropertyNames(other, true)");
   20750   CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
   20751                         "other, 'x', null, null, 1)");
   20752 
   20753   // Reset the failed access check callback so it does not influence
   20754   // the other tests.
   20755   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
   20756 }
   20757 
   20758 
   20759 THREADED_TEST(Regress256330) {
   20760   i::FLAG_allow_natives_syntax = true;
   20761   LocalContext context;
   20762   v8::HandleScope scope(context->GetIsolate());
   20763   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   20764   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   20765   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
   20766   CompileRun("\"use strict\"; var o = new Bug;"
   20767              "function f(o) { o.x = 10; };"
   20768              "f(o); f(o); f(o);"
   20769              "%OptimizeFunctionOnNextCall(f);"
   20770              "f(o);");
   20771   ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
   20772 }
   20773 
   20774 
   20775 THREADED_TEST(CrankshaftInterceptorSetter) {
   20776   i::FLAG_allow_natives_syntax = true;
   20777   v8::HandleScope scope(CcTest::isolate());
   20778   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   20779   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   20780   LocalContext env;
   20781   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   20782   CompileRun("var obj = new Obj;"
   20783              // Initialize fields to avoid transitions later.
   20784              "obj.age = 0;"
   20785              "obj.accessor_age = 42;"
   20786              "function setter(i) { this.accessor_age = i; };"
   20787              "function getter() { return this.accessor_age; };"
   20788              "function setAge(i) { obj.age = i; };"
   20789              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   20790              "setAge(1);"
   20791              "setAge(2);"
   20792              "setAge(3);"
   20793              "%OptimizeFunctionOnNextCall(setAge);"
   20794              "setAge(4);");
   20795   // All stores went through the interceptor.
   20796   ExpectInt32("obj.interceptor_age", 4);
   20797   ExpectInt32("obj.accessor_age", 42);
   20798 }
   20799 
   20800 
   20801 THREADED_TEST(CrankshaftInterceptorGetter) {
   20802   i::FLAG_allow_natives_syntax = true;
   20803   v8::HandleScope scope(CcTest::isolate());
   20804   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   20805   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   20806   LocalContext env;
   20807   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   20808   CompileRun("var obj = new Obj;"
   20809              // Initialize fields to avoid transitions later.
   20810              "obj.age = 1;"
   20811              "obj.accessor_age = 42;"
   20812              "function getter() { return this.accessor_age; };"
   20813              "function getAge() { return obj.interceptor_age; };"
   20814              "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
   20815              "getAge();"
   20816              "getAge();"
   20817              "getAge();"
   20818              "%OptimizeFunctionOnNextCall(getAge);");
   20819   // Access through interceptor.
   20820   ExpectInt32("getAge()", 1);
   20821 }
   20822 
   20823 
   20824 THREADED_TEST(CrankshaftInterceptorFieldRead) {
   20825   i::FLAG_allow_natives_syntax = true;
   20826   v8::HandleScope scope(CcTest::isolate());
   20827   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   20828   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   20829   LocalContext env;
   20830   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   20831   CompileRun("var obj = new Obj;"
   20832              "obj.__proto__.interceptor_age = 42;"
   20833              "obj.age = 100;"
   20834              "function getAge() { return obj.interceptor_age; };");
   20835   ExpectInt32("getAge();", 100);
   20836   ExpectInt32("getAge();", 100);
   20837   ExpectInt32("getAge();", 100);
   20838   CompileRun("%OptimizeFunctionOnNextCall(getAge);");
   20839   // Access through interceptor.
   20840   ExpectInt32("getAge();", 100);
   20841 }
   20842 
   20843 
   20844 THREADED_TEST(CrankshaftInterceptorFieldWrite) {
   20845   i::FLAG_allow_natives_syntax = true;
   20846   v8::HandleScope scope(CcTest::isolate());
   20847   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   20848   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   20849   LocalContext env;
   20850   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   20851   CompileRun("var obj = new Obj;"
   20852              "obj.age = 100000;"
   20853              "function setAge(i) { obj.age = i };"
   20854              "setAge(100);"
   20855              "setAge(101);"
   20856              "setAge(102);"
   20857              "%OptimizeFunctionOnNextCall(setAge);"
   20858              "setAge(103);");
   20859   ExpectInt32("obj.age", 100000);
   20860   ExpectInt32("obj.interceptor_age", 103);
   20861 }
   20862 
   20863 
   20864 #endif  // V8_OS_POSIX
   20865 
   20866 
   20867 static Local<Value> function_new_expected_env;
   20868 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
   20869   CHECK_EQ(function_new_expected_env, info.Data());
   20870   info.GetReturnValue().Set(17);
   20871 }
   20872 
   20873 
   20874 THREADED_TEST(FunctionNew) {
   20875   LocalContext env;
   20876   v8::Isolate* isolate = env->GetIsolate();
   20877   v8::HandleScope scope(isolate);
   20878   Local<Object> data = v8::Object::New();
   20879   function_new_expected_env = data;
   20880   Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
   20881   env->Global()->Set(v8_str("func"), func);
   20882   Local<Value> result = CompileRun("func();");
   20883   CHECK_EQ(v8::Integer::New(17, isolate), result);
   20884   // Verify function not cached
   20885   int serial_number =
   20886       i::Smi::cast(v8::Utils::OpenHandle(*func)
   20887           ->shared()->get_api_func_data()->serial_number())->value();
   20888   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   20889   i::Object* elm = i_isolate->native_context()->function_cache()
   20890       ->GetElementNoExceptionThrown(i_isolate, serial_number);
   20891   CHECK(elm->IsUndefined());
   20892   // Verify that each Function::New creates a new function instance
   20893   Local<Object> data2 = v8::Object::New();
   20894   function_new_expected_env = data2;
   20895   Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
   20896   CHECK(!func2->IsNull());
   20897   CHECK_NE(func, func2);
   20898   env->Global()->Set(v8_str("func2"), func2);
   20899   Local<Value> result2 = CompileRun("func2();");
   20900   CHECK_EQ(v8::Integer::New(17, isolate), result2);
   20901 }
   20902 
   20903 
   20904 TEST(EscapeableHandleScope) {
   20905   HandleScope outer_scope(CcTest::isolate());
   20906   LocalContext context;
   20907   const int runs = 10;
   20908   Local<String> values[runs];
   20909   for (int i = 0; i < runs; i++) {
   20910     v8::EscapableHandleScope inner_scope(CcTest::isolate());
   20911     Local<String> value;
   20912     if (i != 0) value = v8_str("escape value");
   20913     values[i] = inner_scope.Escape(value);
   20914   }
   20915   for (int i = 0; i < runs; i++) {
   20916     Local<String> expected;
   20917     if (i != 0) {
   20918       CHECK_EQ(v8_str("escape value"), values[i]);
   20919     } else {
   20920       CHECK(values[i].IsEmpty());
   20921     }
   20922   }
   20923 }
   20924