Home | History | Annotate | Download | only in cctest
      1 // Copyright 2011 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 <limits.h>
     29 
     30 #include "v8.h"
     31 
     32 #include "api.h"
     33 #include "compilation-cache.h"
     34 #include "execution.h"
     35 #include "snapshot.h"
     36 #include "platform.h"
     37 #include "utils.h"
     38 #include "cctest.h"
     39 #include "parser.h"
     40 #include "unicode-inl.h"
     41 
     42 static const bool kLogThreading = true;
     43 
     44 static bool IsNaN(double x) {
     45 #ifdef WIN32
     46   return _isnan(x);
     47 #else
     48   return isnan(x);
     49 #endif
     50 }
     51 
     52 using ::v8::AccessorInfo;
     53 using ::v8::Arguments;
     54 using ::v8::Context;
     55 using ::v8::Extension;
     56 using ::v8::Function;
     57 using ::v8::FunctionTemplate;
     58 using ::v8::Handle;
     59 using ::v8::HandleScope;
     60 using ::v8::Local;
     61 using ::v8::Message;
     62 using ::v8::MessageCallback;
     63 using ::v8::Object;
     64 using ::v8::ObjectTemplate;
     65 using ::v8::Persistent;
     66 using ::v8::Script;
     67 using ::v8::StackTrace;
     68 using ::v8::String;
     69 using ::v8::TryCatch;
     70 using ::v8::Undefined;
     71 using ::v8::V8;
     72 using ::v8::Value;
     73 
     74 namespace i = ::i;
     75 
     76 
     77 static void ExpectString(const char* code, const char* expected) {
     78   Local<Value> result = CompileRun(code);
     79   CHECK(result->IsString());
     80   String::AsciiValue ascii(result);
     81   CHECK_EQ(expected, *ascii);
     82 }
     83 
     84 
     85 static void ExpectBoolean(const char* code, bool expected) {
     86   Local<Value> result = CompileRun(code);
     87   CHECK(result->IsBoolean());
     88   CHECK_EQ(expected, result->BooleanValue());
     89 }
     90 
     91 
     92 static void ExpectTrue(const char* code) {
     93   ExpectBoolean(code, true);
     94 }
     95 
     96 
     97 static void ExpectFalse(const char* code) {
     98   ExpectBoolean(code, false);
     99 }
    100 
    101 
    102 static void ExpectObject(const char* code, Local<Value> expected) {
    103   Local<Value> result = CompileRun(code);
    104   CHECK(result->Equals(expected));
    105 }
    106 
    107 
    108 static void ExpectUndefined(const char* code) {
    109   Local<Value> result = CompileRun(code);
    110   CHECK(result->IsUndefined());
    111 }
    112 
    113 
    114 static int signature_callback_count;
    115 static v8::Handle<Value> IncrementingSignatureCallback(
    116     const v8::Arguments& args) {
    117   ApiTestFuzzer::Fuzz();
    118   signature_callback_count++;
    119   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
    120   for (int i = 0; i < args.Length(); i++)
    121     result->Set(v8::Integer::New(i), args[i]);
    122   return result;
    123 }
    124 
    125 
    126 static v8::Handle<Value> SignatureCallback(const v8::Arguments& args) {
    127   ApiTestFuzzer::Fuzz();
    128   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
    129   for (int i = 0; i < args.Length(); i++) {
    130     result->Set(v8::Integer::New(i), args[i]);
    131   }
    132   return result;
    133 }
    134 
    135 
    136 THREADED_TEST(Handles) {
    137   v8::HandleScope scope;
    138   Local<Context> local_env;
    139   {
    140     LocalContext env;
    141     local_env = env.local();
    142   }
    143 
    144   // Local context should still be live.
    145   CHECK(!local_env.IsEmpty());
    146   local_env->Enter();
    147 
    148   v8::Handle<v8::Primitive> undef = v8::Undefined();
    149   CHECK(!undef.IsEmpty());
    150   CHECK(undef->IsUndefined());
    151 
    152   const char* c_source = "1 + 2 + 3";
    153   Local<String> source = String::New(c_source);
    154   Local<Script> script = Script::Compile(source);
    155   CHECK_EQ(6, script->Run()->Int32Value());
    156 
    157   local_env->Exit();
    158 }
    159 
    160 
    161 THREADED_TEST(ReceiverSignature) {
    162   v8::HandleScope scope;
    163   LocalContext env;
    164   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
    165   v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
    166   fun->PrototypeTemplate()->Set(
    167       v8_str("m"),
    168       v8::FunctionTemplate::New(IncrementingSignatureCallback,
    169                                 v8::Handle<Value>(),
    170                                 sig));
    171   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
    172   signature_callback_count = 0;
    173   CompileRun(
    174       "var o = new Fun();"
    175       "o.m();");
    176   CHECK_EQ(1, signature_callback_count);
    177   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
    178   sub_fun->Inherit(fun);
    179   env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction());
    180   CompileRun(
    181       "var o = new SubFun();"
    182       "o.m();");
    183   CHECK_EQ(2, signature_callback_count);
    184 
    185   v8::TryCatch try_catch;
    186   CompileRun(
    187       "var o = { };"
    188       "o.m = Fun.prototype.m;"
    189       "o.m();");
    190   CHECK_EQ(2, signature_callback_count);
    191   CHECK(try_catch.HasCaught());
    192   try_catch.Reset();
    193   v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
    194   sub_fun->Inherit(fun);
    195   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
    196   CompileRun(
    197       "var o = new UnrelFun();"
    198       "o.m = Fun.prototype.m;"
    199       "o.m();");
    200   CHECK_EQ(2, signature_callback_count);
    201   CHECK(try_catch.HasCaught());
    202 }
    203 
    204 
    205 
    206 
    207 THREADED_TEST(ArgumentSignature) {
    208   v8::HandleScope scope;
    209   LocalContext env;
    210   v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
    211   cons->SetClassName(v8_str("Cons"));
    212   v8::Handle<v8::Signature> sig =
    213       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
    214   v8::Handle<v8::FunctionTemplate> fun =
    215       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
    216   env->Global()->Set(v8_str("Cons"), cons->GetFunction());
    217   env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
    218 
    219   v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
    220   CHECK(value1->IsTrue());
    221 
    222   v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
    223   CHECK(value2->IsTrue());
    224 
    225   v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
    226   CHECK(value3->IsTrue());
    227 
    228   v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
    229   cons1->SetClassName(v8_str("Cons1"));
    230   v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
    231   cons2->SetClassName(v8_str("Cons2"));
    232   v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
    233   cons3->SetClassName(v8_str("Cons3"));
    234 
    235   v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
    236   v8::Handle<v8::Signature> wsig =
    237       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
    238   v8::Handle<v8::FunctionTemplate> fun2 =
    239       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
    240 
    241   env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
    242   env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
    243   env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
    244   env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
    245   v8::Handle<Value> value4 = CompileRun(
    246       "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
    247       "'[object Cons1],[object Cons2],[object Cons3]'");
    248   CHECK(value4->IsTrue());
    249 
    250   v8::Handle<Value> value5 = CompileRun(
    251       "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
    252   CHECK(value5->IsTrue());
    253 
    254   v8::Handle<Value> value6 = CompileRun(
    255       "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
    256   CHECK(value6->IsTrue());
    257 
    258   v8::Handle<Value> value7 = CompileRun(
    259       "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
    260       "'[object Cons1],[object Cons2],[object Cons3],d';");
    261   CHECK(value7->IsTrue());
    262 
    263   v8::Handle<Value> value8 = CompileRun(
    264       "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
    265   CHECK(value8->IsTrue());
    266 }
    267 
    268 
    269 THREADED_TEST(HulIgennem) {
    270   v8::HandleScope scope;
    271   LocalContext env;
    272   v8::Handle<v8::Primitive> undef = v8::Undefined();
    273   Local<String> undef_str = undef->ToString();
    274   char* value = i::NewArray<char>(undef_str->Length() + 1);
    275   undef_str->WriteAscii(value);
    276   CHECK_EQ(0, strcmp(value, "undefined"));
    277   i::DeleteArray(value);
    278 }
    279 
    280 
    281 THREADED_TEST(Access) {
    282   v8::HandleScope scope;
    283   LocalContext env;
    284   Local<v8::Object> obj = v8::Object::New();
    285   Local<Value> foo_before = obj->Get(v8_str("foo"));
    286   CHECK(foo_before->IsUndefined());
    287   Local<String> bar_str = v8_str("bar");
    288   obj->Set(v8_str("foo"), bar_str);
    289   Local<Value> foo_after = obj->Get(v8_str("foo"));
    290   CHECK(!foo_after->IsUndefined());
    291   CHECK(foo_after->IsString());
    292   CHECK_EQ(bar_str, foo_after);
    293 }
    294 
    295 
    296 THREADED_TEST(AccessElement) {
    297   v8::HandleScope scope;
    298   LocalContext env;
    299   Local<v8::Object> obj = v8::Object::New();
    300   Local<Value> before = obj->Get(1);
    301   CHECK(before->IsUndefined());
    302   Local<String> bar_str = v8_str("bar");
    303   obj->Set(1, bar_str);
    304   Local<Value> after = obj->Get(1);
    305   CHECK(!after->IsUndefined());
    306   CHECK(after->IsString());
    307   CHECK_EQ(bar_str, after);
    308 
    309   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
    310   CHECK_EQ(v8_str("a"), value->Get(0));
    311   CHECK_EQ(v8_str("b"), value->Get(1));
    312 }
    313 
    314 
    315 THREADED_TEST(Script) {
    316   v8::HandleScope scope;
    317   LocalContext env;
    318   const char* c_source = "1 + 2 + 3";
    319   Local<String> source = String::New(c_source);
    320   Local<Script> script = Script::Compile(source);
    321   CHECK_EQ(6, script->Run()->Int32Value());
    322 }
    323 
    324 
    325 static uint16_t* AsciiToTwoByteString(const char* source) {
    326   int array_length = i::StrLength(source) + 1;
    327   uint16_t* converted = i::NewArray<uint16_t>(array_length);
    328   for (int i = 0; i < array_length; i++) converted[i] = source[i];
    329   return converted;
    330 }
    331 
    332 
    333 class TestResource: public String::ExternalStringResource {
    334  public:
    335   static int dispose_count;
    336 
    337   explicit TestResource(uint16_t* data)
    338       : data_(data), length_(0) {
    339     while (data[length_]) ++length_;
    340   }
    341 
    342   ~TestResource() {
    343     i::DeleteArray(data_);
    344     ++dispose_count;
    345   }
    346 
    347   const uint16_t* data() const {
    348     return data_;
    349   }
    350 
    351   size_t length() const {
    352     return length_;
    353   }
    354  private:
    355   uint16_t* data_;
    356   size_t length_;
    357 };
    358 
    359 
    360 int TestResource::dispose_count = 0;
    361 
    362 
    363 class TestAsciiResource: public String::ExternalAsciiStringResource {
    364  public:
    365   static int dispose_count;
    366 
    367   explicit TestAsciiResource(const char* data)
    368       : data_(data),
    369         length_(strlen(data)) { }
    370 
    371   ~TestAsciiResource() {
    372     i::DeleteArray(data_);
    373     ++dispose_count;
    374   }
    375 
    376   const char* data() const {
    377     return data_;
    378   }
    379 
    380   size_t length() const {
    381     return length_;
    382   }
    383  private:
    384   const char* data_;
    385   size_t length_;
    386 };
    387 
    388 
    389 int TestAsciiResource::dispose_count = 0;
    390 
    391 
    392 THREADED_TEST(ScriptUsingStringResource) {
    393   TestResource::dispose_count = 0;
    394   const char* c_source = "1 + 2 * 3";
    395   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
    396   {
    397     v8::HandleScope scope;
    398     LocalContext env;
    399     TestResource* resource = new TestResource(two_byte_source);
    400     Local<String> source = String::NewExternal(resource);
    401     Local<Script> script = Script::Compile(source);
    402     Local<Value> value = script->Run();
    403     CHECK(value->IsNumber());
    404     CHECK_EQ(7, value->Int32Value());
    405     CHECK(source->IsExternal());
    406     CHECK_EQ(resource,
    407              static_cast<TestResource*>(source->GetExternalStringResource()));
    408     HEAP->CollectAllGarbage(false);
    409     CHECK_EQ(0, TestResource::dispose_count);
    410   }
    411   v8::internal::Isolate::Current()->compilation_cache()->Clear();
    412   HEAP->CollectAllGarbage(false);
    413   CHECK_EQ(1, TestResource::dispose_count);
    414 }
    415 
    416 
    417 THREADED_TEST(ScriptUsingAsciiStringResource) {
    418   TestAsciiResource::dispose_count = 0;
    419   const char* c_source = "1 + 2 * 3";
    420   {
    421     v8::HandleScope scope;
    422     LocalContext env;
    423     Local<String> source =
    424         String::NewExternal(new TestAsciiResource(i::StrDup(c_source)));
    425     Local<Script> script = Script::Compile(source);
    426     Local<Value> value = script->Run();
    427     CHECK(value->IsNumber());
    428     CHECK_EQ(7, value->Int32Value());
    429     HEAP->CollectAllGarbage(false);
    430     CHECK_EQ(0, TestAsciiResource::dispose_count);
    431   }
    432   i::Isolate::Current()->compilation_cache()->Clear();
    433   HEAP->CollectAllGarbage(false);
    434   CHECK_EQ(1, TestAsciiResource::dispose_count);
    435 }
    436 
    437 
    438 THREADED_TEST(ScriptMakingExternalString) {
    439   TestResource::dispose_count = 0;
    440   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
    441   {
    442     v8::HandleScope scope;
    443     LocalContext env;
    444     Local<String> source = String::New(two_byte_source);
    445     // Trigger GCs so that the newly allocated string moves to old gen.
    446     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    447     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    448     bool success = source->MakeExternal(new TestResource(two_byte_source));
    449     CHECK(success);
    450     Local<Script> script = Script::Compile(source);
    451     Local<Value> value = script->Run();
    452     CHECK(value->IsNumber());
    453     CHECK_EQ(7, value->Int32Value());
    454     HEAP->CollectAllGarbage(false);
    455     CHECK_EQ(0, TestResource::dispose_count);
    456   }
    457   i::Isolate::Current()->compilation_cache()->Clear();
    458   HEAP->CollectAllGarbage(false);
    459   CHECK_EQ(1, TestResource::dispose_count);
    460 }
    461 
    462 
    463 THREADED_TEST(ScriptMakingExternalAsciiString) {
    464   TestAsciiResource::dispose_count = 0;
    465   const char* c_source = "1 + 2 * 3";
    466   {
    467     v8::HandleScope scope;
    468     LocalContext env;
    469     Local<String> source = v8_str(c_source);
    470     // Trigger GCs so that the newly allocated string moves to old gen.
    471     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    472     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    473     bool success = source->MakeExternal(
    474         new TestAsciiResource(i::StrDup(c_source)));
    475     CHECK(success);
    476     Local<Script> script = Script::Compile(source);
    477     Local<Value> value = script->Run();
    478     CHECK(value->IsNumber());
    479     CHECK_EQ(7, value->Int32Value());
    480     HEAP->CollectAllGarbage(false);
    481     CHECK_EQ(0, TestAsciiResource::dispose_count);
    482   }
    483   i::Isolate::Current()->compilation_cache()->Clear();
    484   HEAP->CollectAllGarbage(false);
    485   CHECK_EQ(1, TestAsciiResource::dispose_count);
    486 }
    487 
    488 
    489 TEST(MakingExternalStringConditions) {
    490   v8::HandleScope scope;
    491   LocalContext env;
    492 
    493   // Free some space in the new space so that we can check freshness.
    494   HEAP->CollectGarbage(i::NEW_SPACE);
    495   HEAP->CollectGarbage(i::NEW_SPACE);
    496 
    497   uint16_t* two_byte_string = AsciiToTwoByteString("small");
    498   Local<String> small_string = String::New(two_byte_string);
    499   i::DeleteArray(two_byte_string);
    500 
    501   // We should refuse to externalize newly created small string.
    502   CHECK(!small_string->CanMakeExternal());
    503   // Trigger GCs so that the newly allocated string moves to old gen.
    504   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    505   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    506   // Old space strings should be accepted.
    507   CHECK(small_string->CanMakeExternal());
    508 
    509   two_byte_string = AsciiToTwoByteString("small 2");
    510   small_string = String::New(two_byte_string);
    511   i::DeleteArray(two_byte_string);
    512 
    513   // We should refuse externalizing newly created small string.
    514   CHECK(!small_string->CanMakeExternal());
    515   for (int i = 0; i < 100; i++) {
    516     String::Value value(small_string);
    517   }
    518   // Frequently used strings should be accepted.
    519   CHECK(small_string->CanMakeExternal());
    520 
    521   const int buf_size = 10 * 1024;
    522   char* buf = i::NewArray<char>(buf_size);
    523   memset(buf, 'a', buf_size);
    524   buf[buf_size - 1] = '\0';
    525 
    526   two_byte_string = AsciiToTwoByteString(buf);
    527   Local<String> large_string = String::New(two_byte_string);
    528   i::DeleteArray(buf);
    529   i::DeleteArray(two_byte_string);
    530   // Large strings should be immediately accepted.
    531   CHECK(large_string->CanMakeExternal());
    532 }
    533 
    534 
    535 TEST(MakingExternalAsciiStringConditions) {
    536   v8::HandleScope scope;
    537   LocalContext env;
    538 
    539   // Free some space in the new space so that we can check freshness.
    540   HEAP->CollectGarbage(i::NEW_SPACE);
    541   HEAP->CollectGarbage(i::NEW_SPACE);
    542 
    543   Local<String> small_string = String::New("small");
    544   // We should refuse to externalize newly created small string.
    545   CHECK(!small_string->CanMakeExternal());
    546   // Trigger GCs so that the newly allocated string moves to old gen.
    547   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    548   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    549   // Old space strings should be accepted.
    550   CHECK(small_string->CanMakeExternal());
    551 
    552   small_string = String::New("small 2");
    553   // We should refuse externalizing newly created small string.
    554   CHECK(!small_string->CanMakeExternal());
    555   for (int i = 0; i < 100; i++) {
    556     String::Value value(small_string);
    557   }
    558   // Frequently used strings should be accepted.
    559   CHECK(small_string->CanMakeExternal());
    560 
    561   const int buf_size = 10 * 1024;
    562   char* buf = i::NewArray<char>(buf_size);
    563   memset(buf, 'a', buf_size);
    564   buf[buf_size - 1] = '\0';
    565   Local<String> large_string = String::New(buf);
    566   i::DeleteArray(buf);
    567   // Large strings should be immediately accepted.
    568   CHECK(large_string->CanMakeExternal());
    569 }
    570 
    571 
    572 THREADED_TEST(UsingExternalString) {
    573   {
    574     v8::HandleScope scope;
    575     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    576     Local<String> string =
    577         String::NewExternal(new TestResource(two_byte_string));
    578     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    579     // Trigger GCs so that the newly allocated string moves to old gen.
    580     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    581     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    582     i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
    583     CHECK(isymbol->IsSymbol());
    584   }
    585   HEAP->CollectAllGarbage(false);
    586   HEAP->CollectAllGarbage(false);
    587 }
    588 
    589 
    590 THREADED_TEST(UsingExternalAsciiString) {
    591   {
    592     v8::HandleScope scope;
    593     const char* one_byte_string = "test string";
    594     Local<String> string = String::NewExternal(
    595         new TestAsciiResource(i::StrDup(one_byte_string)));
    596     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    597     // Trigger GCs so that the newly allocated string moves to old gen.
    598     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    599     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    600     i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
    601     CHECK(isymbol->IsSymbol());
    602   }
    603   HEAP->CollectAllGarbage(false);
    604   HEAP->CollectAllGarbage(false);
    605 }
    606 
    607 
    608 THREADED_TEST(ScavengeExternalString) {
    609   TestResource::dispose_count = 0;
    610   bool in_new_space = false;
    611   {
    612     v8::HandleScope scope;
    613     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    614     Local<String> string =
    615         String::NewExternal(new TestResource(two_byte_string));
    616     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    617     HEAP->CollectGarbage(i::NEW_SPACE);
    618     in_new_space = HEAP->InNewSpace(*istring);
    619     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
    620     CHECK_EQ(0, TestResource::dispose_count);
    621   }
    622   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    623   CHECK_EQ(1, TestResource::dispose_count);
    624 }
    625 
    626 
    627 THREADED_TEST(ScavengeExternalAsciiString) {
    628   TestAsciiResource::dispose_count = 0;
    629   bool in_new_space = false;
    630   {
    631     v8::HandleScope scope;
    632     const char* one_byte_string = "test string";
    633     Local<String> string = String::NewExternal(
    634         new TestAsciiResource(i::StrDup(one_byte_string)));
    635     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    636     HEAP->CollectGarbage(i::NEW_SPACE);
    637     in_new_space = HEAP->InNewSpace(*istring);
    638     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
    639     CHECK_EQ(0, TestAsciiResource::dispose_count);
    640   }
    641   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    642   CHECK_EQ(1, TestAsciiResource::dispose_count);
    643 }
    644 
    645 
    646 class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
    647  public:
    648   static int dispose_calls;
    649 
    650   TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
    651       : TestAsciiResource(data),
    652         dispose_(dispose) { }
    653 
    654   void Dispose() {
    655     ++dispose_calls;
    656     if (dispose_) delete this;
    657   }
    658  private:
    659   bool dispose_;
    660 };
    661 
    662 
    663 int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    664 
    665 
    666 TEST(ExternalStringWithDisposeHandling) {
    667   const char* c_source = "1 + 2 * 3";
    668 
    669   // Use a stack allocated external string resource allocated object.
    670   TestAsciiResource::dispose_count = 0;
    671   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    672   TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
    673   {
    674     v8::HandleScope scope;
    675     LocalContext env;
    676     Local<String> source =  String::NewExternal(&res_stack);
    677     Local<Script> script = Script::Compile(source);
    678     Local<Value> value = script->Run();
    679     CHECK(value->IsNumber());
    680     CHECK_EQ(7, value->Int32Value());
    681     HEAP->CollectAllGarbage(false);
    682     CHECK_EQ(0, TestAsciiResource::dispose_count);
    683   }
    684   i::Isolate::Current()->compilation_cache()->Clear();
    685   HEAP->CollectAllGarbage(false);
    686   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
    687   CHECK_EQ(0, TestAsciiResource::dispose_count);
    688 
    689   // Use a heap allocated external string resource allocated object.
    690   TestAsciiResource::dispose_count = 0;
    691   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    692   TestAsciiResource* res_heap =
    693       new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
    694   {
    695     v8::HandleScope scope;
    696     LocalContext env;
    697     Local<String> source =  String::NewExternal(res_heap);
    698     Local<Script> script = Script::Compile(source);
    699     Local<Value> value = script->Run();
    700     CHECK(value->IsNumber());
    701     CHECK_EQ(7, value->Int32Value());
    702     HEAP->CollectAllGarbage(false);
    703     CHECK_EQ(0, TestAsciiResource::dispose_count);
    704   }
    705   i::Isolate::Current()->compilation_cache()->Clear();
    706   HEAP->CollectAllGarbage(false);
    707   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
    708   CHECK_EQ(1, TestAsciiResource::dispose_count);
    709 }
    710 
    711 
    712 THREADED_TEST(StringConcat) {
    713   {
    714     v8::HandleScope scope;
    715     LocalContext env;
    716     const char* one_byte_string_1 = "function a_times_t";
    717     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
    718     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
    719     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
    720     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    721     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    722     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
    723     Local<String> left = v8_str(one_byte_string_1);
    724 
    725     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
    726     Local<String> right = String::New(two_byte_source);
    727     i::DeleteArray(two_byte_source);
    728 
    729     Local<String> source = String::Concat(left, right);
    730     right = String::NewExternal(
    731         new TestAsciiResource(i::StrDup(one_byte_extern_1)));
    732     source = String::Concat(source, right);
    733     right = String::NewExternal(
    734         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
    735     source = String::Concat(source, right);
    736     right = v8_str(one_byte_string_2);
    737     source = String::Concat(source, right);
    738 
    739     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
    740     right = String::New(two_byte_source);
    741     i::DeleteArray(two_byte_source);
    742 
    743     source = String::Concat(source, right);
    744     right = String::NewExternal(
    745         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
    746     source = String::Concat(source, right);
    747     Local<Script> script = Script::Compile(source);
    748     Local<Value> value = script->Run();
    749     CHECK(value->IsNumber());
    750     CHECK_EQ(68, value->Int32Value());
    751   }
    752   i::Isolate::Current()->compilation_cache()->Clear();
    753   HEAP->CollectAllGarbage(false);
    754   HEAP->CollectAllGarbage(false);
    755 }
    756 
    757 
    758 THREADED_TEST(GlobalProperties) {
    759   v8::HandleScope scope;
    760   LocalContext env;
    761   v8::Handle<v8::Object> global = env->Global();
    762   global->Set(v8_str("pi"), v8_num(3.1415926));
    763   Local<Value> pi = global->Get(v8_str("pi"));
    764   CHECK_EQ(3.1415926, pi->NumberValue());
    765 }
    766 
    767 
    768 static v8::Handle<Value> handle_call(const v8::Arguments& args) {
    769   ApiTestFuzzer::Fuzz();
    770   return v8_num(102);
    771 }
    772 
    773 
    774 static v8::Handle<Value> construct_call(const v8::Arguments& args) {
    775   ApiTestFuzzer::Fuzz();
    776   args.This()->Set(v8_str("x"), v8_num(1));
    777   args.This()->Set(v8_str("y"), v8_num(2));
    778   return args.This();
    779 }
    780 
    781 static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
    782   ApiTestFuzzer::Fuzz();
    783   return v8_num(239);
    784 }
    785 
    786 
    787 THREADED_TEST(FunctionTemplate) {
    788   v8::HandleScope scope;
    789   LocalContext env;
    790   {
    791     Local<v8::FunctionTemplate> fun_templ =
    792         v8::FunctionTemplate::New(handle_call);
    793     Local<Function> fun = fun_templ->GetFunction();
    794     env->Global()->Set(v8_str("obj"), fun);
    795     Local<Script> script = v8_compile("obj()");
    796     CHECK_EQ(102, script->Run()->Int32Value());
    797   }
    798   // Use SetCallHandler to initialize a function template, should work like the
    799   // previous one.
    800   {
    801     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
    802     fun_templ->SetCallHandler(handle_call);
    803     Local<Function> fun = fun_templ->GetFunction();
    804     env->Global()->Set(v8_str("obj"), fun);
    805     Local<Script> script = v8_compile("obj()");
    806     CHECK_EQ(102, script->Run()->Int32Value());
    807   }
    808   // Test constructor calls.
    809   {
    810     Local<v8::FunctionTemplate> fun_templ =
    811         v8::FunctionTemplate::New(construct_call);
    812     fun_templ->SetClassName(v8_str("funky"));
    813     fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), Return239);
    814     Local<Function> fun = fun_templ->GetFunction();
    815     env->Global()->Set(v8_str("obj"), fun);
    816     Local<Script> script = v8_compile("var s = new obj(); s.x");
    817     CHECK_EQ(1, script->Run()->Int32Value());
    818 
    819     Local<Value> result = v8_compile("(new obj()).toString()")->Run();
    820     CHECK_EQ(v8_str("[object funky]"), result);
    821 
    822     result = v8_compile("(new obj()).m")->Run();
    823     CHECK_EQ(239, result->Int32Value());
    824   }
    825 }
    826 
    827 
    828 static void* expected_ptr;
    829 static v8::Handle<v8::Value> callback(const v8::Arguments& args) {
    830   void* ptr = v8::External::Unwrap(args.Data());
    831   CHECK_EQ(expected_ptr, ptr);
    832   return v8::Boolean::New(true);
    833 }
    834 
    835 
    836 static void TestExternalPointerWrapping() {
    837   v8::HandleScope scope;
    838   LocalContext env;
    839 
    840   v8::Handle<v8::Value> data = v8::External::Wrap(expected_ptr);
    841 
    842   v8::Handle<v8::Object> obj = v8::Object::New();
    843   obj->Set(v8_str("func"),
    844            v8::FunctionTemplate::New(callback, data)->GetFunction());
    845   env->Global()->Set(v8_str("obj"), obj);
    846 
    847   CHECK(CompileRun(
    848         "function foo() {\n"
    849         "  for (var i = 0; i < 13; i++) obj.func();\n"
    850         "}\n"
    851         "foo(), true")->BooleanValue());
    852 }
    853 
    854 
    855 THREADED_TEST(ExternalWrap) {
    856   // Check heap allocated object.
    857   int* ptr = new int;
    858   expected_ptr = ptr;
    859   TestExternalPointerWrapping();
    860   delete ptr;
    861 
    862   // Check stack allocated object.
    863   int foo;
    864   expected_ptr = &foo;
    865   TestExternalPointerWrapping();
    866 
    867   // Check not aligned addresses.
    868   const int n = 100;
    869   char* s = new char[n];
    870   for (int i = 0; i < n; i++) {
    871     expected_ptr = s + i;
    872     TestExternalPointerWrapping();
    873   }
    874 
    875   delete[] s;
    876 
    877   // Check several invalid addresses.
    878   expected_ptr = reinterpret_cast<void*>(1);
    879   TestExternalPointerWrapping();
    880 
    881   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
    882   TestExternalPointerWrapping();
    883 
    884   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
    885   TestExternalPointerWrapping();
    886 
    887 #if defined(V8_HOST_ARCH_X64)
    888   // Check a value with a leading 1 bit in x64 Smi encoding.
    889   expected_ptr = reinterpret_cast<void*>(0x400000000);
    890   TestExternalPointerWrapping();
    891 
    892   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
    893   TestExternalPointerWrapping();
    894 
    895   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
    896   TestExternalPointerWrapping();
    897 #endif
    898 }
    899 
    900 
    901 THREADED_TEST(FindInstanceInPrototypeChain) {
    902   v8::HandleScope scope;
    903   LocalContext env;
    904 
    905   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
    906   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
    907   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
    908   derived->Inherit(base);
    909 
    910   Local<v8::Function> base_function = base->GetFunction();
    911   Local<v8::Function> derived_function = derived->GetFunction();
    912   Local<v8::Function> other_function = other->GetFunction();
    913 
    914   Local<v8::Object> base_instance = base_function->NewInstance();
    915   Local<v8::Object> derived_instance = derived_function->NewInstance();
    916   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
    917   Local<v8::Object> other_instance = other_function->NewInstance();
    918   derived_instance2->Set(v8_str("__proto__"), derived_instance);
    919   other_instance->Set(v8_str("__proto__"), derived_instance2);
    920 
    921   // base_instance is only an instance of base.
    922   CHECK_EQ(base_instance,
    923            base_instance->FindInstanceInPrototypeChain(base));
    924   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
    925   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    926 
    927   // derived_instance is an instance of base and derived.
    928   CHECK_EQ(derived_instance,
    929            derived_instance->FindInstanceInPrototypeChain(base));
    930   CHECK_EQ(derived_instance,
    931            derived_instance->FindInstanceInPrototypeChain(derived));
    932   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    933 
    934   // other_instance is an instance of other and its immediate
    935   // prototype derived_instance2 is an instance of base and derived.
    936   // Note, derived_instance is an instance of base and derived too,
    937   // but it comes after derived_instance2 in the prototype chain of
    938   // other_instance.
    939   CHECK_EQ(derived_instance2,
    940            other_instance->FindInstanceInPrototypeChain(base));
    941   CHECK_EQ(derived_instance2,
    942            other_instance->FindInstanceInPrototypeChain(derived));
    943   CHECK_EQ(other_instance,
    944            other_instance->FindInstanceInPrototypeChain(other));
    945 }
    946 
    947 
    948 THREADED_TEST(TinyInteger) {
    949   v8::HandleScope scope;
    950   LocalContext env;
    951   int32_t value = 239;
    952   Local<v8::Integer> value_obj = v8::Integer::New(value);
    953   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    954 }
    955 
    956 
    957 THREADED_TEST(BigSmiInteger) {
    958   v8::HandleScope scope;
    959   LocalContext env;
    960   int32_t value = i::Smi::kMaxValue;
    961   // We cannot add one to a Smi::kMaxValue without wrapping.
    962   if (i::kSmiValueSize < 32) {
    963     CHECK(i::Smi::IsValid(value));
    964     CHECK(!i::Smi::IsValid(value + 1));
    965     Local<v8::Integer> value_obj = v8::Integer::New(value);
    966     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    967   }
    968 }
    969 
    970 
    971 THREADED_TEST(BigInteger) {
    972   v8::HandleScope scope;
    973   LocalContext env;
    974   // We cannot add one to a Smi::kMaxValue without wrapping.
    975   if (i::kSmiValueSize < 32) {
    976     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
    977     // The code will not be run in that case, due to the "if" guard.
    978     int32_t value =
    979         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
    980     CHECK(value > i::Smi::kMaxValue);
    981     CHECK(!i::Smi::IsValid(value));
    982     Local<v8::Integer> value_obj = v8::Integer::New(value);
    983     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    984   }
    985 }
    986 
    987 
    988 THREADED_TEST(TinyUnsignedInteger) {
    989   v8::HandleScope scope;
    990   LocalContext env;
    991   uint32_t value = 239;
    992   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
    993   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    994 }
    995 
    996 
    997 THREADED_TEST(BigUnsignedSmiInteger) {
    998   v8::HandleScope scope;
    999   LocalContext env;
   1000   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
   1001   CHECK(i::Smi::IsValid(value));
   1002   CHECK(!i::Smi::IsValid(value + 1));
   1003   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1004   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1005 }
   1006 
   1007 
   1008 THREADED_TEST(BigUnsignedInteger) {
   1009   v8::HandleScope scope;
   1010   LocalContext env;
   1011   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
   1012   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
   1013   CHECK(!i::Smi::IsValid(value));
   1014   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1015   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1016 }
   1017 
   1018 
   1019 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
   1020   v8::HandleScope scope;
   1021   LocalContext env;
   1022   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
   1023   uint32_t value = INT32_MAX_AS_UINT + 1;
   1024   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
   1025   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1026   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1027 }
   1028 
   1029 
   1030 THREADED_TEST(Number) {
   1031   v8::HandleScope scope;
   1032   LocalContext env;
   1033   double PI = 3.1415926;
   1034   Local<v8::Number> pi_obj = v8::Number::New(PI);
   1035   CHECK_EQ(PI, pi_obj->NumberValue());
   1036 }
   1037 
   1038 
   1039 THREADED_TEST(ToNumber) {
   1040   v8::HandleScope scope;
   1041   LocalContext env;
   1042   Local<String> str = v8_str("3.1415926");
   1043   CHECK_EQ(3.1415926, str->NumberValue());
   1044   v8::Handle<v8::Boolean> t = v8::True();
   1045   CHECK_EQ(1.0, t->NumberValue());
   1046   v8::Handle<v8::Boolean> f = v8::False();
   1047   CHECK_EQ(0.0, f->NumberValue());
   1048 }
   1049 
   1050 
   1051 THREADED_TEST(Date) {
   1052   v8::HandleScope scope;
   1053   LocalContext env;
   1054   double PI = 3.1415926;
   1055   Local<Value> date_obj = v8::Date::New(PI);
   1056   CHECK_EQ(3.0, date_obj->NumberValue());
   1057 }
   1058 
   1059 
   1060 THREADED_TEST(Boolean) {
   1061   v8::HandleScope scope;
   1062   LocalContext env;
   1063   v8::Handle<v8::Boolean> t = v8::True();
   1064   CHECK(t->Value());
   1065   v8::Handle<v8::Boolean> f = v8::False();
   1066   CHECK(!f->Value());
   1067   v8::Handle<v8::Primitive> u = v8::Undefined();
   1068   CHECK(!u->BooleanValue());
   1069   v8::Handle<v8::Primitive> n = v8::Null();
   1070   CHECK(!n->BooleanValue());
   1071   v8::Handle<String> str1 = v8_str("");
   1072   CHECK(!str1->BooleanValue());
   1073   v8::Handle<String> str2 = v8_str("x");
   1074   CHECK(str2->BooleanValue());
   1075   CHECK(!v8::Number::New(0)->BooleanValue());
   1076   CHECK(v8::Number::New(-1)->BooleanValue());
   1077   CHECK(v8::Number::New(1)->BooleanValue());
   1078   CHECK(v8::Number::New(42)->BooleanValue());
   1079   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
   1080 }
   1081 
   1082 
   1083 static v8::Handle<Value> DummyCallHandler(const v8::Arguments& args) {
   1084   ApiTestFuzzer::Fuzz();
   1085   return v8_num(13.4);
   1086 }
   1087 
   1088 
   1089 static v8::Handle<Value> GetM(Local<String> name, const AccessorInfo&) {
   1090   ApiTestFuzzer::Fuzz();
   1091   return v8_num(876);
   1092 }
   1093 
   1094 
   1095 THREADED_TEST(GlobalPrototype) {
   1096   v8::HandleScope scope;
   1097   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
   1098   func_templ->PrototypeTemplate()->Set(
   1099       "dummy",
   1100       v8::FunctionTemplate::New(DummyCallHandler));
   1101   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
   1102   templ->Set("x", v8_num(200));
   1103   templ->SetAccessor(v8_str("m"), GetM);
   1104   LocalContext env(0, templ);
   1105   v8::Handle<v8::Object> obj = env->Global();
   1106   v8::Handle<Script> script = v8_compile("dummy()");
   1107   v8::Handle<Value> result = script->Run();
   1108   CHECK_EQ(13.4, result->NumberValue());
   1109   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
   1110   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
   1111 }
   1112 
   1113 
   1114 THREADED_TEST(ObjectTemplate) {
   1115   v8::HandleScope scope;
   1116   Local<ObjectTemplate> templ1 = ObjectTemplate::New();
   1117   templ1->Set("x", v8_num(10));
   1118   templ1->Set("y", v8_num(13));
   1119   LocalContext env;
   1120   Local<v8::Object> instance1 = templ1->NewInstance();
   1121   env->Global()->Set(v8_str("p"), instance1);
   1122   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
   1123   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
   1124   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
   1125   fun->PrototypeTemplate()->Set("nirk", v8_num(123));
   1126   Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
   1127   templ2->Set("a", v8_num(12));
   1128   templ2->Set("b", templ1);
   1129   Local<v8::Object> instance2 = templ2->NewInstance();
   1130   env->Global()->Set(v8_str("q"), instance2);
   1131   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
   1132   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
   1133   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
   1134   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
   1135 }
   1136 
   1137 
   1138 static v8::Handle<Value> GetFlabby(const v8::Arguments& args) {
   1139   ApiTestFuzzer::Fuzz();
   1140   return v8_num(17.2);
   1141 }
   1142 
   1143 
   1144 static v8::Handle<Value> GetKnurd(Local<String> property, const AccessorInfo&) {
   1145   ApiTestFuzzer::Fuzz();
   1146   return v8_num(15.2);
   1147 }
   1148 
   1149 
   1150 THREADED_TEST(DescriptorInheritance) {
   1151   v8::HandleScope scope;
   1152   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
   1153   super->PrototypeTemplate()->Set("flabby",
   1154                                   v8::FunctionTemplate::New(GetFlabby));
   1155   super->PrototypeTemplate()->Set("PI", v8_num(3.14));
   1156 
   1157   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
   1158 
   1159   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
   1160   base1->Inherit(super);
   1161   base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
   1162 
   1163   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
   1164   base2->Inherit(super);
   1165   base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
   1166 
   1167   LocalContext env;
   1168 
   1169   env->Global()->Set(v8_str("s"), super->GetFunction());
   1170   env->Global()->Set(v8_str("base1"), base1->GetFunction());
   1171   env->Global()->Set(v8_str("base2"), base2->GetFunction());
   1172 
   1173   // Checks right __proto__ chain.
   1174   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
   1175   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
   1176 
   1177   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
   1178 
   1179   // Instance accessor should not be visible on function object or its prototype
   1180   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
   1181   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
   1182   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
   1183 
   1184   env->Global()->Set(v8_str("obj"),
   1185                      base1->GetFunction()->NewInstance());
   1186   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
   1187   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
   1188   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
   1189   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
   1190   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
   1191 
   1192   env->Global()->Set(v8_str("obj2"),
   1193                      base2->GetFunction()->NewInstance());
   1194   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
   1195   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
   1196   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
   1197   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
   1198   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
   1199 
   1200   // base1 and base2 cannot cross reference to each's prototype
   1201   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
   1202   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
   1203 }
   1204 
   1205 
   1206 int echo_named_call_count;
   1207 
   1208 
   1209 static v8::Handle<Value> EchoNamedProperty(Local<String> name,
   1210                                            const AccessorInfo& info) {
   1211   ApiTestFuzzer::Fuzz();
   1212   CHECK_EQ(v8_str("data"), info.Data());
   1213   echo_named_call_count++;
   1214   return name;
   1215 }
   1216 
   1217 
   1218 THREADED_TEST(NamedPropertyHandlerGetter) {
   1219   echo_named_call_count = 0;
   1220   v8::HandleScope scope;
   1221   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1222   templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
   1223                                                      0, 0, 0, 0,
   1224                                                      v8_str("data"));
   1225   LocalContext env;
   1226   env->Global()->Set(v8_str("obj"),
   1227                      templ->GetFunction()->NewInstance());
   1228   CHECK_EQ(echo_named_call_count, 0);
   1229   v8_compile("obj.x")->Run();
   1230   CHECK_EQ(echo_named_call_count, 1);
   1231   const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
   1232   v8::Handle<Value> str = CompileRun(code);
   1233   String::AsciiValue value(str);
   1234   CHECK_EQ(*value, "oddlepoddle");
   1235   // Check default behavior
   1236   CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
   1237   CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
   1238   CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
   1239 }
   1240 
   1241 
   1242 int echo_indexed_call_count = 0;
   1243 
   1244 
   1245 static v8::Handle<Value> EchoIndexedProperty(uint32_t index,
   1246                                              const AccessorInfo& info) {
   1247   ApiTestFuzzer::Fuzz();
   1248   CHECK_EQ(v8_num(637), info.Data());
   1249   echo_indexed_call_count++;
   1250   return v8_num(index);
   1251 }
   1252 
   1253 
   1254 THREADED_TEST(IndexedPropertyHandlerGetter) {
   1255   v8::HandleScope scope;
   1256   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1257   templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
   1258                                                        0, 0, 0, 0,
   1259                                                        v8_num(637));
   1260   LocalContext env;
   1261   env->Global()->Set(v8_str("obj"),
   1262                      templ->GetFunction()->NewInstance());
   1263   Local<Script> script = v8_compile("obj[900]");
   1264   CHECK_EQ(script->Run()->Int32Value(), 900);
   1265 }
   1266 
   1267 
   1268 v8::Handle<v8::Object> bottom;
   1269 
   1270 static v8::Handle<Value> CheckThisIndexedPropertyHandler(
   1271     uint32_t index,
   1272     const AccessorInfo& info) {
   1273   ApiTestFuzzer::Fuzz();
   1274   CHECK(info.This()->Equals(bottom));
   1275   return v8::Handle<Value>();
   1276 }
   1277 
   1278 static v8::Handle<Value> CheckThisNamedPropertyHandler(
   1279     Local<String> name,
   1280     const AccessorInfo& info) {
   1281   ApiTestFuzzer::Fuzz();
   1282   CHECK(info.This()->Equals(bottom));
   1283   return v8::Handle<Value>();
   1284 }
   1285 
   1286 
   1287 v8::Handle<Value> CheckThisIndexedPropertySetter(uint32_t index,
   1288                                                  Local<Value> value,
   1289                                                  const AccessorInfo& info) {
   1290   ApiTestFuzzer::Fuzz();
   1291   CHECK(info.This()->Equals(bottom));
   1292   return v8::Handle<Value>();
   1293 }
   1294 
   1295 
   1296 v8::Handle<Value> CheckThisNamedPropertySetter(Local<String> property,
   1297                                                Local<Value> value,
   1298                                                const AccessorInfo& info) {
   1299   ApiTestFuzzer::Fuzz();
   1300   CHECK(info.This()->Equals(bottom));
   1301   return v8::Handle<Value>();
   1302 }
   1303 
   1304 v8::Handle<v8::Integer> CheckThisIndexedPropertyQuery(
   1305     uint32_t index,
   1306     const AccessorInfo& info) {
   1307   ApiTestFuzzer::Fuzz();
   1308   CHECK(info.This()->Equals(bottom));
   1309   return v8::Handle<v8::Integer>();
   1310 }
   1311 
   1312 
   1313 v8::Handle<v8::Integer> CheckThisNamedPropertyQuery(Local<String> property,
   1314                                                     const AccessorInfo& info) {
   1315   ApiTestFuzzer::Fuzz();
   1316   CHECK(info.This()->Equals(bottom));
   1317   return v8::Handle<v8::Integer>();
   1318 }
   1319 
   1320 
   1321 v8::Handle<v8::Boolean> CheckThisIndexedPropertyDeleter(
   1322     uint32_t index,
   1323     const AccessorInfo& info) {
   1324   ApiTestFuzzer::Fuzz();
   1325   CHECK(info.This()->Equals(bottom));
   1326   return v8::Handle<v8::Boolean>();
   1327 }
   1328 
   1329 
   1330 v8::Handle<v8::Boolean> CheckThisNamedPropertyDeleter(
   1331     Local<String> property,
   1332     const AccessorInfo& info) {
   1333   ApiTestFuzzer::Fuzz();
   1334   CHECK(info.This()->Equals(bottom));
   1335   return v8::Handle<v8::Boolean>();
   1336 }
   1337 
   1338 
   1339 v8::Handle<v8::Array> CheckThisIndexedPropertyEnumerator(
   1340     const AccessorInfo& info) {
   1341   ApiTestFuzzer::Fuzz();
   1342   CHECK(info.This()->Equals(bottom));
   1343   return v8::Handle<v8::Array>();
   1344 }
   1345 
   1346 
   1347 v8::Handle<v8::Array> CheckThisNamedPropertyEnumerator(
   1348     const AccessorInfo& info) {
   1349   ApiTestFuzzer::Fuzz();
   1350   CHECK(info.This()->Equals(bottom));
   1351   return v8::Handle<v8::Array>();
   1352 }
   1353 
   1354 
   1355 THREADED_TEST(PropertyHandlerInPrototype) {
   1356   v8::HandleScope scope;
   1357   LocalContext env;
   1358 
   1359   // Set up a prototype chain with three interceptors.
   1360   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1361   templ->InstanceTemplate()->SetIndexedPropertyHandler(
   1362       CheckThisIndexedPropertyHandler,
   1363       CheckThisIndexedPropertySetter,
   1364       CheckThisIndexedPropertyQuery,
   1365       CheckThisIndexedPropertyDeleter,
   1366       CheckThisIndexedPropertyEnumerator);
   1367 
   1368   templ->InstanceTemplate()->SetNamedPropertyHandler(
   1369       CheckThisNamedPropertyHandler,
   1370       CheckThisNamedPropertySetter,
   1371       CheckThisNamedPropertyQuery,
   1372       CheckThisNamedPropertyDeleter,
   1373       CheckThisNamedPropertyEnumerator);
   1374 
   1375   bottom = templ->GetFunction()->NewInstance();
   1376   Local<v8::Object> top = templ->GetFunction()->NewInstance();
   1377   Local<v8::Object> middle = templ->GetFunction()->NewInstance();
   1378 
   1379   bottom->Set(v8_str("__proto__"), middle);
   1380   middle->Set(v8_str("__proto__"), top);
   1381   env->Global()->Set(v8_str("obj"), bottom);
   1382 
   1383   // Indexed and named get.
   1384   Script::Compile(v8_str("obj[0]"))->Run();
   1385   Script::Compile(v8_str("obj.x"))->Run();
   1386 
   1387   // Indexed and named set.
   1388   Script::Compile(v8_str("obj[1] = 42"))->Run();
   1389   Script::Compile(v8_str("obj.y = 42"))->Run();
   1390 
   1391   // Indexed and named query.
   1392   Script::Compile(v8_str("0 in obj"))->Run();
   1393   Script::Compile(v8_str("'x' in obj"))->Run();
   1394 
   1395   // Indexed and named deleter.
   1396   Script::Compile(v8_str("delete obj[0]"))->Run();
   1397   Script::Compile(v8_str("delete obj.x"))->Run();
   1398 
   1399   // Enumerators.
   1400   Script::Compile(v8_str("for (var p in obj) ;"))->Run();
   1401 }
   1402 
   1403 
   1404 static v8::Handle<Value> PrePropertyHandlerGet(Local<String> key,
   1405                                                const AccessorInfo& info) {
   1406   ApiTestFuzzer::Fuzz();
   1407   if (v8_str("pre")->Equals(key)) {
   1408     return v8_str("PrePropertyHandler: pre");
   1409   }
   1410   return v8::Handle<String>();
   1411 }
   1412 
   1413 
   1414 static v8::Handle<v8::Integer> PrePropertyHandlerQuery(Local<String> key,
   1415                                                        const AccessorInfo&) {
   1416   if (v8_str("pre")->Equals(key)) {
   1417     return v8::Integer::New(v8::None);
   1418   }
   1419 
   1420   return v8::Handle<v8::Integer>();  // do not intercept the call
   1421 }
   1422 
   1423 
   1424 THREADED_TEST(PrePropertyHandler) {
   1425   v8::HandleScope scope;
   1426   v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   1427   desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
   1428                                                     0,
   1429                                                     PrePropertyHandlerQuery);
   1430   LocalContext env(NULL, desc->InstanceTemplate());
   1431   Script::Compile(v8_str(
   1432       "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
   1433   v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
   1434   CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
   1435   v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
   1436   CHECK_EQ(v8_str("Object: on"), result_on);
   1437   v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
   1438   CHECK(result_post.IsEmpty());
   1439 }
   1440 
   1441 
   1442 THREADED_TEST(UndefinedIsNotEnumerable) {
   1443   v8::HandleScope scope;
   1444   LocalContext env;
   1445   v8::Handle<Value> result = Script::Compile(v8_str(
   1446       "this.propertyIsEnumerable(undefined)"))->Run();
   1447   CHECK(result->IsFalse());
   1448 }
   1449 
   1450 
   1451 v8::Handle<Script> call_recursively_script;
   1452 static const int kTargetRecursionDepth = 200;  // near maximum
   1453 
   1454 
   1455 static v8::Handle<Value> CallScriptRecursivelyCall(const v8::Arguments& args) {
   1456   ApiTestFuzzer::Fuzz();
   1457   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   1458   if (depth == kTargetRecursionDepth) return v8::Undefined();
   1459   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
   1460   return call_recursively_script->Run();
   1461 }
   1462 
   1463 
   1464 static v8::Handle<Value> CallFunctionRecursivelyCall(
   1465     const v8::Arguments& args) {
   1466   ApiTestFuzzer::Fuzz();
   1467   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   1468   if (depth == kTargetRecursionDepth) {
   1469     printf("[depth = %d]\n", depth);
   1470     return v8::Undefined();
   1471   }
   1472   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
   1473   v8::Handle<Value> function =
   1474       args.This()->Get(v8_str("callFunctionRecursively"));
   1475   return function.As<Function>()->Call(args.This(), 0, NULL);
   1476 }
   1477 
   1478 
   1479 THREADED_TEST(DeepCrossLanguageRecursion) {
   1480   v8::HandleScope scope;
   1481   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
   1482   global->Set(v8_str("callScriptRecursively"),
   1483               v8::FunctionTemplate::New(CallScriptRecursivelyCall));
   1484   global->Set(v8_str("callFunctionRecursively"),
   1485               v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
   1486   LocalContext env(NULL, global);
   1487 
   1488   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
   1489   call_recursively_script = v8_compile("callScriptRecursively()");
   1490   v8::Handle<Value> result = call_recursively_script->Run();
   1491   call_recursively_script = v8::Handle<Script>();
   1492 
   1493   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
   1494   Script::Compile(v8_str("callFunctionRecursively()"))->Run();
   1495 }
   1496 
   1497 
   1498 static v8::Handle<Value>
   1499     ThrowingPropertyHandlerGet(Local<String> key, const AccessorInfo&) {
   1500   ApiTestFuzzer::Fuzz();
   1501   return v8::ThrowException(key);
   1502 }
   1503 
   1504 
   1505 static v8::Handle<Value> ThrowingPropertyHandlerSet(Local<String> key,
   1506                                                     Local<Value>,
   1507                                                     const AccessorInfo&) {
   1508   v8::ThrowException(key);
   1509   return v8::Undefined();  // not the same as v8::Handle<v8::Value>()
   1510 }
   1511 
   1512 
   1513 THREADED_TEST(CallbackExceptionRegression) {
   1514   v8::HandleScope scope;
   1515   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   1516   obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
   1517                                ThrowingPropertyHandlerSet);
   1518   LocalContext env;
   1519   env->Global()->Set(v8_str("obj"), obj->NewInstance());
   1520   v8::Handle<Value> otto = Script::Compile(v8_str(
   1521       "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
   1522   CHECK_EQ(v8_str("otto"), otto);
   1523   v8::Handle<Value> netto = Script::Compile(v8_str(
   1524       "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
   1525   CHECK_EQ(v8_str("netto"), netto);
   1526 }
   1527 
   1528 
   1529 THREADED_TEST(FunctionPrototype) {
   1530   v8::HandleScope scope;
   1531   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
   1532   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
   1533   LocalContext env;
   1534   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
   1535   Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
   1536   CHECK_EQ(script->Run()->Int32Value(), 321);
   1537 }
   1538 
   1539 
   1540 THREADED_TEST(InternalFields) {
   1541   v8::HandleScope scope;
   1542   LocalContext env;
   1543 
   1544   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1545   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   1546   instance_templ->SetInternalFieldCount(1);
   1547   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   1548   CHECK_EQ(1, obj->InternalFieldCount());
   1549   CHECK(obj->GetInternalField(0)->IsUndefined());
   1550   obj->SetInternalField(0, v8_num(17));
   1551   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
   1552 }
   1553 
   1554 
   1555 THREADED_TEST(GlobalObjectInternalFields) {
   1556   v8::HandleScope scope;
   1557   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   1558   global_template->SetInternalFieldCount(1);
   1559   LocalContext env(NULL, global_template);
   1560   v8::Handle<v8::Object> global_proxy = env->Global();
   1561   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
   1562   CHECK_EQ(1, global->InternalFieldCount());
   1563   CHECK(global->GetInternalField(0)->IsUndefined());
   1564   global->SetInternalField(0, v8_num(17));
   1565   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
   1566 }
   1567 
   1568 
   1569 THREADED_TEST(InternalFieldsNativePointers) {
   1570   v8::HandleScope scope;
   1571   LocalContext env;
   1572 
   1573   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1574   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   1575   instance_templ->SetInternalFieldCount(1);
   1576   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   1577   CHECK_EQ(1, obj->InternalFieldCount());
   1578   CHECK(obj->GetPointerFromInternalField(0) == NULL);
   1579 
   1580   char* data = new char[100];
   1581 
   1582   void* aligned = data;
   1583   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1));
   1584   void* unaligned = data + 1;
   1585   CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1));
   1586 
   1587   // Check reading and writing aligned pointers.
   1588   obj->SetPointerInInternalField(0, aligned);
   1589   HEAP->CollectAllGarbage(false);
   1590   CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
   1591 
   1592   // Check reading and writing unaligned pointers.
   1593   obj->SetPointerInInternalField(0, unaligned);
   1594   HEAP->CollectAllGarbage(false);
   1595   CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
   1596 
   1597   delete[] data;
   1598 }
   1599 
   1600 
   1601 THREADED_TEST(InternalFieldsNativePointersAndExternal) {
   1602   v8::HandleScope scope;
   1603   LocalContext env;
   1604 
   1605   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1606   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   1607   instance_templ->SetInternalFieldCount(1);
   1608   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   1609   CHECK_EQ(1, obj->InternalFieldCount());
   1610   CHECK(obj->GetPointerFromInternalField(0) == NULL);
   1611 
   1612   char* data = new char[100];
   1613 
   1614   void* aligned = data;
   1615   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1));
   1616   void* unaligned = data + 1;
   1617   CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1));
   1618 
   1619   obj->SetPointerInInternalField(0, aligned);
   1620   HEAP->CollectAllGarbage(false);
   1621   CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0)));
   1622 
   1623   obj->SetPointerInInternalField(0, unaligned);
   1624   HEAP->CollectAllGarbage(false);
   1625   CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0)));
   1626 
   1627   obj->SetInternalField(0, v8::External::Wrap(aligned));
   1628   HEAP->CollectAllGarbage(false);
   1629   CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
   1630 
   1631   obj->SetInternalField(0, v8::External::Wrap(unaligned));
   1632   HEAP->CollectAllGarbage(false);
   1633   CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
   1634 
   1635   delete[] data;
   1636 }
   1637 
   1638 
   1639 THREADED_TEST(IdentityHash) {
   1640   v8::HandleScope scope;
   1641   LocalContext env;
   1642 
   1643   // Ensure that the test starts with an fresh heap to test whether the hash
   1644   // code is based on the address.
   1645   HEAP->CollectAllGarbage(false);
   1646   Local<v8::Object> obj = v8::Object::New();
   1647   int hash = obj->GetIdentityHash();
   1648   int hash1 = obj->GetIdentityHash();
   1649   CHECK_EQ(hash, hash1);
   1650   int hash2 = v8::Object::New()->GetIdentityHash();
   1651   // Since the identity hash is essentially a random number two consecutive
   1652   // objects should not be assigned the same hash code. If the test below fails
   1653   // the random number generator should be evaluated.
   1654   CHECK_NE(hash, hash2);
   1655   HEAP->CollectAllGarbage(false);
   1656   int hash3 = v8::Object::New()->GetIdentityHash();
   1657   // Make sure that the identity hash is not based on the initial address of
   1658   // the object alone. If the test below fails the random number generator
   1659   // should be evaluated.
   1660   CHECK_NE(hash, hash3);
   1661   int hash4 = obj->GetIdentityHash();
   1662   CHECK_EQ(hash, hash4);
   1663 
   1664   // Check identity hashes behaviour in the presence of JS accessors.
   1665   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
   1666   {
   1667     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
   1668     Local<v8::Object> o1 = v8::Object::New();
   1669     Local<v8::Object> o2 = v8::Object::New();
   1670     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   1671   }
   1672   {
   1673     CompileRun(
   1674         "function cnst() { return 42; };\n"
   1675         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
   1676     Local<v8::Object> o1 = v8::Object::New();
   1677     Local<v8::Object> o2 = v8::Object::New();
   1678     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   1679   }
   1680 }
   1681 
   1682 
   1683 THREADED_TEST(HiddenProperties) {
   1684   v8::HandleScope scope;
   1685   LocalContext env;
   1686 
   1687   v8::Local<v8::Object> obj = v8::Object::New();
   1688   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   1689   v8::Local<v8::String> empty = v8_str("");
   1690   v8::Local<v8::String> prop_name = v8_str("prop_name");
   1691 
   1692   HEAP->CollectAllGarbage(false);
   1693 
   1694   // Make sure delete of a non-existent hidden value works
   1695   CHECK(obj->DeleteHiddenValue(key));
   1696 
   1697   CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
   1698   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
   1699   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
   1700   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   1701 
   1702   HEAP->CollectAllGarbage(false);
   1703 
   1704   // Make sure we do not find the hidden property.
   1705   CHECK(!obj->Has(empty));
   1706   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   1707   CHECK(obj->Get(empty)->IsUndefined());
   1708   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   1709   CHECK(obj->Set(empty, v8::Integer::New(2003)));
   1710   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   1711   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
   1712 
   1713   HEAP->CollectAllGarbage(false);
   1714 
   1715   // Add another property and delete it afterwards to force the object in
   1716   // slow case.
   1717   CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
   1718   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   1719   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
   1720   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   1721   CHECK(obj->Delete(prop_name));
   1722   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   1723 
   1724   HEAP->CollectAllGarbage(false);
   1725 
   1726   CHECK(obj->DeleteHiddenValue(key));
   1727   CHECK(obj->GetHiddenValue(key).IsEmpty());
   1728 }
   1729 
   1730 
   1731 static bool interceptor_for_hidden_properties_called;
   1732 static v8::Handle<Value> InterceptorForHiddenProperties(
   1733     Local<String> name, const AccessorInfo& info) {
   1734   interceptor_for_hidden_properties_called = true;
   1735   return v8::Handle<Value>();
   1736 }
   1737 
   1738 
   1739 THREADED_TEST(HiddenPropertiesWithInterceptors) {
   1740   v8::HandleScope scope;
   1741   LocalContext context;
   1742 
   1743   interceptor_for_hidden_properties_called = false;
   1744 
   1745   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   1746 
   1747   // Associate an interceptor with an object and start setting hidden values.
   1748   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   1749   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   1750   instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
   1751   Local<v8::Function> function = fun_templ->GetFunction();
   1752   Local<v8::Object> obj = function->NewInstance();
   1753   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
   1754   CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
   1755   CHECK(!interceptor_for_hidden_properties_called);
   1756 }
   1757 
   1758 
   1759 THREADED_TEST(External) {
   1760   v8::HandleScope scope;
   1761   int x = 3;
   1762   Local<v8::External> ext = v8::External::New(&x);
   1763   LocalContext env;
   1764   env->Global()->Set(v8_str("ext"), ext);
   1765   Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
   1766   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
   1767   int* ptr = static_cast<int*>(reext->Value());
   1768   CHECK_EQ(x, 3);
   1769   *ptr = 10;
   1770   CHECK_EQ(x, 10);
   1771 
   1772   // Make sure unaligned pointers are wrapped properly.
   1773   char* data = i::StrDup("0123456789");
   1774   Local<v8::Value> zero = v8::External::Wrap(&data[0]);
   1775   Local<v8::Value> one = v8::External::Wrap(&data[1]);
   1776   Local<v8::Value> two = v8::External::Wrap(&data[2]);
   1777   Local<v8::Value> three = v8::External::Wrap(&data[3]);
   1778 
   1779   char* char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(zero));
   1780   CHECK_EQ('0', *char_ptr);
   1781   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(one));
   1782   CHECK_EQ('1', *char_ptr);
   1783   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(two));
   1784   CHECK_EQ('2', *char_ptr);
   1785   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(three));
   1786   CHECK_EQ('3', *char_ptr);
   1787   i::DeleteArray(data);
   1788 }
   1789 
   1790 
   1791 THREADED_TEST(GlobalHandle) {
   1792   v8::Persistent<String> global;
   1793   {
   1794     v8::HandleScope scope;
   1795     Local<String> str = v8_str("str");
   1796     global = v8::Persistent<String>::New(str);
   1797   }
   1798   CHECK_EQ(global->Length(), 3);
   1799   global.Dispose();
   1800 }
   1801 
   1802 
   1803 static int NumberOfWeakCalls = 0;
   1804 static void WeakPointerCallback(Persistent<Value> handle, void* id) {
   1805   CHECK_EQ(reinterpret_cast<void*>(1234), id);
   1806   NumberOfWeakCalls++;
   1807   handle.Dispose();
   1808 }
   1809 
   1810 THREADED_TEST(ApiObjectGroups) {
   1811   HandleScope scope;
   1812   LocalContext env;
   1813 
   1814   NumberOfWeakCalls = 0;
   1815 
   1816   Persistent<Object> g1s1;
   1817   Persistent<Object> g1s2;
   1818   Persistent<Object> g1c1;
   1819   Persistent<Object> g2s1;
   1820   Persistent<Object> g2s2;
   1821   Persistent<Object> g2c1;
   1822 
   1823   {
   1824     HandleScope scope;
   1825     g1s1 = Persistent<Object>::New(Object::New());
   1826     g1s2 = Persistent<Object>::New(Object::New());
   1827     g1c1 = Persistent<Object>::New(Object::New());
   1828     g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1829     g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1830     g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1831 
   1832     g2s1 = Persistent<Object>::New(Object::New());
   1833     g2s2 = Persistent<Object>::New(Object::New());
   1834     g2c1 = Persistent<Object>::New(Object::New());
   1835     g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1836     g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1837     g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1838   }
   1839 
   1840   Persistent<Object> root = Persistent<Object>::New(g1s1);  // make a root.
   1841 
   1842   // Connect group 1 and 2, make a cycle.
   1843   CHECK(g1s2->Set(0, g2s2));
   1844   CHECK(g2s1->Set(0, g1s1));
   1845 
   1846   {
   1847     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
   1848     Persistent<Value> g1_children[] = { g1c1 };
   1849     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
   1850     Persistent<Value> g2_children[] = { g2c1 };
   1851     V8::AddObjectGroup(g1_objects, 2);
   1852     V8::AddImplicitReferences(g1s1, g1_children, 1);
   1853     V8::AddObjectGroup(g2_objects, 2);
   1854     V8::AddImplicitReferences(g2s2, g2_children, 1);
   1855   }
   1856   // Do a full GC
   1857   HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
   1858 
   1859   // All object should be alive.
   1860   CHECK_EQ(0, NumberOfWeakCalls);
   1861 
   1862   // Weaken the root.
   1863   root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1864   // But make children strong roots---all the objects (except for children)
   1865   // should be collectable now.
   1866   g1c1.ClearWeak();
   1867   g2c1.ClearWeak();
   1868 
   1869   // Groups are deleted, rebuild groups.
   1870   {
   1871     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
   1872     Persistent<Value> g1_children[] = { g1c1 };
   1873     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
   1874     Persistent<Value> g2_children[] = { g2c1 };
   1875     V8::AddObjectGroup(g1_objects, 2);
   1876     V8::AddImplicitReferences(g1s1, g1_children, 1);
   1877     V8::AddObjectGroup(g2_objects, 2);
   1878     V8::AddImplicitReferences(g2s2, g2_children, 1);
   1879   }
   1880 
   1881   HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
   1882 
   1883   // All objects should be gone. 5 global handles in total.
   1884   CHECK_EQ(5, NumberOfWeakCalls);
   1885 
   1886   // And now make children weak again and collect them.
   1887   g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1888   g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1889 
   1890   HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
   1891   CHECK_EQ(7, NumberOfWeakCalls);
   1892 }
   1893 
   1894 
   1895 THREADED_TEST(ApiObjectGroupsCycle) {
   1896   HandleScope scope;
   1897   LocalContext env;
   1898 
   1899   NumberOfWeakCalls = 0;
   1900 
   1901   Persistent<Object> g1s1;
   1902   Persistent<Object> g1s2;
   1903   Persistent<Object> g2s1;
   1904   Persistent<Object> g2s2;
   1905   Persistent<Object> g3s1;
   1906   Persistent<Object> g3s2;
   1907 
   1908   {
   1909     HandleScope scope;
   1910     g1s1 = Persistent<Object>::New(Object::New());
   1911     g1s2 = Persistent<Object>::New(Object::New());
   1912     g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1913     g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1914 
   1915     g2s1 = Persistent<Object>::New(Object::New());
   1916     g2s2 = Persistent<Object>::New(Object::New());
   1917     g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1918     g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1919 
   1920     g3s1 = Persistent<Object>::New(Object::New());
   1921     g3s2 = Persistent<Object>::New(Object::New());
   1922     g3s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1923     g3s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1924   }
   1925 
   1926   Persistent<Object> root = Persistent<Object>::New(g1s1);  // make a root.
   1927 
   1928   // Connect groups.  We're building the following cycle:
   1929   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   1930   // groups.
   1931   {
   1932     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
   1933     Persistent<Value> g1_children[] = { g2s1 };
   1934     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
   1935     Persistent<Value> g2_children[] = { g3s1 };
   1936     Persistent<Value> g3_objects[] = { g3s1, g3s2 };
   1937     Persistent<Value> g3_children[] = { g1s1 };
   1938     V8::AddObjectGroup(g1_objects, 2);
   1939     V8::AddImplicitReferences(g1s1, g1_children, 1);
   1940     V8::AddObjectGroup(g2_objects, 2);
   1941     V8::AddImplicitReferences(g2s1, g2_children, 1);
   1942     V8::AddObjectGroup(g3_objects, 2);
   1943     V8::AddImplicitReferences(g3s1, g3_children, 1);
   1944   }
   1945   // Do a full GC
   1946   HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
   1947 
   1948   // All object should be alive.
   1949   CHECK_EQ(0, NumberOfWeakCalls);
   1950 
   1951   // Weaken the root.
   1952   root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
   1953 
   1954   // Groups are deleted, rebuild groups.
   1955   {
   1956     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
   1957     Persistent<Value> g1_children[] = { g2s1 };
   1958     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
   1959     Persistent<Value> g2_children[] = { g3s1 };
   1960     Persistent<Value> g3_objects[] = { g3s1, g3s2 };
   1961     Persistent<Value> g3_children[] = { g1s1 };
   1962     V8::AddObjectGroup(g1_objects, 2);
   1963     V8::AddImplicitReferences(g1s1, g1_children, 1);
   1964     V8::AddObjectGroup(g2_objects, 2);
   1965     V8::AddImplicitReferences(g2s1, g2_children, 1);
   1966     V8::AddObjectGroup(g3_objects, 2);
   1967     V8::AddImplicitReferences(g3s1, g3_children, 1);
   1968   }
   1969 
   1970   HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
   1971 
   1972   // All objects should be gone. 7 global handles in total.
   1973   CHECK_EQ(7, NumberOfWeakCalls);
   1974 }
   1975 
   1976 
   1977 THREADED_TEST(ScriptException) {
   1978   v8::HandleScope scope;
   1979   LocalContext env;
   1980   Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
   1981   v8::TryCatch try_catch;
   1982   Local<Value> result = script->Run();
   1983   CHECK(result.IsEmpty());
   1984   CHECK(try_catch.HasCaught());
   1985   String::AsciiValue exception_value(try_catch.Exception());
   1986   CHECK_EQ(*exception_value, "panama!");
   1987 }
   1988 
   1989 
   1990 bool message_received;
   1991 
   1992 
   1993 static void check_message(v8::Handle<v8::Message> message,
   1994                           v8::Handle<Value> data) {
   1995   CHECK_EQ(5.76, data->NumberValue());
   1996   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   1997   CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
   1998   message_received = true;
   1999 }
   2000 
   2001 
   2002 THREADED_TEST(MessageHandlerData) {
   2003   message_received = false;
   2004   v8::HandleScope scope;
   2005   CHECK(!message_received);
   2006   v8::V8::AddMessageListener(check_message, v8_num(5.76));
   2007   LocalContext context;
   2008   v8::ScriptOrigin origin =
   2009       v8::ScriptOrigin(v8_str("6.75"));
   2010   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   2011                                                   &origin);
   2012   script->SetData(v8_str("7.56"));
   2013   script->Run();
   2014   CHECK(message_received);
   2015   // clear out the message listener
   2016   v8::V8::RemoveMessageListeners(check_message);
   2017 }
   2018 
   2019 
   2020 THREADED_TEST(GetSetProperty) {
   2021   v8::HandleScope scope;
   2022   LocalContext context;
   2023   context->Global()->Set(v8_str("foo"), v8_num(14));
   2024   context->Global()->Set(v8_str("12"), v8_num(92));
   2025   context->Global()->Set(v8::Integer::New(16), v8_num(32));
   2026   context->Global()->Set(v8_num(13), v8_num(56));
   2027   Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
   2028   CHECK_EQ(14, foo->Int32Value());
   2029   Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
   2030   CHECK_EQ(92, twelve->Int32Value());
   2031   Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
   2032   CHECK_EQ(32, sixteen->Int32Value());
   2033   Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
   2034   CHECK_EQ(56, thirteen->Int32Value());
   2035   CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
   2036   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
   2037   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
   2038   CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
   2039   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
   2040   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
   2041   CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
   2042   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
   2043   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
   2044 }
   2045 
   2046 
   2047 THREADED_TEST(PropertyAttributes) {
   2048   v8::HandleScope scope;
   2049   LocalContext context;
   2050   // read-only
   2051   Local<String> prop = v8_str("read_only");
   2052   context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
   2053   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   2054   Script::Compile(v8_str("read_only = 9"))->Run();
   2055   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   2056   context->Global()->Set(prop, v8_num(10));
   2057   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   2058   // dont-delete
   2059   prop = v8_str("dont_delete");
   2060   context->Global()->Set(prop, v8_num(13), v8::DontDelete);
   2061   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   2062   Script::Compile(v8_str("delete dont_delete"))->Run();
   2063   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   2064 }
   2065 
   2066 
   2067 THREADED_TEST(Array) {
   2068   v8::HandleScope scope;
   2069   LocalContext context;
   2070   Local<v8::Array> array = v8::Array::New();
   2071   CHECK_EQ(0, array->Length());
   2072   CHECK(array->Get(0)->IsUndefined());
   2073   CHECK(!array->Has(0));
   2074   CHECK(array->Get(100)->IsUndefined());
   2075   CHECK(!array->Has(100));
   2076   array->Set(2, v8_num(7));
   2077   CHECK_EQ(3, array->Length());
   2078   CHECK(!array->Has(0));
   2079   CHECK(!array->Has(1));
   2080   CHECK(array->Has(2));
   2081   CHECK_EQ(7, array->Get(2)->Int32Value());
   2082   Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
   2083   Local<v8::Array> arr = obj.As<v8::Array>();
   2084   CHECK_EQ(3, arr->Length());
   2085   CHECK_EQ(1, arr->Get(0)->Int32Value());
   2086   CHECK_EQ(2, arr->Get(1)->Int32Value());
   2087   CHECK_EQ(3, arr->Get(2)->Int32Value());
   2088   array = v8::Array::New(27);
   2089   CHECK_EQ(27, array->Length());
   2090   array = v8::Array::New(-27);
   2091   CHECK_EQ(0, array->Length());
   2092 }
   2093 
   2094 
   2095 v8::Handle<Value> HandleF(const v8::Arguments& args) {
   2096   v8::HandleScope scope;
   2097   ApiTestFuzzer::Fuzz();
   2098   Local<v8::Array> result = v8::Array::New(args.Length());
   2099   for (int i = 0; i < args.Length(); i++)
   2100     result->Set(i, args[i]);
   2101   return scope.Close(result);
   2102 }
   2103 
   2104 
   2105 THREADED_TEST(Vector) {
   2106   v8::HandleScope scope;
   2107   Local<ObjectTemplate> global = ObjectTemplate::New();
   2108   global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
   2109   LocalContext context(0, global);
   2110 
   2111   const char* fun = "f()";
   2112   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
   2113   CHECK_EQ(0, a0->Length());
   2114 
   2115   const char* fun2 = "f(11)";
   2116   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
   2117   CHECK_EQ(1, a1->Length());
   2118   CHECK_EQ(11, a1->Get(0)->Int32Value());
   2119 
   2120   const char* fun3 = "f(12, 13)";
   2121   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
   2122   CHECK_EQ(2, a2->Length());
   2123   CHECK_EQ(12, a2->Get(0)->Int32Value());
   2124   CHECK_EQ(13, a2->Get(1)->Int32Value());
   2125 
   2126   const char* fun4 = "f(14, 15, 16)";
   2127   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
   2128   CHECK_EQ(3, a3->Length());
   2129   CHECK_EQ(14, a3->Get(0)->Int32Value());
   2130   CHECK_EQ(15, a3->Get(1)->Int32Value());
   2131   CHECK_EQ(16, a3->Get(2)->Int32Value());
   2132 
   2133   const char* fun5 = "f(17, 18, 19, 20)";
   2134   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
   2135   CHECK_EQ(4, a4->Length());
   2136   CHECK_EQ(17, a4->Get(0)->Int32Value());
   2137   CHECK_EQ(18, a4->Get(1)->Int32Value());
   2138   CHECK_EQ(19, a4->Get(2)->Int32Value());
   2139   CHECK_EQ(20, a4->Get(3)->Int32Value());
   2140 }
   2141 
   2142 
   2143 THREADED_TEST(FunctionCall) {
   2144   v8::HandleScope scope;
   2145   LocalContext context;
   2146   CompileRun(
   2147     "function Foo() {"
   2148     "  var result = [];"
   2149     "  for (var i = 0; i < arguments.length; i++) {"
   2150     "    result.push(arguments[i]);"
   2151     "  }"
   2152     "  return result;"
   2153     "}");
   2154   Local<Function> Foo =
   2155       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   2156 
   2157   v8::Handle<Value>* args0 = NULL;
   2158   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
   2159   CHECK_EQ(0, a0->Length());
   2160 
   2161   v8::Handle<Value> args1[] = { v8_num(1.1) };
   2162   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
   2163   CHECK_EQ(1, a1->Length());
   2164   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
   2165 
   2166   v8::Handle<Value> args2[] = { v8_num(2.2),
   2167                                 v8_num(3.3) };
   2168   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
   2169   CHECK_EQ(2, a2->Length());
   2170   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
   2171   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
   2172 
   2173   v8::Handle<Value> args3[] = { v8_num(4.4),
   2174                                 v8_num(5.5),
   2175                                 v8_num(6.6) };
   2176   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
   2177   CHECK_EQ(3, a3->Length());
   2178   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
   2179   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
   2180   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
   2181 
   2182   v8::Handle<Value> args4[] = { v8_num(7.7),
   2183                                 v8_num(8.8),
   2184                                 v8_num(9.9),
   2185                                 v8_num(10.11) };
   2186   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
   2187   CHECK_EQ(4, a4->Length());
   2188   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
   2189   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   2190   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   2191   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
   2192 }
   2193 
   2194 
   2195 static const char* js_code_causing_out_of_memory =
   2196     "var a = new Array(); while(true) a.push(a);";
   2197 
   2198 
   2199 // These tests run for a long time and prevent us from running tests
   2200 // that come after them so they cannot run in parallel.
   2201 TEST(OutOfMemory) {
   2202   // It's not possible to read a snapshot into a heap with different dimensions.
   2203   if (i::Snapshot::IsEnabled()) return;
   2204   // Set heap limits.
   2205   static const int K = 1024;
   2206   v8::ResourceConstraints constraints;
   2207   constraints.set_max_young_space_size(256 * K);
   2208   constraints.set_max_old_space_size(4 * K * K);
   2209   v8::SetResourceConstraints(&constraints);
   2210 
   2211   // Execute a script that causes out of memory.
   2212   v8::HandleScope scope;
   2213   LocalContext context;
   2214   v8::V8::IgnoreOutOfMemoryException();
   2215   Local<Script> script =
   2216       Script::Compile(String::New(js_code_causing_out_of_memory));
   2217   Local<Value> result = script->Run();
   2218 
   2219   // Check for out of memory state.
   2220   CHECK(result.IsEmpty());
   2221   CHECK(context->HasOutOfMemoryException());
   2222 }
   2223 
   2224 
   2225 v8::Handle<Value> ProvokeOutOfMemory(const v8::Arguments& args) {
   2226   ApiTestFuzzer::Fuzz();
   2227 
   2228   v8::HandleScope scope;
   2229   LocalContext context;
   2230   Local<Script> script =
   2231       Script::Compile(String::New(js_code_causing_out_of_memory));
   2232   Local<Value> result = script->Run();
   2233 
   2234   // Check for out of memory state.
   2235   CHECK(result.IsEmpty());
   2236   CHECK(context->HasOutOfMemoryException());
   2237 
   2238   return result;
   2239 }
   2240 
   2241 
   2242 TEST(OutOfMemoryNested) {
   2243   // It's not possible to read a snapshot into a heap with different dimensions.
   2244   if (i::Snapshot::IsEnabled()) return;
   2245   // Set heap limits.
   2246   static const int K = 1024;
   2247   v8::ResourceConstraints constraints;
   2248   constraints.set_max_young_space_size(256 * K);
   2249   constraints.set_max_old_space_size(4 * K * K);
   2250   v8::SetResourceConstraints(&constraints);
   2251 
   2252   v8::HandleScope scope;
   2253   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2254   templ->Set(v8_str("ProvokeOutOfMemory"),
   2255              v8::FunctionTemplate::New(ProvokeOutOfMemory));
   2256   LocalContext context(0, templ);
   2257   v8::V8::IgnoreOutOfMemoryException();
   2258   Local<Value> result = CompileRun(
   2259     "var thrown = false;"
   2260     "try {"
   2261     "  ProvokeOutOfMemory();"
   2262     "} catch (e) {"
   2263     "  thrown = true;"
   2264     "}");
   2265   // Check for out of memory state.
   2266   CHECK(result.IsEmpty());
   2267   CHECK(context->HasOutOfMemoryException());
   2268 }
   2269 
   2270 
   2271 TEST(HugeConsStringOutOfMemory) {
   2272   // It's not possible to read a snapshot into a heap with different dimensions.
   2273   if (i::Snapshot::IsEnabled()) return;
   2274   // Set heap limits.
   2275   static const int K = 1024;
   2276   v8::ResourceConstraints constraints;
   2277   constraints.set_max_young_space_size(256 * K);
   2278   constraints.set_max_old_space_size(2 * K * K);
   2279   v8::SetResourceConstraints(&constraints);
   2280 
   2281   // Execute a script that causes out of memory.
   2282   v8::V8::IgnoreOutOfMemoryException();
   2283 
   2284   v8::HandleScope scope;
   2285   LocalContext context;
   2286 
   2287   // Build huge string. This should fail with out of memory exception.
   2288   Local<Value> result = CompileRun(
   2289     "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
   2290     "for (var i = 0; i < 22; i++) { str = str + str; }");
   2291 
   2292   // Check for out of memory state.
   2293   CHECK(result.IsEmpty());
   2294   CHECK(context->HasOutOfMemoryException());
   2295 }
   2296 
   2297 
   2298 THREADED_TEST(ConstructCall) {
   2299   v8::HandleScope scope;
   2300   LocalContext context;
   2301   CompileRun(
   2302     "function Foo() {"
   2303     "  var result = [];"
   2304     "  for (var i = 0; i < arguments.length; i++) {"
   2305     "    result.push(arguments[i]);"
   2306     "  }"
   2307     "  return result;"
   2308     "}");
   2309   Local<Function> Foo =
   2310       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   2311 
   2312   v8::Handle<Value>* args0 = NULL;
   2313   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
   2314   CHECK_EQ(0, a0->Length());
   2315 
   2316   v8::Handle<Value> args1[] = { v8_num(1.1) };
   2317   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
   2318   CHECK_EQ(1, a1->Length());
   2319   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
   2320 
   2321   v8::Handle<Value> args2[] = { v8_num(2.2),
   2322                                 v8_num(3.3) };
   2323   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
   2324   CHECK_EQ(2, a2->Length());
   2325   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
   2326   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
   2327 
   2328   v8::Handle<Value> args3[] = { v8_num(4.4),
   2329                                 v8_num(5.5),
   2330                                 v8_num(6.6) };
   2331   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
   2332   CHECK_EQ(3, a3->Length());
   2333   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
   2334   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
   2335   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
   2336 
   2337   v8::Handle<Value> args4[] = { v8_num(7.7),
   2338                                 v8_num(8.8),
   2339                                 v8_num(9.9),
   2340                                 v8_num(10.11) };
   2341   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
   2342   CHECK_EQ(4, a4->Length());
   2343   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
   2344   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   2345   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   2346   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
   2347 }
   2348 
   2349 
   2350 static void CheckUncle(v8::TryCatch* try_catch) {
   2351   CHECK(try_catch->HasCaught());
   2352   String::AsciiValue str_value(try_catch->Exception());
   2353   CHECK_EQ(*str_value, "uncle?");
   2354   try_catch->Reset();
   2355 }
   2356 
   2357 
   2358 THREADED_TEST(ConversionNumber) {
   2359   v8::HandleScope scope;
   2360   LocalContext env;
   2361   // Very large number.
   2362   CompileRun("var obj = Math.pow(2,32) * 1237;");
   2363   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   2364   CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
   2365   CHECK_EQ(0, obj->ToInt32()->Value());
   2366   CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
   2367   // Large number.
   2368   CompileRun("var obj = -1234567890123;");
   2369   obj = env->Global()->Get(v8_str("obj"));
   2370   CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
   2371   CHECK_EQ(-1912276171, obj->ToInt32()->Value());
   2372   CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
   2373   // Small positive integer.
   2374   CompileRun("var obj = 42;");
   2375   obj = env->Global()->Get(v8_str("obj"));
   2376   CHECK_EQ(42.0, obj->ToNumber()->Value());
   2377   CHECK_EQ(42, obj->ToInt32()->Value());
   2378   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   2379   // Negative integer.
   2380   CompileRun("var obj = -37;");
   2381   obj = env->Global()->Get(v8_str("obj"));
   2382   CHECK_EQ(-37.0, obj->ToNumber()->Value());
   2383   CHECK_EQ(-37, obj->ToInt32()->Value());
   2384   CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
   2385   // Positive non-int32 integer.
   2386   CompileRun("var obj = 0x81234567;");
   2387   obj = env->Global()->Get(v8_str("obj"));
   2388   CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
   2389   CHECK_EQ(-2128394905, obj->ToInt32()->Value());
   2390   CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
   2391   // Fraction.
   2392   CompileRun("var obj = 42.3;");
   2393   obj = env->Global()->Get(v8_str("obj"));
   2394   CHECK_EQ(42.3, obj->ToNumber()->Value());
   2395   CHECK_EQ(42, obj->ToInt32()->Value());
   2396   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   2397   // Large negative fraction.
   2398   CompileRun("var obj = -5726623061.75;");
   2399   obj = env->Global()->Get(v8_str("obj"));
   2400   CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
   2401   CHECK_EQ(-1431655765, obj->ToInt32()->Value());
   2402   CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
   2403 }
   2404 
   2405 
   2406 THREADED_TEST(isNumberType) {
   2407   v8::HandleScope scope;
   2408   LocalContext env;
   2409   // Very large number.
   2410   CompileRun("var obj = Math.pow(2,32) * 1237;");
   2411   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   2412   CHECK(!obj->IsInt32());
   2413   CHECK(!obj->IsUint32());
   2414   // Large negative number.
   2415   CompileRun("var obj = -1234567890123;");
   2416   obj = env->Global()->Get(v8_str("obj"));
   2417   CHECK(!obj->IsInt32());
   2418   CHECK(!obj->IsUint32());
   2419   // Small positive integer.
   2420   CompileRun("var obj = 42;");
   2421   obj = env->Global()->Get(v8_str("obj"));
   2422   CHECK(obj->IsInt32());
   2423   CHECK(obj->IsUint32());
   2424   // Negative integer.
   2425   CompileRun("var obj = -37;");
   2426   obj = env->Global()->Get(v8_str("obj"));
   2427   CHECK(obj->IsInt32());
   2428   CHECK(!obj->IsUint32());
   2429   // Positive non-int32 integer.
   2430   CompileRun("var obj = 0x81234567;");
   2431   obj = env->Global()->Get(v8_str("obj"));
   2432   CHECK(!obj->IsInt32());
   2433   CHECK(obj->IsUint32());
   2434   // Fraction.
   2435   CompileRun("var obj = 42.3;");
   2436   obj = env->Global()->Get(v8_str("obj"));
   2437   CHECK(!obj->IsInt32());
   2438   CHECK(!obj->IsUint32());
   2439   // Large negative fraction.
   2440   CompileRun("var obj = -5726623061.75;");
   2441   obj = env->Global()->Get(v8_str("obj"));
   2442   CHECK(!obj->IsInt32());
   2443   CHECK(!obj->IsUint32());
   2444 }
   2445 
   2446 
   2447 THREADED_TEST(ConversionException) {
   2448   v8::HandleScope scope;
   2449   LocalContext env;
   2450   CompileRun(
   2451     "function TestClass() { };"
   2452     "TestClass.prototype.toString = function () { throw 'uncle?'; };"
   2453     "var obj = new TestClass();");
   2454   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   2455 
   2456   v8::TryCatch try_catch;
   2457 
   2458   Local<Value> to_string_result = obj->ToString();
   2459   CHECK(to_string_result.IsEmpty());
   2460   CheckUncle(&try_catch);
   2461 
   2462   Local<Value> to_number_result = obj->ToNumber();
   2463   CHECK(to_number_result.IsEmpty());
   2464   CheckUncle(&try_catch);
   2465 
   2466   Local<Value> to_integer_result = obj->ToInteger();
   2467   CHECK(to_integer_result.IsEmpty());
   2468   CheckUncle(&try_catch);
   2469 
   2470   Local<Value> to_uint32_result = obj->ToUint32();
   2471   CHECK(to_uint32_result.IsEmpty());
   2472   CheckUncle(&try_catch);
   2473 
   2474   Local<Value> to_int32_result = obj->ToInt32();
   2475   CHECK(to_int32_result.IsEmpty());
   2476   CheckUncle(&try_catch);
   2477 
   2478   Local<Value> to_object_result = v8::Undefined()->ToObject();
   2479   CHECK(to_object_result.IsEmpty());
   2480   CHECK(try_catch.HasCaught());
   2481   try_catch.Reset();
   2482 
   2483   int32_t int32_value = obj->Int32Value();
   2484   CHECK_EQ(0, int32_value);
   2485   CheckUncle(&try_catch);
   2486 
   2487   uint32_t uint32_value = obj->Uint32Value();
   2488   CHECK_EQ(0, uint32_value);
   2489   CheckUncle(&try_catch);
   2490 
   2491   double number_value = obj->NumberValue();
   2492   CHECK_NE(0, IsNaN(number_value));
   2493   CheckUncle(&try_catch);
   2494 
   2495   int64_t integer_value = obj->IntegerValue();
   2496   CHECK_EQ(0.0, static_cast<double>(integer_value));
   2497   CheckUncle(&try_catch);
   2498 }
   2499 
   2500 
   2501 v8::Handle<Value> ThrowFromC(const v8::Arguments& args) {
   2502   ApiTestFuzzer::Fuzz();
   2503   return v8::ThrowException(v8_str("konto"));
   2504 }
   2505 
   2506 
   2507 v8::Handle<Value> CCatcher(const v8::Arguments& args) {
   2508   if (args.Length() < 1) return v8::Boolean::New(false);
   2509   v8::HandleScope scope;
   2510   v8::TryCatch try_catch;
   2511   Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
   2512   CHECK(!try_catch.HasCaught() || result.IsEmpty());
   2513   return v8::Boolean::New(try_catch.HasCaught());
   2514 }
   2515 
   2516 
   2517 THREADED_TEST(APICatch) {
   2518   v8::HandleScope scope;
   2519   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2520   templ->Set(v8_str("ThrowFromC"),
   2521              v8::FunctionTemplate::New(ThrowFromC));
   2522   LocalContext context(0, templ);
   2523   CompileRun(
   2524     "var thrown = false;"
   2525     "try {"
   2526     "  ThrowFromC();"
   2527     "} catch (e) {"
   2528     "  thrown = true;"
   2529     "}");
   2530   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
   2531   CHECK(thrown->BooleanValue());
   2532 }
   2533 
   2534 
   2535 THREADED_TEST(APIThrowTryCatch) {
   2536   v8::HandleScope scope;
   2537   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2538   templ->Set(v8_str("ThrowFromC"),
   2539              v8::FunctionTemplate::New(ThrowFromC));
   2540   LocalContext context(0, templ);
   2541   v8::TryCatch try_catch;
   2542   CompileRun("ThrowFromC();");
   2543   CHECK(try_catch.HasCaught());
   2544 }
   2545 
   2546 
   2547 // Test that a try-finally block doesn't shadow a try-catch block
   2548 // when setting up an external handler.
   2549 //
   2550 // BUG(271): Some of the exception propagation does not work on the
   2551 // ARM simulator because the simulator separates the C++ stack and the
   2552 // JS stack.  This test therefore fails on the simulator.  The test is
   2553 // not threaded to allow the threading tests to run on the simulator.
   2554 TEST(TryCatchInTryFinally) {
   2555   v8::HandleScope scope;
   2556   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2557   templ->Set(v8_str("CCatcher"),
   2558              v8::FunctionTemplate::New(CCatcher));
   2559   LocalContext context(0, templ);
   2560   Local<Value> result = CompileRun("try {"
   2561                                    "  try {"
   2562                                    "    CCatcher('throw 7;');"
   2563                                    "  } finally {"
   2564                                    "  }"
   2565                                    "} catch (e) {"
   2566                                    "}");
   2567   CHECK(result->IsTrue());
   2568 }
   2569 
   2570 
   2571 static void check_reference_error_message(
   2572     v8::Handle<v8::Message> message,
   2573     v8::Handle<v8::Value> data) {
   2574   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
   2575   CHECK(message->Get()->Equals(v8_str(reference_error)));
   2576 }
   2577 
   2578 
   2579 static v8::Handle<Value> Fail(const v8::Arguments& args) {
   2580   ApiTestFuzzer::Fuzz();
   2581   CHECK(false);
   2582   return v8::Undefined();
   2583 }
   2584 
   2585 
   2586 // Test that overwritten methods are not invoked on uncaught exception
   2587 // formatting. However, they are invoked when performing normal error
   2588 // string conversions.
   2589 TEST(APIThrowMessageOverwrittenToString) {
   2590   v8::HandleScope scope;
   2591   v8::V8::AddMessageListener(check_reference_error_message);
   2592   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2593   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
   2594   LocalContext context(NULL, templ);
   2595   CompileRun("asdf;");
   2596   CompileRun("var limit = {};"
   2597              "limit.valueOf = fail;"
   2598              "Error.stackTraceLimit = limit;");
   2599   CompileRun("asdf");
   2600   CompileRun("Array.prototype.pop = fail;");
   2601   CompileRun("Object.prototype.hasOwnProperty = fail;");
   2602   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
   2603   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
   2604   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
   2605   CompileRun("ReferenceError.prototype.toString ="
   2606              "  function() { return 'Whoops' }");
   2607   CompileRun("asdf;");
   2608   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
   2609   CompileRun("asdf;");
   2610   CompileRun("ReferenceError.prototype.constructor = void 0;");
   2611   CompileRun("asdf;");
   2612   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
   2613   CompileRun("asdf;");
   2614   CompileRun("ReferenceError.prototype = new Object();");
   2615   CompileRun("asdf;");
   2616   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
   2617   CHECK(string->Equals(v8_str("Whoops")));
   2618   CompileRun("ReferenceError.prototype.constructor = new Object();"
   2619              "ReferenceError.prototype.constructor.name = 1;"
   2620              "Number.prototype.toString = function() { return 'Whoops'; };"
   2621              "ReferenceError.prototype.toString = Object.prototype.toString;");
   2622   CompileRun("asdf;");
   2623   v8::V8::RemoveMessageListeners(check_message);
   2624 }
   2625 
   2626 
   2627 static void receive_message(v8::Handle<v8::Message> message,
   2628                             v8::Handle<v8::Value> data) {
   2629   message->Get();
   2630   message_received = true;
   2631 }
   2632 
   2633 
   2634 TEST(APIThrowMessage) {
   2635   message_received = false;
   2636   v8::HandleScope scope;
   2637   v8::V8::AddMessageListener(receive_message);
   2638   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2639   templ->Set(v8_str("ThrowFromC"),
   2640              v8::FunctionTemplate::New(ThrowFromC));
   2641   LocalContext context(0, templ);
   2642   CompileRun("ThrowFromC();");
   2643   CHECK(message_received);
   2644   v8::V8::RemoveMessageListeners(check_message);
   2645 }
   2646 
   2647 
   2648 TEST(APIThrowMessageAndVerboseTryCatch) {
   2649   message_received = false;
   2650   v8::HandleScope scope;
   2651   v8::V8::AddMessageListener(receive_message);
   2652   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2653   templ->Set(v8_str("ThrowFromC"),
   2654              v8::FunctionTemplate::New(ThrowFromC));
   2655   LocalContext context(0, templ);
   2656   v8::TryCatch try_catch;
   2657   try_catch.SetVerbose(true);
   2658   Local<Value> result = CompileRun("ThrowFromC();");
   2659   CHECK(try_catch.HasCaught());
   2660   CHECK(result.IsEmpty());
   2661   CHECK(message_received);
   2662   v8::V8::RemoveMessageListeners(check_message);
   2663 }
   2664 
   2665 
   2666 TEST(APIStackOverflowAndVerboseTryCatch) {
   2667   message_received = false;
   2668   v8::HandleScope scope;
   2669   v8::V8::AddMessageListener(receive_message);
   2670   LocalContext context;
   2671   v8::TryCatch try_catch;
   2672   try_catch.SetVerbose(true);
   2673   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
   2674   CHECK(try_catch.HasCaught());
   2675   CHECK(result.IsEmpty());
   2676   CHECK(message_received);
   2677   v8::V8::RemoveMessageListeners(receive_message);
   2678 }
   2679 
   2680 
   2681 THREADED_TEST(ExternalScriptException) {
   2682   v8::HandleScope scope;
   2683   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2684   templ->Set(v8_str("ThrowFromC"),
   2685              v8::FunctionTemplate::New(ThrowFromC));
   2686   LocalContext context(0, templ);
   2687 
   2688   v8::TryCatch try_catch;
   2689   Local<Script> script
   2690       = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
   2691   Local<Value> result = script->Run();
   2692   CHECK(result.IsEmpty());
   2693   CHECK(try_catch.HasCaught());
   2694   String::AsciiValue exception_value(try_catch.Exception());
   2695   CHECK_EQ("konto", *exception_value);
   2696 }
   2697 
   2698 
   2699 
   2700 v8::Handle<Value> CThrowCountDown(const v8::Arguments& args) {
   2701   ApiTestFuzzer::Fuzz();
   2702   CHECK_EQ(4, args.Length());
   2703   int count = args[0]->Int32Value();
   2704   int cInterval = args[2]->Int32Value();
   2705   if (count == 0) {
   2706     return v8::ThrowException(v8_str("FromC"));
   2707   } else {
   2708     Local<v8::Object> global = Context::GetCurrent()->Global();
   2709     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
   2710     v8::Handle<Value> argv[] = { v8_num(count - 1),
   2711                                  args[1],
   2712                                  args[2],
   2713                                  args[3] };
   2714     if (count % cInterval == 0) {
   2715       v8::TryCatch try_catch;
   2716       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
   2717       int expected = args[3]->Int32Value();
   2718       if (try_catch.HasCaught()) {
   2719         CHECK_EQ(expected, count);
   2720         CHECK(result.IsEmpty());
   2721         CHECK(!i::Isolate::Current()->has_scheduled_exception());
   2722       } else {
   2723         CHECK_NE(expected, count);
   2724       }
   2725       return result;
   2726     } else {
   2727       return fun.As<Function>()->Call(global, 4, argv);
   2728     }
   2729   }
   2730 }
   2731 
   2732 
   2733 v8::Handle<Value> JSCheck(const v8::Arguments& args) {
   2734   ApiTestFuzzer::Fuzz();
   2735   CHECK_EQ(3, args.Length());
   2736   bool equality = args[0]->BooleanValue();
   2737   int count = args[1]->Int32Value();
   2738   int expected = args[2]->Int32Value();
   2739   if (equality) {
   2740     CHECK_EQ(count, expected);
   2741   } else {
   2742     CHECK_NE(count, expected);
   2743   }
   2744   return v8::Undefined();
   2745 }
   2746 
   2747 
   2748 THREADED_TEST(EvalInTryFinally) {
   2749   v8::HandleScope scope;
   2750   LocalContext context;
   2751   v8::TryCatch try_catch;
   2752   CompileRun("(function() {"
   2753              "  try {"
   2754              "    eval('asldkf (*&^&*^');"
   2755              "  } finally {"
   2756              "    return;"
   2757              "  }"
   2758              "})()");
   2759   CHECK(!try_catch.HasCaught());
   2760 }
   2761 
   2762 
   2763 // This test works by making a stack of alternating JavaScript and C
   2764 // activations.  These activations set up exception handlers with regular
   2765 // intervals, one interval for C activations and another for JavaScript
   2766 // activations.  When enough activations have been created an exception is
   2767 // thrown and we check that the right activation catches the exception and that
   2768 // no other activations do.  The right activation is always the topmost one with
   2769 // a handler, regardless of whether it is in JavaScript or C.
   2770 //
   2771 // The notation used to describe a test case looks like this:
   2772 //
   2773 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
   2774 //
   2775 // Each entry is an activation, either JS or C.  The index is the count at that
   2776 // level.  Stars identify activations with exception handlers, the @ identifies
   2777 // the exception handler that should catch the exception.
   2778 //
   2779 // BUG(271): Some of the exception propagation does not work on the
   2780 // ARM simulator because the simulator separates the C++ stack and the
   2781 // JS stack.  This test therefore fails on the simulator.  The test is
   2782 // not threaded to allow the threading tests to run on the simulator.
   2783 TEST(ExceptionOrder) {
   2784   v8::HandleScope scope;
   2785   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2786   templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
   2787   templ->Set(v8_str("CThrowCountDown"),
   2788              v8::FunctionTemplate::New(CThrowCountDown));
   2789   LocalContext context(0, templ);
   2790   CompileRun(
   2791     "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
   2792     "  if (count == 0) throw 'FromJS';"
   2793     "  if (count % jsInterval == 0) {"
   2794     "    try {"
   2795     "      var value = CThrowCountDown(count - 1,"
   2796     "                                  jsInterval,"
   2797     "                                  cInterval,"
   2798     "                                  expected);"
   2799     "      check(false, count, expected);"
   2800     "      return value;"
   2801     "    } catch (e) {"
   2802     "      check(true, count, expected);"
   2803     "    }"
   2804     "  } else {"
   2805     "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
   2806     "  }"
   2807     "}");
   2808   Local<Function> fun =
   2809       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
   2810 
   2811   const int argc = 4;
   2812   //                             count      jsInterval cInterval  expected
   2813 
   2814   // *JS[4] *C[3] @JS[2] C[1] JS[0]
   2815   v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
   2816   fun->Call(fun, argc, a0);
   2817 
   2818   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
   2819   v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
   2820   fun->Call(fun, argc, a1);
   2821 
   2822   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
   2823   v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
   2824   fun->Call(fun, argc, a2);
   2825 
   2826   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
   2827   v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
   2828   fun->Call(fun, argc, a3);
   2829 
   2830   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
   2831   v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
   2832   fun->Call(fun, argc, a4);
   2833 
   2834   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
   2835   v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
   2836   fun->Call(fun, argc, a5);
   2837 }
   2838 
   2839 
   2840 v8::Handle<Value> ThrowValue(const v8::Arguments& args) {
   2841   ApiTestFuzzer::Fuzz();
   2842   CHECK_EQ(1, args.Length());
   2843   return v8::ThrowException(args[0]);
   2844 }
   2845 
   2846 
   2847 THREADED_TEST(ThrowValues) {
   2848   v8::HandleScope scope;
   2849   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2850   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
   2851   LocalContext context(0, templ);
   2852   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   2853     "function Run(obj) {"
   2854     "  try {"
   2855     "    Throw(obj);"
   2856     "  } catch (e) {"
   2857     "    return e;"
   2858     "  }"
   2859     "  return 'no exception';"
   2860     "}"
   2861     "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
   2862   CHECK_EQ(5, result->Length());
   2863   CHECK(result->Get(v8::Integer::New(0))->IsString());
   2864   CHECK(result->Get(v8::Integer::New(1))->IsNumber());
   2865   CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
   2866   CHECK(result->Get(v8::Integer::New(2))->IsNumber());
   2867   CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
   2868   CHECK(result->Get(v8::Integer::New(3))->IsNull());
   2869   CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
   2870 }
   2871 
   2872 
   2873 THREADED_TEST(CatchZero) {
   2874   v8::HandleScope scope;
   2875   LocalContext context;
   2876   v8::TryCatch try_catch;
   2877   CHECK(!try_catch.HasCaught());
   2878   Script::Compile(v8_str("throw 10"))->Run();
   2879   CHECK(try_catch.HasCaught());
   2880   CHECK_EQ(10, try_catch.Exception()->Int32Value());
   2881   try_catch.Reset();
   2882   CHECK(!try_catch.HasCaught());
   2883   Script::Compile(v8_str("throw 0"))->Run();
   2884   CHECK(try_catch.HasCaught());
   2885   CHECK_EQ(0, try_catch.Exception()->Int32Value());
   2886 }
   2887 
   2888 
   2889 THREADED_TEST(CatchExceptionFromWith) {
   2890   v8::HandleScope scope;
   2891   LocalContext context;
   2892   v8::TryCatch try_catch;
   2893   CHECK(!try_catch.HasCaught());
   2894   Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
   2895   CHECK(try_catch.HasCaught());
   2896 }
   2897 
   2898 
   2899 THREADED_TEST(TryCatchAndFinallyHidingException) {
   2900   v8::HandleScope scope;
   2901   LocalContext context;
   2902   v8::TryCatch try_catch;
   2903   CHECK(!try_catch.HasCaught());
   2904   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
   2905   CompileRun("f({toString: function() { throw 42; }});");
   2906   CHECK(!try_catch.HasCaught());
   2907 }
   2908 
   2909 
   2910 v8::Handle<v8::Value> WithTryCatch(const v8::Arguments& args) {
   2911   v8::TryCatch try_catch;
   2912   return v8::Undefined();
   2913 }
   2914 
   2915 
   2916 THREADED_TEST(TryCatchAndFinally) {
   2917   v8::HandleScope scope;
   2918   LocalContext context;
   2919   context->Global()->Set(
   2920       v8_str("native_with_try_catch"),
   2921       v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
   2922   v8::TryCatch try_catch;
   2923   CHECK(!try_catch.HasCaught());
   2924   CompileRun(
   2925       "try {\n"
   2926       "  throw new Error('a');\n"
   2927       "} finally {\n"
   2928       "  native_with_try_catch();\n"
   2929       "}\n");
   2930   CHECK(try_catch.HasCaught());
   2931 }
   2932 
   2933 
   2934 THREADED_TEST(Equality) {
   2935   v8::HandleScope scope;
   2936   LocalContext context;
   2937   // Check that equality works at all before relying on CHECK_EQ
   2938   CHECK(v8_str("a")->Equals(v8_str("a")));
   2939   CHECK(!v8_str("a")->Equals(v8_str("b")));
   2940 
   2941   CHECK_EQ(v8_str("a"), v8_str("a"));
   2942   CHECK_NE(v8_str("a"), v8_str("b"));
   2943   CHECK_EQ(v8_num(1), v8_num(1));
   2944   CHECK_EQ(v8_num(1.00), v8_num(1));
   2945   CHECK_NE(v8_num(1), v8_num(2));
   2946 
   2947   // Assume String is not symbol.
   2948   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
   2949   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
   2950   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   2951   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   2952   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
   2953   CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
   2954   Local<Value> not_a_number = v8_num(i::OS::nan_value());
   2955   CHECK(!not_a_number->StrictEquals(not_a_number));
   2956   CHECK(v8::False()->StrictEquals(v8::False()));
   2957   CHECK(!v8::False()->StrictEquals(v8::Undefined()));
   2958 
   2959   v8::Handle<v8::Object> obj = v8::Object::New();
   2960   v8::Persistent<v8::Object> alias = v8::Persistent<v8::Object>::New(obj);
   2961   CHECK(alias->StrictEquals(obj));
   2962   alias.Dispose();
   2963 }
   2964 
   2965 
   2966 THREADED_TEST(MultiRun) {
   2967   v8::HandleScope scope;
   2968   LocalContext context;
   2969   Local<Script> script = Script::Compile(v8_str("x"));
   2970   for (int i = 0; i < 10; i++)
   2971     script->Run();
   2972 }
   2973 
   2974 
   2975 static v8::Handle<Value> GetXValue(Local<String> name,
   2976                                    const AccessorInfo& info) {
   2977   ApiTestFuzzer::Fuzz();
   2978   CHECK_EQ(info.Data(), v8_str("donut"));
   2979   CHECK_EQ(name, v8_str("x"));
   2980   return name;
   2981 }
   2982 
   2983 
   2984 THREADED_TEST(SimplePropertyRead) {
   2985   v8::HandleScope scope;
   2986   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2987   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   2988   LocalContext context;
   2989   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   2990   Local<Script> script = Script::Compile(v8_str("obj.x"));
   2991   for (int i = 0; i < 10; i++) {
   2992     Local<Value> result = script->Run();
   2993     CHECK_EQ(result, v8_str("x"));
   2994   }
   2995 }
   2996 
   2997 THREADED_TEST(DefinePropertyOnAPIAccessor) {
   2998   v8::HandleScope scope;
   2999   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3000   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   3001   LocalContext context;
   3002   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3003 
   3004   // Uses getOwnPropertyDescriptor to check the configurable status
   3005   Local<Script> script_desc
   3006     = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
   3007                              "obj, 'x');"
   3008                              "prop.configurable;"));
   3009   Local<Value> result = script_desc->Run();
   3010   CHECK_EQ(result->BooleanValue(), true);
   3011 
   3012   // Redefine get - but still configurable
   3013   Local<Script> script_define
   3014     = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
   3015                              "            configurable: true };"
   3016                              "Object.defineProperty(obj, 'x', desc);"
   3017                              "obj.x"));
   3018   result = script_define->Run();
   3019   CHECK_EQ(result, v8_num(42));
   3020 
   3021   // Check that the accessor is still configurable
   3022   result = script_desc->Run();
   3023   CHECK_EQ(result->BooleanValue(), true);
   3024 
   3025   // Redefine to a non-configurable
   3026   script_define
   3027     = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
   3028                              "             configurable: false };"
   3029                              "Object.defineProperty(obj, 'x', desc);"
   3030                              "obj.x"));
   3031   result = script_define->Run();
   3032   CHECK_EQ(result, v8_num(43));
   3033   result = script_desc->Run();
   3034   CHECK_EQ(result->BooleanValue(), false);
   3035 
   3036   // Make sure that it is not possible to redefine again
   3037   v8::TryCatch try_catch;
   3038   result = script_define->Run();
   3039   CHECK(try_catch.HasCaught());
   3040   String::AsciiValue exception_value(try_catch.Exception());
   3041   CHECK_EQ(*exception_value,
   3042            "TypeError: Cannot redefine property: defineProperty");
   3043 }
   3044 
   3045 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
   3046   v8::HandleScope scope;
   3047   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3048   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   3049   LocalContext context;
   3050   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3051 
   3052   Local<Script> script_desc = Script::Compile(v8_str("var prop ="
   3053                                     "Object.getOwnPropertyDescriptor( "
   3054                                     "obj, 'x');"
   3055                                     "prop.configurable;"));
   3056   Local<Value> result = script_desc->Run();
   3057   CHECK_EQ(result->BooleanValue(), true);
   3058 
   3059   Local<Script> script_define =
   3060     Script::Compile(v8_str("var desc = {get: function(){return 42; },"
   3061                            "            configurable: true };"
   3062                            "Object.defineProperty(obj, 'x', desc);"
   3063                            "obj.x"));
   3064   result = script_define->Run();
   3065   CHECK_EQ(result, v8_num(42));
   3066 
   3067 
   3068   result = script_desc->Run();
   3069   CHECK_EQ(result->BooleanValue(), true);
   3070 
   3071 
   3072   script_define =
   3073     Script::Compile(v8_str("var desc = {get: function(){return 43; },"
   3074                            "            configurable: false };"
   3075                            "Object.defineProperty(obj, 'x', desc);"
   3076                            "obj.x"));
   3077   result = script_define->Run();
   3078   CHECK_EQ(result, v8_num(43));
   3079   result = script_desc->Run();
   3080 
   3081   CHECK_EQ(result->BooleanValue(), false);
   3082 
   3083   v8::TryCatch try_catch;
   3084   result = script_define->Run();
   3085   CHECK(try_catch.HasCaught());
   3086   String::AsciiValue exception_value(try_catch.Exception());
   3087   CHECK_EQ(*exception_value,
   3088            "TypeError: Cannot redefine property: defineProperty");
   3089 }
   3090 
   3091 
   3092 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
   3093                                                 char const* name) {
   3094   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
   3095 }
   3096 
   3097 
   3098 THREADED_TEST(DefineAPIAccessorOnObject) {
   3099   v8::HandleScope scope;
   3100   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3101   LocalContext context;
   3102 
   3103   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   3104   CompileRun("var obj2 = {};");
   3105 
   3106   CHECK(CompileRun("obj1.x")->IsUndefined());
   3107   CHECK(CompileRun("obj2.x")->IsUndefined());
   3108 
   3109   CHECK(GetGlobalProperty(&context, "obj1")->
   3110       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3111 
   3112   ExpectString("obj1.x", "x");
   3113   CHECK(CompileRun("obj2.x")->IsUndefined());
   3114 
   3115   CHECK(GetGlobalProperty(&context, "obj2")->
   3116       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3117 
   3118   ExpectString("obj1.x", "x");
   3119   ExpectString("obj2.x", "x");
   3120 
   3121   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3122   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3123 
   3124   CompileRun("Object.defineProperty(obj1, 'x',"
   3125              "{ get: function() { return 'y'; }, configurable: true })");
   3126 
   3127   ExpectString("obj1.x", "y");
   3128   ExpectString("obj2.x", "x");
   3129 
   3130   CompileRun("Object.defineProperty(obj2, 'x',"
   3131              "{ get: function() { return 'y'; }, configurable: true })");
   3132 
   3133   ExpectString("obj1.x", "y");
   3134   ExpectString("obj2.x", "y");
   3135 
   3136   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3137   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3138 
   3139   CHECK(GetGlobalProperty(&context, "obj1")->
   3140       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3141   CHECK(GetGlobalProperty(&context, "obj2")->
   3142       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3143 
   3144   ExpectString("obj1.x", "x");
   3145   ExpectString("obj2.x", "x");
   3146 
   3147   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3148   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3149 
   3150   // Define getters/setters, but now make them not configurable.
   3151   CompileRun("Object.defineProperty(obj1, 'x',"
   3152              "{ get: function() { return 'z'; }, configurable: false })");
   3153   CompileRun("Object.defineProperty(obj2, 'x',"
   3154              "{ get: function() { return 'z'; }, configurable: false })");
   3155 
   3156   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3157   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3158 
   3159   ExpectString("obj1.x", "z");
   3160   ExpectString("obj2.x", "z");
   3161 
   3162   CHECK(!GetGlobalProperty(&context, "obj1")->
   3163       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3164   CHECK(!GetGlobalProperty(&context, "obj2")->
   3165       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3166 
   3167   ExpectString("obj1.x", "z");
   3168   ExpectString("obj2.x", "z");
   3169 }
   3170 
   3171 
   3172 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   3173   v8::HandleScope scope;
   3174   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3175   LocalContext context;
   3176 
   3177   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   3178   CompileRun("var obj2 = {};");
   3179 
   3180   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   3181         v8_str("x"),
   3182         GetXValue, NULL,
   3183         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   3184   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   3185         v8_str("x"),
   3186         GetXValue, NULL,
   3187         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   3188 
   3189   ExpectString("obj1.x", "x");
   3190   ExpectString("obj2.x", "x");
   3191 
   3192   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3193   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3194 
   3195   CHECK(!GetGlobalProperty(&context, "obj1")->
   3196       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3197   CHECK(!GetGlobalProperty(&context, "obj2")->
   3198       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3199 
   3200   {
   3201     v8::TryCatch try_catch;
   3202     CompileRun("Object.defineProperty(obj1, 'x',"
   3203         "{get: function() { return 'func'; }})");
   3204     CHECK(try_catch.HasCaught());
   3205     String::AsciiValue exception_value(try_catch.Exception());
   3206     CHECK_EQ(*exception_value,
   3207             "TypeError: Cannot redefine property: defineProperty");
   3208   }
   3209   {
   3210     v8::TryCatch try_catch;
   3211     CompileRun("Object.defineProperty(obj2, 'x',"
   3212         "{get: function() { return 'func'; }})");
   3213     CHECK(try_catch.HasCaught());
   3214     String::AsciiValue exception_value(try_catch.Exception());
   3215     CHECK_EQ(*exception_value,
   3216             "TypeError: Cannot redefine property: defineProperty");
   3217   }
   3218 }
   3219 
   3220 
   3221 static v8::Handle<Value> Get239Value(Local<String> name,
   3222                                      const AccessorInfo& info) {
   3223   ApiTestFuzzer::Fuzz();
   3224   CHECK_EQ(info.Data(), v8_str("donut"));
   3225   CHECK_EQ(name, v8_str("239"));
   3226   return name;
   3227 }
   3228 
   3229 
   3230 THREADED_TEST(ElementAPIAccessor) {
   3231   v8::HandleScope scope;
   3232   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3233   LocalContext context;
   3234 
   3235   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   3236   CompileRun("var obj2 = {};");
   3237 
   3238   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   3239         v8_str("239"),
   3240         Get239Value, NULL,
   3241         v8_str("donut")));
   3242   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   3243         v8_str("239"),
   3244         Get239Value, NULL,
   3245         v8_str("donut")));
   3246 
   3247   ExpectString("obj1[239]", "239");
   3248   ExpectString("obj2[239]", "239");
   3249   ExpectString("obj1['239']", "239");
   3250   ExpectString("obj2['239']", "239");
   3251 }
   3252 
   3253 
   3254 v8::Persistent<Value> xValue;
   3255 
   3256 
   3257 static void SetXValue(Local<String> name,
   3258                       Local<Value> value,
   3259                       const AccessorInfo& info) {
   3260   CHECK_EQ(value, v8_num(4));
   3261   CHECK_EQ(info.Data(), v8_str("donut"));
   3262   CHECK_EQ(name, v8_str("x"));
   3263   CHECK(xValue.IsEmpty());
   3264   xValue = v8::Persistent<Value>::New(value);
   3265 }
   3266 
   3267 
   3268 THREADED_TEST(SimplePropertyWrite) {
   3269   v8::HandleScope scope;
   3270   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3271   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
   3272   LocalContext context;
   3273   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3274   Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
   3275   for (int i = 0; i < 10; i++) {
   3276     CHECK(xValue.IsEmpty());
   3277     script->Run();
   3278     CHECK_EQ(v8_num(4), xValue);
   3279     xValue.Dispose();
   3280     xValue = v8::Persistent<Value>();
   3281   }
   3282 }
   3283 
   3284 
   3285 static v8::Handle<Value> XPropertyGetter(Local<String> property,
   3286                                          const AccessorInfo& info) {
   3287   ApiTestFuzzer::Fuzz();
   3288   CHECK(info.Data()->IsUndefined());
   3289   return property;
   3290 }
   3291 
   3292 
   3293 THREADED_TEST(NamedInterceptorPropertyRead) {
   3294   v8::HandleScope scope;
   3295   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3296   templ->SetNamedPropertyHandler(XPropertyGetter);
   3297   LocalContext context;
   3298   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3299   Local<Script> script = Script::Compile(v8_str("obj.x"));
   3300   for (int i = 0; i < 10; i++) {
   3301     Local<Value> result = script->Run();
   3302     CHECK_EQ(result, v8_str("x"));
   3303   }
   3304 }
   3305 
   3306 
   3307 THREADED_TEST(NamedInterceptorDictionaryIC) {
   3308   v8::HandleScope scope;
   3309   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3310   templ->SetNamedPropertyHandler(XPropertyGetter);
   3311   LocalContext context;
   3312   // Create an object with a named interceptor.
   3313   context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
   3314   Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
   3315   for (int i = 0; i < 10; i++) {
   3316     Local<Value> result = script->Run();
   3317     CHECK_EQ(result, v8_str("x"));
   3318   }
   3319   // Create a slow case object and a function accessing a property in
   3320   // that slow case object (with dictionary probing in generated
   3321   // code). Then force object with a named interceptor into slow-case,
   3322   // pass it to the function, and check that the interceptor is called
   3323   // instead of accessing the local property.
   3324   Local<Value> result =
   3325       CompileRun("function get_x(o) { return o.x; };"
   3326                  "var obj = { x : 42, y : 0 };"
   3327                  "delete obj.y;"
   3328                  "for (var i = 0; i < 10; i++) get_x(obj);"
   3329                  "interceptor_obj.x = 42;"
   3330                  "interceptor_obj.y = 10;"
   3331                  "delete interceptor_obj.y;"
   3332                  "get_x(interceptor_obj)");
   3333   CHECK_EQ(result, v8_str("x"));
   3334 }
   3335 
   3336 
   3337 THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
   3338   v8::HandleScope scope;
   3339 
   3340   v8::Persistent<Context> context1 = Context::New();
   3341 
   3342   context1->Enter();
   3343   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3344   templ->SetNamedPropertyHandler(XPropertyGetter);
   3345   // Create an object with a named interceptor.
   3346   v8::Local<v8::Object> object = templ->NewInstance();
   3347   context1->Global()->Set(v8_str("interceptor_obj"), object);
   3348 
   3349   // Force the object into the slow case.
   3350   CompileRun("interceptor_obj.y = 0;"
   3351              "delete interceptor_obj.y;");
   3352   context1->Exit();
   3353 
   3354   {
   3355     // Introduce the object into a different context.
   3356     // Repeat named loads to exercise ICs.
   3357     LocalContext context2;
   3358     context2->Global()->Set(v8_str("interceptor_obj"), object);
   3359     Local<Value> result =
   3360       CompileRun("function get_x(o) { return o.x; }"
   3361                  "interceptor_obj.x = 42;"
   3362                  "for (var i=0; i != 10; i++) {"
   3363                  "  get_x(interceptor_obj);"
   3364                  "}"
   3365                  "get_x(interceptor_obj)");
   3366     // Check that the interceptor was actually invoked.
   3367     CHECK_EQ(result, v8_str("x"));
   3368   }
   3369 
   3370   // Return to the original context and force some object to the slow case
   3371   // to cause the NormalizedMapCache to verify.
   3372   context1->Enter();
   3373   CompileRun("var obj = { x : 0 }; delete obj.x;");
   3374   context1->Exit();
   3375 
   3376   context1.Dispose();
   3377 }
   3378 
   3379 
   3380 static v8::Handle<Value> SetXOnPrototypeGetter(Local<String> property,
   3381                                                const AccessorInfo& info) {
   3382   // Set x on the prototype object and do not handle the get request.
   3383   v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
   3384   proto.As<v8::Object>()->Set(v8_str("x"), v8::Integer::New(23));
   3385   return v8::Handle<Value>();
   3386 }
   3387 
   3388 
   3389 // This is a regression test for http://crbug.com/20104. Map
   3390 // transitions should not interfere with post interceptor lookup.
   3391 THREADED_TEST(NamedInterceptorMapTransitionRead) {
   3392   v8::HandleScope scope;
   3393   Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
   3394   Local<v8::ObjectTemplate> instance_template
   3395       = function_template->InstanceTemplate();
   3396   instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
   3397   LocalContext context;
   3398   context->Global()->Set(v8_str("F"), function_template->GetFunction());
   3399   // Create an instance of F and introduce a map transition for x.
   3400   CompileRun("var o = new F(); o.x = 23;");
   3401   // Create an instance of F and invoke the getter. The result should be 23.
   3402   Local<Value> result = CompileRun("o = new F(); o.x");
   3403   CHECK_EQ(result->Int32Value(), 23);
   3404 }
   3405 
   3406 
   3407 static v8::Handle<Value> IndexedPropertyGetter(uint32_t index,
   3408                                                const AccessorInfo& info) {
   3409   ApiTestFuzzer::Fuzz();
   3410   if (index == 37) {
   3411     return v8::Handle<Value>(v8_num(625));
   3412   }
   3413   return v8::Handle<Value>();
   3414 }
   3415 
   3416 
   3417 static v8::Handle<Value> IndexedPropertySetter(uint32_t index,
   3418                                                Local<Value> value,
   3419                                                const AccessorInfo& info) {
   3420   ApiTestFuzzer::Fuzz();
   3421   if (index == 39) {
   3422     return value;
   3423   }
   3424   return v8::Handle<Value>();
   3425 }
   3426 
   3427 
   3428 THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
   3429   v8::HandleScope scope;
   3430   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3431   templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
   3432                                    IndexedPropertySetter);
   3433   LocalContext context;
   3434   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3435   Local<Script> getter_script = Script::Compile(v8_str(
   3436       "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
   3437   Local<Script> setter_script = Script::Compile(v8_str(
   3438       "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
   3439       "obj[17] = 23;"
   3440       "obj.foo;"));
   3441   Local<Script> interceptor_setter_script = Script::Compile(v8_str(
   3442       "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
   3443       "obj[39] = 47;"
   3444       "obj.foo;"));  // This setter should not run, due to the interceptor.
   3445   Local<Script> interceptor_getter_script = Script::Compile(v8_str(
   3446       "obj[37];"));
   3447   Local<Value> result = getter_script->Run();
   3448   CHECK_EQ(v8_num(5), result);
   3449   result = setter_script->Run();
   3450   CHECK_EQ(v8_num(23), result);
   3451   result = interceptor_setter_script->Run();
   3452   CHECK_EQ(v8_num(23), result);
   3453   result = interceptor_getter_script->Run();
   3454   CHECK_EQ(v8_num(625), result);
   3455 }
   3456 
   3457 
   3458 static v8::Handle<Value> IdentityIndexedPropertyGetter(
   3459     uint32_t index,
   3460     const AccessorInfo& info) {
   3461   return v8::Integer::NewFromUnsigned(index);
   3462 }
   3463 
   3464 
   3465 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
   3466   v8::HandleScope scope;
   3467   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3468   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3469 
   3470   LocalContext context;
   3471   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3472 
   3473   // Check fast object case.
   3474   const char* fast_case_code =
   3475       "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
   3476   ExpectString(fast_case_code, "0");
   3477 
   3478   // Check slow case.
   3479   const char* slow_case_code =
   3480       "obj.x = 1; delete obj.x;"
   3481       "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
   3482   ExpectString(slow_case_code, "1");
   3483 }
   3484 
   3485 
   3486 THREADED_TEST(IndexedInterceptorWithNoSetter) {
   3487   v8::HandleScope scope;
   3488   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3489   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3490 
   3491   LocalContext context;
   3492   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3493 
   3494   const char* code =
   3495       "try {"
   3496       "  obj[0] = 239;"
   3497       "  for (var i = 0; i < 100; i++) {"
   3498       "    var v = obj[0];"
   3499       "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3500       "  }"
   3501       "  'PASSED'"
   3502       "} catch(e) {"
   3503       "  e"
   3504       "}";
   3505   ExpectString(code, "PASSED");
   3506 }
   3507 
   3508 
   3509 THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
   3510   v8::HandleScope scope;
   3511   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3512   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3513 
   3514   LocalContext context;
   3515   Local<v8::Object> obj = templ->NewInstance();
   3516   obj->TurnOnAccessCheck();
   3517   context->Global()->Set(v8_str("obj"), obj);
   3518 
   3519   const char* code =
   3520       "try {"
   3521       "  for (var i = 0; i < 100; i++) {"
   3522       "    var v = obj[0];"
   3523       "    if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3524       "  }"
   3525       "  'PASSED'"
   3526       "} catch(e) {"
   3527       "  e"
   3528       "}";
   3529   ExpectString(code, "PASSED");
   3530 }
   3531 
   3532 
   3533 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
   3534   i::FLAG_allow_natives_syntax = true;
   3535   v8::HandleScope scope;
   3536   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3537   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3538 
   3539   LocalContext context;
   3540   Local<v8::Object> obj = templ->NewInstance();
   3541   context->Global()->Set(v8_str("obj"), obj);
   3542 
   3543   const char* code =
   3544       "try {"
   3545       "  for (var i = 0; i < 100; i++) {"
   3546       "    var expected = i;"
   3547       "    if (i == 5) {"
   3548       "      %EnableAccessChecks(obj);"
   3549       "      expected = undefined;"
   3550       "    }"
   3551       "    var v = obj[i];"
   3552       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3553       "    if (i == 5) %DisableAccessChecks(obj);"
   3554       "  }"
   3555       "  'PASSED'"
   3556       "} catch(e) {"
   3557       "  e"
   3558       "}";
   3559   ExpectString(code, "PASSED");
   3560 }
   3561 
   3562 
   3563 THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
   3564   v8::HandleScope scope;
   3565   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3566   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3567 
   3568   LocalContext context;
   3569   Local<v8::Object> obj = templ->NewInstance();
   3570   context->Global()->Set(v8_str("obj"), obj);
   3571 
   3572   const char* code =
   3573       "try {"
   3574       "  for (var i = 0; i < 100; i++) {"
   3575       "    var v = obj[i];"
   3576       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3577       "  }"
   3578       "  'PASSED'"
   3579       "} catch(e) {"
   3580       "  e"
   3581       "}";
   3582   ExpectString(code, "PASSED");
   3583 }
   3584 
   3585 
   3586 THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
   3587   v8::HandleScope scope;
   3588   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3589   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3590 
   3591   LocalContext context;
   3592   Local<v8::Object> obj = templ->NewInstance();
   3593   context->Global()->Set(v8_str("obj"), obj);
   3594 
   3595   const char* code =
   3596       "try {"
   3597       "  for (var i = 0; i < 100; i++) {"
   3598       "    var expected = i;"
   3599       "    var key = i;"
   3600       "    if (i == 25) {"
   3601       "       key = -1;"
   3602       "       expected = undefined;"
   3603       "    }"
   3604       "    if (i == 50) {"
   3605       "       /* probe minimal Smi number on 32-bit platforms */"
   3606       "       key = -(1 << 30);"
   3607       "       expected = undefined;"
   3608       "    }"
   3609       "    if (i == 75) {"
   3610       "       /* probe minimal Smi number on 64-bit platforms */"
   3611       "       key = 1 << 31;"
   3612       "       expected = undefined;"
   3613       "    }"
   3614       "    var v = obj[key];"
   3615       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3616       "  }"
   3617       "  'PASSED'"
   3618       "} catch(e) {"
   3619       "  e"
   3620       "}";
   3621   ExpectString(code, "PASSED");
   3622 }
   3623 
   3624 
   3625 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
   3626   v8::HandleScope scope;
   3627   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3628   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3629 
   3630   LocalContext context;
   3631   Local<v8::Object> obj = templ->NewInstance();
   3632   context->Global()->Set(v8_str("obj"), obj);
   3633 
   3634   const char* code =
   3635       "try {"
   3636       "  for (var i = 0; i < 100; i++) {"
   3637       "    var expected = i;"
   3638       "    var key = i;"
   3639       "    if (i == 50) {"
   3640       "       key = 'foobar';"
   3641       "       expected = undefined;"
   3642       "    }"
   3643       "    var v = obj[key];"
   3644       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3645       "  }"
   3646       "  'PASSED'"
   3647       "} catch(e) {"
   3648       "  e"
   3649       "}";
   3650   ExpectString(code, "PASSED");
   3651 }
   3652 
   3653 
   3654 THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
   3655   v8::HandleScope scope;
   3656   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3657   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3658 
   3659   LocalContext context;
   3660   Local<v8::Object> obj = templ->NewInstance();
   3661   context->Global()->Set(v8_str("obj"), obj);
   3662 
   3663   const char* code =
   3664       "var original = obj;"
   3665       "try {"
   3666       "  for (var i = 0; i < 100; i++) {"
   3667       "    var expected = i;"
   3668       "    if (i == 50) {"
   3669       "       obj = {50: 'foobar'};"
   3670       "       expected = 'foobar';"
   3671       "    }"
   3672       "    var v = obj[i];"
   3673       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3674       "    if (i == 50) obj = original;"
   3675       "  }"
   3676       "  'PASSED'"
   3677       "} catch(e) {"
   3678       "  e"
   3679       "}";
   3680   ExpectString(code, "PASSED");
   3681 }
   3682 
   3683 
   3684 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
   3685   v8::HandleScope scope;
   3686   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3687   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3688 
   3689   LocalContext context;
   3690   Local<v8::Object> obj = templ->NewInstance();
   3691   context->Global()->Set(v8_str("obj"), obj);
   3692 
   3693   const char* code =
   3694       "var original = obj;"
   3695       "try {"
   3696       "  for (var i = 0; i < 100; i++) {"
   3697       "    var expected = i;"
   3698       "    if (i == 5) {"
   3699       "       obj = 239;"
   3700       "       expected = undefined;"
   3701       "    }"
   3702       "    var v = obj[i];"
   3703       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3704       "    if (i == 5) obj = original;"
   3705       "  }"
   3706       "  'PASSED'"
   3707       "} catch(e) {"
   3708       "  e"
   3709       "}";
   3710   ExpectString(code, "PASSED");
   3711 }
   3712 
   3713 
   3714 THREADED_TEST(IndexedInterceptorOnProto) {
   3715   v8::HandleScope scope;
   3716   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3717   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   3718 
   3719   LocalContext context;
   3720   Local<v8::Object> obj = templ->NewInstance();
   3721   context->Global()->Set(v8_str("obj"), obj);
   3722 
   3723   const char* code =
   3724       "var o = {__proto__: obj};"
   3725       "try {"
   3726       "  for (var i = 0; i < 100; i++) {"
   3727       "    var v = o[i];"
   3728       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   3729       "  }"
   3730       "  'PASSED'"
   3731       "} catch(e) {"
   3732       "  e"
   3733       "}";
   3734   ExpectString(code, "PASSED");
   3735 }
   3736 
   3737 
   3738 THREADED_TEST(MultiContexts) {
   3739   v8::HandleScope scope;
   3740   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
   3741   templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
   3742 
   3743   Local<String> password = v8_str("Password");
   3744 
   3745   // Create an environment
   3746   LocalContext context0(0, templ);
   3747   context0->SetSecurityToken(password);
   3748   v8::Handle<v8::Object> global0 = context0->Global();
   3749   global0->Set(v8_str("custom"), v8_num(1234));
   3750   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   3751 
   3752   // Create an independent environment
   3753   LocalContext context1(0, templ);
   3754   context1->SetSecurityToken(password);
   3755   v8::Handle<v8::Object> global1 = context1->Global();
   3756   global1->Set(v8_str("custom"), v8_num(1234));
   3757   CHECK_NE(global0, global1);
   3758   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   3759   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
   3760 
   3761   // Now create a new context with the old global
   3762   LocalContext context2(0, templ, global1);
   3763   context2->SetSecurityToken(password);
   3764   v8::Handle<v8::Object> global2 = context2->Global();
   3765   CHECK_EQ(global1, global2);
   3766   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
   3767   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
   3768 }
   3769 
   3770 
   3771 THREADED_TEST(FunctionPrototypeAcrossContexts) {
   3772   // Make sure that functions created by cloning boilerplates cannot
   3773   // communicate through their __proto__ field.
   3774 
   3775   v8::HandleScope scope;
   3776 
   3777   LocalContext env0;
   3778   v8::Handle<v8::Object> global0 =
   3779       env0->Global();
   3780   v8::Handle<v8::Object> object0 =
   3781       global0->Get(v8_str("Object")).As<v8::Object>();
   3782   v8::Handle<v8::Object> tostring0 =
   3783       object0->Get(v8_str("toString")).As<v8::Object>();
   3784   v8::Handle<v8::Object> proto0 =
   3785       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
   3786   proto0->Set(v8_str("custom"), v8_num(1234));
   3787 
   3788   LocalContext env1;
   3789   v8::Handle<v8::Object> global1 =
   3790       env1->Global();
   3791   v8::Handle<v8::Object> object1 =
   3792       global1->Get(v8_str("Object")).As<v8::Object>();
   3793   v8::Handle<v8::Object> tostring1 =
   3794       object1->Get(v8_str("toString")).As<v8::Object>();
   3795   v8::Handle<v8::Object> proto1 =
   3796       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
   3797   CHECK(!proto1->Has(v8_str("custom")));
   3798 }
   3799 
   3800 
   3801 THREADED_TEST(Regress892105) {
   3802   // Make sure that object and array literals created by cloning
   3803   // boilerplates cannot communicate through their __proto__
   3804   // field. This is rather difficult to check, but we try to add stuff
   3805   // to Object.prototype and Array.prototype and create a new
   3806   // environment. This should succeed.
   3807 
   3808   v8::HandleScope scope;
   3809 
   3810   Local<String> source = v8_str("Object.prototype.obj = 1234;"
   3811                                 "Array.prototype.arr = 4567;"
   3812                                 "8901");
   3813 
   3814   LocalContext env0;
   3815   Local<Script> script0 = Script::Compile(source);
   3816   CHECK_EQ(8901.0, script0->Run()->NumberValue());
   3817 
   3818   LocalContext env1;
   3819   Local<Script> script1 = Script::Compile(source);
   3820   CHECK_EQ(8901.0, script1->Run()->NumberValue());
   3821 }
   3822 
   3823 
   3824 THREADED_TEST(UndetectableObject) {
   3825   v8::HandleScope scope;
   3826   LocalContext env;
   3827 
   3828   Local<v8::FunctionTemplate> desc =
   3829       v8::FunctionTemplate::New(0, v8::Handle<Value>());
   3830   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   3831 
   3832   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   3833   env->Global()->Set(v8_str("undetectable"), obj);
   3834 
   3835   ExpectString("undetectable.toString()", "[object Object]");
   3836   ExpectString("typeof undetectable", "undefined");
   3837   ExpectString("typeof(undetectable)", "undefined");
   3838   ExpectBoolean("typeof undetectable == 'undefined'", true);
   3839   ExpectBoolean("typeof undetectable == 'object'", false);
   3840   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   3841   ExpectBoolean("!undetectable", true);
   3842 
   3843   ExpectObject("true&&undetectable", obj);
   3844   ExpectBoolean("false&&undetectable", false);
   3845   ExpectBoolean("true||undetectable", true);
   3846   ExpectObject("false||undetectable", obj);
   3847 
   3848   ExpectObject("undetectable&&true", obj);
   3849   ExpectObject("undetectable&&false", obj);
   3850   ExpectBoolean("undetectable||true", true);
   3851   ExpectBoolean("undetectable||false", false);
   3852 
   3853   ExpectBoolean("undetectable==null", true);
   3854   ExpectBoolean("null==undetectable", true);
   3855   ExpectBoolean("undetectable==undefined", true);
   3856   ExpectBoolean("undefined==undetectable", true);
   3857   ExpectBoolean("undetectable==undetectable", true);
   3858 
   3859 
   3860   ExpectBoolean("undetectable===null", false);
   3861   ExpectBoolean("null===undetectable", false);
   3862   ExpectBoolean("undetectable===undefined", false);
   3863   ExpectBoolean("undefined===undetectable", false);
   3864   ExpectBoolean("undetectable===undetectable", true);
   3865 }
   3866 
   3867 
   3868 
   3869 THREADED_TEST(ExtensibleOnUndetectable) {
   3870   v8::HandleScope scope;
   3871   LocalContext env;
   3872 
   3873   Local<v8::FunctionTemplate> desc =
   3874       v8::FunctionTemplate::New(0, v8::Handle<Value>());
   3875   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   3876 
   3877   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   3878   env->Global()->Set(v8_str("undetectable"), obj);
   3879 
   3880   Local<String> source = v8_str("undetectable.x = 42;"
   3881                                 "undetectable.x");
   3882 
   3883   Local<Script> script = Script::Compile(source);
   3884 
   3885   CHECK_EQ(v8::Integer::New(42), script->Run());
   3886 
   3887   ExpectBoolean("Object.isExtensible(undetectable)", true);
   3888 
   3889   source = v8_str("Object.preventExtensions(undetectable);");
   3890   script = Script::Compile(source);
   3891   script->Run();
   3892   ExpectBoolean("Object.isExtensible(undetectable)", false);
   3893 
   3894   source = v8_str("undetectable.y = 2000;");
   3895   script = Script::Compile(source);
   3896   Local<Value> result = script->Run();
   3897   ExpectBoolean("undetectable.y == undefined", true);
   3898 }
   3899 
   3900 
   3901 
   3902 THREADED_TEST(UndetectableString) {
   3903   v8::HandleScope scope;
   3904   LocalContext env;
   3905 
   3906   Local<String> obj = String::NewUndetectable("foo");
   3907   env->Global()->Set(v8_str("undetectable"), obj);
   3908 
   3909   ExpectString("undetectable", "foo");
   3910   ExpectString("typeof undetectable", "undefined");
   3911   ExpectString("typeof(undetectable)", "undefined");
   3912   ExpectBoolean("typeof undetectable == 'undefined'", true);
   3913   ExpectBoolean("typeof undetectable == 'string'", false);
   3914   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   3915   ExpectBoolean("!undetectable", true);
   3916 
   3917   ExpectObject("true&&undetectable", obj);
   3918   ExpectBoolean("false&&undetectable", false);
   3919   ExpectBoolean("true||undetectable", true);
   3920   ExpectObject("false||undetectable", obj);
   3921 
   3922   ExpectObject("undetectable&&true", obj);
   3923   ExpectObject("undetectable&&false", obj);
   3924   ExpectBoolean("undetectable||true", true);
   3925   ExpectBoolean("undetectable||false", false);
   3926 
   3927   ExpectBoolean("undetectable==null", true);
   3928   ExpectBoolean("null==undetectable", true);
   3929   ExpectBoolean("undetectable==undefined", true);
   3930   ExpectBoolean("undefined==undetectable", true);
   3931   ExpectBoolean("undetectable==undetectable", true);
   3932 
   3933 
   3934   ExpectBoolean("undetectable===null", false);
   3935   ExpectBoolean("null===undetectable", false);
   3936   ExpectBoolean("undetectable===undefined", false);
   3937   ExpectBoolean("undefined===undetectable", false);
   3938   ExpectBoolean("undetectable===undetectable", true);
   3939 }
   3940 
   3941 
   3942 template <typename T> static void USE(T) { }
   3943 
   3944 
   3945 // This test is not intended to be run, just type checked.
   3946 static void PersistentHandles() {
   3947   USE(PersistentHandles);
   3948   Local<String> str = v8_str("foo");
   3949   v8::Persistent<String> p_str = v8::Persistent<String>::New(str);
   3950   USE(p_str);
   3951   Local<Script> scr = Script::Compile(v8_str(""));
   3952   v8::Persistent<Script> p_scr = v8::Persistent<Script>::New(scr);
   3953   USE(p_scr);
   3954   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3955   v8::Persistent<ObjectTemplate> p_templ =
   3956     v8::Persistent<ObjectTemplate>::New(templ);
   3957   USE(p_templ);
   3958 }
   3959 
   3960 
   3961 static v8::Handle<Value> HandleLogDelegator(const v8::Arguments& args) {
   3962   ApiTestFuzzer::Fuzz();
   3963   return v8::Undefined();
   3964 }
   3965 
   3966 
   3967 THREADED_TEST(GlobalObjectTemplate) {
   3968   v8::HandleScope handle_scope;
   3969   Local<ObjectTemplate> global_template = ObjectTemplate::New();
   3970   global_template->Set(v8_str("JSNI_Log"),
   3971                        v8::FunctionTemplate::New(HandleLogDelegator));
   3972   v8::Persistent<Context> context = Context::New(0, global_template);
   3973   Context::Scope context_scope(context);
   3974   Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
   3975   context.Dispose();
   3976 }
   3977 
   3978 
   3979 static const char* kSimpleExtensionSource =
   3980   "function Foo() {"
   3981   "  return 4;"
   3982   "}";
   3983 
   3984 
   3985 THREADED_TEST(SimpleExtensions) {
   3986   v8::HandleScope handle_scope;
   3987   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
   3988   const char* extension_names[] = { "simpletest" };
   3989   v8::ExtensionConfiguration extensions(1, extension_names);
   3990   v8::Handle<Context> context = Context::New(&extensions);
   3991   Context::Scope lock(context);
   3992   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
   3993   CHECK_EQ(result, v8::Integer::New(4));
   3994 }
   3995 
   3996 
   3997 static const char* kEvalExtensionSource1 =
   3998   "function UseEval1() {"
   3999   "  var x = 42;"
   4000   "  return eval('x');"
   4001   "}";
   4002 
   4003 
   4004 static const char* kEvalExtensionSource2 =
   4005   "(function() {"
   4006   "  var x = 42;"
   4007   "  function e() {"
   4008   "    return eval('x');"
   4009   "  }"
   4010   "  this.UseEval2 = e;"
   4011   "})()";
   4012 
   4013 
   4014 THREADED_TEST(UseEvalFromExtension) {
   4015   v8::HandleScope handle_scope;
   4016   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
   4017   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
   4018   const char* extension_names[] = { "evaltest1", "evaltest2" };
   4019   v8::ExtensionConfiguration extensions(2, extension_names);
   4020   v8::Handle<Context> context = Context::New(&extensions);
   4021   Context::Scope lock(context);
   4022   v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
   4023   CHECK_EQ(result, v8::Integer::New(42));
   4024   result = Script::Compile(v8_str("UseEval2()"))->Run();
   4025   CHECK_EQ(result, v8::Integer::New(42));
   4026 }
   4027 
   4028 
   4029 static const char* kWithExtensionSource1 =
   4030   "function UseWith1() {"
   4031   "  var x = 42;"
   4032   "  with({x:87}) { return x; }"
   4033   "}";
   4034 
   4035 
   4036 
   4037 static const char* kWithExtensionSource2 =
   4038   "(function() {"
   4039   "  var x = 42;"
   4040   "  function e() {"
   4041   "    with ({x:87}) { return x; }"
   4042   "  }"
   4043   "  this.UseWith2 = e;"
   4044   "})()";
   4045 
   4046 
   4047 THREADED_TEST(UseWithFromExtension) {
   4048   v8::HandleScope handle_scope;
   4049   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
   4050   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
   4051   const char* extension_names[] = { "withtest1", "withtest2" };
   4052   v8::ExtensionConfiguration extensions(2, extension_names);
   4053   v8::Handle<Context> context = Context::New(&extensions);
   4054   Context::Scope lock(context);
   4055   v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
   4056   CHECK_EQ(result, v8::Integer::New(87));
   4057   result = Script::Compile(v8_str("UseWith2()"))->Run();
   4058   CHECK_EQ(result, v8::Integer::New(87));
   4059 }
   4060 
   4061 
   4062 THREADED_TEST(AutoExtensions) {
   4063   v8::HandleScope handle_scope;
   4064   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
   4065   extension->set_auto_enable(true);
   4066   v8::RegisterExtension(extension);
   4067   v8::Handle<Context> context = Context::New();
   4068   Context::Scope lock(context);
   4069   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
   4070   CHECK_EQ(result, v8::Integer::New(4));
   4071 }
   4072 
   4073 
   4074 static const char* kSyntaxErrorInExtensionSource =
   4075     "[";
   4076 
   4077 
   4078 // Test that a syntax error in an extension does not cause a fatal
   4079 // error but results in an empty context.
   4080 THREADED_TEST(SyntaxErrorExtensions) {
   4081   v8::HandleScope handle_scope;
   4082   v8::RegisterExtension(new Extension("syntaxerror",
   4083                                       kSyntaxErrorInExtensionSource));
   4084   const char* extension_names[] = { "syntaxerror" };
   4085   v8::ExtensionConfiguration extensions(1, extension_names);
   4086   v8::Handle<Context> context = Context::New(&extensions);
   4087   CHECK(context.IsEmpty());
   4088 }
   4089 
   4090 
   4091 static const char* kExceptionInExtensionSource =
   4092     "throw 42";
   4093 
   4094 
   4095 // Test that an exception when installing an extension does not cause
   4096 // a fatal error but results in an empty context.
   4097 THREADED_TEST(ExceptionExtensions) {
   4098   v8::HandleScope handle_scope;
   4099   v8::RegisterExtension(new Extension("exception",
   4100                                       kExceptionInExtensionSource));
   4101   const char* extension_names[] = { "exception" };
   4102   v8::ExtensionConfiguration extensions(1, extension_names);
   4103   v8::Handle<Context> context = Context::New(&extensions);
   4104   CHECK(context.IsEmpty());
   4105 }
   4106 
   4107 
   4108 static const char* kNativeCallInExtensionSource =
   4109     "function call_runtime_last_index_of(x) {"
   4110     "  return %StringLastIndexOf(x, 'bob', 10);"
   4111     "}";
   4112 
   4113 
   4114 static const char* kNativeCallTest =
   4115     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
   4116 
   4117 // Test that a native runtime calls are supported in extensions.
   4118 THREADED_TEST(NativeCallInExtensions) {
   4119   v8::HandleScope handle_scope;
   4120   v8::RegisterExtension(new Extension("nativecall",
   4121                                       kNativeCallInExtensionSource));
   4122   const char* extension_names[] = { "nativecall" };
   4123   v8::ExtensionConfiguration extensions(1, extension_names);
   4124   v8::Handle<Context> context = Context::New(&extensions);
   4125   Context::Scope lock(context);
   4126   v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
   4127   CHECK_EQ(result, v8::Integer::New(3));
   4128 }
   4129 
   4130 
   4131 static void CheckDependencies(const char* name, const char* expected) {
   4132   v8::HandleScope handle_scope;
   4133   v8::ExtensionConfiguration config(1, &name);
   4134   LocalContext context(&config);
   4135   CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
   4136 }
   4137 
   4138 
   4139 /*
   4140  * Configuration:
   4141  *
   4142  *     /-- B <--\
   4143  * A <-          -- D <-- E
   4144  *     \-- C <--/
   4145  */
   4146 THREADED_TEST(ExtensionDependency) {
   4147   static const char* kEDeps[] = { "D" };
   4148   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
   4149   static const char* kDDeps[] = { "B", "C" };
   4150   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
   4151   static const char* kBCDeps[] = { "A" };
   4152   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
   4153   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
   4154   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
   4155   CheckDependencies("A", "undefinedA");
   4156   CheckDependencies("B", "undefinedAB");
   4157   CheckDependencies("C", "undefinedAC");
   4158   CheckDependencies("D", "undefinedABCD");
   4159   CheckDependencies("E", "undefinedABCDE");
   4160   v8::HandleScope handle_scope;
   4161   static const char* exts[2] = { "C", "E" };
   4162   v8::ExtensionConfiguration config(2, exts);
   4163   LocalContext context(&config);
   4164   CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
   4165 }
   4166 
   4167 
   4168 static const char* kExtensionTestScript =
   4169   "native function A();"
   4170   "native function B();"
   4171   "native function C();"
   4172   "function Foo(i) {"
   4173   "  if (i == 0) return A();"
   4174   "  if (i == 1) return B();"
   4175   "  if (i == 2) return C();"
   4176   "}";
   4177 
   4178 
   4179 static v8::Handle<Value> CallFun(const v8::Arguments& args) {
   4180   ApiTestFuzzer::Fuzz();
   4181   if (args.IsConstructCall()) {
   4182     args.This()->Set(v8_str("data"), args.Data());
   4183     return v8::Null();
   4184   }
   4185   return args.Data();
   4186 }
   4187 
   4188 
   4189 class FunctionExtension : public Extension {
   4190  public:
   4191   FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
   4192   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
   4193       v8::Handle<String> name);
   4194 };
   4195 
   4196 
   4197 static int lookup_count = 0;
   4198 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
   4199       v8::Handle<String> name) {
   4200   lookup_count++;
   4201   if (name->Equals(v8_str("A"))) {
   4202     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
   4203   } else if (name->Equals(v8_str("B"))) {
   4204     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
   4205   } else if (name->Equals(v8_str("C"))) {
   4206     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
   4207   } else {
   4208     return v8::Handle<v8::FunctionTemplate>();
   4209   }
   4210 }
   4211 
   4212 
   4213 THREADED_TEST(FunctionLookup) {
   4214   v8::RegisterExtension(new FunctionExtension());
   4215   v8::HandleScope handle_scope;
   4216   static const char* exts[1] = { "functiontest" };
   4217   v8::ExtensionConfiguration config(1, exts);
   4218   LocalContext context(&config);
   4219   CHECK_EQ(3, lookup_count);
   4220   CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
   4221   CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
   4222   CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
   4223 }
   4224 
   4225 
   4226 THREADED_TEST(NativeFunctionConstructCall) {
   4227   v8::RegisterExtension(new FunctionExtension());
   4228   v8::HandleScope handle_scope;
   4229   static const char* exts[1] = { "functiontest" };
   4230   v8::ExtensionConfiguration config(1, exts);
   4231   LocalContext context(&config);
   4232   for (int i = 0; i < 10; i++) {
   4233     // Run a few times to ensure that allocation of objects doesn't
   4234     // change behavior of a constructor function.
   4235     CHECK_EQ(v8::Integer::New(8),
   4236              Script::Compile(v8_str("(new A()).data"))->Run());
   4237     CHECK_EQ(v8::Integer::New(7),
   4238              Script::Compile(v8_str("(new B()).data"))->Run());
   4239     CHECK_EQ(v8::Integer::New(6),
   4240              Script::Compile(v8_str("(new C()).data"))->Run());
   4241   }
   4242 }
   4243 
   4244 
   4245 static const char* last_location;
   4246 static const char* last_message;
   4247 void StoringErrorCallback(const char* location, const char* message) {
   4248   if (last_location == NULL) {
   4249     last_location = location;
   4250     last_message = message;
   4251   }
   4252 }
   4253 
   4254 
   4255 // ErrorReporting creates a circular extensions configuration and
   4256 // tests that the fatal error handler gets called.  This renders V8
   4257 // unusable and therefore this test cannot be run in parallel.
   4258 TEST(ErrorReporting) {
   4259   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   4260   static const char* aDeps[] = { "B" };
   4261   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
   4262   static const char* bDeps[] = { "A" };
   4263   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
   4264   last_location = NULL;
   4265   v8::ExtensionConfiguration config(1, bDeps);
   4266   v8::Handle<Context> context = Context::New(&config);
   4267   CHECK(context.IsEmpty());
   4268   CHECK_NE(last_location, NULL);
   4269 }
   4270 
   4271 
   4272 static const char* js_code_causing_huge_string_flattening =
   4273     "var str = 'X';"
   4274     "for (var i = 0; i < 30; i++) {"
   4275     "  str = str + str;"
   4276     "}"
   4277     "str.match(/X/);";
   4278 
   4279 
   4280 void OOMCallback(const char* location, const char* message) {
   4281   exit(0);
   4282 }
   4283 
   4284 
   4285 TEST(RegexpOutOfMemory) {
   4286   // Execute a script that causes out of memory when flattening a string.
   4287   v8::HandleScope scope;
   4288   v8::V8::SetFatalErrorHandler(OOMCallback);
   4289   LocalContext context;
   4290   Local<Script> script =
   4291       Script::Compile(String::New(js_code_causing_huge_string_flattening));
   4292   last_location = NULL;
   4293   Local<Value> result = script->Run();
   4294 
   4295   CHECK(false);  // Should not return.
   4296 }
   4297 
   4298 
   4299 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
   4300                                              v8::Handle<Value> data) {
   4301   CHECK_EQ(v8::Undefined(), data);
   4302   CHECK(message->GetScriptResourceName()->IsUndefined());
   4303   CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
   4304   message->GetLineNumber();
   4305   message->GetSourceLine();
   4306 }
   4307 
   4308 
   4309 THREADED_TEST(ErrorWithMissingScriptInfo) {
   4310   v8::HandleScope scope;
   4311   LocalContext context;
   4312   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
   4313   Script::Compile(v8_str("throw Error()"))->Run();
   4314   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
   4315 }
   4316 
   4317 
   4318 int global_index = 0;
   4319 
   4320 class Snorkel {
   4321  public:
   4322   Snorkel() { index_ = global_index++; }
   4323   int index_;
   4324 };
   4325 
   4326 class Whammy {
   4327  public:
   4328   Whammy() {
   4329     cursor_ = 0;
   4330   }
   4331   ~Whammy() {
   4332     script_.Dispose();
   4333   }
   4334   v8::Handle<Script> getScript() {
   4335     if (script_.IsEmpty())
   4336       script_ = v8::Persistent<Script>::New(v8_compile("({}).blammo"));
   4337     return Local<Script>(*script_);
   4338   }
   4339 
   4340  public:
   4341   static const int kObjectCount = 256;
   4342   int cursor_;
   4343   v8::Persistent<v8::Object> objects_[kObjectCount];
   4344   v8::Persistent<Script> script_;
   4345 };
   4346 
   4347 static void HandleWeakReference(v8::Persistent<v8::Value> obj, void* data) {
   4348   Snorkel* snorkel = reinterpret_cast<Snorkel*>(data);
   4349   delete snorkel;
   4350   obj.ClearWeak();
   4351 }
   4352 
   4353 v8::Handle<Value> WhammyPropertyGetter(Local<String> name,
   4354                                        const AccessorInfo& info) {
   4355   Whammy* whammy =
   4356     static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
   4357 
   4358   v8::Persistent<v8::Object> prev = whammy->objects_[whammy->cursor_];
   4359 
   4360   v8::Handle<v8::Object> obj = v8::Object::New();
   4361   v8::Persistent<v8::Object> global = v8::Persistent<v8::Object>::New(obj);
   4362   if (!prev.IsEmpty()) {
   4363     prev->Set(v8_str("next"), obj);
   4364     prev.MakeWeak(new Snorkel(), &HandleWeakReference);
   4365     whammy->objects_[whammy->cursor_].Clear();
   4366   }
   4367   whammy->objects_[whammy->cursor_] = global;
   4368   whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
   4369   return whammy->getScript()->Run();
   4370 }
   4371 
   4372 THREADED_TEST(WeakReference) {
   4373   v8::HandleScope handle_scope;
   4374   v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
   4375   Whammy* whammy = new Whammy();
   4376   templ->SetNamedPropertyHandler(WhammyPropertyGetter,
   4377                                  0, 0, 0, 0,
   4378                                  v8::External::New(whammy));
   4379   const char* extension_list[] = { "v8/gc" };
   4380   v8::ExtensionConfiguration extensions(1, extension_list);
   4381   v8::Persistent<Context> context = Context::New(&extensions);
   4382   Context::Scope context_scope(context);
   4383 
   4384   v8::Handle<v8::Object> interceptor = templ->NewInstance();
   4385   context->Global()->Set(v8_str("whammy"), interceptor);
   4386   const char* code =
   4387       "var last;"
   4388       "for (var i = 0; i < 10000; i++) {"
   4389       "  var obj = whammy.length;"
   4390       "  if (last) last.next = obj;"
   4391       "  last = obj;"
   4392       "}"
   4393       "gc();"
   4394       "4";
   4395   v8::Handle<Value> result = CompileRun(code);
   4396   CHECK_EQ(4.0, result->NumberValue());
   4397   delete whammy;
   4398   context.Dispose();
   4399 }
   4400 
   4401 
   4402 static bool in_scavenge = false;
   4403 static int last = -1;
   4404 
   4405 static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) {
   4406   CHECK_EQ(-1, last);
   4407   last = 0;
   4408   obj.Dispose();
   4409   obj.Clear();
   4410   in_scavenge = true;
   4411   HEAP->PerformScavenge();
   4412   in_scavenge = false;
   4413   *(reinterpret_cast<bool*>(data)) = true;
   4414 }
   4415 
   4416 static void CheckIsNotInvokedInScavenge(v8::Persistent<v8::Value> obj,
   4417                                         void* data) {
   4418   CHECK_EQ(0, last);
   4419   last = 1;
   4420   *(reinterpret_cast<bool*>(data)) = in_scavenge;
   4421   obj.Dispose();
   4422   obj.Clear();
   4423 }
   4424 
   4425 THREADED_TEST(NoWeakRefCallbacksInScavenge) {
   4426   // Test verifies that scavenge cannot invoke WeakReferenceCallbacks.
   4427   // Calling callbacks from scavenges is unsafe as objects held by those
   4428   // handlers might have become strongly reachable, but scavenge doesn't
   4429   // check that.
   4430   v8::Persistent<Context> context = Context::New();
   4431   Context::Scope context_scope(context);
   4432 
   4433   v8::Persistent<v8::Object> object_a;
   4434   v8::Persistent<v8::Object> object_b;
   4435 
   4436   {
   4437     v8::HandleScope handle_scope;
   4438     object_b = v8::Persistent<v8::Object>::New(v8::Object::New());
   4439     object_a = v8::Persistent<v8::Object>::New(v8::Object::New());
   4440   }
   4441 
   4442   bool object_a_disposed = false;
   4443   object_a.MakeWeak(&object_a_disposed, &ForceScavenge);
   4444   bool released_in_scavenge = false;
   4445   object_b.MakeWeak(&released_in_scavenge, &CheckIsNotInvokedInScavenge);
   4446 
   4447   while (!object_a_disposed) {
   4448     HEAP->CollectAllGarbage(false);
   4449   }
   4450   CHECK(!released_in_scavenge);
   4451 }
   4452 
   4453 
   4454 v8::Handle<Function> args_fun;
   4455 
   4456 
   4457 static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) {
   4458   ApiTestFuzzer::Fuzz();
   4459   CHECK_EQ(args_fun, args.Callee());
   4460   CHECK_EQ(3, args.Length());
   4461   CHECK_EQ(v8::Integer::New(1), args[0]);
   4462   CHECK_EQ(v8::Integer::New(2), args[1]);
   4463   CHECK_EQ(v8::Integer::New(3), args[2]);
   4464   CHECK_EQ(v8::Undefined(), args[3]);
   4465   v8::HandleScope scope;
   4466   HEAP->CollectAllGarbage(false);
   4467   return v8::Undefined();
   4468 }
   4469 
   4470 
   4471 THREADED_TEST(Arguments) {
   4472   v8::HandleScope scope;
   4473   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
   4474   global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
   4475   LocalContext context(NULL, global);
   4476   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
   4477   v8_compile("f(1, 2, 3)")->Run();
   4478 }
   4479 
   4480 
   4481 static v8::Handle<Value> NoBlockGetterX(Local<String> name,
   4482                                         const AccessorInfo&) {
   4483   return v8::Handle<Value>();
   4484 }
   4485 
   4486 
   4487 static v8::Handle<Value> NoBlockGetterI(uint32_t index,
   4488                                         const AccessorInfo&) {
   4489   return v8::Handle<Value>();
   4490 }
   4491 
   4492 
   4493 static v8::Handle<v8::Boolean> PDeleter(Local<String> name,
   4494                                         const AccessorInfo&) {
   4495   if (!name->Equals(v8_str("foo"))) {
   4496     return v8::Handle<v8::Boolean>();  // not intercepted
   4497   }
   4498 
   4499   return v8::False();  // intercepted, and don't delete the property
   4500 }
   4501 
   4502 
   4503 static v8::Handle<v8::Boolean> IDeleter(uint32_t index, const AccessorInfo&) {
   4504   if (index != 2) {
   4505     return v8::Handle<v8::Boolean>();  // not intercepted
   4506   }
   4507 
   4508   return v8::False();  // intercepted, and don't delete the property
   4509 }
   4510 
   4511 
   4512 THREADED_TEST(Deleter) {
   4513   v8::HandleScope scope;
   4514   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   4515   obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
   4516   obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
   4517   LocalContext context;
   4518   context->Global()->Set(v8_str("k"), obj->NewInstance());
   4519   CompileRun(
   4520     "k.foo = 'foo';"
   4521     "k.bar = 'bar';"
   4522     "k[2] = 2;"
   4523     "k[4] = 4;");
   4524   CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
   4525   CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
   4526 
   4527   CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
   4528   CHECK(v8_compile("k.bar")->Run()->IsUndefined());
   4529 
   4530   CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
   4531   CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
   4532 
   4533   CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
   4534   CHECK(v8_compile("k[4]")->Run()->IsUndefined());
   4535 }
   4536 
   4537 
   4538 static v8::Handle<Value> GetK(Local<String> name, const AccessorInfo&) {
   4539   ApiTestFuzzer::Fuzz();
   4540   if (name->Equals(v8_str("foo")) ||
   4541       name->Equals(v8_str("bar")) ||
   4542       name->Equals(v8_str("baz"))) {
   4543     return v8::Undefined();
   4544   }
   4545   return v8::Handle<Value>();
   4546 }
   4547 
   4548 
   4549 static v8::Handle<Value> IndexedGetK(uint32_t index, const AccessorInfo&) {
   4550   ApiTestFuzzer::Fuzz();
   4551   if (index == 0 || index == 1) return v8::Undefined();
   4552   return v8::Handle<Value>();
   4553 }
   4554 
   4555 
   4556 static v8::Handle<v8::Array> NamedEnum(const AccessorInfo&) {
   4557   ApiTestFuzzer::Fuzz();
   4558   v8::Handle<v8::Array> result = v8::Array::New(3);
   4559   result->Set(v8::Integer::New(0), v8_str("foo"));
   4560   result->Set(v8::Integer::New(1), v8_str("bar"));
   4561   result->Set(v8::Integer::New(2), v8_str("baz"));
   4562   return result;
   4563 }
   4564 
   4565 
   4566 static v8::Handle<v8::Array> IndexedEnum(const AccessorInfo&) {
   4567   ApiTestFuzzer::Fuzz();
   4568   v8::Handle<v8::Array> result = v8::Array::New(2);
   4569   result->Set(v8::Integer::New(0), v8_str("0"));
   4570   result->Set(v8::Integer::New(1), v8_str("1"));
   4571   return result;
   4572 }
   4573 
   4574 
   4575 THREADED_TEST(Enumerators) {
   4576   v8::HandleScope scope;
   4577   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   4578   obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
   4579   obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
   4580   LocalContext context;
   4581   context->Global()->Set(v8_str("k"), obj->NewInstance());
   4582   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   4583     "k[10] = 0;"
   4584     "k.a = 0;"
   4585     "k[5] = 0;"
   4586     "k.b = 0;"
   4587     "k[4294967295] = 0;"
   4588     "k.c = 0;"
   4589     "k[4294967296] = 0;"
   4590     "k.d = 0;"
   4591     "k[140000] = 0;"
   4592     "k.e = 0;"
   4593     "k[30000000000] = 0;"
   4594     "k.f = 0;"
   4595     "var result = [];"
   4596     "for (var prop in k) {"
   4597     "  result.push(prop);"
   4598     "}"
   4599     "result"));
   4600   // Check that we get all the property names returned including the
   4601   // ones from the enumerators in the right order: indexed properties
   4602   // in numerical order, indexed interceptor properties, named
   4603   // properties in insertion order, named interceptor properties.
   4604   // This order is not mandated by the spec, so this test is just
   4605   // documenting our behavior.
   4606   CHECK_EQ(17, result->Length());
   4607   // Indexed properties in numerical order.
   4608   CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
   4609   CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
   4610   CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
   4611   CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
   4612   // Indexed interceptor properties in the order they are returned
   4613   // from the enumerator interceptor.
   4614   CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
   4615   CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
   4616   // Named properties in insertion order.
   4617   CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
   4618   CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
   4619   CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
   4620   CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
   4621   CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
   4622   CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
   4623   CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
   4624   CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
   4625   // Named interceptor properties.
   4626   CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
   4627   CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
   4628   CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
   4629 }
   4630 
   4631 
   4632 int p_getter_count;
   4633 int p_getter_count2;
   4634 
   4635 
   4636 static v8::Handle<Value> PGetter(Local<String> name, const AccessorInfo& info) {
   4637   ApiTestFuzzer::Fuzz();
   4638   p_getter_count++;
   4639   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
   4640   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   4641   if (name->Equals(v8_str("p1"))) {
   4642     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   4643   } else if (name->Equals(v8_str("p2"))) {
   4644     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   4645   } else if (name->Equals(v8_str("p3"))) {
   4646     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   4647   } else if (name->Equals(v8_str("p4"))) {
   4648     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   4649   }
   4650   return v8::Undefined();
   4651 }
   4652 
   4653 
   4654 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
   4655   ApiTestFuzzer::Fuzz();
   4656   LocalContext context;
   4657   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   4658   CompileRun(
   4659     "o1.__proto__ = { };"
   4660     "var o2 = { __proto__: o1 };"
   4661     "var o3 = { __proto__: o2 };"
   4662     "var o4 = { __proto__: o3 };"
   4663     "for (var i = 0; i < 10; i++) o4.p4;"
   4664     "for (var i = 0; i < 10; i++) o3.p3;"
   4665     "for (var i = 0; i < 10; i++) o2.p2;"
   4666     "for (var i = 0; i < 10; i++) o1.p1;");
   4667 }
   4668 
   4669 
   4670 static v8::Handle<Value> PGetter2(Local<String> name,
   4671                                   const AccessorInfo& info) {
   4672   ApiTestFuzzer::Fuzz();
   4673   p_getter_count2++;
   4674   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
   4675   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   4676   if (name->Equals(v8_str("p1"))) {
   4677     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   4678   } else if (name->Equals(v8_str("p2"))) {
   4679     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   4680   } else if (name->Equals(v8_str("p3"))) {
   4681     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   4682   } else if (name->Equals(v8_str("p4"))) {
   4683     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   4684   }
   4685   return v8::Undefined();
   4686 }
   4687 
   4688 
   4689 THREADED_TEST(GetterHolders) {
   4690   v8::HandleScope scope;
   4691   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   4692   obj->SetAccessor(v8_str("p1"), PGetter);
   4693   obj->SetAccessor(v8_str("p2"), PGetter);
   4694   obj->SetAccessor(v8_str("p3"), PGetter);
   4695   obj->SetAccessor(v8_str("p4"), PGetter);
   4696   p_getter_count = 0;
   4697   RunHolderTest(obj);
   4698   CHECK_EQ(40, p_getter_count);
   4699 }
   4700 
   4701 
   4702 THREADED_TEST(PreInterceptorHolders) {
   4703   v8::HandleScope scope;
   4704   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   4705   obj->SetNamedPropertyHandler(PGetter2);
   4706   p_getter_count2 = 0;
   4707   RunHolderTest(obj);
   4708   CHECK_EQ(40, p_getter_count2);
   4709 }
   4710 
   4711 
   4712 THREADED_TEST(ObjectInstantiation) {
   4713   v8::HandleScope scope;
   4714   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   4715   templ->SetAccessor(v8_str("t"), PGetter2);
   4716   LocalContext context;
   4717   context->Global()->Set(v8_str("o"), templ->NewInstance());
   4718   for (int i = 0; i < 100; i++) {
   4719     v8::HandleScope inner_scope;
   4720     v8::Handle<v8::Object> obj = templ->NewInstance();
   4721     CHECK_NE(obj, context->Global()->Get(v8_str("o")));
   4722     context->Global()->Set(v8_str("o2"), obj);
   4723     v8::Handle<Value> value =
   4724         Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
   4725     CHECK_EQ(v8::True(), value);
   4726     context->Global()->Set(v8_str("o"), obj);
   4727   }
   4728 }
   4729 
   4730 
   4731 static int StrCmp16(uint16_t* a, uint16_t* b) {
   4732   while (true) {
   4733     if (*a == 0 && *b == 0) return 0;
   4734     if (*a != *b) return 0 + *a - *b;
   4735     a++;
   4736     b++;
   4737   }
   4738 }
   4739 
   4740 
   4741 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
   4742   while (true) {
   4743     if (n-- == 0) return 0;
   4744     if (*a == 0 && *b == 0) return 0;
   4745     if (*a != *b) return 0 + *a - *b;
   4746     a++;
   4747     b++;
   4748   }
   4749 }
   4750 
   4751 
   4752 THREADED_TEST(StringWrite) {
   4753   v8::HandleScope scope;
   4754   v8::Handle<String> str = v8_str("abcde");
   4755   // abc<Icelandic eth><Unicode snowman>.
   4756   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
   4757 
   4758   CHECK_EQ(5, str2->Length());
   4759 
   4760   char buf[100];
   4761   char utf8buf[100];
   4762   uint16_t wbuf[100];
   4763   int len;
   4764   int charlen;
   4765 
   4766   memset(utf8buf, 0x1, sizeof(utf8buf));
   4767   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   4768   CHECK_EQ(9, len);
   4769   CHECK_EQ(5, charlen);
   4770   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   4771 
   4772   memset(utf8buf, 0x1, sizeof(utf8buf));
   4773   len = str2->WriteUtf8(utf8buf, 8, &charlen);
   4774   CHECK_EQ(8, len);
   4775   CHECK_EQ(5, charlen);
   4776   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
   4777 
   4778   memset(utf8buf, 0x1, sizeof(utf8buf));
   4779   len = str2->WriteUtf8(utf8buf, 7, &charlen);
   4780   CHECK_EQ(5, len);
   4781   CHECK_EQ(4, charlen);
   4782   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   4783 
   4784   memset(utf8buf, 0x1, sizeof(utf8buf));
   4785   len = str2->WriteUtf8(utf8buf, 6, &charlen);
   4786   CHECK_EQ(5, len);
   4787   CHECK_EQ(4, charlen);
   4788   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   4789 
   4790   memset(utf8buf, 0x1, sizeof(utf8buf));
   4791   len = str2->WriteUtf8(utf8buf, 5, &charlen);
   4792   CHECK_EQ(5, len);
   4793   CHECK_EQ(4, charlen);
   4794   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   4795 
   4796   memset(utf8buf, 0x1, sizeof(utf8buf));
   4797   len = str2->WriteUtf8(utf8buf, 4, &charlen);
   4798   CHECK_EQ(3, len);
   4799   CHECK_EQ(3, charlen);
   4800   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   4801 
   4802   memset(utf8buf, 0x1, sizeof(utf8buf));
   4803   len = str2->WriteUtf8(utf8buf, 3, &charlen);
   4804   CHECK_EQ(3, len);
   4805   CHECK_EQ(3, charlen);
   4806   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   4807 
   4808   memset(utf8buf, 0x1, sizeof(utf8buf));
   4809   len = str2->WriteUtf8(utf8buf, 2, &charlen);
   4810   CHECK_EQ(2, len);
   4811   CHECK_EQ(2, charlen);
   4812   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
   4813 
   4814   memset(buf, 0x1, sizeof(buf));
   4815   memset(wbuf, 0x1, sizeof(wbuf));
   4816   len = str->WriteAscii(buf);
   4817   CHECK_EQ(5, len);
   4818   len = str->Write(wbuf);
   4819   CHECK_EQ(5, len);
   4820   CHECK_EQ(0, strcmp("abcde", buf));
   4821   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   4822   CHECK_EQ(0, StrCmp16(answer1, wbuf));
   4823 
   4824   memset(buf, 0x1, sizeof(buf));
   4825   memset(wbuf, 0x1, sizeof(wbuf));
   4826   len = str->WriteAscii(buf, 0, 4);
   4827   CHECK_EQ(4, len);
   4828   len = str->Write(wbuf, 0, 4);
   4829   CHECK_EQ(4, len);
   4830   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
   4831   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
   4832   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
   4833 
   4834   memset(buf, 0x1, sizeof(buf));
   4835   memset(wbuf, 0x1, sizeof(wbuf));
   4836   len = str->WriteAscii(buf, 0, 5);
   4837   CHECK_EQ(5, len);
   4838   len = str->Write(wbuf, 0, 5);
   4839   CHECK_EQ(5, len);
   4840   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
   4841   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
   4842   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
   4843 
   4844   memset(buf, 0x1, sizeof(buf));
   4845   memset(wbuf, 0x1, sizeof(wbuf));
   4846   len = str->WriteAscii(buf, 0, 6);
   4847   CHECK_EQ(5, len);
   4848   len = str->Write(wbuf, 0, 6);
   4849   CHECK_EQ(5, len);
   4850   CHECK_EQ(0, strcmp("abcde", buf));
   4851   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   4852   CHECK_EQ(0, StrCmp16(answer4, wbuf));
   4853 
   4854   memset(buf, 0x1, sizeof(buf));
   4855   memset(wbuf, 0x1, sizeof(wbuf));
   4856   len = str->WriteAscii(buf, 4, -1);
   4857   CHECK_EQ(1, len);
   4858   len = str->Write(wbuf, 4, -1);
   4859   CHECK_EQ(1, len);
   4860   CHECK_EQ(0, strcmp("e", buf));
   4861   uint16_t answer5[] = {'e', '\0'};
   4862   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   4863 
   4864   memset(buf, 0x1, sizeof(buf));
   4865   memset(wbuf, 0x1, sizeof(wbuf));
   4866   len = str->WriteAscii(buf, 4, 6);
   4867   CHECK_EQ(1, len);
   4868   len = str->Write(wbuf, 4, 6);
   4869   CHECK_EQ(1, len);
   4870   CHECK_EQ(0, strcmp("e", buf));
   4871   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   4872 
   4873   memset(buf, 0x1, sizeof(buf));
   4874   memset(wbuf, 0x1, sizeof(wbuf));
   4875   len = str->WriteAscii(buf, 4, 1);
   4876   CHECK_EQ(1, len);
   4877   len = str->Write(wbuf, 4, 1);
   4878   CHECK_EQ(1, len);
   4879   CHECK_EQ(0, strncmp("e\1", buf, 2));
   4880   uint16_t answer6[] = {'e', 0x101};
   4881   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
   4882 
   4883   memset(buf, 0x1, sizeof(buf));
   4884   memset(wbuf, 0x1, sizeof(wbuf));
   4885   len = str->WriteAscii(buf, 3, 1);
   4886   CHECK_EQ(1, len);
   4887   len = str->Write(wbuf, 3, 1);
   4888   CHECK_EQ(1, len);
   4889   CHECK_EQ(0, strncmp("d\1", buf, 2));
   4890   uint16_t answer7[] = {'d', 0x101};
   4891   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
   4892 }
   4893 
   4894 
   4895 THREADED_TEST(ToArrayIndex) {
   4896   v8::HandleScope scope;
   4897   LocalContext context;
   4898 
   4899   v8::Handle<String> str = v8_str("42");
   4900   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
   4901   CHECK(!index.IsEmpty());
   4902   CHECK_EQ(42.0, index->Uint32Value());
   4903   str = v8_str("42asdf");
   4904   index = str->ToArrayIndex();
   4905   CHECK(index.IsEmpty());
   4906   str = v8_str("-42");
   4907   index = str->ToArrayIndex();
   4908   CHECK(index.IsEmpty());
   4909   str = v8_str("4294967295");
   4910   index = str->ToArrayIndex();
   4911   CHECK(!index.IsEmpty());
   4912   CHECK_EQ(4294967295.0, index->Uint32Value());
   4913   v8::Handle<v8::Number> num = v8::Number::New(1);
   4914   index = num->ToArrayIndex();
   4915   CHECK(!index.IsEmpty());
   4916   CHECK_EQ(1.0, index->Uint32Value());
   4917   num = v8::Number::New(-1);
   4918   index = num->ToArrayIndex();
   4919   CHECK(index.IsEmpty());
   4920   v8::Handle<v8::Object> obj = v8::Object::New();
   4921   index = obj->ToArrayIndex();
   4922   CHECK(index.IsEmpty());
   4923 }
   4924 
   4925 
   4926 THREADED_TEST(ErrorConstruction) {
   4927   v8::HandleScope scope;
   4928   LocalContext context;
   4929 
   4930   v8::Handle<String> foo = v8_str("foo");
   4931   v8::Handle<String> message = v8_str("message");
   4932   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
   4933   CHECK(range_error->IsObject());
   4934   v8::Handle<v8::Object> range_obj = range_error.As<v8::Object>();
   4935   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
   4936   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
   4937   CHECK(reference_error->IsObject());
   4938   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
   4939   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
   4940   CHECK(syntax_error->IsObject());
   4941   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
   4942   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
   4943   CHECK(type_error->IsObject());
   4944   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
   4945   v8::Handle<Value> error = v8::Exception::Error(foo);
   4946   CHECK(error->IsObject());
   4947   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
   4948 }
   4949 
   4950 
   4951 static v8::Handle<Value> YGetter(Local<String> name, const AccessorInfo& info) {
   4952   ApiTestFuzzer::Fuzz();
   4953   return v8_num(10);
   4954 }
   4955 
   4956 
   4957 static void YSetter(Local<String> name,
   4958                     Local<Value> value,
   4959                     const AccessorInfo& info) {
   4960   if (info.This()->Has(name)) {
   4961     info.This()->Delete(name);
   4962   }
   4963   info.This()->Set(name, value);
   4964 }
   4965 
   4966 
   4967 THREADED_TEST(DeleteAccessor) {
   4968   v8::HandleScope scope;
   4969   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   4970   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
   4971   LocalContext context;
   4972   v8::Handle<v8::Object> holder = obj->NewInstance();
   4973   context->Global()->Set(v8_str("holder"), holder);
   4974   v8::Handle<Value> result = CompileRun(
   4975       "holder.y = 11; holder.y = 12; holder.y");
   4976   CHECK_EQ(12, result->Uint32Value());
   4977 }
   4978 
   4979 
   4980 THREADED_TEST(TypeSwitch) {
   4981   v8::HandleScope scope;
   4982   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
   4983   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
   4984   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
   4985   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
   4986   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
   4987   LocalContext context;
   4988   v8::Handle<v8::Object> obj0 = v8::Object::New();
   4989   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
   4990   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
   4991   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
   4992   for (int i = 0; i < 10; i++) {
   4993     CHECK_EQ(0, type_switch->match(obj0));
   4994     CHECK_EQ(1, type_switch->match(obj1));
   4995     CHECK_EQ(2, type_switch->match(obj2));
   4996     CHECK_EQ(3, type_switch->match(obj3));
   4997     CHECK_EQ(3, type_switch->match(obj3));
   4998     CHECK_EQ(2, type_switch->match(obj2));
   4999     CHECK_EQ(1, type_switch->match(obj1));
   5000     CHECK_EQ(0, type_switch->match(obj0));
   5001   }
   5002 }
   5003 
   5004 
   5005 // For use within the TestSecurityHandler() test.
   5006 static bool g_security_callback_result = false;
   5007 static bool NamedSecurityTestCallback(Local<v8::Object> global,
   5008                                       Local<Value> name,
   5009                                       v8::AccessType type,
   5010                                       Local<Value> data) {
   5011   // Always allow read access.
   5012   if (type == v8::ACCESS_GET)
   5013     return true;
   5014 
   5015   // Sometimes allow other access.
   5016   return g_security_callback_result;
   5017 }
   5018 
   5019 
   5020 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
   5021                                         uint32_t key,
   5022                                         v8::AccessType type,
   5023                                         Local<Value> data) {
   5024   // Always allow read access.
   5025   if (type == v8::ACCESS_GET)
   5026     return true;
   5027 
   5028   // Sometimes allow other access.
   5029   return g_security_callback_result;
   5030 }
   5031 
   5032 
   5033 static int trouble_nesting = 0;
   5034 static v8::Handle<Value> TroubleCallback(const v8::Arguments& args) {
   5035   ApiTestFuzzer::Fuzz();
   5036   trouble_nesting++;
   5037 
   5038   // Call a JS function that throws an uncaught exception.
   5039   Local<v8::Object> arg_this = Context::GetCurrent()->Global();
   5040   Local<Value> trouble_callee = (trouble_nesting == 3) ?
   5041     arg_this->Get(v8_str("trouble_callee")) :
   5042     arg_this->Get(v8_str("trouble_caller"));
   5043   CHECK(trouble_callee->IsFunction());
   5044   return Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL);
   5045 }
   5046 
   5047 
   5048 static int report_count = 0;
   5049 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
   5050                                              v8::Handle<Value>) {
   5051   report_count++;
   5052 }
   5053 
   5054 
   5055 // Counts uncaught exceptions, but other tests running in parallel
   5056 // also have uncaught exceptions.
   5057 TEST(ApiUncaughtException) {
   5058   report_count = 0;
   5059   v8::HandleScope scope;
   5060   LocalContext env;
   5061   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
   5062 
   5063   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
   5064   v8::Local<v8::Object> global = env->Global();
   5065   global->Set(v8_str("trouble"), fun->GetFunction());
   5066 
   5067   Script::Compile(v8_str("function trouble_callee() {"
   5068                          "  var x = null;"
   5069                          "  return x.foo;"
   5070                          "};"
   5071                          "function trouble_caller() {"
   5072                          "  trouble();"
   5073                          "};"))->Run();
   5074   Local<Value> trouble = global->Get(v8_str("trouble"));
   5075   CHECK(trouble->IsFunction());
   5076   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
   5077   CHECK(trouble_callee->IsFunction());
   5078   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
   5079   CHECK(trouble_caller->IsFunction());
   5080   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
   5081   CHECK_EQ(1, report_count);
   5082   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
   5083 }
   5084 
   5085 static const char* script_resource_name = "ExceptionInNativeScript.js";
   5086 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
   5087                                                 v8::Handle<Value>) {
   5088   v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
   5089   CHECK(!name_val.IsEmpty() && name_val->IsString());
   5090   v8::String::AsciiValue name(message->GetScriptResourceName());
   5091   CHECK_EQ(script_resource_name, *name);
   5092   CHECK_EQ(3, message->GetLineNumber());
   5093   v8::String::AsciiValue source_line(message->GetSourceLine());
   5094   CHECK_EQ("  new o.foo();", *source_line);
   5095 }
   5096 
   5097 TEST(ExceptionInNativeScript) {
   5098   v8::HandleScope scope;
   5099   LocalContext env;
   5100   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
   5101 
   5102   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
   5103   v8::Local<v8::Object> global = env->Global();
   5104   global->Set(v8_str("trouble"), fun->GetFunction());
   5105 
   5106   Script::Compile(v8_str("function trouble() {\n"
   5107                          "  var o = {};\n"
   5108                          "  new o.foo();\n"
   5109                          "};"), v8::String::New(script_resource_name))->Run();
   5110   Local<Value> trouble = global->Get(v8_str("trouble"));
   5111   CHECK(trouble->IsFunction());
   5112   Function::Cast(*trouble)->Call(global, 0, NULL);
   5113   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
   5114 }
   5115 
   5116 
   5117 TEST(CompilationErrorUsingTryCatchHandler) {
   5118   v8::HandleScope scope;
   5119   LocalContext env;
   5120   v8::TryCatch try_catch;
   5121   Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
   5122   CHECK_NE(NULL, *try_catch.Exception());
   5123   CHECK(try_catch.HasCaught());
   5124 }
   5125 
   5126 
   5127 TEST(TryCatchFinallyUsingTryCatchHandler) {
   5128   v8::HandleScope scope;
   5129   LocalContext env;
   5130   v8::TryCatch try_catch;
   5131   Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
   5132   CHECK(!try_catch.HasCaught());
   5133   Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
   5134   CHECK(try_catch.HasCaught());
   5135   try_catch.Reset();
   5136   Script::Compile(v8_str("(function() {"
   5137                          "try { throw ''; } finally { return; }"
   5138                          "})()"))->Run();
   5139   CHECK(!try_catch.HasCaught());
   5140   Script::Compile(v8_str("(function()"
   5141                          "  { try { throw ''; } finally { throw 0; }"
   5142                          "})()"))->Run();
   5143   CHECK(try_catch.HasCaught());
   5144 }
   5145 
   5146 
   5147 // SecurityHandler can't be run twice
   5148 TEST(SecurityHandler) {
   5149   v8::HandleScope scope0;
   5150   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   5151   global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
   5152                                            IndexedSecurityTestCallback);
   5153   // Create an environment
   5154   v8::Persistent<Context> context0 =
   5155     Context::New(NULL, global_template);
   5156   context0->Enter();
   5157 
   5158   v8::Handle<v8::Object> global0 = context0->Global();
   5159   v8::Handle<Script> script0 = v8_compile("foo = 111");
   5160   script0->Run();
   5161   global0->Set(v8_str("0"), v8_num(999));
   5162   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
   5163   CHECK_EQ(111, foo0->Int32Value());
   5164   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
   5165   CHECK_EQ(999, z0->Int32Value());
   5166 
   5167   // Create another environment, should fail security checks.
   5168   v8::HandleScope scope1;
   5169 
   5170   v8::Persistent<Context> context1 =
   5171     Context::New(NULL, global_template);
   5172   context1->Enter();
   5173 
   5174   v8::Handle<v8::Object> global1 = context1->Global();
   5175   global1->Set(v8_str("othercontext"), global0);
   5176   // This set will fail the security check.
   5177   v8::Handle<Script> script1 =
   5178     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
   5179   script1->Run();
   5180   // This read will pass the security check.
   5181   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
   5182   CHECK_EQ(111, foo1->Int32Value());
   5183   // This read will pass the security check.
   5184   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
   5185   CHECK_EQ(999, z1->Int32Value());
   5186 
   5187   // Create another environment, should pass security checks.
   5188   { g_security_callback_result = true;  // allow security handler to pass.
   5189     v8::HandleScope scope2;
   5190     LocalContext context2;
   5191     v8::Handle<v8::Object> global2 = context2->Global();
   5192     global2->Set(v8_str("othercontext"), global0);
   5193     v8::Handle<Script> script2 =
   5194         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
   5195     script2->Run();
   5196     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
   5197     CHECK_EQ(333, foo2->Int32Value());
   5198     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
   5199     CHECK_EQ(888, z2->Int32Value());
   5200   }
   5201 
   5202   context1->Exit();
   5203   context1.Dispose();
   5204 
   5205   context0->Exit();
   5206   context0.Dispose();
   5207 }
   5208 
   5209 
   5210 THREADED_TEST(SecurityChecks) {
   5211   v8::HandleScope handle_scope;
   5212   LocalContext env1;
   5213   v8::Persistent<Context> env2 = Context::New();
   5214 
   5215   Local<Value> foo = v8_str("foo");
   5216   Local<Value> bar = v8_str("bar");
   5217 
   5218   // Set to the same domain.
   5219   env1->SetSecurityToken(foo);
   5220 
   5221   // Create a function in env1.
   5222   Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
   5223   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
   5224   CHECK(spy->IsFunction());
   5225 
   5226   // Create another function accessing global objects.
   5227   Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
   5228   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
   5229   CHECK(spy2->IsFunction());
   5230 
   5231   // Switch to env2 in the same domain and invoke spy on env2.
   5232   {
   5233     env2->SetSecurityToken(foo);
   5234     // Enter env2
   5235     Context::Scope scope_env2(env2);
   5236     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
   5237     CHECK(result->IsFunction());
   5238   }
   5239 
   5240   {
   5241     env2->SetSecurityToken(bar);
   5242     Context::Scope scope_env2(env2);
   5243 
   5244     // Call cross_domain_call, it should throw an exception
   5245     v8::TryCatch try_catch;
   5246     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
   5247     CHECK(try_catch.HasCaught());
   5248   }
   5249 
   5250   env2.Dispose();
   5251 }
   5252 
   5253 
   5254 // Regression test case for issue 1183439.
   5255 THREADED_TEST(SecurityChecksForPrototypeChain) {
   5256   v8::HandleScope scope;
   5257   LocalContext current;
   5258   v8::Persistent<Context> other = Context::New();
   5259 
   5260   // Change context to be able to get to the Object function in the
   5261   // other context without hitting the security checks.
   5262   v8::Local<Value> other_object;
   5263   { Context::Scope scope(other);
   5264     other_object = other->Global()->Get(v8_str("Object"));
   5265     other->Global()->Set(v8_num(42), v8_num(87));
   5266   }
   5267 
   5268   current->Global()->Set(v8_str("other"), other->Global());
   5269   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
   5270 
   5271   // Make sure the security check fails here and we get an undefined
   5272   // result instead of getting the Object function. Repeat in a loop
   5273   // to make sure to exercise the IC code.
   5274   v8::Local<Script> access_other0 = v8_compile("other.Object");
   5275   v8::Local<Script> access_other1 = v8_compile("other[42]");
   5276   for (int i = 0; i < 5; i++) {
   5277     CHECK(!access_other0->Run()->Equals(other_object));
   5278     CHECK(access_other0->Run()->IsUndefined());
   5279     CHECK(!access_other1->Run()->Equals(v8_num(87)));
   5280     CHECK(access_other1->Run()->IsUndefined());
   5281   }
   5282 
   5283   // Create an object that has 'other' in its prototype chain and make
   5284   // sure we cannot access the Object function indirectly through
   5285   // that. Repeat in a loop to make sure to exercise the IC code.
   5286   v8_compile("function F() { };"
   5287              "F.prototype = other;"
   5288              "var f = new F();")->Run();
   5289   v8::Local<Script> access_f0 = v8_compile("f.Object");
   5290   v8::Local<Script> access_f1 = v8_compile("f[42]");
   5291   for (int j = 0; j < 5; j++) {
   5292     CHECK(!access_f0->Run()->Equals(other_object));
   5293     CHECK(access_f0->Run()->IsUndefined());
   5294     CHECK(!access_f1->Run()->Equals(v8_num(87)));
   5295     CHECK(access_f1->Run()->IsUndefined());
   5296   }
   5297 
   5298   // Now it gets hairy: Set the prototype for the other global object
   5299   // to be the current global object. The prototype chain for 'f' now
   5300   // goes through 'other' but ends up in the current global object.
   5301   { Context::Scope scope(other);
   5302     other->Global()->Set(v8_str("__proto__"), current->Global());
   5303   }
   5304   // Set a named and an index property on the current global
   5305   // object. To force the lookup to go through the other global object,
   5306   // the properties must not exist in the other global object.
   5307   current->Global()->Set(v8_str("foo"), v8_num(100));
   5308   current->Global()->Set(v8_num(99), v8_num(101));
   5309   // Try to read the properties from f and make sure that the access
   5310   // gets stopped by the security checks on the other global object.
   5311   Local<Script> access_f2 = v8_compile("f.foo");
   5312   Local<Script> access_f3 = v8_compile("f[99]");
   5313   for (int k = 0; k < 5; k++) {
   5314     CHECK(!access_f2->Run()->Equals(v8_num(100)));
   5315     CHECK(access_f2->Run()->IsUndefined());
   5316     CHECK(!access_f3->Run()->Equals(v8_num(101)));
   5317     CHECK(access_f3->Run()->IsUndefined());
   5318   }
   5319   other.Dispose();
   5320 }
   5321 
   5322 
   5323 THREADED_TEST(CrossDomainDelete) {
   5324   v8::HandleScope handle_scope;
   5325   LocalContext env1;
   5326   v8::Persistent<Context> env2 = Context::New();
   5327 
   5328   Local<Value> foo = v8_str("foo");
   5329   Local<Value> bar = v8_str("bar");
   5330 
   5331   // Set to the same domain.
   5332   env1->SetSecurityToken(foo);
   5333   env2->SetSecurityToken(foo);
   5334 
   5335   env1->Global()->Set(v8_str("prop"), v8_num(3));
   5336   env2->Global()->Set(v8_str("env1"), env1->Global());
   5337 
   5338   // Change env2 to a different domain and delete env1.prop.
   5339   env2->SetSecurityToken(bar);
   5340   {
   5341     Context::Scope scope_env2(env2);
   5342     Local<Value> result =
   5343         Script::Compile(v8_str("delete env1.prop"))->Run();
   5344     CHECK(result->IsFalse());
   5345   }
   5346 
   5347   // Check that env1.prop still exists.
   5348   Local<Value> v = env1->Global()->Get(v8_str("prop"));
   5349   CHECK(v->IsNumber());
   5350   CHECK_EQ(3, v->Int32Value());
   5351 
   5352   env2.Dispose();
   5353 }
   5354 
   5355 
   5356 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
   5357   v8::HandleScope handle_scope;
   5358   LocalContext env1;
   5359   v8::Persistent<Context> env2 = Context::New();
   5360 
   5361   Local<Value> foo = v8_str("foo");
   5362   Local<Value> bar = v8_str("bar");
   5363 
   5364   // Set to the same domain.
   5365   env1->SetSecurityToken(foo);
   5366   env2->SetSecurityToken(foo);
   5367 
   5368   env1->Global()->Set(v8_str("prop"), v8_num(3));
   5369   env2->Global()->Set(v8_str("env1"), env1->Global());
   5370 
   5371   // env1.prop is enumerable in env2.
   5372   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
   5373   {
   5374     Context::Scope scope_env2(env2);
   5375     Local<Value> result = Script::Compile(test)->Run();
   5376     CHECK(result->IsTrue());
   5377   }
   5378 
   5379   // Change env2 to a different domain and test again.
   5380   env2->SetSecurityToken(bar);
   5381   {
   5382     Context::Scope scope_env2(env2);
   5383     Local<Value> result = Script::Compile(test)->Run();
   5384     CHECK(result->IsFalse());
   5385   }
   5386 
   5387   env2.Dispose();
   5388 }
   5389 
   5390 
   5391 THREADED_TEST(CrossDomainForIn) {
   5392   v8::HandleScope handle_scope;
   5393   LocalContext env1;
   5394   v8::Persistent<Context> env2 = Context::New();
   5395 
   5396   Local<Value> foo = v8_str("foo");
   5397   Local<Value> bar = v8_str("bar");
   5398 
   5399   // Set to the same domain.
   5400   env1->SetSecurityToken(foo);
   5401   env2->SetSecurityToken(foo);
   5402 
   5403   env1->Global()->Set(v8_str("prop"), v8_num(3));
   5404   env2->Global()->Set(v8_str("env1"), env1->Global());
   5405 
   5406   // Change env2 to a different domain and set env1's global object
   5407   // as the __proto__ of an object in env2 and enumerate properties
   5408   // in for-in. It shouldn't enumerate properties on env1's global
   5409   // object.
   5410   env2->SetSecurityToken(bar);
   5411   {
   5412     Context::Scope scope_env2(env2);
   5413     Local<Value> result =
   5414         CompileRun("(function(){var obj = {'__proto__':env1};"
   5415                    "for (var p in obj)"
   5416                    "   if (p == 'prop') return false;"
   5417                    "return true;})()");
   5418     CHECK(result->IsTrue());
   5419   }
   5420   env2.Dispose();
   5421 }
   5422 
   5423 
   5424 TEST(ContextDetachGlobal) {
   5425   v8::HandleScope handle_scope;
   5426   LocalContext env1;
   5427   v8::Persistent<Context> env2 = Context::New();
   5428 
   5429   Local<v8::Object> global1 = env1->Global();
   5430 
   5431   Local<Value> foo = v8_str("foo");
   5432 
   5433   // Set to the same domain.
   5434   env1->SetSecurityToken(foo);
   5435   env2->SetSecurityToken(foo);
   5436 
   5437   // Enter env2
   5438   env2->Enter();
   5439 
   5440   // Create a function in env2 and add a reference to it in env1.
   5441   Local<v8::Object> global2 = env2->Global();
   5442   global2->Set(v8_str("prop"), v8::Integer::New(1));
   5443   CompileRun("function getProp() {return prop;}");
   5444 
   5445   env1->Global()->Set(v8_str("getProp"),
   5446                       global2->Get(v8_str("getProp")));
   5447 
   5448   // Detach env2's global, and reuse the global object of env2
   5449   env2->Exit();
   5450   env2->DetachGlobal();
   5451   // env2 has a new global object.
   5452   CHECK(!env2->Global()->Equals(global2));
   5453 
   5454   v8::Persistent<Context> env3 =
   5455       Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
   5456   env3->SetSecurityToken(v8_str("bar"));
   5457   env3->Enter();
   5458 
   5459   Local<v8::Object> global3 = env3->Global();
   5460   CHECK_EQ(global2, global3);
   5461   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
   5462   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
   5463   global3->Set(v8_str("prop"), v8::Integer::New(-1));
   5464   global3->Set(v8_str("prop2"), v8::Integer::New(2));
   5465   env3->Exit();
   5466 
   5467   // Call getProp in env1, and it should return the value 1
   5468   {
   5469     Local<Value> get_prop = global1->Get(v8_str("getProp"));
   5470     CHECK(get_prop->IsFunction());
   5471     v8::TryCatch try_catch;
   5472     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
   5473     CHECK(!try_catch.HasCaught());
   5474     CHECK_EQ(1, r->Int32Value());
   5475   }
   5476 
   5477   // Check that env3 is not accessible from env1
   5478   {
   5479     Local<Value> r = global3->Get(v8_str("prop2"));
   5480     CHECK(r->IsUndefined());
   5481   }
   5482 
   5483   env2.Dispose();
   5484   env3.Dispose();
   5485 }
   5486 
   5487 
   5488 TEST(DetachAndReattachGlobal) {
   5489   v8::HandleScope scope;
   5490   LocalContext env1;
   5491 
   5492   // Create second environment.
   5493   v8::Persistent<Context> env2 = Context::New();
   5494 
   5495   Local<Value> foo = v8_str("foo");
   5496 
   5497   // Set same security token for env1 and env2.
   5498   env1->SetSecurityToken(foo);
   5499   env2->SetSecurityToken(foo);
   5500 
   5501   // Create a property on the global object in env2.
   5502   {
   5503     v8::Context::Scope scope(env2);
   5504     env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
   5505   }
   5506 
   5507   // Create a reference to env2 global from env1 global.
   5508   env1->Global()->Set(v8_str("other"), env2->Global());
   5509 
   5510   // Check that we have access to other.p in env2 from env1.
   5511   Local<Value> result = CompileRun("other.p");
   5512   CHECK(result->IsInt32());
   5513   CHECK_EQ(42, result->Int32Value());
   5514 
   5515   // Hold on to global from env2 and detach global from env2.
   5516   Local<v8::Object> global2 = env2->Global();
   5517   env2->DetachGlobal();
   5518 
   5519   // Check that the global has been detached. No other.p property can
   5520   // be found.
   5521   result = CompileRun("other.p");
   5522   CHECK(result->IsUndefined());
   5523 
   5524   // Reuse global2 for env3.
   5525   v8::Persistent<Context> env3 =
   5526       Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
   5527   CHECK_EQ(global2, env3->Global());
   5528 
   5529   // Start by using the same security token for env3 as for env1 and env2.
   5530   env3->SetSecurityToken(foo);
   5531 
   5532   // Create a property on the global object in env3.
   5533   {
   5534     v8::Context::Scope scope(env3);
   5535     env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
   5536   }
   5537 
   5538   // Check that other.p is now the property in env3 and that we have access.
   5539   result = CompileRun("other.p");
   5540   CHECK(result->IsInt32());
   5541   CHECK_EQ(24, result->Int32Value());
   5542 
   5543   // Change security token for env3 to something different from env1 and env2.
   5544   env3->SetSecurityToken(v8_str("bar"));
   5545 
   5546   // Check that we do not have access to other.p in env1. |other| is now
   5547   // the global object for env3 which has a different security token,
   5548   // so access should be blocked.
   5549   result = CompileRun("other.p");
   5550   CHECK(result->IsUndefined());
   5551 
   5552   // Detach the global for env3 and reattach it to env2.
   5553   env3->DetachGlobal();
   5554   env2->ReattachGlobal(global2);
   5555 
   5556   // Check that we have access to other.p again in env1.  |other| is now
   5557   // the global object for env2 which has the same security token as env1.
   5558   result = CompileRun("other.p");
   5559   CHECK(result->IsInt32());
   5560   CHECK_EQ(42, result->Int32Value());
   5561 
   5562   env2.Dispose();
   5563   env3.Dispose();
   5564 }
   5565 
   5566 
   5567 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
   5568 static bool NamedAccessBlocker(Local<v8::Object> global,
   5569                                Local<Value> name,
   5570                                v8::AccessType type,
   5571                                Local<Value> data) {
   5572   return Context::GetCurrent()->Global()->Equals(global) ||
   5573       allowed_access_type[type];
   5574 }
   5575 
   5576 
   5577 static bool IndexedAccessBlocker(Local<v8::Object> global,
   5578                                  uint32_t key,
   5579                                  v8::AccessType type,
   5580                                  Local<Value> data) {
   5581   return Context::GetCurrent()->Global()->Equals(global) ||
   5582       allowed_access_type[type];
   5583 }
   5584 
   5585 
   5586 static int g_echo_value = -1;
   5587 static v8::Handle<Value> EchoGetter(Local<String> name,
   5588                                     const AccessorInfo& info) {
   5589   return v8_num(g_echo_value);
   5590 }
   5591 
   5592 
   5593 static void EchoSetter(Local<String> name,
   5594                        Local<Value> value,
   5595                        const AccessorInfo&) {
   5596   if (value->IsNumber())
   5597     g_echo_value = value->Int32Value();
   5598 }
   5599 
   5600 
   5601 static v8::Handle<Value> UnreachableGetter(Local<String> name,
   5602                                            const AccessorInfo& info) {
   5603   CHECK(false);  // This function should not be called..
   5604   return v8::Undefined();
   5605 }
   5606 
   5607 
   5608 static void UnreachableSetter(Local<String>, Local<Value>,
   5609                               const AccessorInfo&) {
   5610   CHECK(false);  // This function should nto be called.
   5611 }
   5612 
   5613 
   5614 TEST(AccessControl) {
   5615   v8::HandleScope handle_scope;
   5616   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   5617 
   5618   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   5619                                            IndexedAccessBlocker);
   5620 
   5621   // Add an accessor accessible by cross-domain JS code.
   5622   global_template->SetAccessor(
   5623       v8_str("accessible_prop"),
   5624       EchoGetter, EchoSetter,
   5625       v8::Handle<Value>(),
   5626       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   5627 
   5628   // Add an accessor that is not accessible by cross-domain JS code.
   5629   global_template->SetAccessor(v8_str("blocked_prop"),
   5630                                UnreachableGetter, UnreachableSetter,
   5631                                v8::Handle<Value>(),
   5632                                v8::DEFAULT);
   5633 
   5634   // Create an environment
   5635   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
   5636   context0->Enter();
   5637 
   5638   v8::Handle<v8::Object> global0 = context0->Global();
   5639 
   5640   // Define a property with JS getter and setter.
   5641   CompileRun(
   5642       "function getter() { return 'getter'; };\n"
   5643       "function setter() { return 'setter'; }\n"
   5644       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   5645 
   5646   Local<Value> getter = global0->Get(v8_str("getter"));
   5647   Local<Value> setter = global0->Get(v8_str("setter"));
   5648 
   5649   // And define normal element.
   5650   global0->Set(239, v8_str("239"));
   5651 
   5652   // Define an element with JS getter and setter.
   5653   CompileRun(
   5654       "function el_getter() { return 'el_getter'; };\n"
   5655       "function el_setter() { return 'el_setter'; };\n"
   5656       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   5657 
   5658   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
   5659   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
   5660 
   5661   v8::HandleScope scope1;
   5662 
   5663   v8::Persistent<Context> context1 = Context::New();
   5664   context1->Enter();
   5665 
   5666   v8::Handle<v8::Object> global1 = context1->Global();
   5667   global1->Set(v8_str("other"), global0);
   5668 
   5669   // Access blocked property.
   5670   CompileRun("other.blocked_prop = 1");
   5671 
   5672   ExpectUndefined("other.blocked_prop");
   5673   ExpectUndefined(
   5674       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
   5675   ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
   5676 
   5677   // Enable ACCESS_HAS
   5678   allowed_access_type[v8::ACCESS_HAS] = true;
   5679   ExpectUndefined("other.blocked_prop");
   5680   // ... and now we can get the descriptor...
   5681   ExpectUndefined(
   5682       "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
   5683   // ... and enumerate the property.
   5684   ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
   5685   allowed_access_type[v8::ACCESS_HAS] = false;
   5686 
   5687   // Access blocked element.
   5688   CompileRun("other[239] = 1");
   5689 
   5690   ExpectUndefined("other[239]");
   5691   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
   5692   ExpectFalse("propertyIsEnumerable.call(other, '239')");
   5693 
   5694   // Enable ACCESS_HAS
   5695   allowed_access_type[v8::ACCESS_HAS] = true;
   5696   ExpectUndefined("other[239]");
   5697   // ... and now we can get the descriptor...
   5698   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
   5699   // ... and enumerate the property.
   5700   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   5701   allowed_access_type[v8::ACCESS_HAS] = false;
   5702 
   5703   // Access a property with JS accessor.
   5704   CompileRun("other.js_accessor_p = 2");
   5705 
   5706   ExpectUndefined("other.js_accessor_p");
   5707   ExpectUndefined(
   5708       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
   5709 
   5710   // Enable ACCESS_HAS.
   5711   allowed_access_type[v8::ACCESS_HAS] = true;
   5712   ExpectUndefined("other.js_accessor_p");
   5713   ExpectUndefined(
   5714       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
   5715   ExpectUndefined(
   5716       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
   5717   ExpectUndefined(
   5718       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   5719   allowed_access_type[v8::ACCESS_HAS] = false;
   5720 
   5721   // Enable both ACCESS_HAS and ACCESS_GET.
   5722   allowed_access_type[v8::ACCESS_HAS] = true;
   5723   allowed_access_type[v8::ACCESS_GET] = true;
   5724 
   5725   ExpectString("other.js_accessor_p", "getter");
   5726   ExpectObject(
   5727       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   5728   ExpectUndefined(
   5729       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
   5730   ExpectUndefined(
   5731       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   5732 
   5733   allowed_access_type[v8::ACCESS_GET] = false;
   5734   allowed_access_type[v8::ACCESS_HAS] = false;
   5735 
   5736   // Enable both ACCESS_HAS and ACCESS_SET.
   5737   allowed_access_type[v8::ACCESS_HAS] = true;
   5738   allowed_access_type[v8::ACCESS_SET] = true;
   5739 
   5740   ExpectUndefined("other.js_accessor_p");
   5741   ExpectUndefined(
   5742       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
   5743   ExpectObject(
   5744       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   5745   ExpectUndefined(
   5746       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   5747 
   5748   allowed_access_type[v8::ACCESS_SET] = false;
   5749   allowed_access_type[v8::ACCESS_HAS] = false;
   5750 
   5751   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
   5752   allowed_access_type[v8::ACCESS_HAS] = true;
   5753   allowed_access_type[v8::ACCESS_GET] = true;
   5754   allowed_access_type[v8::ACCESS_SET] = true;
   5755 
   5756   ExpectString("other.js_accessor_p", "getter");
   5757   ExpectObject(
   5758       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   5759   ExpectObject(
   5760       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   5761   ExpectUndefined(
   5762       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   5763 
   5764   allowed_access_type[v8::ACCESS_SET] = false;
   5765   allowed_access_type[v8::ACCESS_GET] = false;
   5766   allowed_access_type[v8::ACCESS_HAS] = false;
   5767 
   5768   // Access an element with JS accessor.
   5769   CompileRun("other[42] = 2");
   5770 
   5771   ExpectUndefined("other[42]");
   5772   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
   5773 
   5774   // Enable ACCESS_HAS.
   5775   allowed_access_type[v8::ACCESS_HAS] = true;
   5776   ExpectUndefined("other[42]");
   5777   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
   5778   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
   5779   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   5780   allowed_access_type[v8::ACCESS_HAS] = false;
   5781 
   5782   // Enable both ACCESS_HAS and ACCESS_GET.
   5783   allowed_access_type[v8::ACCESS_HAS] = true;
   5784   allowed_access_type[v8::ACCESS_GET] = true;
   5785 
   5786   ExpectString("other[42]", "el_getter");
   5787   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   5788   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
   5789   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   5790 
   5791   allowed_access_type[v8::ACCESS_GET] = false;
   5792   allowed_access_type[v8::ACCESS_HAS] = false;
   5793 
   5794   // Enable both ACCESS_HAS and ACCESS_SET.
   5795   allowed_access_type[v8::ACCESS_HAS] = true;
   5796   allowed_access_type[v8::ACCESS_SET] = true;
   5797 
   5798   ExpectUndefined("other[42]");
   5799   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
   5800   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   5801   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   5802 
   5803   allowed_access_type[v8::ACCESS_SET] = false;
   5804   allowed_access_type[v8::ACCESS_HAS] = false;
   5805 
   5806   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
   5807   allowed_access_type[v8::ACCESS_HAS] = true;
   5808   allowed_access_type[v8::ACCESS_GET] = true;
   5809   allowed_access_type[v8::ACCESS_SET] = true;
   5810 
   5811   ExpectString("other[42]", "el_getter");
   5812   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   5813   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   5814   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   5815 
   5816   allowed_access_type[v8::ACCESS_SET] = false;
   5817   allowed_access_type[v8::ACCESS_GET] = false;
   5818   allowed_access_type[v8::ACCESS_HAS] = false;
   5819 
   5820   v8::Handle<Value> value;
   5821 
   5822   // Access accessible property
   5823   value = CompileRun("other.accessible_prop = 3");
   5824   CHECK(value->IsNumber());
   5825   CHECK_EQ(3, value->Int32Value());
   5826   CHECK_EQ(3, g_echo_value);
   5827 
   5828   value = CompileRun("other.accessible_prop");
   5829   CHECK(value->IsNumber());
   5830   CHECK_EQ(3, value->Int32Value());
   5831 
   5832   value = CompileRun(
   5833       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   5834   CHECK(value->IsNumber());
   5835   CHECK_EQ(3, value->Int32Value());
   5836 
   5837   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   5838   CHECK(value->IsTrue());
   5839 
   5840   // Enumeration doesn't enumerate accessors from inaccessible objects in
   5841   // the prototype chain even if the accessors are in themselves accessible.
   5842   value =
   5843       CompileRun("(function(){var obj = {'__proto__':other};"
   5844                  "for (var p in obj)"
   5845                  "   if (p == 'accessible_prop' || p == 'blocked_prop') {"
   5846                  "     return false;"
   5847                  "   }"
   5848                  "return true;})()");
   5849   CHECK(value->IsTrue());
   5850 
   5851   context1->Exit();
   5852   context0->Exit();
   5853   context1.Dispose();
   5854   context0.Dispose();
   5855 }
   5856 
   5857 
   5858 TEST(AccessControlES5) {
   5859   v8::HandleScope handle_scope;
   5860   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   5861 
   5862   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   5863                                            IndexedAccessBlocker);
   5864 
   5865   // Add accessible accessor.
   5866   global_template->SetAccessor(
   5867       v8_str("accessible_prop"),
   5868       EchoGetter, EchoSetter,
   5869       v8::Handle<Value>(),
   5870       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   5871 
   5872 
   5873   // Add an accessor that is not accessible by cross-domain JS code.
   5874   global_template->SetAccessor(v8_str("blocked_prop"),
   5875                                UnreachableGetter, UnreachableSetter,
   5876                                v8::Handle<Value>(),
   5877                                v8::DEFAULT);
   5878 
   5879   // Create an environment
   5880   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
   5881   context0->Enter();
   5882 
   5883   v8::Handle<v8::Object> global0 = context0->Global();
   5884 
   5885   v8::Persistent<Context> context1 = Context::New();
   5886   context1->Enter();
   5887   v8::Handle<v8::Object> global1 = context1->Global();
   5888   global1->Set(v8_str("other"), global0);
   5889 
   5890   // Regression test for issue 1154.
   5891   ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
   5892 
   5893   ExpectUndefined("other.blocked_prop");
   5894 
   5895   // Regression test for issue 1027.
   5896   CompileRun("Object.defineProperty(\n"
   5897              "  other, 'blocked_prop', {configurable: false})");
   5898   ExpectUndefined("other.blocked_prop");
   5899   ExpectUndefined(
   5900       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
   5901 
   5902   // Regression test for issue 1171.
   5903   ExpectTrue("Object.isExtensible(other)");
   5904   CompileRun("Object.preventExtensions(other)");
   5905   ExpectTrue("Object.isExtensible(other)");
   5906 
   5907   // Object.seal and Object.freeze.
   5908   CompileRun("Object.freeze(other)");
   5909   ExpectTrue("Object.isExtensible(other)");
   5910 
   5911   CompileRun("Object.seal(other)");
   5912   ExpectTrue("Object.isExtensible(other)");
   5913 
   5914   // Regression test for issue 1250.
   5915   // Make sure that we can set the accessible accessors value using normal
   5916   // assignment.
   5917   CompileRun("other.accessible_prop = 42");
   5918   CHECK_EQ(42, g_echo_value);
   5919 
   5920   v8::Handle<Value> value;
   5921   // We follow Safari in ignoring assignments to host object accessors.
   5922   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
   5923   value = CompileRun("other.accessible_prop == 42");
   5924   CHECK(value->IsTrue());
   5925 }
   5926 
   5927 
   5928 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
   5929                                             Local<Value> name,
   5930                                             v8::AccessType type,
   5931                                             Local<Value> data) {
   5932   return false;
   5933 }
   5934 
   5935 
   5936 static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
   5937                                               uint32_t key,
   5938                                               v8::AccessType type,
   5939                                               Local<Value> data) {
   5940   return false;
   5941 }
   5942 
   5943 
   5944 THREADED_TEST(AccessControlGetOwnPropertyNames) {
   5945   v8::HandleScope handle_scope;
   5946   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
   5947 
   5948   obj_template->Set(v8_str("x"), v8::Integer::New(42));
   5949   obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
   5950                                         GetOwnPropertyNamesIndexedBlocker);
   5951 
   5952   // Create an environment
   5953   v8::Persistent<Context> context0 = Context::New(NULL, obj_template);
   5954   context0->Enter();
   5955 
   5956   v8::Handle<v8::Object> global0 = context0->Global();
   5957 
   5958   v8::HandleScope scope1;
   5959 
   5960   v8::Persistent<Context> context1 = Context::New();
   5961   context1->Enter();
   5962 
   5963   v8::Handle<v8::Object> global1 = context1->Global();
   5964   global1->Set(v8_str("other"), global0);
   5965   global1->Set(v8_str("object"), obj_template->NewInstance());
   5966 
   5967   v8::Handle<Value> value;
   5968 
   5969   // Attempt to get the property names of the other global object and
   5970   // of an object that requires access checks.  Accessing the other
   5971   // global object should be blocked by access checks on the global
   5972   // proxy object.  Accessing the object that requires access checks
   5973   // is blocked by the access checks on the object itself.
   5974   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
   5975   CHECK(value->IsTrue());
   5976 
   5977   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
   5978   CHECK(value->IsTrue());
   5979 
   5980   context1->Exit();
   5981   context0->Exit();
   5982   context1.Dispose();
   5983   context0.Dispose();
   5984 }
   5985 
   5986 
   5987 static v8::Handle<v8::Array> NamedPropertyEnumerator(const AccessorInfo& info) {
   5988   v8::Handle<v8::Array> result = v8::Array::New(1);
   5989   result->Set(0, v8_str("x"));
   5990   return result;
   5991 }
   5992 
   5993 
   5994 THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
   5995   v8::HandleScope handle_scope;
   5996   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
   5997 
   5998   obj_template->Set(v8_str("x"), v8::Integer::New(42));
   5999   obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
   6000                                         NamedPropertyEnumerator);
   6001 
   6002   LocalContext context;
   6003   v8::Handle<v8::Object> global = context->Global();
   6004   global->Set(v8_str("object"), obj_template->NewInstance());
   6005 
   6006   v8::Handle<Value> value =
   6007       CompileRun("Object.getOwnPropertyNames(object).join(',')");
   6008   CHECK_EQ(v8_str("x"), value);
   6009 }
   6010 
   6011 
   6012 static v8::Handle<Value> ConstTenGetter(Local<String> name,
   6013                                         const AccessorInfo& info) {
   6014   return v8_num(10);
   6015 }
   6016 
   6017 
   6018 THREADED_TEST(CrossDomainAccessors) {
   6019   v8::HandleScope handle_scope;
   6020 
   6021   v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
   6022 
   6023   v8::Handle<v8::ObjectTemplate> global_template =
   6024       func_template->InstanceTemplate();
   6025 
   6026   v8::Handle<v8::ObjectTemplate> proto_template =
   6027       func_template->PrototypeTemplate();
   6028 
   6029   // Add an accessor to proto that's accessible by cross-domain JS code.
   6030   proto_template->SetAccessor(v8_str("accessible"),
   6031                               ConstTenGetter, 0,
   6032                               v8::Handle<Value>(),
   6033                               v8::ALL_CAN_READ);
   6034 
   6035   // Add an accessor that is not accessible by cross-domain JS code.
   6036   global_template->SetAccessor(v8_str("unreachable"),
   6037                                UnreachableGetter, 0,
   6038                                v8::Handle<Value>(),
   6039                                v8::DEFAULT);
   6040 
   6041   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
   6042   context0->Enter();
   6043 
   6044   Local<v8::Object> global = context0->Global();
   6045   // Add a normal property that shadows 'accessible'
   6046   global->Set(v8_str("accessible"), v8_num(11));
   6047 
   6048   // Enter a new context.
   6049   v8::HandleScope scope1;
   6050   v8::Persistent<Context> context1 = Context::New();
   6051   context1->Enter();
   6052 
   6053   v8::Handle<v8::Object> global1 = context1->Global();
   6054   global1->Set(v8_str("other"), global);
   6055 
   6056   // Should return 10, instead of 11
   6057   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
   6058   CHECK(value->IsNumber());
   6059   CHECK_EQ(10, value->Int32Value());
   6060 
   6061   value = v8_compile("other.unreachable")->Run();
   6062   CHECK(value->IsUndefined());
   6063 
   6064   context1->Exit();
   6065   context0->Exit();
   6066   context1.Dispose();
   6067   context0.Dispose();
   6068 }
   6069 
   6070 
   6071 static int named_access_count = 0;
   6072 static int indexed_access_count = 0;
   6073 
   6074 static bool NamedAccessCounter(Local<v8::Object> global,
   6075                                Local<Value> name,
   6076                                v8::AccessType type,
   6077                                Local<Value> data) {
   6078   named_access_count++;
   6079   return true;
   6080 }
   6081 
   6082 
   6083 static bool IndexedAccessCounter(Local<v8::Object> global,
   6084                                  uint32_t key,
   6085                                  v8::AccessType type,
   6086                                  Local<Value> data) {
   6087   indexed_access_count++;
   6088   return true;
   6089 }
   6090 
   6091 
   6092 // This one is too easily disturbed by other tests.
   6093 TEST(AccessControlIC) {
   6094   named_access_count = 0;
   6095   indexed_access_count = 0;
   6096 
   6097   v8::HandleScope handle_scope;
   6098 
   6099   // Create an environment.
   6100   v8::Persistent<Context> context0 = Context::New();
   6101   context0->Enter();
   6102 
   6103   // Create an object that requires access-check functions to be
   6104   // called for cross-domain access.
   6105   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   6106   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   6107                                            IndexedAccessCounter);
   6108   Local<v8::Object> object = object_template->NewInstance();
   6109 
   6110   v8::HandleScope scope1;
   6111 
   6112   // Create another environment.
   6113   v8::Persistent<Context> context1 = Context::New();
   6114   context1->Enter();
   6115 
   6116   // Make easy access to the object from the other environment.
   6117   v8::Handle<v8::Object> global1 = context1->Global();
   6118   global1->Set(v8_str("obj"), object);
   6119 
   6120   v8::Handle<Value> value;
   6121 
   6122   // Check that the named access-control function is called every time.
   6123   CompileRun("function testProp(obj) {"
   6124              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   6125              "  for (var j = 0; j < 10; j++) obj.prop;"
   6126              "  return obj.prop"
   6127              "}");
   6128   value = CompileRun("testProp(obj)");
   6129   CHECK(value->IsNumber());
   6130   CHECK_EQ(1, value->Int32Value());
   6131   CHECK_EQ(21, named_access_count);
   6132 
   6133   // Check that the named access-control function is called every time.
   6134   CompileRun("var p = 'prop';"
   6135              "function testKeyed(obj) {"
   6136              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   6137              "  for (var j = 0; j < 10; j++) obj[p];"
   6138              "  return obj[p];"
   6139              "}");
   6140   // Use obj which requires access checks.  No inline caching is used
   6141   // in that case.
   6142   value = CompileRun("testKeyed(obj)");
   6143   CHECK(value->IsNumber());
   6144   CHECK_EQ(1, value->Int32Value());
   6145   CHECK_EQ(42, named_access_count);
   6146   // Force the inline caches into generic state and try again.
   6147   CompileRun("testKeyed({ a: 0 })");
   6148   CompileRun("testKeyed({ b: 0 })");
   6149   value = CompileRun("testKeyed(obj)");
   6150   CHECK(value->IsNumber());
   6151   CHECK_EQ(1, value->Int32Value());
   6152   CHECK_EQ(63, named_access_count);
   6153 
   6154   // Check that the indexed access-control function is called every time.
   6155   CompileRun("function testIndexed(obj) {"
   6156              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   6157              "  for (var j = 0; j < 10; j++) obj[0];"
   6158              "  return obj[0]"
   6159              "}");
   6160   value = CompileRun("testIndexed(obj)");
   6161   CHECK(value->IsNumber());
   6162   CHECK_EQ(1, value->Int32Value());
   6163   CHECK_EQ(21, indexed_access_count);
   6164   // Force the inline caches into generic state.
   6165   CompileRun("testIndexed(new Array(1))");
   6166   // Test that the indexed access check is called.
   6167   value = CompileRun("testIndexed(obj)");
   6168   CHECK(value->IsNumber());
   6169   CHECK_EQ(1, value->Int32Value());
   6170   CHECK_EQ(42, indexed_access_count);
   6171 
   6172   // Check that the named access check is called when invoking
   6173   // functions on an object that requires access checks.
   6174   CompileRun("obj.f = function() {}");
   6175   CompileRun("function testCallNormal(obj) {"
   6176              "  for (var i = 0; i < 10; i++) obj.f();"
   6177              "}");
   6178   CompileRun("testCallNormal(obj)");
   6179   CHECK_EQ(74, named_access_count);
   6180 
   6181   // Force obj into slow case.
   6182   value = CompileRun("delete obj.prop");
   6183   CHECK(value->BooleanValue());
   6184   // Force inline caches into dictionary probing mode.
   6185   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   6186   // Test that the named access check is called.
   6187   value = CompileRun("testProp(obj);");
   6188   CHECK(value->IsNumber());
   6189   CHECK_EQ(1, value->Int32Value());
   6190   CHECK_EQ(96, named_access_count);
   6191 
   6192   // Force the call inline cache into dictionary probing mode.
   6193   CompileRun("o.f = function() {}; testCallNormal(o)");
   6194   // Test that the named access check is still called for each
   6195   // invocation of the function.
   6196   value = CompileRun("testCallNormal(obj)");
   6197   CHECK_EQ(106, named_access_count);
   6198 
   6199   context1->Exit();
   6200   context0->Exit();
   6201   context1.Dispose();
   6202   context0.Dispose();
   6203 }
   6204 
   6205 
   6206 static bool NamedAccessFlatten(Local<v8::Object> global,
   6207                                Local<Value> name,
   6208                                v8::AccessType type,
   6209                                Local<Value> data) {
   6210   char buf[100];
   6211   int len;
   6212 
   6213   CHECK(name->IsString());
   6214 
   6215   memset(buf, 0x1, sizeof(buf));
   6216   len = name.As<String>()->WriteAscii(buf);
   6217   CHECK_EQ(4, len);
   6218 
   6219   uint16_t buf2[100];
   6220 
   6221   memset(buf, 0x1, sizeof(buf));
   6222   len = name.As<String>()->Write(buf2);
   6223   CHECK_EQ(4, len);
   6224 
   6225   return true;
   6226 }
   6227 
   6228 
   6229 static bool IndexedAccessFlatten(Local<v8::Object> global,
   6230                                  uint32_t key,
   6231                                  v8::AccessType type,
   6232                                  Local<Value> data) {
   6233   return true;
   6234 }
   6235 
   6236 
   6237 // Regression test.  In access checks, operations that may cause
   6238 // garbage collection are not allowed.  It used to be the case that
   6239 // using the Write operation on a string could cause a garbage
   6240 // collection due to flattening of the string.  This is no longer the
   6241 // case.
   6242 THREADED_TEST(AccessControlFlatten) {
   6243   named_access_count = 0;
   6244   indexed_access_count = 0;
   6245 
   6246   v8::HandleScope handle_scope;
   6247 
   6248   // Create an environment.
   6249   v8::Persistent<Context> context0 = Context::New();
   6250   context0->Enter();
   6251 
   6252   // Create an object that requires access-check functions to be
   6253   // called for cross-domain access.
   6254   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   6255   object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
   6256                                            IndexedAccessFlatten);
   6257   Local<v8::Object> object = object_template->NewInstance();
   6258 
   6259   v8::HandleScope scope1;
   6260 
   6261   // Create another environment.
   6262   v8::Persistent<Context> context1 = Context::New();
   6263   context1->Enter();
   6264 
   6265   // Make easy access to the object from the other environment.
   6266   v8::Handle<v8::Object> global1 = context1->Global();
   6267   global1->Set(v8_str("obj"), object);
   6268 
   6269   v8::Handle<Value> value;
   6270 
   6271   value = v8_compile("var p = 'as' + 'df';")->Run();
   6272   value = v8_compile("obj[p];")->Run();
   6273 
   6274   context1->Exit();
   6275   context0->Exit();
   6276   context1.Dispose();
   6277   context0.Dispose();
   6278 }
   6279 
   6280 
   6281 static v8::Handle<Value> AccessControlNamedGetter(
   6282     Local<String>, const AccessorInfo&) {
   6283   return v8::Integer::New(42);
   6284 }
   6285 
   6286 
   6287 static v8::Handle<Value> AccessControlNamedSetter(
   6288     Local<String>, Local<Value> value, const AccessorInfo&) {
   6289   return value;
   6290 }
   6291 
   6292 
   6293 static v8::Handle<Value> AccessControlIndexedGetter(
   6294       uint32_t index,
   6295       const AccessorInfo& info) {
   6296   return v8_num(42);
   6297 }
   6298 
   6299 
   6300 static v8::Handle<Value> AccessControlIndexedSetter(
   6301     uint32_t, Local<Value> value, const AccessorInfo&) {
   6302   return value;
   6303 }
   6304 
   6305 
   6306 THREADED_TEST(AccessControlInterceptorIC) {
   6307   named_access_count = 0;
   6308   indexed_access_count = 0;
   6309 
   6310   v8::HandleScope handle_scope;
   6311 
   6312   // Create an environment.
   6313   v8::Persistent<Context> context0 = Context::New();
   6314   context0->Enter();
   6315 
   6316   // Create an object that requires access-check functions to be
   6317   // called for cross-domain access.  The object also has interceptors
   6318   // interceptor.
   6319   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   6320   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   6321                                            IndexedAccessCounter);
   6322   object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
   6323                                            AccessControlNamedSetter);
   6324   object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
   6325                                              AccessControlIndexedSetter);
   6326   Local<v8::Object> object = object_template->NewInstance();
   6327 
   6328   v8::HandleScope scope1;
   6329 
   6330   // Create another environment.
   6331   v8::Persistent<Context> context1 = Context::New();
   6332   context1->Enter();
   6333 
   6334   // Make easy access to the object from the other environment.
   6335   v8::Handle<v8::Object> global1 = context1->Global();
   6336   global1->Set(v8_str("obj"), object);
   6337 
   6338   v8::Handle<Value> value;
   6339 
   6340   // Check that the named access-control function is called every time
   6341   // eventhough there is an interceptor on the object.
   6342   value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
   6343   value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
   6344                      "obj.x")->Run();
   6345   CHECK(value->IsNumber());
   6346   CHECK_EQ(42, value->Int32Value());
   6347   CHECK_EQ(21, named_access_count);
   6348 
   6349   value = v8_compile("var p = 'x';")->Run();
   6350   value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
   6351   value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
   6352                      "obj[p]")->Run();
   6353   CHECK(value->IsNumber());
   6354   CHECK_EQ(42, value->Int32Value());
   6355   CHECK_EQ(42, named_access_count);
   6356 
   6357   // Check that the indexed access-control function is called every
   6358   // time eventhough there is an interceptor on the object.
   6359   value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
   6360   value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
   6361                      "obj[0]")->Run();
   6362   CHECK(value->IsNumber());
   6363   CHECK_EQ(42, value->Int32Value());
   6364   CHECK_EQ(21, indexed_access_count);
   6365 
   6366   context1->Exit();
   6367   context0->Exit();
   6368   context1.Dispose();
   6369   context0.Dispose();
   6370 }
   6371 
   6372 
   6373 THREADED_TEST(Version) {
   6374   v8::V8::GetVersion();
   6375 }
   6376 
   6377 
   6378 static v8::Handle<Value> InstanceFunctionCallback(const v8::Arguments& args) {
   6379   ApiTestFuzzer::Fuzz();
   6380   return v8_num(12);
   6381 }
   6382 
   6383 
   6384 THREADED_TEST(InstanceProperties) {
   6385   v8::HandleScope handle_scope;
   6386   LocalContext context;
   6387 
   6388   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   6389   Local<ObjectTemplate> instance = t->InstanceTemplate();
   6390 
   6391   instance->Set(v8_str("x"), v8_num(42));
   6392   instance->Set(v8_str("f"),
   6393                 v8::FunctionTemplate::New(InstanceFunctionCallback));
   6394 
   6395   Local<Value> o = t->GetFunction()->NewInstance();
   6396 
   6397   context->Global()->Set(v8_str("i"), o);
   6398   Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
   6399   CHECK_EQ(42, value->Int32Value());
   6400 
   6401   value = Script::Compile(v8_str("i.f()"))->Run();
   6402   CHECK_EQ(12, value->Int32Value());
   6403 }
   6404 
   6405 
   6406 static v8::Handle<Value>
   6407 GlobalObjectInstancePropertiesGet(Local<String> key, const AccessorInfo&) {
   6408   ApiTestFuzzer::Fuzz();
   6409   return v8::Handle<Value>();
   6410 }
   6411 
   6412 
   6413 THREADED_TEST(GlobalObjectInstanceProperties) {
   6414   v8::HandleScope handle_scope;
   6415 
   6416   Local<Value> global_object;
   6417 
   6418   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   6419   t->InstanceTemplate()->SetNamedPropertyHandler(
   6420       GlobalObjectInstancePropertiesGet);
   6421   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   6422   instance_template->Set(v8_str("x"), v8_num(42));
   6423   instance_template->Set(v8_str("f"),
   6424                          v8::FunctionTemplate::New(InstanceFunctionCallback));
   6425 
   6426   // The script to check how Crankshaft compiles missing global function
   6427   // invocations.  function g is not defined and should throw on call.
   6428   const char* script =
   6429       "function wrapper(call) {"
   6430       "  var x = 0, y = 1;"
   6431       "  for (var i = 0; i < 1000; i++) {"
   6432       "    x += i * 100;"
   6433       "    y += i * 100;"
   6434       "  }"
   6435       "  if (call) g();"
   6436       "}"
   6437       "for (var i = 0; i < 17; i++) wrapper(false);"
   6438       "var thrown = 0;"
   6439       "try { wrapper(true); } catch (e) { thrown = 1; };"
   6440       "thrown";
   6441 
   6442   {
   6443     LocalContext env(NULL, instance_template);
   6444     // Hold on to the global object so it can be used again in another
   6445     // environment initialization.
   6446     global_object = env->Global();
   6447 
   6448     Local<Value> value = Script::Compile(v8_str("x"))->Run();
   6449     CHECK_EQ(42, value->Int32Value());
   6450     value = Script::Compile(v8_str("f()"))->Run();
   6451     CHECK_EQ(12, value->Int32Value());
   6452     value = Script::Compile(v8_str(script))->Run();
   6453     CHECK_EQ(1, value->Int32Value());
   6454   }
   6455 
   6456   {
   6457     // Create new environment reusing the global object.
   6458     LocalContext env(NULL, instance_template, global_object);
   6459     Local<Value> value = Script::Compile(v8_str("x"))->Run();
   6460     CHECK_EQ(42, value->Int32Value());
   6461     value = Script::Compile(v8_str("f()"))->Run();
   6462     CHECK_EQ(12, value->Int32Value());
   6463     value = Script::Compile(v8_str(script))->Run();
   6464     CHECK_EQ(1, value->Int32Value());
   6465   }
   6466 }
   6467 
   6468 
   6469 THREADED_TEST(CallKnownGlobalReceiver) {
   6470   v8::HandleScope handle_scope;
   6471 
   6472   Local<Value> global_object;
   6473 
   6474   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   6475   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   6476 
   6477   // The script to check that we leave global object not
   6478   // global object proxy on stack when we deoptimize from inside
   6479   // arguments evaluation.
   6480   // To provoke error we need to both force deoptimization
   6481   // from arguments evaluation and to force CallIC to take
   6482   // CallIC_Miss code path that can't cope with global proxy.
   6483   const char* script =
   6484       "function bar(x, y) { try { } finally { } }"
   6485       "function baz(x) { try { } finally { } }"
   6486       "function bom(x) { try { } finally { } }"
   6487       "function foo(x) { bar([x], bom(2)); }"
   6488       "for (var i = 0; i < 10000; i++) foo(1);"
   6489       "foo";
   6490 
   6491   Local<Value> foo;
   6492   {
   6493     LocalContext env(NULL, instance_template);
   6494     // Hold on to the global object so it can be used again in another
   6495     // environment initialization.
   6496     global_object = env->Global();
   6497     foo = Script::Compile(v8_str(script))->Run();
   6498   }
   6499 
   6500   {
   6501     // Create new environment reusing the global object.
   6502     LocalContext env(NULL, instance_template, global_object);
   6503     env->Global()->Set(v8_str("foo"), foo);
   6504     Local<Value> value = Script::Compile(v8_str("foo()"))->Run();
   6505   }
   6506 }
   6507 
   6508 
   6509 static v8::Handle<Value> ShadowFunctionCallback(const v8::Arguments& args) {
   6510   ApiTestFuzzer::Fuzz();
   6511   return v8_num(42);
   6512 }
   6513 
   6514 
   6515 static int shadow_y;
   6516 static int shadow_y_setter_call_count;
   6517 static int shadow_y_getter_call_count;
   6518 
   6519 
   6520 static void ShadowYSetter(Local<String>, Local<Value>, const AccessorInfo&) {
   6521   shadow_y_setter_call_count++;
   6522   shadow_y = 42;
   6523 }
   6524 
   6525 
   6526 static v8::Handle<Value> ShadowYGetter(Local<String> name,
   6527                                        const AccessorInfo& info) {
   6528   ApiTestFuzzer::Fuzz();
   6529   shadow_y_getter_call_count++;
   6530   return v8_num(shadow_y);
   6531 }
   6532 
   6533 
   6534 static v8::Handle<Value> ShadowIndexedGet(uint32_t index,
   6535                                           const AccessorInfo& info) {
   6536   return v8::Handle<Value>();
   6537 }
   6538 
   6539 
   6540 static v8::Handle<Value> ShadowNamedGet(Local<String> key,
   6541                                         const AccessorInfo&) {
   6542   return v8::Handle<Value>();
   6543 }
   6544 
   6545 
   6546 THREADED_TEST(ShadowObject) {
   6547   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   6548   v8::HandleScope handle_scope;
   6549 
   6550   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
   6551   LocalContext context(NULL, global_template);
   6552 
   6553   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   6554   t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
   6555   t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
   6556   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   6557   Local<ObjectTemplate> instance = t->InstanceTemplate();
   6558 
   6559   // Only allow calls of f on instances of t.
   6560   Local<v8::Signature> signature = v8::Signature::New(t);
   6561   proto->Set(v8_str("f"),
   6562              v8::FunctionTemplate::New(ShadowFunctionCallback,
   6563                                        Local<Value>(),
   6564                                        signature));
   6565   proto->Set(v8_str("x"), v8_num(12));
   6566 
   6567   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   6568 
   6569   Local<Value> o = t->GetFunction()->NewInstance();
   6570   context->Global()->Set(v8_str("__proto__"), o);
   6571 
   6572   Local<Value> value =
   6573       Script::Compile(v8_str("propertyIsEnumerable(0)"))->Run();
   6574   CHECK(value->IsBoolean());
   6575   CHECK(!value->BooleanValue());
   6576 
   6577   value = Script::Compile(v8_str("x"))->Run();
   6578   CHECK_EQ(12, value->Int32Value());
   6579 
   6580   value = Script::Compile(v8_str("f()"))->Run();
   6581   CHECK_EQ(42, value->Int32Value());
   6582 
   6583   Script::Compile(v8_str("y = 42"))->Run();
   6584   CHECK_EQ(1, shadow_y_setter_call_count);
   6585   value = Script::Compile(v8_str("y"))->Run();
   6586   CHECK_EQ(1, shadow_y_getter_call_count);
   6587   CHECK_EQ(42, value->Int32Value());
   6588 }
   6589 
   6590 
   6591 THREADED_TEST(HiddenPrototype) {
   6592   v8::HandleScope handle_scope;
   6593   LocalContext context;
   6594 
   6595   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
   6596   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   6597   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   6598   t1->SetHiddenPrototype(true);
   6599   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   6600   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   6601   t2->SetHiddenPrototype(true);
   6602   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   6603   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   6604   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   6605 
   6606   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   6607   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   6608   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   6609   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   6610 
   6611   // Setting the prototype on an object skips hidden prototypes.
   6612   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   6613   o0->Set(v8_str("__proto__"), o1);
   6614   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   6615   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   6616   o0->Set(v8_str("__proto__"), o2);
   6617   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   6618   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   6619   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   6620   o0->Set(v8_str("__proto__"), o3);
   6621   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   6622   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   6623   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   6624   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   6625 
   6626   // Getting the prototype of o0 should get the first visible one
   6627   // which is o3.  Therefore, z should not be defined on the prototype
   6628   // object.
   6629   Local<Value> proto = o0->Get(v8_str("__proto__"));
   6630   CHECK(proto->IsObject());
   6631   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
   6632 }
   6633 
   6634 
   6635 THREADED_TEST(SetPrototype) {
   6636   v8::HandleScope handle_scope;
   6637   LocalContext context;
   6638 
   6639   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
   6640   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   6641   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   6642   t1->SetHiddenPrototype(true);
   6643   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   6644   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   6645   t2->SetHiddenPrototype(true);
   6646   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   6647   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   6648   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   6649 
   6650   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   6651   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   6652   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   6653   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   6654 
   6655   // Setting the prototype on an object does not skip hidden prototypes.
   6656   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   6657   CHECK(o0->SetPrototype(o1));
   6658   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   6659   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   6660   CHECK(o1->SetPrototype(o2));
   6661   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   6662   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   6663   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   6664   CHECK(o2->SetPrototype(o3));
   6665   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   6666   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   6667   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   6668   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   6669 
   6670   // Getting the prototype of o0 should get the first visible one
   6671   // which is o3.  Therefore, z should not be defined on the prototype
   6672   // object.
   6673   Local<Value> proto = o0->Get(v8_str("__proto__"));
   6674   CHECK(proto->IsObject());
   6675   CHECK_EQ(proto.As<v8::Object>(), o3);
   6676 
   6677   // However, Object::GetPrototype ignores hidden prototype.
   6678   Local<Value> proto0 = o0->GetPrototype();
   6679   CHECK(proto0->IsObject());
   6680   CHECK_EQ(proto0.As<v8::Object>(), o1);
   6681 
   6682   Local<Value> proto1 = o1->GetPrototype();
   6683   CHECK(proto1->IsObject());
   6684   CHECK_EQ(proto1.As<v8::Object>(), o2);
   6685 
   6686   Local<Value> proto2 = o2->GetPrototype();
   6687   CHECK(proto2->IsObject());
   6688   CHECK_EQ(proto2.As<v8::Object>(), o3);
   6689 }
   6690 
   6691 
   6692 THREADED_TEST(SetPrototypeThrows) {
   6693   v8::HandleScope handle_scope;
   6694   LocalContext context;
   6695 
   6696   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   6697 
   6698   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
   6699   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
   6700 
   6701   CHECK(o0->SetPrototype(o1));
   6702   // If setting the prototype leads to the cycle, SetPrototype should
   6703   // return false and keep VM in sane state.
   6704   v8::TryCatch try_catch;
   6705   CHECK(!o1->SetPrototype(o0));
   6706   CHECK(!try_catch.HasCaught());
   6707   ASSERT(!i::Isolate::Current()->has_pending_exception());
   6708 
   6709   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
   6710 }
   6711 
   6712 
   6713 THREADED_TEST(GetterSetterExceptions) {
   6714   v8::HandleScope handle_scope;
   6715   LocalContext context;
   6716   CompileRun(
   6717     "function Foo() { };"
   6718     "function Throw() { throw 5; };"
   6719     "var x = { };"
   6720     "x.__defineSetter__('set', Throw);"
   6721     "x.__defineGetter__('get', Throw);");
   6722   Local<v8::Object> x =
   6723       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
   6724   v8::TryCatch try_catch;
   6725   x->Set(v8_str("set"), v8::Integer::New(8));
   6726   x->Get(v8_str("get"));
   6727   x->Set(v8_str("set"), v8::Integer::New(8));
   6728   x->Get(v8_str("get"));
   6729   x->Set(v8_str("set"), v8::Integer::New(8));
   6730   x->Get(v8_str("get"));
   6731   x->Set(v8_str("set"), v8::Integer::New(8));
   6732   x->Get(v8_str("get"));
   6733 }
   6734 
   6735 
   6736 THREADED_TEST(Constructor) {
   6737   v8::HandleScope handle_scope;
   6738   LocalContext context;
   6739   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   6740   templ->SetClassName(v8_str("Fun"));
   6741   Local<Function> cons = templ->GetFunction();
   6742   context->Global()->Set(v8_str("Fun"), cons);
   6743   Local<v8::Object> inst = cons->NewInstance();
   6744   i::Handle<i::JSObject> obj = v8::Utils::OpenHandle(*inst);
   6745   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   6746   CHECK(value->BooleanValue());
   6747 }
   6748 
   6749 THREADED_TEST(FunctionDescriptorException) {
   6750   v8::HandleScope handle_scope;
   6751   LocalContext context;
   6752   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   6753   templ->SetClassName(v8_str("Fun"));
   6754   Local<Function> cons = templ->GetFunction();
   6755   context->Global()->Set(v8_str("Fun"), cons);
   6756   Local<Value> value = CompileRun(
   6757     "function test() {"
   6758     "  try {"
   6759     "    (new Fun()).blah()"
   6760     "  } catch (e) {"
   6761     "    var str = String(e);"
   6762     "    if (str.indexOf('TypeError') == -1) return 1;"
   6763     "    if (str.indexOf('[object Fun]') != -1) return 2;"
   6764     "    if (str.indexOf('#<Fun>') == -1) return 3;"
   6765     "    return 0;"
   6766     "  }"
   6767     "  return 4;"
   6768     "}"
   6769     "test();");
   6770   CHECK_EQ(0, value->Int32Value());
   6771 }
   6772 
   6773 
   6774 THREADED_TEST(EvalAliasedDynamic) {
   6775   v8::HandleScope scope;
   6776   LocalContext current;
   6777 
   6778   // Tests where aliased eval can only be resolved dynamically.
   6779   Local<Script> script =
   6780       Script::Compile(v8_str("function f(x) { "
   6781                              "  var foo = 2;"
   6782                              "  with (x) { return eval('foo'); }"
   6783                              "}"
   6784                              "foo = 0;"
   6785                              "result1 = f(new Object());"
   6786                              "result2 = f(this);"
   6787                              "var x = new Object();"
   6788                              "x.eval = function(x) { return 1; };"
   6789                              "result3 = f(x);"));
   6790   script->Run();
   6791   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
   6792   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
   6793   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
   6794 
   6795   v8::TryCatch try_catch;
   6796   script =
   6797     Script::Compile(v8_str("function f(x) { "
   6798                            "  var bar = 2;"
   6799                            "  with (x) { return eval('bar'); }"
   6800                            "}"
   6801                            "f(this)"));
   6802   script->Run();
   6803   CHECK(try_catch.HasCaught());
   6804   try_catch.Reset();
   6805 }
   6806 
   6807 
   6808 THREADED_TEST(CrossEval) {
   6809   v8::HandleScope scope;
   6810   LocalContext other;
   6811   LocalContext current;
   6812 
   6813   Local<String> token = v8_str("<security token>");
   6814   other->SetSecurityToken(token);
   6815   current->SetSecurityToken(token);
   6816 
   6817   // Setup reference from current to other.
   6818   current->Global()->Set(v8_str("other"), other->Global());
   6819 
   6820   // Check that new variables are introduced in other context.
   6821   Local<Script> script =
   6822       Script::Compile(v8_str("other.eval('var foo = 1234')"));
   6823   script->Run();
   6824   Local<Value> foo = other->Global()->Get(v8_str("foo"));
   6825   CHECK_EQ(1234, foo->Int32Value());
   6826   CHECK(!current->Global()->Has(v8_str("foo")));
   6827 
   6828   // Check that writing to non-existing properties introduces them in
   6829   // the other context.
   6830   script =
   6831       Script::Compile(v8_str("other.eval('na = 1234')"));
   6832   script->Run();
   6833   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
   6834   CHECK(!current->Global()->Has(v8_str("na")));
   6835 
   6836   // Check that global variables in current context are not visible in other
   6837   // context.
   6838   v8::TryCatch try_catch;
   6839   script =
   6840       Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
   6841   Local<Value> result = script->Run();
   6842   CHECK(try_catch.HasCaught());
   6843   try_catch.Reset();
   6844 
   6845   // Check that local variables in current context are not visible in other
   6846   // context.
   6847   script =
   6848       Script::Compile(v8_str("(function() { "
   6849                              "  var baz = 87;"
   6850                              "  return other.eval('baz');"
   6851                              "})();"));
   6852   result = script->Run();
   6853   CHECK(try_catch.HasCaught());
   6854   try_catch.Reset();
   6855 
   6856   // Check that global variables in the other environment are visible
   6857   // when evaluting code.
   6858   other->Global()->Set(v8_str("bis"), v8_num(1234));
   6859   script = Script::Compile(v8_str("other.eval('bis')"));
   6860   CHECK_EQ(1234, script->Run()->Int32Value());
   6861   CHECK(!try_catch.HasCaught());
   6862 
   6863   // Check that the 'this' pointer points to the global object evaluating
   6864   // code.
   6865   other->Global()->Set(v8_str("t"), other->Global());
   6866   script = Script::Compile(v8_str("other.eval('this == t')"));
   6867   result = script->Run();
   6868   CHECK(result->IsTrue());
   6869   CHECK(!try_catch.HasCaught());
   6870 
   6871   // Check that variables introduced in with-statement are not visible in
   6872   // other context.
   6873   script =
   6874       Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
   6875   result = script->Run();
   6876   CHECK(try_catch.HasCaught());
   6877   try_catch.Reset();
   6878 
   6879   // Check that you cannot use 'eval.call' with another object than the
   6880   // current global object.
   6881   script =
   6882       Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
   6883   result = script->Run();
   6884   CHECK(try_catch.HasCaught());
   6885 }
   6886 
   6887 
   6888 // Test that calling eval in a context which has been detached from
   6889 // its global throws an exception.  This behavior is consistent with
   6890 // other JavaScript implementations.
   6891 THREADED_TEST(EvalInDetachedGlobal) {
   6892   v8::HandleScope scope;
   6893 
   6894   v8::Persistent<Context> context0 = Context::New();
   6895   v8::Persistent<Context> context1 = Context::New();
   6896 
   6897   // Setup function in context0 that uses eval from context0.
   6898   context0->Enter();
   6899   v8::Handle<v8::Value> fun =
   6900       CompileRun("var x = 42;"
   6901                  "(function() {"
   6902                  "  var e = eval;"
   6903                  "  return function(s) { return e(s); }"
   6904                  "})()");
   6905   context0->Exit();
   6906 
   6907   // Put the function into context1 and call it before and after
   6908   // detaching the global.  Before detaching, the call succeeds and
   6909   // after detaching and exception is thrown.
   6910   context1->Enter();
   6911   context1->Global()->Set(v8_str("fun"), fun);
   6912   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
   6913   CHECK_EQ(42, x_value->Int32Value());
   6914   context0->DetachGlobal();
   6915   v8::TryCatch catcher;
   6916   x_value = CompileRun("fun('x')");
   6917   CHECK(x_value.IsEmpty());
   6918   CHECK(catcher.HasCaught());
   6919   context1->Exit();
   6920 
   6921   context1.Dispose();
   6922   context0.Dispose();
   6923 }
   6924 
   6925 
   6926 THREADED_TEST(CrossLazyLoad) {
   6927   v8::HandleScope scope;
   6928   LocalContext other;
   6929   LocalContext current;
   6930 
   6931   Local<String> token = v8_str("<security token>");
   6932   other->SetSecurityToken(token);
   6933   current->SetSecurityToken(token);
   6934 
   6935   // Setup reference from current to other.
   6936   current->Global()->Set(v8_str("other"), other->Global());
   6937 
   6938   // Trigger lazy loading in other context.
   6939   Local<Script> script =
   6940       Script::Compile(v8_str("other.eval('new Date(42)')"));
   6941   Local<Value> value = script->Run();
   6942   CHECK_EQ(42.0, value->NumberValue());
   6943 }
   6944 
   6945 
   6946 static v8::Handle<Value> call_as_function(const v8::Arguments& args) {
   6947   ApiTestFuzzer::Fuzz();
   6948   if (args.IsConstructCall()) {
   6949     if (args[0]->IsInt32()) {
   6950        return v8_num(-args[0]->Int32Value());
   6951     }
   6952   }
   6953 
   6954   return args[0];
   6955 }
   6956 
   6957 
   6958 // Test that a call handler can be set for objects which will allow
   6959 // non-function objects created through the API to be called as
   6960 // functions.
   6961 THREADED_TEST(CallAsFunction) {
   6962   v8::HandleScope scope;
   6963   LocalContext context;
   6964 
   6965   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   6966   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   6967   instance_template->SetCallAsFunctionHandler(call_as_function);
   6968   Local<v8::Object> instance = t->GetFunction()->NewInstance();
   6969   context->Global()->Set(v8_str("obj"), instance);
   6970   v8::TryCatch try_catch;
   6971   Local<Value> value;
   6972   CHECK(!try_catch.HasCaught());
   6973 
   6974   value = CompileRun("obj(42)");
   6975   CHECK(!try_catch.HasCaught());
   6976   CHECK_EQ(42, value->Int32Value());
   6977 
   6978   value = CompileRun("(function(o){return o(49)})(obj)");
   6979   CHECK(!try_catch.HasCaught());
   6980   CHECK_EQ(49, value->Int32Value());
   6981 
   6982   // test special case of call as function
   6983   value = CompileRun("[obj]['0'](45)");
   6984   CHECK(!try_catch.HasCaught());
   6985   CHECK_EQ(45, value->Int32Value());
   6986 
   6987   value = CompileRun("obj.call = Function.prototype.call;"
   6988                      "obj.call(null, 87)");
   6989   CHECK(!try_catch.HasCaught());
   6990   CHECK_EQ(87, value->Int32Value());
   6991 
   6992   // Regression tests for bug #1116356: Calling call through call/apply
   6993   // must work for non-function receivers.
   6994   const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   6995   value = CompileRun(apply_99);
   6996   CHECK(!try_catch.HasCaught());
   6997   CHECK_EQ(99, value->Int32Value());
   6998 
   6999   const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   7000   value = CompileRun(call_17);
   7001   CHECK(!try_catch.HasCaught());
   7002   CHECK_EQ(17, value->Int32Value());
   7003 
   7004   // Check that the call-as-function handler can be called through
   7005   // new.
   7006   value = CompileRun("new obj(43)");
   7007   CHECK(!try_catch.HasCaught());
   7008   CHECK_EQ(-43, value->Int32Value());
   7009 }
   7010 
   7011 
   7012 static int CountHandles() {
   7013   return v8::HandleScope::NumberOfHandles();
   7014 }
   7015 
   7016 
   7017 static int Recurse(int depth, int iterations) {
   7018   v8::HandleScope scope;
   7019   if (depth == 0) return CountHandles();
   7020   for (int i = 0; i < iterations; i++) {
   7021     Local<v8::Number> n = v8::Integer::New(42);
   7022   }
   7023   return Recurse(depth - 1, iterations);
   7024 }
   7025 
   7026 
   7027 THREADED_TEST(HandleIteration) {
   7028   static const int kIterations = 500;
   7029   static const int kNesting = 200;
   7030   CHECK_EQ(0, CountHandles());
   7031   {
   7032     v8::HandleScope scope1;
   7033     CHECK_EQ(0, CountHandles());
   7034     for (int i = 0; i < kIterations; i++) {
   7035       Local<v8::Number> n = v8::Integer::New(42);
   7036       CHECK_EQ(i + 1, CountHandles());
   7037     }
   7038 
   7039     CHECK_EQ(kIterations, CountHandles());
   7040     {
   7041       v8::HandleScope scope2;
   7042       for (int j = 0; j < kIterations; j++) {
   7043         Local<v8::Number> n = v8::Integer::New(42);
   7044         CHECK_EQ(j + 1 + kIterations, CountHandles());
   7045       }
   7046     }
   7047     CHECK_EQ(kIterations, CountHandles());
   7048   }
   7049   CHECK_EQ(0, CountHandles());
   7050   CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
   7051 }
   7052 
   7053 
   7054 static v8::Handle<Value> InterceptorHasOwnPropertyGetter(
   7055     Local<String> name,
   7056     const AccessorInfo& info) {
   7057   ApiTestFuzzer::Fuzz();
   7058   return v8::Handle<Value>();
   7059 }
   7060 
   7061 
   7062 THREADED_TEST(InterceptorHasOwnProperty) {
   7063   v8::HandleScope scope;
   7064   LocalContext context;
   7065   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   7066   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   7067   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
   7068   Local<Function> function = fun_templ->GetFunction();
   7069   context->Global()->Set(v8_str("constructor"), function);
   7070   v8::Handle<Value> value = CompileRun(
   7071       "var o = new constructor();"
   7072       "o.hasOwnProperty('ostehaps');");
   7073   CHECK_EQ(false, value->BooleanValue());
   7074   value = CompileRun(
   7075       "o.ostehaps = 42;"
   7076       "o.hasOwnProperty('ostehaps');");
   7077   CHECK_EQ(true, value->BooleanValue());
   7078   value = CompileRun(
   7079       "var p = new constructor();"
   7080       "p.hasOwnProperty('ostehaps');");
   7081   CHECK_EQ(false, value->BooleanValue());
   7082 }
   7083 
   7084 
   7085 static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC(
   7086     Local<String> name,
   7087     const AccessorInfo& info) {
   7088   ApiTestFuzzer::Fuzz();
   7089   HEAP->CollectAllGarbage(false);
   7090   return v8::Handle<Value>();
   7091 }
   7092 
   7093 
   7094 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
   7095   v8::HandleScope scope;
   7096   LocalContext context;
   7097   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   7098   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   7099   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
   7100   Local<Function> function = fun_templ->GetFunction();
   7101   context->Global()->Set(v8_str("constructor"), function);
   7102   // Let's first make some stuff so we can be sure to get a good GC.
   7103   CompileRun(
   7104       "function makestr(size) {"
   7105       "  switch (size) {"
   7106       "    case 1: return 'f';"
   7107       "    case 2: return 'fo';"
   7108       "    case 3: return 'foo';"
   7109       "  }"
   7110       "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
   7111       "}"
   7112       "var x = makestr(12345);"
   7113       "x = makestr(31415);"
   7114       "x = makestr(23456);");
   7115   v8::Handle<Value> value = CompileRun(
   7116       "var o = new constructor();"
   7117       "o.__proto__ = new String(x);"
   7118       "o.hasOwnProperty('ostehaps');");
   7119   CHECK_EQ(false, value->BooleanValue());
   7120 }
   7121 
   7122 
   7123 typedef v8::Handle<Value> (*NamedPropertyGetter)(Local<String> property,
   7124                                                  const AccessorInfo& info);
   7125 
   7126 
   7127 static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
   7128                                    const char* source,
   7129                                    int expected) {
   7130   v8::HandleScope scope;
   7131   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7132   templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
   7133   LocalContext context;
   7134   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7135   v8::Handle<Value> value = CompileRun(source);
   7136   CHECK_EQ(expected, value->Int32Value());
   7137 }
   7138 
   7139 
   7140 static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
   7141                                                  const AccessorInfo& info) {
   7142   ApiTestFuzzer::Fuzz();
   7143   CHECK_EQ(v8_str("data"), info.Data());
   7144   CHECK_EQ(v8_str("x"), name);
   7145   return v8::Integer::New(42);
   7146 }
   7147 
   7148 
   7149 // This test should hit the load IC for the interceptor case.
   7150 THREADED_TEST(InterceptorLoadIC) {
   7151   CheckInterceptorLoadIC(InterceptorLoadICGetter,
   7152     "var result = 0;"
   7153     "for (var i = 0; i < 1000; i++) {"
   7154     "  result = o.x;"
   7155     "}",
   7156     42);
   7157 }
   7158 
   7159 
   7160 // Below go several tests which verify that JITing for various
   7161 // configurations of interceptor and explicit fields works fine
   7162 // (those cases are special cased to get better performance).
   7163 
   7164 static v8::Handle<Value> InterceptorLoadXICGetter(Local<String> name,
   7165                                                  const AccessorInfo& info) {
   7166   ApiTestFuzzer::Fuzz();
   7167   return v8_str("x")->Equals(name)
   7168       ? v8::Integer::New(42) : v8::Handle<v8::Value>();
   7169 }
   7170 
   7171 
   7172 THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
   7173   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   7174     "var result = 0;"
   7175     "o.y = 239;"
   7176     "for (var i = 0; i < 1000; i++) {"
   7177     "  result = o.y;"
   7178     "}",
   7179     239);
   7180 }
   7181 
   7182 
   7183 THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
   7184   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   7185     "var result = 0;"
   7186     "o.__proto__ = { 'y': 239 };"
   7187     "for (var i = 0; i < 1000; i++) {"
   7188     "  result = o.y + o.x;"
   7189     "}",
   7190     239 + 42);
   7191 }
   7192 
   7193 
   7194 THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
   7195   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   7196     "var result = 0;"
   7197     "o.__proto__.y = 239;"
   7198     "for (var i = 0; i < 1000; i++) {"
   7199     "  result = o.y + o.x;"
   7200     "}",
   7201     239 + 42);
   7202 }
   7203 
   7204 
   7205 THREADED_TEST(InterceptorLoadICUndefined) {
   7206   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   7207     "var result = 0;"
   7208     "for (var i = 0; i < 1000; i++) {"
   7209     "  result = (o.y == undefined) ? 239 : 42;"
   7210     "}",
   7211     239);
   7212 }
   7213 
   7214 
   7215 THREADED_TEST(InterceptorLoadICWithOverride) {
   7216   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   7217     "fst = new Object();  fst.__proto__ = o;"
   7218     "snd = new Object();  snd.__proto__ = fst;"
   7219     "var result1 = 0;"
   7220     "for (var i = 0; i < 1000;  i++) {"
   7221     "  result1 = snd.x;"
   7222     "}"
   7223     "fst.x = 239;"
   7224     "var result = 0;"
   7225     "for (var i = 0; i < 1000; i++) {"
   7226     "  result = snd.x;"
   7227     "}"
   7228     "result + result1",
   7229     239 + 42);
   7230 }
   7231 
   7232 
   7233 // Test the case when we stored field into
   7234 // a stub, but interceptor produced value on its own.
   7235 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
   7236   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   7237     "proto = new Object();"
   7238     "o.__proto__ = proto;"
   7239     "proto.x = 239;"
   7240     "for (var i = 0; i < 1000; i++) {"
   7241     "  o.x;"
   7242     // Now it should be ICed and keep a reference to x defined on proto
   7243     "}"
   7244     "var result = 0;"
   7245     "for (var i = 0; i < 1000; i++) {"
   7246     "  result += o.x;"
   7247     "}"
   7248     "result;",
   7249     42 * 1000);
   7250 }
   7251 
   7252 
   7253 // Test the case when we stored field into
   7254 // a stub, but it got invalidated later on.
   7255 THREADED_TEST(InterceptorLoadICInvalidatedField) {
   7256   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   7257     "proto1 = new Object();"
   7258     "proto2 = new Object();"
   7259     "o.__proto__ = proto1;"
   7260     "proto1.__proto__ = proto2;"
   7261     "proto2.y = 239;"
   7262     "for (var i = 0; i < 1000; i++) {"
   7263     "  o.y;"
   7264     // Now it should be ICed and keep a reference to y defined on proto2
   7265     "}"
   7266     "proto1.y = 42;"
   7267     "var result = 0;"
   7268     "for (var i = 0; i < 1000; i++) {"
   7269     "  result += o.y;"
   7270     "}"
   7271     "result;",
   7272     42 * 1000);
   7273 }
   7274 
   7275 
   7276 static int interceptor_load_not_handled_calls = 0;
   7277 static v8::Handle<Value> InterceptorLoadNotHandled(Local<String> name,
   7278                                                    const AccessorInfo& info) {
   7279   ++interceptor_load_not_handled_calls;
   7280   return v8::Handle<v8::Value>();
   7281 }
   7282 
   7283 
   7284 // Test how post-interceptor lookups are done in the non-cacheable
   7285 // case: the interceptor should not be invoked during this lookup.
   7286 THREADED_TEST(InterceptorLoadICPostInterceptor) {
   7287   interceptor_load_not_handled_calls = 0;
   7288   CheckInterceptorLoadIC(InterceptorLoadNotHandled,
   7289     "receiver = new Object();"
   7290     "receiver.__proto__ = o;"
   7291     "proto = new Object();"
   7292     "/* Make proto a slow-case object. */"
   7293     "for (var i = 0; i < 1000; i++) {"
   7294     "  proto[\"xxxxxxxx\" + i] = [];"
   7295     "}"
   7296     "proto.x = 17;"
   7297     "o.__proto__ = proto;"
   7298     "var result = 0;"
   7299     "for (var i = 0; i < 1000; i++) {"
   7300     "  result += receiver.x;"
   7301     "}"
   7302     "result;",
   7303     17 * 1000);
   7304   CHECK_EQ(1000, interceptor_load_not_handled_calls);
   7305 }
   7306 
   7307 
   7308 // Test the case when we stored field into
   7309 // a stub, but it got invalidated later on due to override on
   7310 // global object which is between interceptor and fields' holders.
   7311 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
   7312   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   7313     "o.__proto__ = this;"  // set a global to be a proto of o.
   7314     "this.__proto__.y = 239;"
   7315     "for (var i = 0; i < 10; i++) {"
   7316     "  if (o.y != 239) throw 'oops: ' + o.y;"
   7317     // Now it should be ICed and keep a reference to y defined on field_holder.
   7318     "}"
   7319     "this.y = 42;"  // Assign on a global.
   7320     "var result = 0;"
   7321     "for (var i = 0; i < 10; i++) {"
   7322     "  result += o.y;"
   7323     "}"
   7324     "result;",
   7325     42 * 10);
   7326 }
   7327 
   7328 
   7329 static void SetOnThis(Local<String> name,
   7330                       Local<Value> value,
   7331                       const AccessorInfo& info) {
   7332   info.This()->ForceSet(name, value);
   7333 }
   7334 
   7335 
   7336 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
   7337   v8::HandleScope scope;
   7338   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7339   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   7340   templ->SetAccessor(v8_str("y"), Return239);
   7341   LocalContext context;
   7342   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7343 
   7344   // Check the case when receiver and interceptor's holder
   7345   // are the same objects.
   7346   v8::Handle<Value> value = CompileRun(
   7347       "var result = 0;"
   7348       "for (var i = 0; i < 7; i++) {"
   7349       "  result = o.y;"
   7350       "}");
   7351   CHECK_EQ(239, value->Int32Value());
   7352 
   7353   // Check the case when interceptor's holder is in proto chain
   7354   // of receiver.
   7355   value = CompileRun(
   7356       "r = { __proto__: o };"
   7357       "var result = 0;"
   7358       "for (var i = 0; i < 7; i++) {"
   7359       "  result = r.y;"
   7360       "}");
   7361   CHECK_EQ(239, value->Int32Value());
   7362 }
   7363 
   7364 
   7365 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
   7366   v8::HandleScope scope;
   7367   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   7368   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   7369   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   7370   templ_p->SetAccessor(v8_str("y"), Return239);
   7371 
   7372   LocalContext context;
   7373   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   7374   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   7375 
   7376   // Check the case when receiver and interceptor's holder
   7377   // are the same objects.
   7378   v8::Handle<Value> value = CompileRun(
   7379       "o.__proto__ = p;"
   7380       "var result = 0;"
   7381       "for (var i = 0; i < 7; i++) {"
   7382       "  result = o.x + o.y;"
   7383       "}");
   7384   CHECK_EQ(239 + 42, value->Int32Value());
   7385 
   7386   // Check the case when interceptor's holder is in proto chain
   7387   // of receiver.
   7388   value = CompileRun(
   7389       "r = { __proto__: o };"
   7390       "var result = 0;"
   7391       "for (var i = 0; i < 7; i++) {"
   7392       "  result = r.x + r.y;"
   7393       "}");
   7394   CHECK_EQ(239 + 42, value->Int32Value());
   7395 }
   7396 
   7397 
   7398 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
   7399   v8::HandleScope scope;
   7400   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7401   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   7402   templ->SetAccessor(v8_str("y"), Return239);
   7403 
   7404   LocalContext context;
   7405   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7406 
   7407   v8::Handle<Value> value = CompileRun(
   7408     "fst = new Object();  fst.__proto__ = o;"
   7409     "snd = new Object();  snd.__proto__ = fst;"
   7410     "var result1 = 0;"
   7411     "for (var i = 0; i < 7;  i++) {"
   7412     "  result1 = snd.x;"
   7413     "}"
   7414     "fst.x = 239;"
   7415     "var result = 0;"
   7416     "for (var i = 0; i < 7; i++) {"
   7417     "  result = snd.x;"
   7418     "}"
   7419     "result + result1");
   7420   CHECK_EQ(239 + 42, value->Int32Value());
   7421 }
   7422 
   7423 
   7424 // Test the case when we stored callback into
   7425 // a stub, but interceptor produced value on its own.
   7426 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
   7427   v8::HandleScope scope;
   7428   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   7429   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   7430   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   7431   templ_p->SetAccessor(v8_str("y"), Return239);
   7432 
   7433   LocalContext context;
   7434   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   7435   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   7436 
   7437   v8::Handle<Value> value = CompileRun(
   7438     "o.__proto__ = p;"
   7439     "for (var i = 0; i < 7; i++) {"
   7440     "  o.x;"
   7441     // Now it should be ICed and keep a reference to x defined on p
   7442     "}"
   7443     "var result = 0;"
   7444     "for (var i = 0; i < 7; i++) {"
   7445     "  result += o.x;"
   7446     "}"
   7447     "result");
   7448   CHECK_EQ(42 * 7, value->Int32Value());
   7449 }
   7450 
   7451 
   7452 // Test the case when we stored callback into
   7453 // a stub, but it got invalidated later on.
   7454 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
   7455   v8::HandleScope scope;
   7456   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   7457   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   7458   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   7459   templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
   7460 
   7461   LocalContext context;
   7462   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   7463   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   7464 
   7465   v8::Handle<Value> value = CompileRun(
   7466     "inbetween = new Object();"
   7467     "o.__proto__ = inbetween;"
   7468     "inbetween.__proto__ = p;"
   7469     "for (var i = 0; i < 10; i++) {"
   7470     "  o.y;"
   7471     // Now it should be ICed and keep a reference to y defined on p
   7472     "}"
   7473     "inbetween.y = 42;"
   7474     "var result = 0;"
   7475     "for (var i = 0; i < 10; i++) {"
   7476     "  result += o.y;"
   7477     "}"
   7478     "result");
   7479   CHECK_EQ(42 * 10, value->Int32Value());
   7480 }
   7481 
   7482 
   7483 // Test the case when we stored callback into
   7484 // a stub, but it got invalidated later on due to override on
   7485 // global object which is between interceptor and callbacks' holders.
   7486 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
   7487   v8::HandleScope scope;
   7488   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   7489   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   7490   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   7491   templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
   7492 
   7493   LocalContext context;
   7494   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   7495   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   7496 
   7497   v8::Handle<Value> value = CompileRun(
   7498     "o.__proto__ = this;"
   7499     "this.__proto__ = p;"
   7500     "for (var i = 0; i < 10; i++) {"
   7501     "  if (o.y != 239) throw 'oops: ' + o.y;"
   7502     // Now it should be ICed and keep a reference to y defined on p
   7503     "}"
   7504     "this.y = 42;"
   7505     "var result = 0;"
   7506     "for (var i = 0; i < 10; i++) {"
   7507     "  result += o.y;"
   7508     "}"
   7509     "result");
   7510   CHECK_EQ(42 * 10, value->Int32Value());
   7511 }
   7512 
   7513 
   7514 static v8::Handle<Value> InterceptorLoadICGetter0(Local<String> name,
   7515                                                   const AccessorInfo& info) {
   7516   ApiTestFuzzer::Fuzz();
   7517   CHECK(v8_str("x")->Equals(name));
   7518   return v8::Integer::New(0);
   7519 }
   7520 
   7521 
   7522 THREADED_TEST(InterceptorReturningZero) {
   7523   CheckInterceptorLoadIC(InterceptorLoadICGetter0,
   7524      "o.x == undefined ? 1 : 0",
   7525      0);
   7526 }
   7527 
   7528 
   7529 static v8::Handle<Value> InterceptorStoreICSetter(
   7530     Local<String> key, Local<Value> value, const AccessorInfo&) {
   7531   CHECK(v8_str("x")->Equals(key));
   7532   CHECK_EQ(42, value->Int32Value());
   7533   return value;
   7534 }
   7535 
   7536 
   7537 // This test should hit the store IC for the interceptor case.
   7538 THREADED_TEST(InterceptorStoreIC) {
   7539   v8::HandleScope scope;
   7540   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7541   templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
   7542                                  InterceptorStoreICSetter,
   7543                                  0, 0, 0, v8_str("data"));
   7544   LocalContext context;
   7545   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7546   v8::Handle<Value> value = CompileRun(
   7547     "for (var i = 0; i < 1000; i++) {"
   7548     "  o.x = 42;"
   7549     "}");
   7550 }
   7551 
   7552 
   7553 THREADED_TEST(InterceptorStoreICWithNoSetter) {
   7554   v8::HandleScope scope;
   7555   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7556   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   7557   LocalContext context;
   7558   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7559   v8::Handle<Value> value = CompileRun(
   7560     "for (var i = 0; i < 1000; i++) {"
   7561     "  o.y = 239;"
   7562     "}"
   7563     "42 + o.y");
   7564   CHECK_EQ(239 + 42, value->Int32Value());
   7565 }
   7566 
   7567 
   7568 
   7569 
   7570 v8::Handle<Value> call_ic_function;
   7571 v8::Handle<Value> call_ic_function2;
   7572 v8::Handle<Value> call_ic_function3;
   7573 
   7574 static v8::Handle<Value> InterceptorCallICGetter(Local<String> name,
   7575                                                  const AccessorInfo& info) {
   7576   ApiTestFuzzer::Fuzz();
   7577   CHECK(v8_str("x")->Equals(name));
   7578   return call_ic_function;
   7579 }
   7580 
   7581 
   7582 // This test should hit the call IC for the interceptor case.
   7583 THREADED_TEST(InterceptorCallIC) {
   7584   v8::HandleScope scope;
   7585   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7586   templ->SetNamedPropertyHandler(InterceptorCallICGetter);
   7587   LocalContext context;
   7588   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7589   call_ic_function =
   7590       v8_compile("function f(x) { return x + 1; }; f")->Run();
   7591   v8::Handle<Value> value = CompileRun(
   7592     "var result = 0;"
   7593     "for (var i = 0; i < 1000; i++) {"
   7594     "  result = o.x(41);"
   7595     "}");
   7596   CHECK_EQ(42, value->Int32Value());
   7597 }
   7598 
   7599 
   7600 // This test checks that if interceptor doesn't provide
   7601 // a value, we can fetch regular value.
   7602 THREADED_TEST(InterceptorCallICSeesOthers) {
   7603   v8::HandleScope scope;
   7604   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7605   templ->SetNamedPropertyHandler(NoBlockGetterX);
   7606   LocalContext context;
   7607   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7608   v8::Handle<Value> value = CompileRun(
   7609     "o.x = function f(x) { return x + 1; };"
   7610     "var result = 0;"
   7611     "for (var i = 0; i < 7; i++) {"
   7612     "  result = o.x(41);"
   7613     "}");
   7614   CHECK_EQ(42, value->Int32Value());
   7615 }
   7616 
   7617 
   7618 static v8::Handle<Value> call_ic_function4;
   7619 static v8::Handle<Value> InterceptorCallICGetter4(Local<String> name,
   7620                                                   const AccessorInfo& info) {
   7621   ApiTestFuzzer::Fuzz();
   7622   CHECK(v8_str("x")->Equals(name));
   7623   return call_ic_function4;
   7624 }
   7625 
   7626 
   7627 // This test checks that if interceptor provides a function,
   7628 // even if we cached shadowed variant, interceptor's function
   7629 // is invoked
   7630 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
   7631   v8::HandleScope scope;
   7632   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7633   templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
   7634   LocalContext context;
   7635   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7636   call_ic_function4 =
   7637       v8_compile("function f(x) { return x - 1; }; f")->Run();
   7638   v8::Handle<Value> value = CompileRun(
   7639     "o.__proto__.x = function(x) { return x + 1; };"
   7640     "var result = 0;"
   7641     "for (var i = 0; i < 1000; i++) {"
   7642     "  result = o.x(42);"
   7643     "}");
   7644   CHECK_EQ(41, value->Int32Value());
   7645 }
   7646 
   7647 
   7648 // Test the case when we stored cacheable lookup into
   7649 // a stub, but it got invalidated later on
   7650 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
   7651   v8::HandleScope scope;
   7652   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7653   templ->SetNamedPropertyHandler(NoBlockGetterX);
   7654   LocalContext context;
   7655   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7656   v8::Handle<Value> value = CompileRun(
   7657     "proto1 = new Object();"
   7658     "proto2 = new Object();"
   7659     "o.__proto__ = proto1;"
   7660     "proto1.__proto__ = proto2;"
   7661     "proto2.y = function(x) { return x + 1; };"
   7662     // Invoke it many times to compile a stub
   7663     "for (var i = 0; i < 7; i++) {"
   7664     "  o.y(42);"
   7665     "}"
   7666     "proto1.y = function(x) { return x - 1; };"
   7667     "var result = 0;"
   7668     "for (var i = 0; i < 7; i++) {"
   7669     "  result += o.y(42);"
   7670     "}");
   7671   CHECK_EQ(41 * 7, value->Int32Value());
   7672 }
   7673 
   7674 
   7675 static v8::Handle<Value> call_ic_function5;
   7676 static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name,
   7677                                                   const AccessorInfo& info) {
   7678   ApiTestFuzzer::Fuzz();
   7679   if (v8_str("x")->Equals(name))
   7680     return call_ic_function5;
   7681   else
   7682     return Local<Value>();
   7683 }
   7684 
   7685 
   7686 // This test checks that if interceptor doesn't provide a function,
   7687 // cached constant function is used
   7688 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
   7689   v8::HandleScope scope;
   7690   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7691   templ->SetNamedPropertyHandler(NoBlockGetterX);
   7692   LocalContext context;
   7693   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7694   v8::Handle<Value> value = CompileRun(
   7695     "function inc(x) { return x + 1; };"
   7696     "inc(1);"
   7697     "o.x = inc;"
   7698     "var result = 0;"
   7699     "for (var i = 0; i < 1000; i++) {"
   7700     "  result = o.x(42);"
   7701     "}");
   7702   CHECK_EQ(43, value->Int32Value());
   7703 }
   7704 
   7705 
   7706 // This test checks that if interceptor provides a function,
   7707 // even if we cached constant function, interceptor's function
   7708 // is invoked
   7709 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
   7710   v8::HandleScope scope;
   7711   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7712   templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
   7713   LocalContext context;
   7714   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7715   call_ic_function5 =
   7716       v8_compile("function f(x) { return x - 1; }; f")->Run();
   7717   v8::Handle<Value> value = CompileRun(
   7718     "function inc(x) { return x + 1; };"
   7719     "inc(1);"
   7720     "o.x = inc;"
   7721     "var result = 0;"
   7722     "for (var i = 0; i < 1000; i++) {"
   7723     "  result = o.x(42);"
   7724     "}");
   7725   CHECK_EQ(41, value->Int32Value());
   7726 }
   7727 
   7728 
   7729 // Test the case when we stored constant function into
   7730 // a stub, but it got invalidated later on
   7731 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
   7732   v8::HandleScope scope;
   7733   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7734   templ->SetNamedPropertyHandler(NoBlockGetterX);
   7735   LocalContext context;
   7736   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7737   v8::Handle<Value> value = CompileRun(
   7738     "function inc(x) { return x + 1; };"
   7739     "inc(1);"
   7740     "proto1 = new Object();"
   7741     "proto2 = new Object();"
   7742     "o.__proto__ = proto1;"
   7743     "proto1.__proto__ = proto2;"
   7744     "proto2.y = inc;"
   7745     // Invoke it many times to compile a stub
   7746     "for (var i = 0; i < 7; i++) {"
   7747     "  o.y(42);"
   7748     "}"
   7749     "proto1.y = function(x) { return x - 1; };"
   7750     "var result = 0;"
   7751     "for (var i = 0; i < 7; i++) {"
   7752     "  result += o.y(42);"
   7753     "}");
   7754   CHECK_EQ(41 * 7, value->Int32Value());
   7755 }
   7756 
   7757 
   7758 // Test the case when we stored constant function into
   7759 // a stub, but it got invalidated later on due to override on
   7760 // global object which is between interceptor and constant function' holders.
   7761 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
   7762   v8::HandleScope scope;
   7763   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7764   templ->SetNamedPropertyHandler(NoBlockGetterX);
   7765   LocalContext context;
   7766   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7767   v8::Handle<Value> value = CompileRun(
   7768     "function inc(x) { return x + 1; };"
   7769     "inc(1);"
   7770     "o.__proto__ = this;"
   7771     "this.__proto__.y = inc;"
   7772     // Invoke it many times to compile a stub
   7773     "for (var i = 0; i < 7; i++) {"
   7774     "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
   7775     "}"
   7776     "this.y = function(x) { return x - 1; };"
   7777     "var result = 0;"
   7778     "for (var i = 0; i < 7; i++) {"
   7779     "  result += o.y(42);"
   7780     "}");
   7781   CHECK_EQ(41 * 7, value->Int32Value());
   7782 }
   7783 
   7784 
   7785 // Test the case when actual function to call sits on global object.
   7786 THREADED_TEST(InterceptorCallICCachedFromGlobal) {
   7787   v8::HandleScope scope;
   7788   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   7789   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   7790 
   7791   LocalContext context;
   7792   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   7793 
   7794   v8::Handle<Value> value = CompileRun(
   7795     "try {"
   7796     "  o.__proto__ = this;"
   7797     "  for (var i = 0; i < 10; i++) {"
   7798     "    var v = o.parseFloat('239');"
   7799     "    if (v != 239) throw v;"
   7800       // Now it should be ICed and keep a reference to parseFloat.
   7801     "  }"
   7802     "  var result = 0;"
   7803     "  for (var i = 0; i < 10; i++) {"
   7804     "    result += o.parseFloat('239');"
   7805     "  }"
   7806     "  result"
   7807     "} catch(e) {"
   7808     "  e"
   7809     "};");
   7810   CHECK_EQ(239 * 10, value->Int32Value());
   7811 }
   7812 
   7813 static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
   7814                                                   const AccessorInfo& info) {
   7815   ApiTestFuzzer::Fuzz();
   7816   int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data()));
   7817   ++(*call_count);
   7818   if ((*call_count) % 20 == 0) {
   7819     HEAP->CollectAllGarbage(true);
   7820   }
   7821   return v8::Handle<Value>();
   7822 }
   7823 
   7824 static v8::Handle<Value> FastApiCallback_TrivialSignature(
   7825     const v8::Arguments& args) {
   7826   ApiTestFuzzer::Fuzz();
   7827   CHECK_EQ(args.This(), args.Holder());
   7828   CHECK(args.Data()->Equals(v8_str("method_data")));
   7829   return v8::Integer::New(args[0]->Int32Value() + 1);
   7830 }
   7831 
   7832 static v8::Handle<Value> FastApiCallback_SimpleSignature(
   7833     const v8::Arguments& args) {
   7834   ApiTestFuzzer::Fuzz();
   7835   CHECK_EQ(args.This()->GetPrototype(), args.Holder());
   7836   CHECK(args.Data()->Equals(v8_str("method_data")));
   7837   // Note, we're using HasRealNamedProperty instead of Has to avoid
   7838   // invoking the interceptor again.
   7839   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
   7840   return v8::Integer::New(args[0]->Int32Value() + 1);
   7841 }
   7842 
   7843 // Helper to maximize the odds of object moving.
   7844 static void GenerateSomeGarbage() {
   7845   CompileRun(
   7846       "var garbage;"
   7847       "for (var i = 0; i < 1000; i++) {"
   7848       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   7849       "}"
   7850       "garbage = undefined;");
   7851 }
   7852 
   7853 
   7854 v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) {
   7855   static int count = 0;
   7856   if (count++ % 3 == 0) {
   7857     HEAP->  CollectAllGarbage(true);  // This should move the stub
   7858     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   7859   }
   7860   return v8::Handle<v8::Value>();
   7861 }
   7862 
   7863 
   7864 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   7865   v8::HandleScope scope;
   7866   LocalContext context;
   7867   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
   7868   nativeobject_templ->Set("callback",
   7869                           v8::FunctionTemplate::New(DirectApiCallback));
   7870   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   7871   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   7872   // call the api function multiple times to ensure direct call stub creation.
   7873   CompileRun(
   7874         "function f() {"
   7875         "  for (var i = 1; i <= 30; i++) {"
   7876         "    nativeobject.callback();"
   7877         "  }"
   7878         "}"
   7879         "f();");
   7880 }
   7881 
   7882 
   7883 v8::Handle<v8::Value> ThrowingDirectApiCallback(const v8::Arguments& args) {
   7884   return v8::ThrowException(v8_str("g"));
   7885 }
   7886 
   7887 
   7888 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   7889   v8::HandleScope scope;
   7890   LocalContext context;
   7891   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
   7892   nativeobject_templ->Set("callback",
   7893                           v8::FunctionTemplate::New(ThrowingDirectApiCallback));
   7894   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   7895   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   7896   // call the api function multiple times to ensure direct call stub creation.
   7897   v8::Handle<Value> result = CompileRun(
   7898       "var result = '';"
   7899       "function f() {"
   7900       "  for (var i = 1; i <= 5; i++) {"
   7901       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   7902       "  }"
   7903       "}"
   7904       "f(); result;");
   7905   CHECK_EQ(v8_str("ggggg"), result);
   7906 }
   7907 
   7908 
   7909 v8::Handle<v8::Value> DirectGetterCallback(Local<String> name,
   7910                                            const v8::AccessorInfo& info) {
   7911   if (++p_getter_count % 3 == 0) {
   7912     HEAP->CollectAllGarbage(true);
   7913     GenerateSomeGarbage();
   7914   }
   7915   return v8::Handle<v8::Value>();
   7916 }
   7917 
   7918 
   7919 THREADED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   7920   v8::HandleScope scope;
   7921   LocalContext context;
   7922   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
   7923   obj->SetAccessor(v8_str("p1"), DirectGetterCallback);
   7924   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   7925   p_getter_count = 0;
   7926   CompileRun(
   7927       "function f() {"
   7928       "  for (var i = 0; i < 30; i++) o1.p1;"
   7929       "}"
   7930       "f();");
   7931   CHECK_EQ(30, p_getter_count);
   7932 }
   7933 
   7934 
   7935 v8::Handle<v8::Value> ThrowingDirectGetterCallback(
   7936     Local<String> name, const v8::AccessorInfo& info) {
   7937   return v8::ThrowException(v8_str("g"));
   7938 }
   7939 
   7940 
   7941 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   7942   v8::HandleScope scope;
   7943   LocalContext context;
   7944   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
   7945   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   7946   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   7947   v8::Handle<Value> result = CompileRun(
   7948       "var result = '';"
   7949       "for (var i = 0; i < 5; i++) {"
   7950       "    try { o1.p1; } catch (e) { result += e; }"
   7951       "}"
   7952       "result;");
   7953   CHECK_EQ(v8_str("ggggg"), result);
   7954 }
   7955 
   7956 
   7957 THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   7958   int interceptor_call_count = 0;
   7959   v8::HandleScope scope;
   7960   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   7961   v8::Handle<v8::FunctionTemplate> method_templ =
   7962       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
   7963                                 v8_str("method_data"),
   7964                                 v8::Handle<v8::Signature>());
   7965   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   7966   proto_templ->Set(v8_str("method"), method_templ);
   7967   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   7968   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   7969                                  NULL, NULL, NULL, NULL,
   7970                                  v8::External::Wrap(&interceptor_call_count));
   7971   LocalContext context;
   7972   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   7973   GenerateSomeGarbage();
   7974   context->Global()->Set(v8_str("o"), fun->NewInstance());
   7975   v8::Handle<Value> value = CompileRun(
   7976       "var result = 0;"
   7977       "for (var i = 0; i < 100; i++) {"
   7978       "  result = o.method(41);"
   7979       "}");
   7980   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   7981   CHECK_EQ(100, interceptor_call_count);
   7982 }
   7983 
   7984 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   7985   int interceptor_call_count = 0;
   7986   v8::HandleScope scope;
   7987   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   7988   v8::Handle<v8::FunctionTemplate> method_templ =
   7989       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   7990                                 v8_str("method_data"),
   7991                                 v8::Signature::New(fun_templ));
   7992   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   7993   proto_templ->Set(v8_str("method"), method_templ);
   7994   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   7995   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   7996                                  NULL, NULL, NULL, NULL,
   7997                                  v8::External::Wrap(&interceptor_call_count));
   7998   LocalContext context;
   7999   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8000   GenerateSomeGarbage();
   8001   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8002   v8::Handle<Value> value = CompileRun(
   8003       "o.foo = 17;"
   8004       "var receiver = {};"
   8005       "receiver.__proto__ = o;"
   8006       "var result = 0;"
   8007       "for (var i = 0; i < 100; i++) {"
   8008       "  result = receiver.method(41);"
   8009       "}");
   8010   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   8011   CHECK_EQ(100, interceptor_call_count);
   8012 }
   8013 
   8014 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   8015   int interceptor_call_count = 0;
   8016   v8::HandleScope scope;
   8017   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8018   v8::Handle<v8::FunctionTemplate> method_templ =
   8019       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   8020                                 v8_str("method_data"),
   8021                                 v8::Signature::New(fun_templ));
   8022   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   8023   proto_templ->Set(v8_str("method"), method_templ);
   8024   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   8025   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   8026                                  NULL, NULL, NULL, NULL,
   8027                                  v8::External::Wrap(&interceptor_call_count));
   8028   LocalContext context;
   8029   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8030   GenerateSomeGarbage();
   8031   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8032   v8::Handle<Value> value = CompileRun(
   8033       "o.foo = 17;"
   8034       "var receiver = {};"
   8035       "receiver.__proto__ = o;"
   8036       "var result = 0;"
   8037       "var saved_result = 0;"
   8038       "for (var i = 0; i < 100; i++) {"
   8039       "  result = receiver.method(41);"
   8040       "  if (i == 50) {"
   8041       "    saved_result = result;"
   8042       "    receiver = {method: function(x) { return x - 1 }};"
   8043       "  }"
   8044       "}");
   8045   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   8046   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   8047   CHECK_GE(interceptor_call_count, 50);
   8048 }
   8049 
   8050 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   8051   int interceptor_call_count = 0;
   8052   v8::HandleScope scope;
   8053   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8054   v8::Handle<v8::FunctionTemplate> method_templ =
   8055       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   8056                                 v8_str("method_data"),
   8057                                 v8::Signature::New(fun_templ));
   8058   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   8059   proto_templ->Set(v8_str("method"), method_templ);
   8060   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   8061   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   8062                                  NULL, NULL, NULL, NULL,
   8063                                  v8::External::Wrap(&interceptor_call_count));
   8064   LocalContext context;
   8065   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8066   GenerateSomeGarbage();
   8067   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8068   v8::Handle<Value> value = CompileRun(
   8069       "o.foo = 17;"
   8070       "var receiver = {};"
   8071       "receiver.__proto__ = o;"
   8072       "var result = 0;"
   8073       "var saved_result = 0;"
   8074       "for (var i = 0; i < 100; i++) {"
   8075       "  result = receiver.method(41);"
   8076       "  if (i == 50) {"
   8077       "    saved_result = result;"
   8078       "    o.method = function(x) { return x - 1 };"
   8079       "  }"
   8080       "}");
   8081   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   8082   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   8083   CHECK_GE(interceptor_call_count, 50);
   8084 }
   8085 
   8086 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   8087   int interceptor_call_count = 0;
   8088   v8::HandleScope scope;
   8089   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8090   v8::Handle<v8::FunctionTemplate> method_templ =
   8091       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   8092                                 v8_str("method_data"),
   8093                                 v8::Signature::New(fun_templ));
   8094   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   8095   proto_templ->Set(v8_str("method"), method_templ);
   8096   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   8097   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   8098                                  NULL, NULL, NULL, NULL,
   8099                                  v8::External::Wrap(&interceptor_call_count));
   8100   LocalContext context;
   8101   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8102   GenerateSomeGarbage();
   8103   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8104   v8::TryCatch try_catch;
   8105   v8::Handle<Value> value = CompileRun(
   8106       "o.foo = 17;"
   8107       "var receiver = {};"
   8108       "receiver.__proto__ = o;"
   8109       "var result = 0;"
   8110       "var saved_result = 0;"
   8111       "for (var i = 0; i < 100; i++) {"
   8112       "  result = receiver.method(41);"
   8113       "  if (i == 50) {"
   8114       "    saved_result = result;"
   8115       "    receiver = 333;"
   8116       "  }"
   8117       "}");
   8118   CHECK(try_catch.HasCaught());
   8119   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
   8120            try_catch.Exception()->ToString());
   8121   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   8122   CHECK_GE(interceptor_call_count, 50);
   8123 }
   8124 
   8125 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   8126   int interceptor_call_count = 0;
   8127   v8::HandleScope scope;
   8128   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8129   v8::Handle<v8::FunctionTemplate> method_templ =
   8130       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   8131                                 v8_str("method_data"),
   8132                                 v8::Signature::New(fun_templ));
   8133   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   8134   proto_templ->Set(v8_str("method"), method_templ);
   8135   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   8136   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   8137                                  NULL, NULL, NULL, NULL,
   8138                                  v8::External::Wrap(&interceptor_call_count));
   8139   LocalContext context;
   8140   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8141   GenerateSomeGarbage();
   8142   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8143   v8::TryCatch try_catch;
   8144   v8::Handle<Value> value = CompileRun(
   8145       "o.foo = 17;"
   8146       "var receiver = {};"
   8147       "receiver.__proto__ = o;"
   8148       "var result = 0;"
   8149       "var saved_result = 0;"
   8150       "for (var i = 0; i < 100; i++) {"
   8151       "  result = receiver.method(41);"
   8152       "  if (i == 50) {"
   8153       "    saved_result = result;"
   8154       "    receiver = {method: receiver.method};"
   8155       "  }"
   8156       "}");
   8157   CHECK(try_catch.HasCaught());
   8158   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
   8159            try_catch.Exception()->ToString());
   8160   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   8161   CHECK_GE(interceptor_call_count, 50);
   8162 }
   8163 
   8164 THREADED_TEST(CallICFastApi_TrivialSignature) {
   8165   v8::HandleScope scope;
   8166   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8167   v8::Handle<v8::FunctionTemplate> method_templ =
   8168       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
   8169                                 v8_str("method_data"),
   8170                                 v8::Handle<v8::Signature>());
   8171   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   8172   proto_templ->Set(v8_str("method"), method_templ);
   8173   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   8174   LocalContext context;
   8175   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8176   GenerateSomeGarbage();
   8177   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8178   v8::Handle<Value> value = CompileRun(
   8179       "var result = 0;"
   8180       "for (var i = 0; i < 100; i++) {"
   8181       "  result = o.method(41);"
   8182       "}");
   8183 
   8184   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   8185 }
   8186 
   8187 THREADED_TEST(CallICFastApi_SimpleSignature) {
   8188   v8::HandleScope scope;
   8189   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8190   v8::Handle<v8::FunctionTemplate> method_templ =
   8191       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   8192                                 v8_str("method_data"),
   8193                                 v8::Signature::New(fun_templ));
   8194   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   8195   proto_templ->Set(v8_str("method"), method_templ);
   8196   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   8197   LocalContext context;
   8198   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8199   GenerateSomeGarbage();
   8200   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8201   v8::Handle<Value> value = CompileRun(
   8202       "o.foo = 17;"
   8203       "var receiver = {};"
   8204       "receiver.__proto__ = o;"
   8205       "var result = 0;"
   8206       "for (var i = 0; i < 100; i++) {"
   8207       "  result = receiver.method(41);"
   8208       "}");
   8209 
   8210   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   8211 }
   8212 
   8213 THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   8214   v8::HandleScope scope;
   8215   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8216   v8::Handle<v8::FunctionTemplate> method_templ =
   8217       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   8218                                 v8_str("method_data"),
   8219                                 v8::Signature::New(fun_templ));
   8220   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   8221   proto_templ->Set(v8_str("method"), method_templ);
   8222   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   8223   LocalContext context;
   8224   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8225   GenerateSomeGarbage();
   8226   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8227   v8::Handle<Value> value = CompileRun(
   8228       "o.foo = 17;"
   8229       "var receiver = {};"
   8230       "receiver.__proto__ = o;"
   8231       "var result = 0;"
   8232       "var saved_result = 0;"
   8233       "for (var i = 0; i < 100; i++) {"
   8234       "  result = receiver.method(41);"
   8235       "  if (i == 50) {"
   8236       "    saved_result = result;"
   8237       "    receiver = {method: function(x) { return x - 1 }};"
   8238       "  }"
   8239       "}");
   8240   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   8241   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   8242 }
   8243 
   8244 THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   8245   v8::HandleScope scope;
   8246   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8247   v8::Handle<v8::FunctionTemplate> method_templ =
   8248       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   8249                                 v8_str("method_data"),
   8250                                 v8::Signature::New(fun_templ));
   8251   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   8252   proto_templ->Set(v8_str("method"), method_templ);
   8253   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   8254   LocalContext context;
   8255   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   8256   GenerateSomeGarbage();
   8257   context->Global()->Set(v8_str("o"), fun->NewInstance());
   8258   v8::TryCatch try_catch;
   8259   v8::Handle<Value> value = CompileRun(
   8260       "o.foo = 17;"
   8261       "var receiver = {};"
   8262       "receiver.__proto__ = o;"
   8263       "var result = 0;"
   8264       "var saved_result = 0;"
   8265       "for (var i = 0; i < 100; i++) {"
   8266       "  result = receiver.method(41);"
   8267       "  if (i == 50) {"
   8268       "    saved_result = result;"
   8269       "    receiver = 333;"
   8270       "  }"
   8271       "}");
   8272   CHECK(try_catch.HasCaught());
   8273   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
   8274            try_catch.Exception()->ToString());
   8275   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   8276 }
   8277 
   8278 
   8279 v8::Handle<Value> keyed_call_ic_function;
   8280 
   8281 static v8::Handle<Value> InterceptorKeyedCallICGetter(
   8282     Local<String> name, const AccessorInfo& info) {
   8283   ApiTestFuzzer::Fuzz();
   8284   if (v8_str("x")->Equals(name)) {
   8285     return keyed_call_ic_function;
   8286   }
   8287   return v8::Handle<Value>();
   8288 }
   8289 
   8290 
   8291 // Test the case when we stored cacheable lookup into
   8292 // a stub, but the function name changed (to another cacheable function).
   8293 THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
   8294   v8::HandleScope scope;
   8295   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8296   templ->SetNamedPropertyHandler(NoBlockGetterX);
   8297   LocalContext context;
   8298   context->Global()->Set(v8_str("o"), templ->NewInstance());
   8299   v8::Handle<Value> value = CompileRun(
   8300     "proto = new Object();"
   8301     "proto.y = function(x) { return x + 1; };"
   8302     "proto.z = function(x) { return x - 1; };"
   8303     "o.__proto__ = proto;"
   8304     "var result = 0;"
   8305     "var method = 'y';"
   8306     "for (var i = 0; i < 10; i++) {"
   8307     "  if (i == 5) { method = 'z'; };"
   8308     "  result += o[method](41);"
   8309     "}");
   8310   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   8311 }
   8312 
   8313 
   8314 // Test the case when we stored cacheable lookup into
   8315 // a stub, but the function name changed (and the new function is present
   8316 // both before and after the interceptor in the prototype chain).
   8317 THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
   8318   v8::HandleScope scope;
   8319   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8320   templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
   8321   LocalContext context;
   8322   context->Global()->Set(v8_str("proto1"), templ->NewInstance());
   8323   keyed_call_ic_function =
   8324       v8_compile("function f(x) { return x - 1; }; f")->Run();
   8325   v8::Handle<Value> value = CompileRun(
   8326     "o = new Object();"
   8327     "proto2 = new Object();"
   8328     "o.y = function(x) { return x + 1; };"
   8329     "proto2.y = function(x) { return x + 2; };"
   8330     "o.__proto__ = proto1;"
   8331     "proto1.__proto__ = proto2;"
   8332     "var result = 0;"
   8333     "var method = 'x';"
   8334     "for (var i = 0; i < 10; i++) {"
   8335     "  if (i == 5) { method = 'y'; };"
   8336     "  result += o[method](41);"
   8337     "}");
   8338   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   8339 }
   8340 
   8341 
   8342 // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
   8343 // on the global object.
   8344 THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
   8345   v8::HandleScope scope;
   8346   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8347   templ->SetNamedPropertyHandler(NoBlockGetterX);
   8348   LocalContext context;
   8349   context->Global()->Set(v8_str("o"), templ->NewInstance());
   8350   v8::Handle<Value> value = CompileRun(
   8351     "function inc(x) { return x + 1; };"
   8352     "inc(1);"
   8353     "function dec(x) { return x - 1; };"
   8354     "dec(1);"
   8355     "o.__proto__ = this;"
   8356     "this.__proto__.x = inc;"
   8357     "this.__proto__.y = dec;"
   8358     "var result = 0;"
   8359     "var method = 'x';"
   8360     "for (var i = 0; i < 10; i++) {"
   8361     "  if (i == 5) { method = 'y'; };"
   8362     "  result += o[method](41);"
   8363     "}");
   8364   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   8365 }
   8366 
   8367 
   8368 // Test the case when actual function to call sits on global object.
   8369 THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
   8370   v8::HandleScope scope;
   8371   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   8372   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   8373   LocalContext context;
   8374   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   8375 
   8376   v8::Handle<Value> value = CompileRun(
   8377     "function len(x) { return x.length; };"
   8378     "o.__proto__ = this;"
   8379     "var m = 'parseFloat';"
   8380     "var result = 0;"
   8381     "for (var i = 0; i < 10; i++) {"
   8382     "  if (i == 5) {"
   8383     "    m = 'len';"
   8384     "    saved_result = result;"
   8385     "  };"
   8386     "  result = o[m]('239');"
   8387     "}");
   8388   CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
   8389   CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   8390 }
   8391 
   8392 // Test the map transition before the interceptor.
   8393 THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
   8394   v8::HandleScope scope;
   8395   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   8396   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   8397   LocalContext context;
   8398   context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
   8399 
   8400   v8::Handle<Value> value = CompileRun(
   8401     "var o = new Object();"
   8402     "o.__proto__ = proto;"
   8403     "o.method = function(x) { return x + 1; };"
   8404     "var m = 'method';"
   8405     "var result = 0;"
   8406     "for (var i = 0; i < 10; i++) {"
   8407     "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
   8408     "  result += o[m](41);"
   8409     "}");
   8410   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   8411 }
   8412 
   8413 
   8414 // Test the map transition after the interceptor.
   8415 THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
   8416   v8::HandleScope scope;
   8417   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   8418   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   8419   LocalContext context;
   8420   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   8421 
   8422   v8::Handle<Value> value = CompileRun(
   8423     "var proto = new Object();"
   8424     "o.__proto__ = proto;"
   8425     "proto.method = function(x) { return x + 1; };"
   8426     "var m = 'method';"
   8427     "var result = 0;"
   8428     "for (var i = 0; i < 10; i++) {"
   8429     "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
   8430     "  result += o[m](41);"
   8431     "}");
   8432   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   8433 }
   8434 
   8435 
   8436 static int interceptor_call_count = 0;
   8437 
   8438 static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name,
   8439                                                      const AccessorInfo& info) {
   8440   ApiTestFuzzer::Fuzz();
   8441   if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
   8442     return call_ic_function2;
   8443   }
   8444   return v8::Handle<Value>();
   8445 }
   8446 
   8447 
   8448 // This test should hit load and call ICs for the interceptor case.
   8449 // Once in a while, the interceptor will reply that a property was not
   8450 // found in which case we should get a reference error.
   8451 THREADED_TEST(InterceptorICReferenceErrors) {
   8452   v8::HandleScope scope;
   8453   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8454   templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
   8455   LocalContext context(0, templ, v8::Handle<Value>());
   8456   call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
   8457   v8::Handle<Value> value = CompileRun(
   8458     "function f() {"
   8459     "  for (var i = 0; i < 1000; i++) {"
   8460     "    try { x; } catch(e) { return true; }"
   8461     "  }"
   8462     "  return false;"
   8463     "};"
   8464     "f();");
   8465   CHECK_EQ(true, value->BooleanValue());
   8466   interceptor_call_count = 0;
   8467   value = CompileRun(
   8468     "function g() {"
   8469     "  for (var i = 0; i < 1000; i++) {"
   8470     "    try { x(42); } catch(e) { return true; }"
   8471     "  }"
   8472     "  return false;"
   8473     "};"
   8474     "g();");
   8475   CHECK_EQ(true, value->BooleanValue());
   8476 }
   8477 
   8478 
   8479 static int interceptor_ic_exception_get_count = 0;
   8480 
   8481 static v8::Handle<Value> InterceptorICExceptionGetter(
   8482     Local<String> name,
   8483     const AccessorInfo& info) {
   8484   ApiTestFuzzer::Fuzz();
   8485   if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
   8486     return call_ic_function3;
   8487   }
   8488   if (interceptor_ic_exception_get_count == 20) {
   8489     return v8::ThrowException(v8_num(42));
   8490   }
   8491   // Do not handle get for properties other than x.
   8492   return v8::Handle<Value>();
   8493 }
   8494 
   8495 // Test interceptor load/call IC where the interceptor throws an
   8496 // exception once in a while.
   8497 THREADED_TEST(InterceptorICGetterExceptions) {
   8498   interceptor_ic_exception_get_count = 0;
   8499   v8::HandleScope scope;
   8500   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8501   templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
   8502   LocalContext context(0, templ, v8::Handle<Value>());
   8503   call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
   8504   v8::Handle<Value> value = CompileRun(
   8505     "function f() {"
   8506     "  for (var i = 0; i < 100; i++) {"
   8507     "    try { x; } catch(e) { return true; }"
   8508     "  }"
   8509     "  return false;"
   8510     "};"
   8511     "f();");
   8512   CHECK_EQ(true, value->BooleanValue());
   8513   interceptor_ic_exception_get_count = 0;
   8514   value = CompileRun(
   8515     "function f() {"
   8516     "  for (var i = 0; i < 100; i++) {"
   8517     "    try { x(42); } catch(e) { return true; }"
   8518     "  }"
   8519     "  return false;"
   8520     "};"
   8521     "f();");
   8522   CHECK_EQ(true, value->BooleanValue());
   8523 }
   8524 
   8525 
   8526 static int interceptor_ic_exception_set_count = 0;
   8527 
   8528 static v8::Handle<Value> InterceptorICExceptionSetter(
   8529       Local<String> key, Local<Value> value, const AccessorInfo&) {
   8530   ApiTestFuzzer::Fuzz();
   8531   if (++interceptor_ic_exception_set_count > 20) {
   8532     return v8::ThrowException(v8_num(42));
   8533   }
   8534   // Do not actually handle setting.
   8535   return v8::Handle<Value>();
   8536 }
   8537 
   8538 // Test interceptor store IC where the interceptor throws an exception
   8539 // once in a while.
   8540 THREADED_TEST(InterceptorICSetterExceptions) {
   8541   interceptor_ic_exception_set_count = 0;
   8542   v8::HandleScope scope;
   8543   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8544   templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
   8545   LocalContext context(0, templ, v8::Handle<Value>());
   8546   v8::Handle<Value> value = CompileRun(
   8547     "function f() {"
   8548     "  for (var i = 0; i < 100; i++) {"
   8549     "    try { x = 42; } catch(e) { return true; }"
   8550     "  }"
   8551     "  return false;"
   8552     "};"
   8553     "f();");
   8554   CHECK_EQ(true, value->BooleanValue());
   8555 }
   8556 
   8557 
   8558 // Test that we ignore null interceptors.
   8559 THREADED_TEST(NullNamedInterceptor) {
   8560   v8::HandleScope scope;
   8561   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8562   templ->SetNamedPropertyHandler(0);
   8563   LocalContext context;
   8564   templ->Set("x", v8_num(42));
   8565   v8::Handle<v8::Object> obj = templ->NewInstance();
   8566   context->Global()->Set(v8_str("obj"), obj);
   8567   v8::Handle<Value> value = CompileRun("obj.x");
   8568   CHECK(value->IsInt32());
   8569   CHECK_EQ(42, value->Int32Value());
   8570 }
   8571 
   8572 
   8573 // Test that we ignore null interceptors.
   8574 THREADED_TEST(NullIndexedInterceptor) {
   8575   v8::HandleScope scope;
   8576   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8577   templ->SetIndexedPropertyHandler(0);
   8578   LocalContext context;
   8579   templ->Set("42", v8_num(42));
   8580   v8::Handle<v8::Object> obj = templ->NewInstance();
   8581   context->Global()->Set(v8_str("obj"), obj);
   8582   v8::Handle<Value> value = CompileRun("obj[42]");
   8583   CHECK(value->IsInt32());
   8584   CHECK_EQ(42, value->Int32Value());
   8585 }
   8586 
   8587 
   8588 THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
   8589   v8::HandleScope scope;
   8590   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   8591   templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   8592   LocalContext env;
   8593   env->Global()->Set(v8_str("obj"),
   8594                      templ->GetFunction()->NewInstance());
   8595   ExpectTrue("obj.x === 42");
   8596   ExpectTrue("!obj.propertyIsEnumerable('x')");
   8597 }
   8598 
   8599 
   8600 static Handle<Value> ThrowingGetter(Local<String> name,
   8601                                     const AccessorInfo& info) {
   8602   ApiTestFuzzer::Fuzz();
   8603   ThrowException(Handle<Value>());
   8604   return Undefined();
   8605 }
   8606 
   8607 
   8608 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   8609   HandleScope scope;
   8610   LocalContext context;
   8611 
   8612   Local<FunctionTemplate> templ = FunctionTemplate::New();
   8613   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   8614   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   8615 
   8616   Local<Object> instance = templ->GetFunction()->NewInstance();
   8617 
   8618   Local<Object> another = Object::New();
   8619   another->SetPrototype(instance);
   8620 
   8621   Local<Object> with_js_getter = CompileRun(
   8622       "o = {};\n"
   8623       "o.__defineGetter__('f', function() { throw undefined; });\n"
   8624       "o\n").As<Object>();
   8625   CHECK(!with_js_getter.IsEmpty());
   8626 
   8627   TryCatch try_catch;
   8628 
   8629   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
   8630   CHECK(try_catch.HasCaught());
   8631   try_catch.Reset();
   8632   CHECK(result.IsEmpty());
   8633 
   8634   result = another->GetRealNamedProperty(v8_str("f"));
   8635   CHECK(try_catch.HasCaught());
   8636   try_catch.Reset();
   8637   CHECK(result.IsEmpty());
   8638 
   8639   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
   8640   CHECK(try_catch.HasCaught());
   8641   try_catch.Reset();
   8642   CHECK(result.IsEmpty());
   8643 
   8644   result = another->Get(v8_str("f"));
   8645   CHECK(try_catch.HasCaught());
   8646   try_catch.Reset();
   8647   CHECK(result.IsEmpty());
   8648 
   8649   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
   8650   CHECK(try_catch.HasCaught());
   8651   try_catch.Reset();
   8652   CHECK(result.IsEmpty());
   8653 
   8654   result = with_js_getter->Get(v8_str("f"));
   8655   CHECK(try_catch.HasCaught());
   8656   try_catch.Reset();
   8657   CHECK(result.IsEmpty());
   8658 }
   8659 
   8660 
   8661 static Handle<Value> ThrowingCallbackWithTryCatch(const Arguments& args) {
   8662   TryCatch try_catch;
   8663   // Verboseness is important: it triggers message delivery which can call into
   8664   // external code.
   8665   try_catch.SetVerbose(true);
   8666   CompileRun("throw 'from JS';");
   8667   CHECK(try_catch.HasCaught());
   8668   CHECK(!i::Isolate::Current()->has_pending_exception());
   8669   CHECK(!i::Isolate::Current()->has_scheduled_exception());
   8670   return Undefined();
   8671 }
   8672 
   8673 
   8674 static int call_depth;
   8675 
   8676 
   8677 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
   8678   TryCatch try_catch;
   8679 }
   8680 
   8681 
   8682 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
   8683   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   8684 }
   8685 
   8686 
   8687 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
   8688   if (--call_depth) ThrowException(v8_str("ThrowViaApi"));
   8689 }
   8690 
   8691 
   8692 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
   8693   Handle<String> errorMessageString = message->Get();
   8694   CHECK(!errorMessageString.IsEmpty());
   8695   message->GetStackTrace();
   8696   message->GetScriptResourceName();
   8697 }
   8698 
   8699 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   8700   HandleScope scope;
   8701   LocalContext context;
   8702 
   8703   Local<Function> func =
   8704       FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction();
   8705   context->Global()->Set(v8_str("func"), func);
   8706 
   8707   MessageCallback callbacks[] =
   8708       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
   8709   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   8710     MessageCallback callback = callbacks[i];
   8711     if (callback != NULL) {
   8712       V8::AddMessageListener(callback);
   8713     }
   8714     call_depth = 5;
   8715     ExpectFalse(
   8716         "var thrown = false;\n"
   8717         "try { func(); } catch(e) { thrown = true; }\n"
   8718         "thrown\n");
   8719     if (callback != NULL) {
   8720       V8::RemoveMessageListeners(callback);
   8721     }
   8722   }
   8723 }
   8724 
   8725 
   8726 static v8::Handle<Value> ParentGetter(Local<String> name,
   8727                                       const AccessorInfo& info) {
   8728   ApiTestFuzzer::Fuzz();
   8729   return v8_num(1);
   8730 }
   8731 
   8732 
   8733 static v8::Handle<Value> ChildGetter(Local<String> name,
   8734                                      const AccessorInfo& info) {
   8735   ApiTestFuzzer::Fuzz();
   8736   return v8_num(42);
   8737 }
   8738 
   8739 
   8740 THREADED_TEST(Overriding) {
   8741   v8::HandleScope scope;
   8742   LocalContext context;
   8743 
   8744   // Parent template.
   8745   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
   8746   Local<ObjectTemplate> parent_instance_templ =
   8747       parent_templ->InstanceTemplate();
   8748   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   8749 
   8750   // Template that inherits from the parent template.
   8751   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
   8752   Local<ObjectTemplate> child_instance_templ =
   8753       child_templ->InstanceTemplate();
   8754   child_templ->Inherit(parent_templ);
   8755   // Override 'f'.  The child version of 'f' should get called for child
   8756   // instances.
   8757   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   8758   // Add 'g' twice.  The 'g' added last should get called for instances.
   8759   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   8760   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   8761 
   8762   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   8763   // so 'h' can be shadowed on the instance object.
   8764   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   8765   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
   8766       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   8767 
   8768   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   8769   // but the attribute does not have effect because it is duplicated with
   8770   // NULL setter.
   8771   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
   8772       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   8773 
   8774 
   8775 
   8776   // Instantiate the child template.
   8777   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
   8778 
   8779   // Check that the child function overrides the parent one.
   8780   context->Global()->Set(v8_str("o"), instance);
   8781   Local<Value> value = v8_compile("o.f")->Run();
   8782   // Check that the 'g' that was added last is hit.
   8783   CHECK_EQ(42, value->Int32Value());
   8784   value = v8_compile("o.g")->Run();
   8785   CHECK_EQ(42, value->Int32Value());
   8786 
   8787   // Check 'h' can be shadowed.
   8788   value = v8_compile("o.h = 3; o.h")->Run();
   8789   CHECK_EQ(3, value->Int32Value());
   8790 
   8791   // Check 'i' is cannot be shadowed or changed.
   8792   value = v8_compile("o.i = 3; o.i")->Run();
   8793   CHECK_EQ(42, value->Int32Value());
   8794 }
   8795 
   8796 
   8797 static v8::Handle<Value> IsConstructHandler(const v8::Arguments& args) {
   8798   ApiTestFuzzer::Fuzz();
   8799   if (args.IsConstructCall()) {
   8800     return v8::Boolean::New(true);
   8801   }
   8802   return v8::Boolean::New(false);
   8803 }
   8804 
   8805 
   8806 THREADED_TEST(IsConstructCall) {
   8807   v8::HandleScope scope;
   8808 
   8809   // Function template with call handler.
   8810   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   8811   templ->SetCallHandler(IsConstructHandler);
   8812 
   8813   LocalContext context;
   8814 
   8815   context->Global()->Set(v8_str("f"), templ->GetFunction());
   8816   Local<Value> value = v8_compile("f()")->Run();
   8817   CHECK(!value->BooleanValue());
   8818   value = v8_compile("new f()")->Run();
   8819   CHECK(value->BooleanValue());
   8820 }
   8821 
   8822 
   8823 THREADED_TEST(ObjectProtoToString) {
   8824   v8::HandleScope scope;
   8825   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   8826   templ->SetClassName(v8_str("MyClass"));
   8827 
   8828   LocalContext context;
   8829 
   8830   Local<String> customized_tostring = v8_str("customized toString");
   8831 
   8832   // Replace Object.prototype.toString
   8833   v8_compile("Object.prototype.toString = function() {"
   8834                   "  return 'customized toString';"
   8835                   "}")->Run();
   8836 
   8837   // Normal ToString call should call replaced Object.prototype.toString
   8838   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
   8839   Local<String> value = instance->ToString();
   8840   CHECK(value->IsString() && value->Equals(customized_tostring));
   8841 
   8842   // ObjectProtoToString should not call replace toString function.
   8843   value = instance->ObjectProtoToString();
   8844   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
   8845 
   8846   // Check global
   8847   value = context->Global()->ObjectProtoToString();
   8848   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
   8849 
   8850   // Check ordinary object
   8851   Local<Value> object = v8_compile("new Object()")->Run();
   8852   value = object.As<v8::Object>()->ObjectProtoToString();
   8853   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
   8854 }
   8855 
   8856 
   8857 THREADED_TEST(ObjectGetConstructorName) {
   8858   v8::HandleScope scope;
   8859   LocalContext context;
   8860   v8_compile("function Parent() {};"
   8861              "function Child() {};"
   8862              "Child.prototype = new Parent();"
   8863              "var outer = { inner: function() { } };"
   8864              "var p = new Parent();"
   8865              "var c = new Child();"
   8866              "var x = new outer.inner();")->Run();
   8867 
   8868   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
   8869   CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
   8870       v8_str("Parent")));
   8871 
   8872   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
   8873   CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
   8874       v8_str("Child")));
   8875 
   8876   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
   8877   CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
   8878       v8_str("outer.inner")));
   8879 }
   8880 
   8881 
   8882 bool ApiTestFuzzer::fuzzing_ = false;
   8883 i::Semaphore* ApiTestFuzzer::all_tests_done_=
   8884   i::OS::CreateSemaphore(0);
   8885 int ApiTestFuzzer::active_tests_;
   8886 int ApiTestFuzzer::tests_being_run_;
   8887 int ApiTestFuzzer::current_;
   8888 
   8889 
   8890 // We are in a callback and want to switch to another thread (if we
   8891 // are currently running the thread fuzzing test).
   8892 void ApiTestFuzzer::Fuzz() {
   8893   if (!fuzzing_) return;
   8894   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   8895   test->ContextSwitch();
   8896 }
   8897 
   8898 
   8899 // Let the next thread go.  Since it is also waiting on the V8 lock it may
   8900 // not start immediately.
   8901 bool ApiTestFuzzer::NextThread() {
   8902   int test_position = GetNextTestNumber();
   8903   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   8904   if (test_position == current_) {
   8905     if (kLogThreading)
   8906       printf("Stay with %s\n", test_name);
   8907     return false;
   8908   }
   8909   if (kLogThreading) {
   8910     printf("Switch from %s to %s\n",
   8911            test_name,
   8912            RegisterThreadedTest::nth(test_position)->name());
   8913   }
   8914   current_ = test_position;
   8915   RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
   8916   return true;
   8917 }
   8918 
   8919 
   8920 void ApiTestFuzzer::Run() {
   8921   // When it is our turn...
   8922   gate_->Wait();
   8923   {
   8924     // ... get the V8 lock and start running the test.
   8925     v8::Locker locker;
   8926     CallTest();
   8927   }
   8928   // This test finished.
   8929   active_ = false;
   8930   active_tests_--;
   8931   // If it was the last then signal that fact.
   8932   if (active_tests_ == 0) {
   8933     all_tests_done_->Signal();
   8934   } else {
   8935     // Otherwise select a new test and start that.
   8936     NextThread();
   8937   }
   8938 }
   8939 
   8940 
   8941 static unsigned linear_congruential_generator;
   8942 
   8943 
   8944 void ApiTestFuzzer::Setup(PartOfTest part) {
   8945   linear_congruential_generator = i::FLAG_testing_prng_seed;
   8946   fuzzing_ = true;
   8947   int start = (part == FIRST_PART) ? 0 : (RegisterThreadedTest::count() >> 1);
   8948   int end = (part == FIRST_PART)
   8949       ? (RegisterThreadedTest::count() >> 1)
   8950       : RegisterThreadedTest::count();
   8951   active_tests_ = tests_being_run_ = end - start;
   8952   for (int i = 0; i < tests_being_run_; i++) {
   8953     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(
   8954         i::Isolate::Current(), i + start);
   8955   }
   8956   for (int i = 0; i < active_tests_; i++) {
   8957     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   8958   }
   8959 }
   8960 
   8961 
   8962 static void CallTestNumber(int test_number) {
   8963   (RegisterThreadedTest::nth(test_number)->callback())();
   8964 }
   8965 
   8966 
   8967 void ApiTestFuzzer::RunAllTests() {
   8968   // Set off the first test.
   8969   current_ = -1;
   8970   NextThread();
   8971   // Wait till they are all done.
   8972   all_tests_done_->Wait();
   8973 }
   8974 
   8975 
   8976 int ApiTestFuzzer::GetNextTestNumber() {
   8977   int next_test;
   8978   do {
   8979     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   8980     linear_congruential_generator *= 1664525u;
   8981     linear_congruential_generator += 1013904223u;
   8982   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   8983   return next_test;
   8984 }
   8985 
   8986 
   8987 void ApiTestFuzzer::ContextSwitch() {
   8988   // If the new thread is the same as the current thread there is nothing to do.
   8989   if (NextThread()) {
   8990     // Now it can start.
   8991     v8::Unlocker unlocker;
   8992     // Wait till someone starts us again.
   8993     gate_->Wait();
   8994     // And we're off.
   8995   }
   8996 }
   8997 
   8998 
   8999 void ApiTestFuzzer::TearDown() {
   9000   fuzzing_ = false;
   9001   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   9002     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   9003     if (fuzzer != NULL) fuzzer->Join();
   9004   }
   9005 }
   9006 
   9007 
   9008 // Lets not be needlessly self-referential.
   9009 TEST(Threading) {
   9010   ApiTestFuzzer::Setup(ApiTestFuzzer::FIRST_PART);
   9011   ApiTestFuzzer::RunAllTests();
   9012   ApiTestFuzzer::TearDown();
   9013 }
   9014 
   9015 TEST(Threading2) {
   9016   ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART);
   9017   ApiTestFuzzer::RunAllTests();
   9018   ApiTestFuzzer::TearDown();
   9019 }
   9020 
   9021 
   9022 void ApiTestFuzzer::CallTest() {
   9023   if (kLogThreading)
   9024     printf("Start test %d\n", test_number_);
   9025   CallTestNumber(test_number_);
   9026   if (kLogThreading)
   9027     printf("End test %d\n", test_number_);
   9028 }
   9029 
   9030 
   9031 static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) {
   9032   CHECK(v8::Locker::IsLocked());
   9033   ApiTestFuzzer::Fuzz();
   9034   v8::Unlocker unlocker;
   9035   const char* code = "throw 7;";
   9036   {
   9037     v8::Locker nested_locker;
   9038     v8::HandleScope scope;
   9039     v8::Handle<Value> exception;
   9040     { v8::TryCatch try_catch;
   9041       v8::Handle<Value> value = CompileRun(code);
   9042       CHECK(value.IsEmpty());
   9043       CHECK(try_catch.HasCaught());
   9044       // Make sure to wrap the exception in a new handle because
   9045       // the handle returned from the TryCatch is destroyed
   9046       // when the TryCatch is destroyed.
   9047       exception = Local<Value>::New(try_catch.Exception());
   9048     }
   9049     return v8::ThrowException(exception);
   9050   }
   9051 }
   9052 
   9053 
   9054 static v8::Handle<Value> ThrowInJSNoCatch(const v8::Arguments& args) {
   9055   CHECK(v8::Locker::IsLocked());
   9056   ApiTestFuzzer::Fuzz();
   9057   v8::Unlocker unlocker;
   9058   const char* code = "throw 7;";
   9059   {
   9060     v8::Locker nested_locker;
   9061     v8::HandleScope scope;
   9062     v8::Handle<Value> value = CompileRun(code);
   9063     CHECK(value.IsEmpty());
   9064     return v8_str("foo");
   9065   }
   9066 }
   9067 
   9068 
   9069 // These are locking tests that don't need to be run again
   9070 // as part of the locking aggregation tests.
   9071 TEST(NestedLockers) {
   9072   v8::Locker locker;
   9073   CHECK(v8::Locker::IsLocked());
   9074   v8::HandleScope scope;
   9075   LocalContext env;
   9076   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
   9077   Local<Function> fun = fun_templ->GetFunction();
   9078   env->Global()->Set(v8_str("throw_in_js"), fun);
   9079   Local<Script> script = v8_compile("(function () {"
   9080                                     "  try {"
   9081                                     "    throw_in_js();"
   9082                                     "    return 42;"
   9083                                     "  } catch (e) {"
   9084                                     "    return e * 13;"
   9085                                     "  }"
   9086                                     "})();");
   9087   CHECK_EQ(91, script->Run()->Int32Value());
   9088 }
   9089 
   9090 
   9091 // These are locking tests that don't need to be run again
   9092 // as part of the locking aggregation tests.
   9093 TEST(NestedLockersNoTryCatch) {
   9094   v8::Locker locker;
   9095   v8::HandleScope scope;
   9096   LocalContext env;
   9097   Local<v8::FunctionTemplate> fun_templ =
   9098       v8::FunctionTemplate::New(ThrowInJSNoCatch);
   9099   Local<Function> fun = fun_templ->GetFunction();
   9100   env->Global()->Set(v8_str("throw_in_js"), fun);
   9101   Local<Script> script = v8_compile("(function () {"
   9102                                     "  try {"
   9103                                     "    throw_in_js();"
   9104                                     "    return 42;"
   9105                                     "  } catch (e) {"
   9106                                     "    return e * 13;"
   9107                                     "  }"
   9108                                     "})();");
   9109   CHECK_EQ(91, script->Run()->Int32Value());
   9110 }
   9111 
   9112 
   9113 THREADED_TEST(RecursiveLocking) {
   9114   v8::Locker locker;
   9115   {
   9116     v8::Locker locker2;
   9117     CHECK(v8::Locker::IsLocked());
   9118   }
   9119 }
   9120 
   9121 
   9122 static v8::Handle<Value> UnlockForAMoment(const v8::Arguments& args) {
   9123   ApiTestFuzzer::Fuzz();
   9124   v8::Unlocker unlocker;
   9125   return v8::Undefined();
   9126 }
   9127 
   9128 
   9129 THREADED_TEST(LockUnlockLock) {
   9130   {
   9131     v8::Locker locker;
   9132     v8::HandleScope scope;
   9133     LocalContext env;
   9134     Local<v8::FunctionTemplate> fun_templ =
   9135         v8::FunctionTemplate::New(UnlockForAMoment);
   9136     Local<Function> fun = fun_templ->GetFunction();
   9137     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   9138     Local<Script> script = v8_compile("(function () {"
   9139                                       "  unlock_for_a_moment();"
   9140                                       "  return 42;"
   9141                                       "})();");
   9142     CHECK_EQ(42, script->Run()->Int32Value());
   9143   }
   9144   {
   9145     v8::Locker locker;
   9146     v8::HandleScope scope;
   9147     LocalContext env;
   9148     Local<v8::FunctionTemplate> fun_templ =
   9149         v8::FunctionTemplate::New(UnlockForAMoment);
   9150     Local<Function> fun = fun_templ->GetFunction();
   9151     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   9152     Local<Script> script = v8_compile("(function () {"
   9153                                       "  unlock_for_a_moment();"
   9154                                       "  return 42;"
   9155                                       "})();");
   9156     CHECK_EQ(42, script->Run()->Int32Value());
   9157   }
   9158 }
   9159 
   9160 
   9161 static int GetGlobalObjectsCount() {
   9162   int count = 0;
   9163   i::HeapIterator it;
   9164   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
   9165     if (object->IsJSGlobalObject()) count++;
   9166   return count;
   9167 }
   9168 
   9169 
   9170 static void CheckSurvivingGlobalObjectsCount(int expected) {
   9171   // We need to collect all garbage twice to be sure that everything
   9172   // has been collected.  This is because inline caches are cleared in
   9173   // the first garbage collection but some of the maps have already
   9174   // been marked at that point.  Therefore some of the maps are not
   9175   // collected until the second garbage collection.
   9176   HEAP->CollectAllGarbage(false);
   9177   HEAP->CollectAllGarbage(false);
   9178   int count = GetGlobalObjectsCount();
   9179 #ifdef DEBUG
   9180   if (count != expected) HEAP->TracePathToGlobal();
   9181 #endif
   9182   CHECK_EQ(expected, count);
   9183 }
   9184 
   9185 
   9186 TEST(DontLeakGlobalObjects) {
   9187   // Regression test for issues 1139850 and 1174891.
   9188 
   9189   v8::V8::Initialize();
   9190 
   9191   for (int i = 0; i < 5; i++) {
   9192     { v8::HandleScope scope;
   9193       LocalContext context;
   9194     }
   9195     CheckSurvivingGlobalObjectsCount(0);
   9196 
   9197     { v8::HandleScope scope;
   9198       LocalContext context;
   9199       v8_compile("Date")->Run();
   9200     }
   9201     CheckSurvivingGlobalObjectsCount(0);
   9202 
   9203     { v8::HandleScope scope;
   9204       LocalContext context;
   9205       v8_compile("/aaa/")->Run();
   9206     }
   9207     CheckSurvivingGlobalObjectsCount(0);
   9208 
   9209     { v8::HandleScope scope;
   9210       const char* extension_list[] = { "v8/gc" };
   9211       v8::ExtensionConfiguration extensions(1, extension_list);
   9212       LocalContext context(&extensions);
   9213       v8_compile("gc();")->Run();
   9214     }
   9215     CheckSurvivingGlobalObjectsCount(0);
   9216   }
   9217 }
   9218 
   9219 
   9220 v8::Persistent<v8::Object> some_object;
   9221 v8::Persistent<v8::Object> bad_handle;
   9222 
   9223 void NewPersistentHandleCallback(v8::Persistent<v8::Value> handle, void*) {
   9224   v8::HandleScope scope;
   9225   bad_handle = v8::Persistent<v8::Object>::New(some_object);
   9226   handle.Dispose();
   9227 }
   9228 
   9229 
   9230 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   9231   LocalContext context;
   9232 
   9233   v8::Persistent<v8::Object> handle1, handle2;
   9234   {
   9235     v8::HandleScope scope;
   9236     some_object = v8::Persistent<v8::Object>::New(v8::Object::New());
   9237     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
   9238     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
   9239   }
   9240   // Note: order is implementation dependent alas: currently
   9241   // global handle nodes are processed by PostGarbageCollectionProcessing
   9242   // in reverse allocation order, so if second allocated handle is deleted,
   9243   // weak callback of the first handle would be able to 'reallocate' it.
   9244   handle1.MakeWeak(NULL, NewPersistentHandleCallback);
   9245   handle2.Dispose();
   9246   HEAP->CollectAllGarbage(false);
   9247 }
   9248 
   9249 
   9250 v8::Persistent<v8::Object> to_be_disposed;
   9251 
   9252 void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) {
   9253   to_be_disposed.Dispose();
   9254   HEAP->CollectAllGarbage(false);
   9255   handle.Dispose();
   9256 }
   9257 
   9258 
   9259 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   9260   LocalContext context;
   9261 
   9262   v8::Persistent<v8::Object> handle1, handle2;
   9263   {
   9264     v8::HandleScope scope;
   9265     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
   9266     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
   9267   }
   9268   handle1.MakeWeak(NULL, DisposeAndForceGcCallback);
   9269   to_be_disposed = handle2;
   9270   HEAP->CollectAllGarbage(false);
   9271 }
   9272 
   9273 void DisposingCallback(v8::Persistent<v8::Value> handle, void*) {
   9274   handle.Dispose();
   9275 }
   9276 
   9277 void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) {
   9278   v8::HandleScope scope;
   9279   v8::Persistent<v8::Object>::New(v8::Object::New());
   9280   handle.Dispose();
   9281 }
   9282 
   9283 
   9284 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   9285   LocalContext context;
   9286 
   9287   v8::Persistent<v8::Object> handle1, handle2, handle3;
   9288   {
   9289     v8::HandleScope scope;
   9290     handle3 = v8::Persistent<v8::Object>::New(v8::Object::New());
   9291     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
   9292     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
   9293   }
   9294   handle2.MakeWeak(NULL, DisposingCallback);
   9295   handle3.MakeWeak(NULL, HandleCreatingCallback);
   9296   HEAP->CollectAllGarbage(false);
   9297 }
   9298 
   9299 
   9300 THREADED_TEST(CheckForCrossContextObjectLiterals) {
   9301   v8::V8::Initialize();
   9302 
   9303   const int nof = 2;
   9304   const char* sources[nof] = {
   9305     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   9306     "Object()"
   9307   };
   9308 
   9309   for (int i = 0; i < nof; i++) {
   9310     const char* source = sources[i];
   9311     { v8::HandleScope scope;
   9312       LocalContext context;
   9313       CompileRun(source);
   9314     }
   9315     { v8::HandleScope scope;
   9316       LocalContext context;
   9317       CompileRun(source);
   9318     }
   9319   }
   9320 }
   9321 
   9322 
   9323 static v8::Handle<Value> NestedScope(v8::Persistent<Context> env) {
   9324   v8::HandleScope inner;
   9325   env->Enter();
   9326   v8::Handle<Value> three = v8_num(3);
   9327   v8::Handle<Value> value = inner.Close(three);
   9328   env->Exit();
   9329   return value;
   9330 }
   9331 
   9332 
   9333 THREADED_TEST(NestedHandleScopeAndContexts) {
   9334   v8::HandleScope outer;
   9335   v8::Persistent<Context> env = Context::New();
   9336   env->Enter();
   9337   v8::Handle<Value> value = NestedScope(env);
   9338   v8::Handle<String> str = value->ToString();
   9339   env->Exit();
   9340   env.Dispose();
   9341 }
   9342 
   9343 
   9344 THREADED_TEST(ExternalAllocatedMemory) {
   9345   v8::HandleScope outer;
   9346   v8::Persistent<Context> env = Context::New();
   9347   const int kSize = 1024*1024;
   9348   CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize);
   9349   CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0);
   9350 }
   9351 
   9352 
   9353 THREADED_TEST(DisposeEnteredContext) {
   9354   v8::HandleScope scope;
   9355   LocalContext outer;
   9356   { v8::Persistent<v8::Context> inner = v8::Context::New();
   9357     inner->Enter();
   9358     inner.Dispose();
   9359     inner.Clear();
   9360     inner->Exit();
   9361   }
   9362 }
   9363 
   9364 
   9365 // Regression test for issue 54, object templates with internal fields
   9366 // but no accessors or interceptors did not get their internal field
   9367 // count set on instances.
   9368 THREADED_TEST(Regress54) {
   9369   v8::HandleScope outer;
   9370   LocalContext context;
   9371   static v8::Persistent<v8::ObjectTemplate> templ;
   9372   if (templ.IsEmpty()) {
   9373     v8::HandleScope inner;
   9374     v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
   9375     local->SetInternalFieldCount(1);
   9376     templ = v8::Persistent<v8::ObjectTemplate>::New(inner.Close(local));
   9377   }
   9378   v8::Handle<v8::Object> result = templ->NewInstance();
   9379   CHECK_EQ(1, result->InternalFieldCount());
   9380 }
   9381 
   9382 
   9383 // If part of the threaded tests, this test makes ThreadingTest fail
   9384 // on mac.
   9385 TEST(CatchStackOverflow) {
   9386   v8::HandleScope scope;
   9387   LocalContext context;
   9388   v8::TryCatch try_catch;
   9389   v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
   9390     "function f() {"
   9391     "  return f();"
   9392     "}"
   9393     ""
   9394     "f();"));
   9395   v8::Handle<v8::Value> result = script->Run();
   9396   CHECK(result.IsEmpty());
   9397 }
   9398 
   9399 
   9400 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
   9401                                     const char* resource_name,
   9402                                     int line_offset) {
   9403   v8::HandleScope scope;
   9404   v8::TryCatch try_catch;
   9405   v8::Handle<v8::Value> result = script->Run();
   9406   CHECK(result.IsEmpty());
   9407   CHECK(try_catch.HasCaught());
   9408   v8::Handle<v8::Message> message = try_catch.Message();
   9409   CHECK(!message.IsEmpty());
   9410   CHECK_EQ(10 + line_offset, message->GetLineNumber());
   9411   CHECK_EQ(91, message->GetStartPosition());
   9412   CHECK_EQ(92, message->GetEndPosition());
   9413   CHECK_EQ(2, message->GetStartColumn());
   9414   CHECK_EQ(3, message->GetEndColumn());
   9415   v8::String::AsciiValue line(message->GetSourceLine());
   9416   CHECK_EQ("  throw 'nirk';", *line);
   9417   v8::String::AsciiValue name(message->GetScriptResourceName());
   9418   CHECK_EQ(resource_name, *name);
   9419 }
   9420 
   9421 
   9422 THREADED_TEST(TryCatchSourceInfo) {
   9423   v8::HandleScope scope;
   9424   LocalContext context;
   9425   v8::Handle<v8::String> source = v8::String::New(
   9426       "function Foo() {\n"
   9427       "  return Bar();\n"
   9428       "}\n"
   9429       "\n"
   9430       "function Bar() {\n"
   9431       "  return Baz();\n"
   9432       "}\n"
   9433       "\n"
   9434       "function Baz() {\n"
   9435       "  throw 'nirk';\n"
   9436       "}\n"
   9437       "\n"
   9438       "Foo();\n");
   9439 
   9440   const char* resource_name;
   9441   v8::Handle<v8::Script> script;
   9442   resource_name = "test.js";
   9443   script = v8::Script::Compile(source, v8::String::New(resource_name));
   9444   CheckTryCatchSourceInfo(script, resource_name, 0);
   9445 
   9446   resource_name = "test1.js";
   9447   v8::ScriptOrigin origin1(v8::String::New(resource_name));
   9448   script = v8::Script::Compile(source, &origin1);
   9449   CheckTryCatchSourceInfo(script, resource_name, 0);
   9450 
   9451   resource_name = "test2.js";
   9452   v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
   9453   script = v8::Script::Compile(source, &origin2);
   9454   CheckTryCatchSourceInfo(script, resource_name, 7);
   9455 }
   9456 
   9457 
   9458 THREADED_TEST(CompilationCache) {
   9459   v8::HandleScope scope;
   9460   LocalContext context;
   9461   v8::Handle<v8::String> source0 = v8::String::New("1234");
   9462   v8::Handle<v8::String> source1 = v8::String::New("1234");
   9463   v8::Handle<v8::Script> script0 =
   9464       v8::Script::Compile(source0, v8::String::New("test.js"));
   9465   v8::Handle<v8::Script> script1 =
   9466       v8::Script::Compile(source1, v8::String::New("test.js"));
   9467   v8::Handle<v8::Script> script2 =
   9468       v8::Script::Compile(source0);  // different origin
   9469   CHECK_EQ(1234, script0->Run()->Int32Value());
   9470   CHECK_EQ(1234, script1->Run()->Int32Value());
   9471   CHECK_EQ(1234, script2->Run()->Int32Value());
   9472 }
   9473 
   9474 
   9475 static v8::Handle<Value> FunctionNameCallback(const v8::Arguments& args) {
   9476   ApiTestFuzzer::Fuzz();
   9477   return v8_num(42);
   9478 }
   9479 
   9480 
   9481 THREADED_TEST(CallbackFunctionName) {
   9482   v8::HandleScope scope;
   9483   LocalContext context;
   9484   Local<ObjectTemplate> t = ObjectTemplate::New();
   9485   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
   9486   context->Global()->Set(v8_str("obj"), t->NewInstance());
   9487   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
   9488   CHECK(value->IsString());
   9489   v8::String::AsciiValue name(value);
   9490   CHECK_EQ("asdf", *name);
   9491 }
   9492 
   9493 
   9494 THREADED_TEST(DateAccess) {
   9495   v8::HandleScope scope;
   9496   LocalContext context;
   9497   v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
   9498   CHECK(date->IsDate());
   9499   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->NumberValue());
   9500 }
   9501 
   9502 
   9503 void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
   9504   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   9505   v8::Handle<v8::Array> props = obj->GetPropertyNames();
   9506   CHECK_EQ(elmc, props->Length());
   9507   for (int i = 0; i < elmc; i++) {
   9508     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
   9509     CHECK_EQ(elmv[i], *elm);
   9510   }
   9511 }
   9512 
   9513 
   9514 THREADED_TEST(PropertyEnumeration) {
   9515   v8::HandleScope scope;
   9516   LocalContext context;
   9517   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
   9518       "var result = [];"
   9519       "result[0] = {};"
   9520       "result[1] = {a: 1, b: 2};"
   9521       "result[2] = [1, 2, 3];"
   9522       "var proto = {x: 1, y: 2, z: 3};"
   9523       "var x = { __proto__: proto, w: 0, z: 1 };"
   9524       "result[3] = x;"
   9525       "result;"))->Run();
   9526   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   9527   CHECK_EQ(4, elms->Length());
   9528   int elmc0 = 0;
   9529   const char** elmv0 = NULL;
   9530   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   9531   int elmc1 = 2;
   9532   const char* elmv1[] = {"a", "b"};
   9533   CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
   9534   int elmc2 = 3;
   9535   const char* elmv2[] = {"0", "1", "2"};
   9536   CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
   9537   int elmc3 = 4;
   9538   const char* elmv3[] = {"w", "z", "x", "y"};
   9539   CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
   9540 }
   9541 
   9542 THREADED_TEST(PropertyEnumeration2) {
   9543   v8::HandleScope scope;
   9544   LocalContext context;
   9545   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
   9546       "var result = [];"
   9547       "result[0] = {};"
   9548       "result[1] = {a: 1, b: 2};"
   9549       "result[2] = [1, 2, 3];"
   9550       "var proto = {x: 1, y: 2, z: 3};"
   9551       "var x = { __proto__: proto, w: 0, z: 1 };"
   9552       "result[3] = x;"
   9553       "result;"))->Run();
   9554   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   9555   CHECK_EQ(4, elms->Length());
   9556   int elmc0 = 0;
   9557   const char** elmv0 = NULL;
   9558   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   9559 
   9560   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
   9561   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
   9562   CHECK_EQ(0, props->Length());
   9563   for (uint32_t i = 0; i < props->Length(); i++) {
   9564     printf("p[%d]\n", i);
   9565   }
   9566 }
   9567 
   9568 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
   9569                                   Local<Value> name,
   9570                                   v8::AccessType type,
   9571                                   Local<Value> data) {
   9572   return type != v8::ACCESS_SET;
   9573 }
   9574 
   9575 
   9576 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
   9577                                     uint32_t key,
   9578                                     v8::AccessType type,
   9579                                     Local<Value> data) {
   9580   return type != v8::ACCESS_SET;
   9581 }
   9582 
   9583 
   9584 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
   9585   v8::HandleScope scope;
   9586   LocalContext context;
   9587   Local<ObjectTemplate> templ = ObjectTemplate::New();
   9588   templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   9589                                  IndexedSetAccessBlocker);
   9590   templ->Set(v8_str("x"), v8::True());
   9591   Local<v8::Object> instance = templ->NewInstance();
   9592   context->Global()->Set(v8_str("obj"), instance);
   9593   Local<Value> value = CompileRun("obj.x");
   9594   CHECK(value->BooleanValue());
   9595 }
   9596 
   9597 
   9598 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
   9599                                   Local<Value> name,
   9600                                   v8::AccessType type,
   9601                                   Local<Value> data) {
   9602   return false;
   9603 }
   9604 
   9605 
   9606 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
   9607                                     uint32_t key,
   9608                                     v8::AccessType type,
   9609                                     Local<Value> data) {
   9610   return false;
   9611 }
   9612 
   9613 
   9614 
   9615 THREADED_TEST(AccessChecksReenabledCorrectly) {
   9616   v8::HandleScope scope;
   9617   LocalContext context;
   9618   Local<ObjectTemplate> templ = ObjectTemplate::New();
   9619   templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   9620                                  IndexedGetAccessBlocker);
   9621   templ->Set(v8_str("a"), v8_str("a"));
   9622   // Add more than 8 (see kMaxFastProperties) properties
   9623   // so that the constructor will force copying map.
   9624   // Cannot sprintf, gcc complains unsafety.
   9625   char buf[4];
   9626   for (char i = '0'; i <= '9' ; i++) {
   9627     buf[0] = i;
   9628     for (char j = '0'; j <= '9'; j++) {
   9629       buf[1] = j;
   9630       for (char k = '0'; k <= '9'; k++) {
   9631         buf[2] = k;
   9632         buf[3] = 0;
   9633         templ->Set(v8_str(buf), v8::Number::New(k));
   9634       }
   9635     }
   9636   }
   9637 
   9638   Local<v8::Object> instance_1 = templ->NewInstance();
   9639   context->Global()->Set(v8_str("obj_1"), instance_1);
   9640 
   9641   Local<Value> value_1 = CompileRun("obj_1.a");
   9642   CHECK(value_1->IsUndefined());
   9643 
   9644   Local<v8::Object> instance_2 = templ->NewInstance();
   9645   context->Global()->Set(v8_str("obj_2"), instance_2);
   9646 
   9647   Local<Value> value_2 = CompileRun("obj_2.a");
   9648   CHECK(value_2->IsUndefined());
   9649 }
   9650 
   9651 
   9652 // This tests that access check information remains on the global
   9653 // object template when creating contexts.
   9654 THREADED_TEST(AccessControlRepeatedContextCreation) {
   9655   v8::HandleScope handle_scope;
   9656   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   9657   global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   9658                                            IndexedSetAccessBlocker);
   9659   i::Handle<i::ObjectTemplateInfo> internal_template =
   9660       v8::Utils::OpenHandle(*global_template);
   9661   CHECK(!internal_template->constructor()->IsUndefined());
   9662   i::Handle<i::FunctionTemplateInfo> constructor(
   9663       i::FunctionTemplateInfo::cast(internal_template->constructor()));
   9664   CHECK(!constructor->access_check_info()->IsUndefined());
   9665   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
   9666   CHECK(!constructor->access_check_info()->IsUndefined());
   9667 }
   9668 
   9669 
   9670 THREADED_TEST(TurnOnAccessCheck) {
   9671   v8::HandleScope handle_scope;
   9672 
   9673   // Create an environment with access check to the global object disabled by
   9674   // default.
   9675   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   9676   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   9677                                            IndexedGetAccessBlocker,
   9678                                            v8::Handle<v8::Value>(),
   9679                                            false);
   9680   v8::Persistent<Context> context = Context::New(NULL, global_template);
   9681   Context::Scope context_scope(context);
   9682 
   9683   // Set up a property and a number of functions.
   9684   context->Global()->Set(v8_str("a"), v8_num(1));
   9685   CompileRun("function f1() {return a;}"
   9686              "function f2() {return a;}"
   9687              "function g1() {return h();}"
   9688              "function g2() {return h();}"
   9689              "function h() {return 1;}");
   9690   Local<Function> f1 =
   9691       Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   9692   Local<Function> f2 =
   9693       Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   9694   Local<Function> g1 =
   9695       Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   9696   Local<Function> g2 =
   9697       Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   9698   Local<Function> h =
   9699       Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   9700 
   9701   // Get the global object.
   9702   v8::Handle<v8::Object> global = context->Global();
   9703 
   9704   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   9705   // uses the runtime system to retreive property a whereas f2 uses global load
   9706   // inline cache.
   9707   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   9708   for (int i = 0; i < 4; i++) {
   9709     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   9710   }
   9711 
   9712   // Same for g1 and g2.
   9713   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   9714   for (int i = 0; i < 4; i++) {
   9715     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   9716   }
   9717 
   9718   // Detach the global and turn on access check.
   9719   context->DetachGlobal();
   9720   context->Global()->TurnOnAccessCheck();
   9721 
   9722   // Failing access check to property get results in undefined.
   9723   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   9724   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   9725 
   9726   // Failing access check to function call results in exception.
   9727   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   9728   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   9729 
   9730   // No failing access check when just returning a constant.
   9731   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   9732 }
   9733 
   9734 
   9735 v8::Handle<v8::String> a;
   9736 v8::Handle<v8::String> h;
   9737 
   9738 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
   9739                                        Local<Value> name,
   9740                                        v8::AccessType type,
   9741                                        Local<Value> data) {
   9742   return !(name->Equals(a) || name->Equals(h));
   9743 }
   9744 
   9745 
   9746 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
   9747   v8::HandleScope handle_scope;
   9748 
   9749   // Create an environment with access check to the global object disabled by
   9750   // default. When the registered access checker will block access to properties
   9751   // a and h
   9752   a = v8_str("a");
   9753   h = v8_str("h");
   9754   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   9755   global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
   9756                                            IndexedGetAccessBlocker,
   9757                                            v8::Handle<v8::Value>(),
   9758                                            false);
   9759   v8::Persistent<Context> context = Context::New(NULL, global_template);
   9760   Context::Scope context_scope(context);
   9761 
   9762   // Set up a property and a number of functions.
   9763   context->Global()->Set(v8_str("a"), v8_num(1));
   9764   static const char* source = "function f1() {return a;}"
   9765                               "function f2() {return a;}"
   9766                               "function g1() {return h();}"
   9767                               "function g2() {return h();}"
   9768                               "function h() {return 1;}";
   9769 
   9770   CompileRun(source);
   9771   Local<Function> f1;
   9772   Local<Function> f2;
   9773   Local<Function> g1;
   9774   Local<Function> g2;
   9775   Local<Function> h;
   9776   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   9777   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   9778   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   9779   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   9780   h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   9781 
   9782   // Get the global object.
   9783   v8::Handle<v8::Object> global = context->Global();
   9784 
   9785   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   9786   // uses the runtime system to retreive property a whereas f2 uses global load
   9787   // inline cache.
   9788   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   9789   for (int i = 0; i < 4; i++) {
   9790     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   9791   }
   9792 
   9793   // Same for g1 and g2.
   9794   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   9795   for (int i = 0; i < 4; i++) {
   9796     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   9797   }
   9798 
   9799   // Detach the global and turn on access check now blocking access to property
   9800   // a and function h.
   9801   context->DetachGlobal();
   9802   context->Global()->TurnOnAccessCheck();
   9803 
   9804   // Failing access check to property get results in undefined.
   9805   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   9806   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   9807 
   9808   // Failing access check to function call results in exception.
   9809   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   9810   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   9811 
   9812   // No failing access check when just returning a constant.
   9813   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   9814 
   9815   // Now compile the source again. And get the newly compiled functions, except
   9816   // for h for which access is blocked.
   9817   CompileRun(source);
   9818   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   9819   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   9820   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   9821   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   9822   CHECK(context->Global()->Get(v8_str("h"))->IsUndefined());
   9823 
   9824   // Failing access check to property get results in undefined.
   9825   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   9826   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   9827 
   9828   // Failing access check to function call results in exception.
   9829   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   9830   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   9831 }
   9832 
   9833 
   9834 // This test verifies that pre-compilation (aka preparsing) can be called
   9835 // without initializing the whole VM. Thus we cannot run this test in a
   9836 // multi-threaded setup.
   9837 TEST(PreCompile) {
   9838   // TODO(155): This test would break without the initialization of V8. This is
   9839   // a workaround for now to make this test not fail.
   9840   v8::V8::Initialize();
   9841   const char* script = "function foo(a) { return a+1; }";
   9842   v8::ScriptData* sd =
   9843       v8::ScriptData::PreCompile(script, i::StrLength(script));
   9844   CHECK_NE(sd->Length(), 0);
   9845   CHECK_NE(sd->Data(), NULL);
   9846   CHECK(!sd->HasError());
   9847   delete sd;
   9848 }
   9849 
   9850 
   9851 TEST(PreCompileWithError) {
   9852   v8::V8::Initialize();
   9853   const char* script = "function foo(a) { return 1 * * 2; }";
   9854   v8::ScriptData* sd =
   9855       v8::ScriptData::PreCompile(script, i::StrLength(script));
   9856   CHECK(sd->HasError());
   9857   delete sd;
   9858 }
   9859 
   9860 
   9861 TEST(Regress31661) {
   9862   v8::V8::Initialize();
   9863   const char* script = " The Definintive Guide";
   9864   v8::ScriptData* sd =
   9865       v8::ScriptData::PreCompile(script, i::StrLength(script));
   9866   CHECK(sd->HasError());
   9867   delete sd;
   9868 }
   9869 
   9870 
   9871 // Tests that ScriptData can be serialized and deserialized.
   9872 TEST(PreCompileSerialization) {
   9873   v8::V8::Initialize();
   9874   const char* script = "function foo(a) { return a+1; }";
   9875   v8::ScriptData* sd =
   9876       v8::ScriptData::PreCompile(script, i::StrLength(script));
   9877 
   9878   // Serialize.
   9879   int serialized_data_length = sd->Length();
   9880   char* serialized_data = i::NewArray<char>(serialized_data_length);
   9881   memcpy(serialized_data, sd->Data(), serialized_data_length);
   9882 
   9883   // Deserialize.
   9884   v8::ScriptData* deserialized_sd =
   9885       v8::ScriptData::New(serialized_data, serialized_data_length);
   9886 
   9887   // Verify that the original is the same as the deserialized.
   9888   CHECK_EQ(sd->Length(), deserialized_sd->Length());
   9889   CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
   9890   CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
   9891 
   9892   delete sd;
   9893   delete deserialized_sd;
   9894 }
   9895 
   9896 
   9897 // Attempts to deserialize bad data.
   9898 TEST(PreCompileDeserializationError) {
   9899   v8::V8::Initialize();
   9900   const char* data = "DONT CARE";
   9901   int invalid_size = 3;
   9902   v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
   9903 
   9904   CHECK_EQ(0, sd->Length());
   9905 
   9906   delete sd;
   9907 }
   9908 
   9909 
   9910 // Attempts to deserialize bad data.
   9911 TEST(PreCompileInvalidPreparseDataError) {
   9912   v8::V8::Initialize();
   9913   v8::HandleScope scope;
   9914   LocalContext context;
   9915 
   9916   const char* script = "function foo(){ return 5;}\n"
   9917       "function bar(){ return 6 + 7;}  foo();";
   9918   v8::ScriptData* sd =
   9919       v8::ScriptData::PreCompile(script, i::StrLength(script));
   9920   CHECK(!sd->HasError());
   9921   // ScriptDataImpl private implementation details
   9922   const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
   9923   const int kFunctionEntrySize = i::FunctionEntry::kSize;
   9924   const int kFunctionEntryStartOffset = 0;
   9925   const int kFunctionEntryEndOffset = 1;
   9926   unsigned* sd_data =
   9927       reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   9928 
   9929   // Overwrite function bar's end position with 0.
   9930   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
   9931   v8::TryCatch try_catch;
   9932 
   9933   Local<String> source = String::New(script);
   9934   Local<Script> compiled_script = Script::New(source, NULL, sd);
   9935   CHECK(try_catch.HasCaught());
   9936   String::AsciiValue exception_value(try_catch.Message()->Get());
   9937   CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
   9938            *exception_value);
   9939 
   9940   try_catch.Reset();
   9941   // Overwrite function bar's start position with 200.  The function entry
   9942   // will not be found when searching for it by position.
   9943   sd = v8::ScriptData::PreCompile(script, i::StrLength(script));
   9944   sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   9945   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
   9946       200;
   9947   compiled_script = Script::New(source, NULL, sd);
   9948   CHECK(try_catch.HasCaught());
   9949   String::AsciiValue second_exception_value(try_catch.Message()->Get());
   9950   CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
   9951            *second_exception_value);
   9952 
   9953   delete sd;
   9954 }
   9955 
   9956 
   9957 // Verifies that the Handle<String> and const char* versions of the API produce
   9958 // the same results (at least for one trivial case).
   9959 TEST(PreCompileAPIVariationsAreSame) {
   9960   v8::V8::Initialize();
   9961   v8::HandleScope scope;
   9962 
   9963   const char* cstring = "function foo(a) { return a+1; }";
   9964 
   9965   v8::ScriptData* sd_from_cstring =
   9966       v8::ScriptData::PreCompile(cstring, i::StrLength(cstring));
   9967 
   9968   TestAsciiResource* resource = new TestAsciiResource(cstring);
   9969   v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
   9970       v8::String::NewExternal(resource));
   9971 
   9972   v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
   9973       v8::String::New(cstring));
   9974 
   9975   CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
   9976   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
   9977                      sd_from_external_string->Data(),
   9978                      sd_from_cstring->Length()));
   9979 
   9980   CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
   9981   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
   9982                      sd_from_string->Data(),
   9983                      sd_from_cstring->Length()));
   9984 
   9985 
   9986   delete sd_from_cstring;
   9987   delete sd_from_external_string;
   9988   delete sd_from_string;
   9989 }
   9990 
   9991 
   9992 // This tests that we do not allow dictionary load/call inline caches
   9993 // to use functions that have not yet been compiled.  The potential
   9994 // problem of loading a function that has not yet been compiled can
   9995 // arise because we share code between contexts via the compilation
   9996 // cache.
   9997 THREADED_TEST(DictionaryICLoadedFunction) {
   9998   v8::HandleScope scope;
   9999   // Test LoadIC.
   10000   for (int i = 0; i < 2; i++) {
   10001     LocalContext context;
   10002     context->Global()->Set(v8_str("tmp"), v8::True());
   10003     context->Global()->Delete(v8_str("tmp"));
   10004     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   10005   }
   10006   // Test CallIC.
   10007   for (int i = 0; i < 2; i++) {
   10008     LocalContext context;
   10009     context->Global()->Set(v8_str("tmp"), v8::True());
   10010     context->Global()->Delete(v8_str("tmp"));
   10011     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   10012   }
   10013 }
   10014 
   10015 
   10016 // Test that cross-context new calls use the context of the callee to
   10017 // create the new JavaScript object.
   10018 THREADED_TEST(CrossContextNew) {
   10019   v8::HandleScope scope;
   10020   v8::Persistent<Context> context0 = Context::New();
   10021   v8::Persistent<Context> context1 = Context::New();
   10022 
   10023   // Allow cross-domain access.
   10024   Local<String> token = v8_str("<security token>");
   10025   context0->SetSecurityToken(token);
   10026   context1->SetSecurityToken(token);
   10027 
   10028   // Set an 'x' property on the Object prototype and define a
   10029   // constructor function in context0.
   10030   context0->Enter();
   10031   CompileRun("Object.prototype.x = 42; function C() {};");
   10032   context0->Exit();
   10033 
   10034   // Call the constructor function from context0 and check that the
   10035   // result has the 'x' property.
   10036   context1->Enter();
   10037   context1->Global()->Set(v8_str("other"), context0->Global());
   10038   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   10039   CHECK(value->IsInt32());
   10040   CHECK_EQ(42, value->Int32Value());
   10041   context1->Exit();
   10042 
   10043   // Dispose the contexts to allow them to be garbage collected.
   10044   context0.Dispose();
   10045   context1.Dispose();
   10046 }
   10047 
   10048 
   10049 class RegExpInterruptTest {
   10050  public:
   10051   RegExpInterruptTest() : block_(NULL) {}
   10052   ~RegExpInterruptTest() { delete block_; }
   10053   void RunTest() {
   10054     block_ = i::OS::CreateSemaphore(0);
   10055     gc_count_ = 0;
   10056     gc_during_regexp_ = 0;
   10057     regexp_success_ = false;
   10058     gc_success_ = false;
   10059     GCThread gc_thread(i::Isolate::Current(), this);
   10060     gc_thread.Start();
   10061     v8::Locker::StartPreemption(1);
   10062 
   10063     LongRunningRegExp();
   10064     {
   10065       v8::Unlocker unlock;
   10066       gc_thread.Join();
   10067     }
   10068     v8::Locker::StopPreemption();
   10069     CHECK(regexp_success_);
   10070     CHECK(gc_success_);
   10071   }
   10072  private:
   10073   // Number of garbage collections required.
   10074   static const int kRequiredGCs = 5;
   10075 
   10076   class GCThread : public i::Thread {
   10077    public:
   10078     explicit GCThread(i::Isolate* isolate, RegExpInterruptTest* test)
   10079         : Thread(isolate, "GCThread"), test_(test) {}
   10080     virtual void Run() {
   10081       test_->CollectGarbage();
   10082     }
   10083    private:
   10084      RegExpInterruptTest* test_;
   10085   };
   10086 
   10087   void CollectGarbage() {
   10088     block_->Wait();
   10089     while (gc_during_regexp_ < kRequiredGCs) {
   10090       {
   10091         v8::Locker lock;
   10092         // TODO(lrn): Perhaps create some garbage before collecting.
   10093         HEAP->CollectAllGarbage(false);
   10094         gc_count_++;
   10095       }
   10096       i::OS::Sleep(1);
   10097     }
   10098     gc_success_ = true;
   10099   }
   10100 
   10101   void LongRunningRegExp() {
   10102     block_->Signal();  // Enable garbage collection thread on next preemption.
   10103     int rounds = 0;
   10104     while (gc_during_regexp_ < kRequiredGCs) {
   10105       int gc_before = gc_count_;
   10106       {
   10107         // Match 15-30 "a"'s against 14 and a "b".
   10108         const char* c_source =
   10109             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   10110             ".exec('aaaaaaaaaaaaaaab') === null";
   10111         Local<String> source = String::New(c_source);
   10112         Local<Script> script = Script::Compile(source);
   10113         Local<Value> result = script->Run();
   10114         if (!result->BooleanValue()) {
   10115           gc_during_regexp_ = kRequiredGCs;  // Allow gc thread to exit.
   10116           return;
   10117         }
   10118       }
   10119       {
   10120         // Match 15-30 "a"'s against 15 and a "b".
   10121         const char* c_source =
   10122             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   10123             ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
   10124         Local<String> source = String::New(c_source);
   10125         Local<Script> script = Script::Compile(source);
   10126         Local<Value> result = script->Run();
   10127         if (!result->BooleanValue()) {
   10128           gc_during_regexp_ = kRequiredGCs;
   10129           return;
   10130         }
   10131       }
   10132       int gc_after = gc_count_;
   10133       gc_during_regexp_ += gc_after - gc_before;
   10134       rounds++;
   10135       i::OS::Sleep(1);
   10136     }
   10137     regexp_success_ = true;
   10138   }
   10139 
   10140   i::Semaphore* block_;
   10141   int gc_count_;
   10142   int gc_during_regexp_;
   10143   bool regexp_success_;
   10144   bool gc_success_;
   10145 };
   10146 
   10147 
   10148 // Test that a regular expression execution can be interrupted and
   10149 // survive a garbage collection.
   10150 TEST(RegExpInterruption) {
   10151   v8::Locker lock;
   10152   v8::V8::Initialize();
   10153   v8::HandleScope scope;
   10154   Local<Context> local_env;
   10155   {
   10156     LocalContext env;
   10157     local_env = env.local();
   10158   }
   10159 
   10160   // Local context should still be live.
   10161   CHECK(!local_env.IsEmpty());
   10162   local_env->Enter();
   10163 
   10164   // Should complete without problems.
   10165   RegExpInterruptTest().RunTest();
   10166 
   10167   local_env->Exit();
   10168 }
   10169 
   10170 
   10171 class ApplyInterruptTest {
   10172  public:
   10173   ApplyInterruptTest() : block_(NULL) {}
   10174   ~ApplyInterruptTest() { delete block_; }
   10175   void RunTest() {
   10176     block_ = i::OS::CreateSemaphore(0);
   10177     gc_count_ = 0;
   10178     gc_during_apply_ = 0;
   10179     apply_success_ = false;
   10180     gc_success_ = false;
   10181     GCThread gc_thread(i::Isolate::Current(), this);
   10182     gc_thread.Start();
   10183     v8::Locker::StartPreemption(1);
   10184 
   10185     LongRunningApply();
   10186     {
   10187       v8::Unlocker unlock;
   10188       gc_thread.Join();
   10189     }
   10190     v8::Locker::StopPreemption();
   10191     CHECK(apply_success_);
   10192     CHECK(gc_success_);
   10193   }
   10194  private:
   10195   // Number of garbage collections required.
   10196   static const int kRequiredGCs = 2;
   10197 
   10198   class GCThread : public i::Thread {
   10199    public:
   10200     explicit GCThread(i::Isolate* isolate, ApplyInterruptTest* test)
   10201         : Thread(isolate, "GCThread"), test_(test) {}
   10202     virtual void Run() {
   10203       test_->CollectGarbage();
   10204     }
   10205    private:
   10206      ApplyInterruptTest* test_;
   10207   };
   10208 
   10209   void CollectGarbage() {
   10210     block_->Wait();
   10211     while (gc_during_apply_ < kRequiredGCs) {
   10212       {
   10213         v8::Locker lock;
   10214         HEAP->CollectAllGarbage(false);
   10215         gc_count_++;
   10216       }
   10217       i::OS::Sleep(1);
   10218     }
   10219     gc_success_ = true;
   10220   }
   10221 
   10222   void LongRunningApply() {
   10223     block_->Signal();
   10224     int rounds = 0;
   10225     while (gc_during_apply_ < kRequiredGCs) {
   10226       int gc_before = gc_count_;
   10227       {
   10228         const char* c_source =
   10229             "function do_very_little(bar) {"
   10230             "  this.foo = bar;"
   10231             "}"
   10232             "for (var i = 0; i < 100000; i++) {"
   10233             "  do_very_little.apply(this, ['bar']);"
   10234             "}";
   10235         Local<String> source = String::New(c_source);
   10236         Local<Script> script = Script::Compile(source);
   10237         Local<Value> result = script->Run();
   10238         // Check that no exception was thrown.
   10239         CHECK(!result.IsEmpty());
   10240       }
   10241       int gc_after = gc_count_;
   10242       gc_during_apply_ += gc_after - gc_before;
   10243       rounds++;
   10244     }
   10245     apply_success_ = true;
   10246   }
   10247 
   10248   i::Semaphore* block_;
   10249   int gc_count_;
   10250   int gc_during_apply_;
   10251   bool apply_success_;
   10252   bool gc_success_;
   10253 };
   10254 
   10255 
   10256 // Test that nothing bad happens if we get a preemption just when we were
   10257 // about to do an apply().
   10258 TEST(ApplyInterruption) {
   10259   v8::Locker lock;
   10260   v8::V8::Initialize();
   10261   v8::HandleScope scope;
   10262   Local<Context> local_env;
   10263   {
   10264     LocalContext env;
   10265     local_env = env.local();
   10266   }
   10267 
   10268   // Local context should still be live.
   10269   CHECK(!local_env.IsEmpty());
   10270   local_env->Enter();
   10271 
   10272   // Should complete without problems.
   10273   ApplyInterruptTest().RunTest();
   10274 
   10275   local_env->Exit();
   10276 }
   10277 
   10278 
   10279 // Verify that we can clone an object
   10280 TEST(ObjectClone) {
   10281   v8::HandleScope scope;
   10282   LocalContext env;
   10283 
   10284   const char* sample =
   10285     "var rv = {};"      \
   10286     "rv.alpha = 'hello';" \
   10287     "rv.beta = 123;"     \
   10288     "rv;";
   10289 
   10290   // Create an object, verify basics.
   10291   Local<Value> val = CompileRun(sample);
   10292   CHECK(val->IsObject());
   10293   Local<v8::Object> obj = val.As<v8::Object>();
   10294   obj->Set(v8_str("gamma"), v8_str("cloneme"));
   10295 
   10296   CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
   10297   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
   10298   CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
   10299 
   10300   // Clone it.
   10301   Local<v8::Object> clone = obj->Clone();
   10302   CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
   10303   CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
   10304   CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
   10305 
   10306   // Set a property on the clone, verify each object.
   10307   clone->Set(v8_str("beta"), v8::Integer::New(456));
   10308   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
   10309   CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
   10310 }
   10311 
   10312 
   10313 class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
   10314  public:
   10315   explicit AsciiVectorResource(i::Vector<const char> vector)
   10316       : data_(vector) {}
   10317   virtual ~AsciiVectorResource() {}
   10318   virtual size_t length() const { return data_.length(); }
   10319   virtual const char* data() const { return data_.start(); }
   10320  private:
   10321   i::Vector<const char> data_;
   10322 };
   10323 
   10324 
   10325 class UC16VectorResource : public v8::String::ExternalStringResource {
   10326  public:
   10327   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   10328       : data_(vector) {}
   10329   virtual ~UC16VectorResource() {}
   10330   virtual size_t length() const { return data_.length(); }
   10331   virtual const i::uc16* data() const { return data_.start(); }
   10332  private:
   10333   i::Vector<const i::uc16> data_;
   10334 };
   10335 
   10336 
   10337 static void MorphAString(i::String* string,
   10338                          AsciiVectorResource* ascii_resource,
   10339                          UC16VectorResource* uc16_resource) {
   10340   CHECK(i::StringShape(string).IsExternal());
   10341   if (string->IsAsciiRepresentation()) {
   10342     // Check old map is not symbol or long.
   10343     CHECK(string->map() == HEAP->external_ascii_string_map());
   10344     // Morph external string to be TwoByte string.
   10345     string->set_map(HEAP->external_string_map());
   10346     i::ExternalTwoByteString* morphed =
   10347          i::ExternalTwoByteString::cast(string);
   10348     morphed->set_resource(uc16_resource);
   10349   } else {
   10350     // Check old map is not symbol or long.
   10351     CHECK(string->map() == HEAP->external_string_map());
   10352     // Morph external string to be ASCII string.
   10353     string->set_map(HEAP->external_ascii_string_map());
   10354     i::ExternalAsciiString* morphed =
   10355          i::ExternalAsciiString::cast(string);
   10356     morphed->set_resource(ascii_resource);
   10357   }
   10358 }
   10359 
   10360 
   10361 // Test that we can still flatten a string if the components it is built up
   10362 // from have been turned into 16 bit strings in the mean time.
   10363 THREADED_TEST(MorphCompositeStringTest) {
   10364   const char* c_string = "Now is the time for all good men"
   10365                          " to come to the aid of the party";
   10366   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   10367   {
   10368     v8::HandleScope scope;
   10369     LocalContext env;
   10370     AsciiVectorResource ascii_resource(
   10371         i::Vector<const char>(c_string, i::StrLength(c_string)));
   10372     UC16VectorResource uc16_resource(
   10373         i::Vector<const uint16_t>(two_byte_string,
   10374                                   i::StrLength(c_string)));
   10375 
   10376     Local<String> lhs(v8::Utils::ToLocal(
   10377         FACTORY->NewExternalStringFromAscii(&ascii_resource)));
   10378     Local<String> rhs(v8::Utils::ToLocal(
   10379         FACTORY->NewExternalStringFromAscii(&ascii_resource)));
   10380 
   10381     env->Global()->Set(v8_str("lhs"), lhs);
   10382     env->Global()->Set(v8_str("rhs"), rhs);
   10383 
   10384     CompileRun(
   10385         "var cons = lhs + rhs;"
   10386         "var slice = lhs.substring(1, lhs.length - 1);"
   10387         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   10388 
   10389     MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
   10390     MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
   10391 
   10392     // Now do some stuff to make sure the strings are flattened, etc.
   10393     CompileRun(
   10394         "/[^a-z]/.test(cons);"
   10395         "/[^a-z]/.test(slice);"
   10396         "/[^a-z]/.test(slice_on_cons);");
   10397     const char* expected_cons =
   10398         "Now is the time for all good men to come to the aid of the party"
   10399         "Now is the time for all good men to come to the aid of the party";
   10400     const char* expected_slice =
   10401         "ow is the time for all good men to come to the aid of the part";
   10402     const char* expected_slice_on_cons =
   10403         "ow is the time for all good men to come to the aid of the party"
   10404         "Now is the time for all good men to come to the aid of the part";
   10405     CHECK_EQ(String::New(expected_cons),
   10406              env->Global()->Get(v8_str("cons")));
   10407     CHECK_EQ(String::New(expected_slice),
   10408              env->Global()->Get(v8_str("slice")));
   10409     CHECK_EQ(String::New(expected_slice_on_cons),
   10410              env->Global()->Get(v8_str("slice_on_cons")));
   10411   }
   10412   i::DeleteArray(two_byte_string);
   10413 }
   10414 
   10415 
   10416 TEST(CompileExternalTwoByteSource) {
   10417   v8::HandleScope scope;
   10418   LocalContext context;
   10419 
   10420   // This is a very short list of sources, which currently is to check for a
   10421   // regression caused by r2703.
   10422   const char* ascii_sources[] = {
   10423     "0.5",
   10424     "-0.5",   // This mainly testes PushBack in the Scanner.
   10425     "--0.5",  // This mainly testes PushBack in the Scanner.
   10426     NULL
   10427   };
   10428 
   10429   // Compile the sources as external two byte strings.
   10430   for (int i = 0; ascii_sources[i] != NULL; i++) {
   10431     uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
   10432     UC16VectorResource uc16_resource(
   10433         i::Vector<const uint16_t>(two_byte_string,
   10434                                   i::StrLength(ascii_sources[i])));
   10435     v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
   10436     v8::Script::Compile(source);
   10437     i::DeleteArray(two_byte_string);
   10438   }
   10439 }
   10440 
   10441 
   10442 class RegExpStringModificationTest {
   10443  public:
   10444   RegExpStringModificationTest()
   10445       : block_(i::OS::CreateSemaphore(0)),
   10446         morphs_(0),
   10447         morphs_during_regexp_(0),
   10448         ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
   10449         uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
   10450   ~RegExpStringModificationTest() { delete block_; }
   10451   void RunTest() {
   10452     regexp_success_ = false;
   10453     morph_success_ = false;
   10454 
   10455     // Initialize the contents of two_byte_content_ to be a uc16 representation
   10456     // of "aaaaaaaaaaaaaab".
   10457     for (int i = 0; i < 14; i++) {
   10458       two_byte_content_[i] = 'a';
   10459     }
   10460     two_byte_content_[14] = 'b';
   10461 
   10462     // Create the input string for the regexp - the one we are going to change
   10463     // properties of.
   10464     input_ = FACTORY->NewExternalStringFromAscii(&ascii_resource_);
   10465 
   10466     // Inject the input as a global variable.
   10467     i::Handle<i::String> input_name =
   10468         FACTORY->NewStringFromAscii(i::Vector<const char>("input", 5));
   10469     i::Isolate::Current()->global_context()->global()->SetProperty(
   10470         *input_name,
   10471         *input_,
   10472         NONE,
   10473         i::kNonStrictMode)->ToObjectChecked();
   10474 
   10475     MorphThread morph_thread(i::Isolate::Current(), this);
   10476     morph_thread.Start();
   10477     v8::Locker::StartPreemption(1);
   10478     LongRunningRegExp();
   10479     {
   10480       v8::Unlocker unlock;
   10481       morph_thread.Join();
   10482     }
   10483     v8::Locker::StopPreemption();
   10484     CHECK(regexp_success_);
   10485     CHECK(morph_success_);
   10486   }
   10487  private:
   10488 
   10489   // Number of string modifications required.
   10490   static const int kRequiredModifications = 5;
   10491   static const int kMaxModifications = 100;
   10492 
   10493   class MorphThread : public i::Thread {
   10494    public:
   10495     explicit MorphThread(i::Isolate* isolate,
   10496                          RegExpStringModificationTest* test)
   10497         : Thread(isolate, "MorphThread"), test_(test) {}
   10498     virtual void Run() {
   10499       test_->MorphString();
   10500     }
   10501    private:
   10502      RegExpStringModificationTest* test_;
   10503   };
   10504 
   10505   void MorphString() {
   10506     block_->Wait();
   10507     while (morphs_during_regexp_ < kRequiredModifications &&
   10508            morphs_ < kMaxModifications) {
   10509       {
   10510         v8::Locker lock;
   10511         // Swap string between ascii and two-byte representation.
   10512         i::String* string = *input_;
   10513         MorphAString(string, &ascii_resource_, &uc16_resource_);
   10514         morphs_++;
   10515       }
   10516       i::OS::Sleep(1);
   10517     }
   10518     morph_success_ = true;
   10519   }
   10520 
   10521   void LongRunningRegExp() {
   10522     block_->Signal();  // Enable morphing thread on next preemption.
   10523     while (morphs_during_regexp_ < kRequiredModifications &&
   10524            morphs_ < kMaxModifications) {
   10525       int morphs_before = morphs_;
   10526       {
   10527         v8::HandleScope scope;
   10528         // Match 15-30 "a"'s against 14 and a "b".
   10529         const char* c_source =
   10530             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   10531             ".exec(input) === null";
   10532         Local<String> source = String::New(c_source);
   10533         Local<Script> script = Script::Compile(source);
   10534         Local<Value> result = script->Run();
   10535         CHECK(result->IsTrue());
   10536       }
   10537       int morphs_after = morphs_;
   10538       morphs_during_regexp_ += morphs_after - morphs_before;
   10539     }
   10540     regexp_success_ = true;
   10541   }
   10542 
   10543   i::uc16 two_byte_content_[15];
   10544   i::Semaphore* block_;
   10545   int morphs_;
   10546   int morphs_during_regexp_;
   10547   bool regexp_success_;
   10548   bool morph_success_;
   10549   i::Handle<i::String> input_;
   10550   AsciiVectorResource ascii_resource_;
   10551   UC16VectorResource uc16_resource_;
   10552 };
   10553 
   10554 
   10555 // Test that a regular expression execution can be interrupted and
   10556 // the string changed without failing.
   10557 TEST(RegExpStringModification) {
   10558   v8::Locker lock;
   10559   v8::V8::Initialize();
   10560   v8::HandleScope scope;
   10561   Local<Context> local_env;
   10562   {
   10563     LocalContext env;
   10564     local_env = env.local();
   10565   }
   10566 
   10567   // Local context should still be live.
   10568   CHECK(!local_env.IsEmpty());
   10569   local_env->Enter();
   10570 
   10571   // Should complete without problems.
   10572   RegExpStringModificationTest().RunTest();
   10573 
   10574   local_env->Exit();
   10575 }
   10576 
   10577 
   10578 // Test that we can set a property on the global object even if there
   10579 // is a read-only property in the prototype chain.
   10580 TEST(ReadOnlyPropertyInGlobalProto) {
   10581   v8::HandleScope scope;
   10582   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   10583   LocalContext context(0, templ);
   10584   v8::Handle<v8::Object> global = context->Global();
   10585   v8::Handle<v8::Object> global_proto =
   10586       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
   10587   global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
   10588   global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
   10589   // Check without 'eval' or 'with'.
   10590   v8::Handle<v8::Value> res =
   10591       CompileRun("function f() { x = 42; return x; }; f()");
   10592   // Check with 'eval'.
   10593   res = CompileRun("function f() { eval('1'); y = 42; return y; }; f()");
   10594   CHECK_EQ(v8::Integer::New(42), res);
   10595   // Check with 'with'.
   10596   res = CompileRun("function f() { with (this) { y = 42 }; return y; }; f()");
   10597   CHECK_EQ(v8::Integer::New(42), res);
   10598 }
   10599 
   10600 static int force_set_set_count = 0;
   10601 static int force_set_get_count = 0;
   10602 bool pass_on_get = false;
   10603 
   10604 static v8::Handle<v8::Value> ForceSetGetter(v8::Local<v8::String> name,
   10605                                             const v8::AccessorInfo& info) {
   10606   force_set_get_count++;
   10607   if (pass_on_get) {
   10608     return v8::Handle<v8::Value>();
   10609   } else {
   10610     return v8::Int32::New(3);
   10611   }
   10612 }
   10613 
   10614 static void ForceSetSetter(v8::Local<v8::String> name,
   10615                            v8::Local<v8::Value> value,
   10616                            const v8::AccessorInfo& info) {
   10617   force_set_set_count++;
   10618 }
   10619 
   10620 static v8::Handle<v8::Value> ForceSetInterceptSetter(
   10621     v8::Local<v8::String> name,
   10622     v8::Local<v8::Value> value,
   10623     const v8::AccessorInfo& info) {
   10624   force_set_set_count++;
   10625   return v8::Undefined();
   10626 }
   10627 
   10628 TEST(ForceSet) {
   10629   force_set_get_count = 0;
   10630   force_set_set_count = 0;
   10631   pass_on_get = false;
   10632 
   10633   v8::HandleScope scope;
   10634   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   10635   v8::Handle<v8::String> access_property = v8::String::New("a");
   10636   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
   10637   LocalContext context(NULL, templ);
   10638   v8::Handle<v8::Object> global = context->Global();
   10639 
   10640   // Ordinary properties
   10641   v8::Handle<v8::String> simple_property = v8::String::New("p");
   10642   global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
   10643   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   10644   // This should fail because the property is read-only
   10645   global->Set(simple_property, v8::Int32::New(5));
   10646   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   10647   // This should succeed even though the property is read-only
   10648   global->ForceSet(simple_property, v8::Int32::New(6));
   10649   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
   10650 
   10651   // Accessors
   10652   CHECK_EQ(0, force_set_set_count);
   10653   CHECK_EQ(0, force_set_get_count);
   10654   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   10655   // CHECK_EQ the property shouldn't override it, just call the setter
   10656   // which in this case does nothing.
   10657   global->Set(access_property, v8::Int32::New(7));
   10658   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   10659   CHECK_EQ(1, force_set_set_count);
   10660   CHECK_EQ(2, force_set_get_count);
   10661   // Forcing the property to be set should override the accessor without
   10662   // calling it
   10663   global->ForceSet(access_property, v8::Int32::New(8));
   10664   CHECK_EQ(8, global->Get(access_property)->Int32Value());
   10665   CHECK_EQ(1, force_set_set_count);
   10666   CHECK_EQ(2, force_set_get_count);
   10667 }
   10668 
   10669 TEST(ForceSetWithInterceptor) {
   10670   force_set_get_count = 0;
   10671   force_set_set_count = 0;
   10672   pass_on_get = false;
   10673 
   10674   v8::HandleScope scope;
   10675   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   10676   templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
   10677   LocalContext context(NULL, templ);
   10678   v8::Handle<v8::Object> global = context->Global();
   10679 
   10680   v8::Handle<v8::String> some_property = v8::String::New("a");
   10681   CHECK_EQ(0, force_set_set_count);
   10682   CHECK_EQ(0, force_set_get_count);
   10683   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   10684   // Setting the property shouldn't override it, just call the setter
   10685   // which in this case does nothing.
   10686   global->Set(some_property, v8::Int32::New(7));
   10687   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   10688   CHECK_EQ(1, force_set_set_count);
   10689   CHECK_EQ(2, force_set_get_count);
   10690   // Getting the property when the interceptor returns an empty handle
   10691   // should yield undefined, since the property isn't present on the
   10692   // object itself yet.
   10693   pass_on_get = true;
   10694   CHECK(global->Get(some_property)->IsUndefined());
   10695   CHECK_EQ(1, force_set_set_count);
   10696   CHECK_EQ(3, force_set_get_count);
   10697   // Forcing the property to be set should cause the value to be
   10698   // set locally without calling the interceptor.
   10699   global->ForceSet(some_property, v8::Int32::New(8));
   10700   CHECK_EQ(8, global->Get(some_property)->Int32Value());
   10701   CHECK_EQ(1, force_set_set_count);
   10702   CHECK_EQ(4, force_set_get_count);
   10703   // Reenabling the interceptor should cause it to take precedence over
   10704   // the property
   10705   pass_on_get = false;
   10706   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   10707   CHECK_EQ(1, force_set_set_count);
   10708   CHECK_EQ(5, force_set_get_count);
   10709   // The interceptor should also work for other properties
   10710   CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
   10711   CHECK_EQ(1, force_set_set_count);
   10712   CHECK_EQ(6, force_set_get_count);
   10713 }
   10714 
   10715 
   10716 THREADED_TEST(ForceDelete) {
   10717   v8::HandleScope scope;
   10718   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   10719   LocalContext context(NULL, templ);
   10720   v8::Handle<v8::Object> global = context->Global();
   10721 
   10722   // Ordinary properties
   10723   v8::Handle<v8::String> simple_property = v8::String::New("p");
   10724   global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
   10725   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   10726   // This should fail because the property is dont-delete.
   10727   CHECK(!global->Delete(simple_property));
   10728   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   10729   // This should succeed even though the property is dont-delete.
   10730   CHECK(global->ForceDelete(simple_property));
   10731   CHECK(global->Get(simple_property)->IsUndefined());
   10732 }
   10733 
   10734 
   10735 static int force_delete_interceptor_count = 0;
   10736 static bool pass_on_delete = false;
   10737 
   10738 
   10739 static v8::Handle<v8::Boolean> ForceDeleteDeleter(
   10740     v8::Local<v8::String> name,
   10741     const v8::AccessorInfo& info) {
   10742   force_delete_interceptor_count++;
   10743   if (pass_on_delete) {
   10744     return v8::Handle<v8::Boolean>();
   10745   } else {
   10746     return v8::True();
   10747   }
   10748 }
   10749 
   10750 
   10751 THREADED_TEST(ForceDeleteWithInterceptor) {
   10752   force_delete_interceptor_count = 0;
   10753   pass_on_delete = false;
   10754 
   10755   v8::HandleScope scope;
   10756   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   10757   templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
   10758   LocalContext context(NULL, templ);
   10759   v8::Handle<v8::Object> global = context->Global();
   10760 
   10761   v8::Handle<v8::String> some_property = v8::String::New("a");
   10762   global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
   10763 
   10764   // Deleting a property should get intercepted and nothing should
   10765   // happen.
   10766   CHECK_EQ(0, force_delete_interceptor_count);
   10767   CHECK(global->Delete(some_property));
   10768   CHECK_EQ(1, force_delete_interceptor_count);
   10769   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   10770   // Deleting the property when the interceptor returns an empty
   10771   // handle should not delete the property since it is DontDelete.
   10772   pass_on_delete = true;
   10773   CHECK(!global->Delete(some_property));
   10774   CHECK_EQ(2, force_delete_interceptor_count);
   10775   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   10776   // Forcing the property to be deleted should delete the value
   10777   // without calling the interceptor.
   10778   CHECK(global->ForceDelete(some_property));
   10779   CHECK(global->Get(some_property)->IsUndefined());
   10780   CHECK_EQ(2, force_delete_interceptor_count);
   10781 }
   10782 
   10783 
   10784 // Make sure that forcing a delete invalidates any IC stubs, so we
   10785 // don't read the hole value.
   10786 THREADED_TEST(ForceDeleteIC) {
   10787   v8::HandleScope scope;
   10788   LocalContext context;
   10789   // Create a DontDelete variable on the global object.
   10790   CompileRun("this.__proto__ = { foo: 'horse' };"
   10791              "var foo = 'fish';"
   10792              "function f() { return foo.length; }");
   10793   // Initialize the IC for foo in f.
   10794   CompileRun("for (var i = 0; i < 4; i++) f();");
   10795   // Make sure the value of foo is correct before the deletion.
   10796   CHECK_EQ(4, CompileRun("f()")->Int32Value());
   10797   // Force the deletion of foo.
   10798   CHECK(context->Global()->ForceDelete(v8_str("foo")));
   10799   // Make sure the value for foo is read from the prototype, and that
   10800   // we don't get in trouble with reading the deleted cell value
   10801   // sentinel.
   10802   CHECK_EQ(5, CompileRun("f()")->Int32Value());
   10803 }
   10804 
   10805 
   10806 v8::Persistent<Context> calling_context0;
   10807 v8::Persistent<Context> calling_context1;
   10808 v8::Persistent<Context> calling_context2;
   10809 
   10810 
   10811 // Check that the call to the callback is initiated in
   10812 // calling_context2, the directly calling context is calling_context1
   10813 // and the callback itself is in calling_context0.
   10814 static v8::Handle<Value> GetCallingContextCallback(const v8::Arguments& args) {
   10815   ApiTestFuzzer::Fuzz();
   10816   CHECK(Context::GetCurrent() == calling_context0);
   10817   CHECK(Context::GetCalling() == calling_context1);
   10818   CHECK(Context::GetEntered() == calling_context2);
   10819   return v8::Integer::New(42);
   10820 }
   10821 
   10822 
   10823 THREADED_TEST(GetCallingContext) {
   10824   v8::HandleScope scope;
   10825 
   10826   calling_context0 = Context::New();
   10827   calling_context1 = Context::New();
   10828   calling_context2 = Context::New();
   10829 
   10830   // Allow cross-domain access.
   10831   Local<String> token = v8_str("<security token>");
   10832   calling_context0->SetSecurityToken(token);
   10833   calling_context1->SetSecurityToken(token);
   10834   calling_context2->SetSecurityToken(token);
   10835 
   10836   // Create an object with a C++ callback in context0.
   10837   calling_context0->Enter();
   10838   Local<v8::FunctionTemplate> callback_templ =
   10839       v8::FunctionTemplate::New(GetCallingContextCallback);
   10840   calling_context0->Global()->Set(v8_str("callback"),
   10841                                   callback_templ->GetFunction());
   10842   calling_context0->Exit();
   10843 
   10844   // Expose context0 in context1 and setup a function that calls the
   10845   // callback function.
   10846   calling_context1->Enter();
   10847   calling_context1->Global()->Set(v8_str("context0"),
   10848                                   calling_context0->Global());
   10849   CompileRun("function f() { context0.callback() }");
   10850   calling_context1->Exit();
   10851 
   10852   // Expose context1 in context2 and call the callback function in
   10853   // context0 indirectly through f in context1.
   10854   calling_context2->Enter();
   10855   calling_context2->Global()->Set(v8_str("context1"),
   10856                                   calling_context1->Global());
   10857   CompileRun("context1.f()");
   10858   calling_context2->Exit();
   10859 
   10860   // Dispose the contexts to allow them to be garbage collected.
   10861   calling_context0.Dispose();
   10862   calling_context1.Dispose();
   10863   calling_context2.Dispose();
   10864   calling_context0.Clear();
   10865   calling_context1.Clear();
   10866   calling_context2.Clear();
   10867 }
   10868 
   10869 
   10870 // Check that a variable declaration with no explicit initialization
   10871 // value does not shadow an existing property in the prototype chain.
   10872 //
   10873 // This is consistent with Firefox and Safari.
   10874 //
   10875 // See http://crbug.com/12548.
   10876 THREADED_TEST(InitGlobalVarInProtoChain) {
   10877   v8::HandleScope scope;
   10878   LocalContext context;
   10879   // Introduce a variable in the prototype chain.
   10880   CompileRun("__proto__.x = 42");
   10881   v8::Handle<v8::Value> result = CompileRun("var x; x");
   10882   CHECK(!result->IsUndefined());
   10883   CHECK_EQ(42, result->Int32Value());
   10884 }
   10885 
   10886 
   10887 // Regression test for issue 398.
   10888 // If a function is added to an object, creating a constant function
   10889 // field, and the result is cloned, replacing the constant function on the
   10890 // original should not affect the clone.
   10891 // See http://code.google.com/p/v8/issues/detail?id=398
   10892 THREADED_TEST(ReplaceConstantFunction) {
   10893   v8::HandleScope scope;
   10894   LocalContext context;
   10895   v8::Handle<v8::Object> obj = v8::Object::New();
   10896   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
   10897   v8::Handle<v8::String> foo_string = v8::String::New("foo");
   10898   obj->Set(foo_string, func_templ->GetFunction());
   10899   v8::Handle<v8::Object> obj_clone = obj->Clone();
   10900   obj_clone->Set(foo_string, v8::String::New("Hello"));
   10901   CHECK(!obj->Get(foo_string)->IsUndefined());
   10902 }
   10903 
   10904 
   10905 // Regression test for http://crbug.com/16276.
   10906 THREADED_TEST(Regress16276) {
   10907   v8::HandleScope scope;
   10908   LocalContext context;
   10909   // Force the IC in f to be a dictionary load IC.
   10910   CompileRun("function f(obj) { return obj.x; }\n"
   10911              "var obj = { x: { foo: 42 }, y: 87 };\n"
   10912              "var x = obj.x;\n"
   10913              "delete obj.y;\n"
   10914              "for (var i = 0; i < 5; i++) f(obj);");
   10915   // Detach the global object to make 'this' refer directly to the
   10916   // global object (not the proxy), and make sure that the dictionary
   10917   // load IC doesn't mess up loading directly from the global object.
   10918   context->DetachGlobal();
   10919   CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
   10920 }
   10921 
   10922 
   10923 THREADED_TEST(PixelArray) {
   10924   v8::HandleScope scope;
   10925   LocalContext context;
   10926   const int kElementCount = 260;
   10927   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   10928   i::Handle<i::ExternalPixelArray> pixels =
   10929       i::Handle<i::ExternalPixelArray>::cast(
   10930           FACTORY->NewExternalArray(kElementCount,
   10931                                        v8::kExternalPixelArray,
   10932                                        pixel_data));
   10933   HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   10934   for (int i = 0; i < kElementCount; i++) {
   10935     pixels->set(i, i % 256);
   10936   }
   10937   HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   10938   for (int i = 0; i < kElementCount; i++) {
   10939     CHECK_EQ(i % 256, pixels->get(i));
   10940     CHECK_EQ(i % 256, pixel_data[i]);
   10941   }
   10942 
   10943   v8::Handle<v8::Object> obj = v8::Object::New();
   10944   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   10945   // Set the elements to be the pixels.
   10946   // jsobj->set_elements(*pixels);
   10947   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   10948   CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   10949   obj->Set(v8_str("field"), v8::Int32::New(1503));
   10950   context->Global()->Set(v8_str("pixels"), obj);
   10951   v8::Handle<v8::Value> result = CompileRun("pixels.field");
   10952   CHECK_EQ(1503, result->Int32Value());
   10953   result = CompileRun("pixels[1]");
   10954   CHECK_EQ(1, result->Int32Value());
   10955 
   10956   result = CompileRun("var sum = 0;"
   10957                       "for (var i = 0; i < 8; i++) {"
   10958                       "  sum += pixels[i] = pixels[i] = -i;"
   10959                       "}"
   10960                       "sum;");
   10961   CHECK_EQ(-28, result->Int32Value());
   10962 
   10963   result = CompileRun("var sum = 0;"
   10964                       "for (var i = 0; i < 8; i++) {"
   10965                       "  sum += pixels[i] = pixels[i] = 0;"
   10966                       "}"
   10967                       "sum;");
   10968   CHECK_EQ(0, result->Int32Value());
   10969 
   10970   result = CompileRun("var sum = 0;"
   10971                       "for (var i = 0; i < 8; i++) {"
   10972                       "  sum += pixels[i] = pixels[i] = 255;"
   10973                       "}"
   10974                       "sum;");
   10975   CHECK_EQ(8 * 255, result->Int32Value());
   10976 
   10977   result = CompileRun("var sum = 0;"
   10978                       "for (var i = 0; i < 8; i++) {"
   10979                       "  sum += pixels[i] = pixels[i] = 256 + i;"
   10980                       "}"
   10981                       "sum;");
   10982   CHECK_EQ(2076, result->Int32Value());
   10983 
   10984   result = CompileRun("var sum = 0;"
   10985                       "for (var i = 0; i < 8; i++) {"
   10986                       "  sum += pixels[i] = pixels[i] = i;"
   10987                       "}"
   10988                       "sum;");
   10989   CHECK_EQ(28, result->Int32Value());
   10990 
   10991   result = CompileRun("var sum = 0;"
   10992                       "for (var i = 0; i < 8; i++) {"
   10993                       "  sum += pixels[i];"
   10994                       "}"
   10995                       "sum;");
   10996   CHECK_EQ(28, result->Int32Value());
   10997 
   10998   i::Handle<i::Smi> value(i::Smi::FromInt(2));
   10999   i::SetElement(jsobj, 1, value, i::kNonStrictMode);
   11000   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   11001   *value.location() = i::Smi::FromInt(256);
   11002   i::SetElement(jsobj, 1, value, i::kNonStrictMode);
   11003   CHECK_EQ(255,
   11004            i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   11005   *value.location() = i::Smi::FromInt(-1);
   11006   i::SetElement(jsobj, 1, value, i::kNonStrictMode);
   11007   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   11008 
   11009   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11010                       "  pixels[i] = (i * 65) - 109;"
   11011                       "}"
   11012                       "pixels[1] + pixels[6];");
   11013   CHECK_EQ(255, result->Int32Value());
   11014   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
   11015   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   11016   CHECK_EQ(21,
   11017            i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
   11018   CHECK_EQ(86,
   11019            i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
   11020   CHECK_EQ(151,
   11021            i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
   11022   CHECK_EQ(216,
   11023            i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   11024   CHECK_EQ(255,
   11025            i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   11026   CHECK_EQ(255,
   11027            i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   11028   result = CompileRun("var sum = 0;"
   11029                       "for (var i = 0; i < 8; i++) {"
   11030                       "  sum += pixels[i];"
   11031                       "}"
   11032                       "sum;");
   11033   CHECK_EQ(984, result->Int32Value());
   11034 
   11035   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11036                       "  pixels[i] = (i * 1.1);"
   11037                       "}"
   11038                       "pixels[1] + pixels[6];");
   11039   CHECK_EQ(8, result->Int32Value());
   11040   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
   11041   CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   11042   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
   11043   CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
   11044   CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
   11045   CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   11046   CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   11047   CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   11048 
   11049   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11050                       "  pixels[7] = undefined;"
   11051                       "}"
   11052                       "pixels[7];");
   11053   CHECK_EQ(0, result->Int32Value());
   11054   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   11055 
   11056   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11057                       "  pixels[6] = '2.3';"
   11058                       "}"
   11059                       "pixels[6];");
   11060   CHECK_EQ(2, result->Int32Value());
   11061   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   11062 
   11063   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11064                       "  pixels[5] = NaN;"
   11065                       "}"
   11066                       "pixels[5];");
   11067   CHECK_EQ(0, result->Int32Value());
   11068   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   11069 
   11070   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11071                       "  pixels[8] = Infinity;"
   11072                       "}"
   11073                       "pixels[8];");
   11074   CHECK_EQ(255, result->Int32Value());
   11075   CHECK_EQ(255,
   11076            i::Smi::cast(jsobj->GetElement(8)->ToObjectChecked())->value());
   11077 
   11078   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11079                       "  pixels[9] = -Infinity;"
   11080                       "}"
   11081                       "pixels[9];");
   11082   CHECK_EQ(0, result->Int32Value());
   11083   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9)->ToObjectChecked())->value());
   11084 
   11085   result = CompileRun("pixels[3] = 33;"
   11086                       "delete pixels[3];"
   11087                       "pixels[3];");
   11088   CHECK_EQ(33, result->Int32Value());
   11089 
   11090   result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
   11091                       "pixels[2] = 12; pixels[3] = 13;"
   11092                       "pixels.__defineGetter__('2',"
   11093                       "function() { return 120; });"
   11094                       "pixels[2];");
   11095   CHECK_EQ(12, result->Int32Value());
   11096 
   11097   result = CompileRun("var js_array = new Array(40);"
   11098                       "js_array[0] = 77;"
   11099                       "js_array;");
   11100   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   11101 
   11102   result = CompileRun("pixels[1] = 23;"
   11103                       "pixels.__proto__ = [];"
   11104                       "js_array.__proto__ = pixels;"
   11105                       "js_array.concat(pixels);");
   11106   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   11107   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   11108 
   11109   result = CompileRun("pixels[1] = 23;");
   11110   CHECK_EQ(23, result->Int32Value());
   11111 
   11112   // Test for index greater than 255.  Regression test for:
   11113   // http://code.google.com/p/chromium/issues/detail?id=26337.
   11114   result = CompileRun("pixels[256] = 255;");
   11115   CHECK_EQ(255, result->Int32Value());
   11116   result = CompileRun("var i = 0;"
   11117                       "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
   11118                       "i");
   11119   CHECK_EQ(255, result->Int32Value());
   11120 
   11121   // Make sure that pixel array ICs recognize when a non-pixel array
   11122   // is passed to it.
   11123   result = CompileRun("function pa_load(p) {"
   11124                       "  var sum = 0;"
   11125                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   11126                       "  return sum;"
   11127                       "}"
   11128                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   11129                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   11130                       "just_ints = new Object();"
   11131                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   11132                       "for (var i = 0; i < 10; ++i) {"
   11133                       "  result = pa_load(just_ints);"
   11134                       "}"
   11135                       "result");
   11136   CHECK_EQ(32640, result->Int32Value());
   11137 
   11138   // Make sure that pixel array ICs recognize out-of-bound accesses.
   11139   result = CompileRun("function pa_load(p, start) {"
   11140                       "  var sum = 0;"
   11141                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   11142                       "  return sum;"
   11143                       "}"
   11144                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   11145                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   11146                       "for (var i = 0; i < 10; ++i) {"
   11147                       "  result = pa_load(pixels,-10);"
   11148                       "}"
   11149                       "result");
   11150   CHECK_EQ(0, result->Int32Value());
   11151 
   11152   // Make sure that generic ICs properly handles a pixel array.
   11153   result = CompileRun("function pa_load(p) {"
   11154                       "  var sum = 0;"
   11155                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   11156                       "  return sum;"
   11157                       "}"
   11158                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   11159                       "just_ints = new Object();"
   11160                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   11161                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   11162                       "for (var i = 0; i < 10; ++i) {"
   11163                       "  result = pa_load(pixels);"
   11164                       "}"
   11165                       "result");
   11166   CHECK_EQ(32640, result->Int32Value());
   11167 
   11168   // Make sure that generic load ICs recognize out-of-bound accesses in
   11169   // pixel arrays.
   11170   result = CompileRun("function pa_load(p, start) {"
   11171                       "  var sum = 0;"
   11172                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   11173                       "  return sum;"
   11174                       "}"
   11175                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   11176                       "just_ints = new Object();"
   11177                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   11178                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
   11179                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   11180                       "for (var i = 0; i < 10; ++i) {"
   11181                       "  result = pa_load(pixels,-10);"
   11182                       "}"
   11183                       "result");
   11184   CHECK_EQ(0, result->Int32Value());
   11185 
   11186   // Make sure that generic ICs properly handles other types than pixel
   11187   // arrays (that the inlined fast pixel array test leaves the right information
   11188   // in the right registers).
   11189   result = CompileRun("function pa_load(p) {"
   11190                       "  var sum = 0;"
   11191                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   11192                       "  return sum;"
   11193                       "}"
   11194                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   11195                       "just_ints = new Object();"
   11196                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   11197                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   11198                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   11199                       "sparse_array = new Object();"
   11200                       "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
   11201                       "sparse_array[1000000] = 3;"
   11202                       "for (var i = 0; i < 10; ++i) {"
   11203                       "  result = pa_load(sparse_array);"
   11204                       "}"
   11205                       "result");
   11206   CHECK_EQ(32640, result->Int32Value());
   11207 
   11208   // Make sure that pixel array store ICs clamp values correctly.
   11209   result = CompileRun("function pa_store(p) {"
   11210                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   11211                       "}"
   11212                       "pa_store(pixels);"
   11213                       "var sum = 0;"
   11214                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   11215                       "sum");
   11216   CHECK_EQ(48896, result->Int32Value());
   11217 
   11218   // Make sure that pixel array stores correctly handle accesses outside
   11219   // of the pixel array..
   11220   result = CompileRun("function pa_store(p,start) {"
   11221                       "  for (var j = 0; j < 256; j++) {"
   11222                       "    p[j+start] = j * 2;"
   11223                       "  }"
   11224                       "}"
   11225                       "pa_store(pixels,0);"
   11226                       "pa_store(pixels,-128);"
   11227                       "var sum = 0;"
   11228                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   11229                       "sum");
   11230   CHECK_EQ(65280, result->Int32Value());
   11231 
   11232   // Make sure that the generic store stub correctly handle accesses outside
   11233   // of the pixel array..
   11234   result = CompileRun("function pa_store(p,start) {"
   11235                       "  for (var j = 0; j < 256; j++) {"
   11236                       "    p[j+start] = j * 2;"
   11237                       "  }"
   11238                       "}"
   11239                       "pa_store(pixels,0);"
   11240                       "just_ints = new Object();"
   11241                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   11242                       "pa_store(just_ints, 0);"
   11243                       "pa_store(pixels,-128);"
   11244                       "var sum = 0;"
   11245                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   11246                       "sum");
   11247   CHECK_EQ(65280, result->Int32Value());
   11248 
   11249   // Make sure that the generic keyed store stub clamps pixel array values
   11250   // correctly.
   11251   result = CompileRun("function pa_store(p) {"
   11252                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   11253                       "}"
   11254                       "pa_store(pixels);"
   11255                       "just_ints = new Object();"
   11256                       "pa_store(just_ints);"
   11257                       "pa_store(pixels);"
   11258                       "var sum = 0;"
   11259                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   11260                       "sum");
   11261   CHECK_EQ(48896, result->Int32Value());
   11262 
   11263   // Make sure that pixel array loads are optimized by crankshaft.
   11264   result = CompileRun("function pa_load(p) {"
   11265                       "  var sum = 0;"
   11266                       "  for (var i=0; i<256; ++i) {"
   11267                       "    sum += p[i];"
   11268                       "  }"
   11269                       "  return sum; "
   11270                       "}"
   11271                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   11272                       "for (var i = 0; i < 5000; ++i) {"
   11273                       "  result = pa_load(pixels);"
   11274                       "}"
   11275                       "result");
   11276   CHECK_EQ(32640, result->Int32Value());
   11277 
   11278   // Make sure that pixel array stores are optimized by crankshaft.
   11279   result = CompileRun("function pa_init(p) {"
   11280                       "for (var i = 0; i < 256; ++i) { p[i] = i; }"
   11281                       "}"
   11282                       "function pa_load(p) {"
   11283                       "  var sum = 0;"
   11284                       "  for (var i=0; i<256; ++i) {"
   11285                       "    sum += p[i];"
   11286                       "  }"
   11287                       "  return sum; "
   11288                       "}"
   11289                       "for (var i = 0; i < 5000; ++i) {"
   11290                       "  pa_init(pixels);"
   11291                       "}"
   11292                       "result = pa_load(pixels);"
   11293                       "result");
   11294   CHECK_EQ(32640, result->Int32Value());
   11295 
   11296   free(pixel_data);
   11297 }
   11298 
   11299 
   11300 THREADED_TEST(PixelArrayInfo) {
   11301   v8::HandleScope scope;
   11302   LocalContext context;
   11303   for (int size = 0; size < 100; size += 10) {
   11304     uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
   11305     v8::Handle<v8::Object> obj = v8::Object::New();
   11306     obj->SetIndexedPropertiesToPixelData(pixel_data, size);
   11307     CHECK(obj->HasIndexedPropertiesInPixelData());
   11308     CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
   11309     CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
   11310     free(pixel_data);
   11311   }
   11312 }
   11313 
   11314 
   11315 static v8::Handle<Value> NotHandledIndexedPropertyGetter(
   11316     uint32_t index,
   11317     const AccessorInfo& info) {
   11318   ApiTestFuzzer::Fuzz();
   11319   return v8::Handle<Value>();
   11320 }
   11321 
   11322 
   11323 static v8::Handle<Value> NotHandledIndexedPropertySetter(
   11324     uint32_t index,
   11325     Local<Value> value,
   11326     const AccessorInfo& info) {
   11327   ApiTestFuzzer::Fuzz();
   11328   return v8::Handle<Value>();
   11329 }
   11330 
   11331 
   11332 THREADED_TEST(PixelArrayWithInterceptor) {
   11333   v8::HandleScope scope;
   11334   LocalContext context;
   11335   const int kElementCount = 260;
   11336   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   11337   i::Handle<i::ExternalPixelArray> pixels =
   11338       i::Handle<i::ExternalPixelArray>::cast(
   11339           FACTORY->NewExternalArray(kElementCount,
   11340                                     v8::kExternalPixelArray,
   11341                                     pixel_data));
   11342   for (int i = 0; i < kElementCount; i++) {
   11343     pixels->set(i, i % 256);
   11344   }
   11345   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   11346   templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
   11347                                    NotHandledIndexedPropertySetter);
   11348   v8::Handle<v8::Object> obj = templ->NewInstance();
   11349   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   11350   context->Global()->Set(v8_str("pixels"), obj);
   11351   v8::Handle<v8::Value> result = CompileRun("pixels[1]");
   11352   CHECK_EQ(1, result->Int32Value());
   11353   result = CompileRun("var sum = 0;"
   11354                       "for (var i = 0; i < 8; i++) {"
   11355                       "  sum += pixels[i] = pixels[i] = -i;"
   11356                       "}"
   11357                       "sum;");
   11358   CHECK_EQ(-28, result->Int32Value());
   11359   result = CompileRun("pixels.hasOwnProperty('1')");
   11360   CHECK(result->BooleanValue());
   11361   free(pixel_data);
   11362 }
   11363 
   11364 
   11365 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
   11366   switch (array_type) {
   11367     case v8::kExternalByteArray:
   11368     case v8::kExternalUnsignedByteArray:
   11369     case v8::kExternalPixelArray:
   11370       return 1;
   11371       break;
   11372     case v8::kExternalShortArray:
   11373     case v8::kExternalUnsignedShortArray:
   11374       return 2;
   11375       break;
   11376     case v8::kExternalIntArray:
   11377     case v8::kExternalUnsignedIntArray:
   11378     case v8::kExternalFloatArray:
   11379       return 4;
   11380       break;
   11381     default:
   11382       UNREACHABLE();
   11383       return -1;
   11384   }
   11385   UNREACHABLE();
   11386   return -1;
   11387 }
   11388 
   11389 
   11390 template <class ExternalArrayClass, class ElementType>
   11391 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
   11392                                     int64_t low,
   11393                                     int64_t high) {
   11394   v8::HandleScope scope;
   11395   LocalContext context;
   11396   const int kElementCount = 40;
   11397   int element_size = ExternalArrayElementSize(array_type);
   11398   ElementType* array_data =
   11399       static_cast<ElementType*>(malloc(kElementCount * element_size));
   11400   i::Handle<ExternalArrayClass> array =
   11401       i::Handle<ExternalArrayClass>::cast(
   11402           FACTORY->NewExternalArray(kElementCount, array_type, array_data));
   11403   HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   11404   for (int i = 0; i < kElementCount; i++) {
   11405     array->set(i, static_cast<ElementType>(i));
   11406   }
   11407   HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   11408   for (int i = 0; i < kElementCount; i++) {
   11409     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array->get(i)));
   11410     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
   11411   }
   11412 
   11413   v8::Handle<v8::Object> obj = v8::Object::New();
   11414   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   11415   // Set the elements to be the external array.
   11416   obj->SetIndexedPropertiesToExternalArrayData(array_data,
   11417                                                array_type,
   11418                                                kElementCount);
   11419   CHECK_EQ(
   11420       1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
   11421   obj->Set(v8_str("field"), v8::Int32::New(1503));
   11422   context->Global()->Set(v8_str("ext_array"), obj);
   11423   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
   11424   CHECK_EQ(1503, result->Int32Value());
   11425   result = CompileRun("ext_array[1]");
   11426   CHECK_EQ(1, result->Int32Value());
   11427 
   11428   // Check pass through of assigned smis
   11429   result = CompileRun("var sum = 0;"
   11430                       "for (var i = 0; i < 8; i++) {"
   11431                       "  sum += ext_array[i] = ext_array[i] = -i;"
   11432                       "}"
   11433                       "sum;");
   11434   CHECK_EQ(-28, result->Int32Value());
   11435 
   11436   // Check assigned smis
   11437   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11438                       "  ext_array[i] = i;"
   11439                       "}"
   11440                       "var sum = 0;"
   11441                       "for (var i = 0; i < 8; i++) {"
   11442                       "  sum += ext_array[i];"
   11443                       "}"
   11444                       "sum;");
   11445   CHECK_EQ(28, result->Int32Value());
   11446 
   11447   // Check assigned smis in reverse order
   11448   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   11449                       "  ext_array[i] = i;"
   11450                       "}"
   11451                       "var sum = 0;"
   11452                       "for (var i = 0; i < 8; i++) {"
   11453                       "  sum += ext_array[i];"
   11454                       "}"
   11455                       "sum;");
   11456   CHECK_EQ(28, result->Int32Value());
   11457 
   11458   // Check pass through of assigned HeapNumbers
   11459   result = CompileRun("var sum = 0;"
   11460                       "for (var i = 0; i < 16; i+=2) {"
   11461                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   11462                       "}"
   11463                       "sum;");
   11464   CHECK_EQ(-28, result->Int32Value());
   11465 
   11466   // Check assigned HeapNumbers
   11467   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   11468                       "  ext_array[i] = (i * 0.5);"
   11469                       "}"
   11470                       "var sum = 0;"
   11471                       "for (var i = 0; i < 16; i+=2) {"
   11472                       "  sum += ext_array[i];"
   11473                       "}"
   11474                       "sum;");
   11475   CHECK_EQ(28, result->Int32Value());
   11476 
   11477   // Check assigned HeapNumbers in reverse order
   11478   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   11479                       "  ext_array[i] = (i * 0.5);"
   11480                       "}"
   11481                       "var sum = 0;"
   11482                       "for (var i = 0; i < 16; i+=2) {"
   11483                       "  sum += ext_array[i];"
   11484                       "}"
   11485                       "sum;");
   11486   CHECK_EQ(28, result->Int32Value());
   11487 
   11488   i::ScopedVector<char> test_buf(1024);
   11489 
   11490   // Check legal boundary conditions.
   11491   // The repeated loads and stores ensure the ICs are exercised.
   11492   const char* boundary_program =
   11493       "var res = 0;"
   11494       "for (var i = 0; i < 16; i++) {"
   11495       "  ext_array[i] = %lld;"
   11496       "  if (i > 8) {"
   11497       "    res = ext_array[i];"
   11498       "  }"
   11499       "}"
   11500       "res;";
   11501   i::OS::SNPrintF(test_buf,
   11502                   boundary_program,
   11503                   low);
   11504   result = CompileRun(test_buf.start());
   11505   CHECK_EQ(low, result->IntegerValue());
   11506 
   11507   i::OS::SNPrintF(test_buf,
   11508                   boundary_program,
   11509                   high);
   11510   result = CompileRun(test_buf.start());
   11511   CHECK_EQ(high, result->IntegerValue());
   11512 
   11513   // Check misprediction of type in IC.
   11514   result = CompileRun("var tmp_array = ext_array;"
   11515                       "var sum = 0;"
   11516                       "for (var i = 0; i < 8; i++) {"
   11517                       "  tmp_array[i] = i;"
   11518                       "  sum += tmp_array[i];"
   11519                       "  if (i == 4) {"
   11520                       "    tmp_array = {};"
   11521                       "  }"
   11522                       "}"
   11523                       "sum;");
   11524   HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   11525   CHECK_EQ(28, result->Int32Value());
   11526 
   11527   // Make sure out-of-range loads do not throw.
   11528   i::OS::SNPrintF(test_buf,
   11529                   "var caught_exception = false;"
   11530                   "try {"
   11531                   "  ext_array[%d];"
   11532                   "} catch (e) {"
   11533                   "  caught_exception = true;"
   11534                   "}"
   11535                   "caught_exception;",
   11536                   kElementCount);
   11537   result = CompileRun(test_buf.start());
   11538   CHECK_EQ(false, result->BooleanValue());
   11539 
   11540   // Make sure out-of-range stores do not throw.
   11541   i::OS::SNPrintF(test_buf,
   11542                   "var caught_exception = false;"
   11543                   "try {"
   11544                   "  ext_array[%d] = 1;"
   11545                   "} catch (e) {"
   11546                   "  caught_exception = true;"
   11547                   "}"
   11548                   "caught_exception;",
   11549                   kElementCount);
   11550   result = CompileRun(test_buf.start());
   11551   CHECK_EQ(false, result->BooleanValue());
   11552 
   11553   // Check other boundary conditions, values and operations.
   11554   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11555                       "  ext_array[7] = undefined;"
   11556                       "}"
   11557                       "ext_array[7];");
   11558   CHECK_EQ(0, result->Int32Value());
   11559   CHECK_EQ(
   11560       0, static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number()));
   11561 
   11562   result = CompileRun("for (var i = 0; i < 8; i++) {"
   11563                       "  ext_array[6] = '2.3';"
   11564                       "}"
   11565                       "ext_array[6];");
   11566   CHECK_EQ(2, result->Int32Value());
   11567   CHECK_EQ(
   11568       2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number()));
   11569 
   11570   if (array_type != v8::kExternalFloatArray) {
   11571     // Though the specification doesn't state it, be explicit about
   11572     // converting NaNs and +/-Infinity to zero.
   11573     result = CompileRun("for (var i = 0; i < 8; i++) {"
   11574                         "  ext_array[i] = 5;"
   11575                         "}"
   11576                         "for (var i = 0; i < 8; i++) {"
   11577                         "  ext_array[i] = NaN;"
   11578                         "}"
   11579                         "ext_array[5];");
   11580     CHECK_EQ(0, result->Int32Value());
   11581     CHECK_EQ(0,
   11582              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   11583 
   11584     result = CompileRun("for (var i = 0; i < 8; i++) {"
   11585                         "  ext_array[i] = 5;"
   11586                         "}"
   11587                         "for (var i = 0; i < 8; i++) {"
   11588                         "  ext_array[i] = Infinity;"
   11589                         "}"
   11590                         "ext_array[5];");
   11591     int expected_value =
   11592         (array_type == v8::kExternalPixelArray) ? 255 : 0;
   11593     CHECK_EQ(expected_value, result->Int32Value());
   11594     CHECK_EQ(expected_value,
   11595              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   11596 
   11597     result = CompileRun("for (var i = 0; i < 8; i++) {"
   11598                         "  ext_array[i] = 5;"
   11599                         "}"
   11600                         "for (var i = 0; i < 8; i++) {"
   11601                         "  ext_array[i] = -Infinity;"
   11602                         "}"
   11603                         "ext_array[5];");
   11604     CHECK_EQ(0, result->Int32Value());
   11605     CHECK_EQ(0,
   11606              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   11607 
   11608     // Check truncation behavior of integral arrays.
   11609     const char* unsigned_data =
   11610         "var source_data = [0.6, 10.6];"
   11611         "var expected_results = [0, 10];";
   11612     const char* signed_data =
   11613         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   11614         "var expected_results = [0, 10, 0, -10];";
   11615     const char* pixel_data =
   11616         "var source_data = [0.6, 10.6];"
   11617         "var expected_results = [1, 11];";
   11618     bool is_unsigned =
   11619         (array_type == v8::kExternalUnsignedByteArray ||
   11620          array_type == v8::kExternalUnsignedShortArray ||
   11621          array_type == v8::kExternalUnsignedIntArray);
   11622     bool is_pixel_data = array_type == v8::kExternalPixelArray;
   11623 
   11624     i::OS::SNPrintF(test_buf,
   11625                     "%s"
   11626                     "var all_passed = true;"
   11627                     "for (var i = 0; i < source_data.length; i++) {"
   11628                     "  for (var j = 0; j < 8; j++) {"
   11629                     "    ext_array[j] = source_data[i];"
   11630                     "  }"
   11631                     "  all_passed = all_passed &&"
   11632                     "               (ext_array[5] == expected_results[i]);"
   11633                     "}"
   11634                     "all_passed;",
   11635                     (is_unsigned ?
   11636                          unsigned_data :
   11637                          (is_pixel_data ? pixel_data : signed_data)));
   11638     result = CompileRun(test_buf.start());
   11639     CHECK_EQ(true, result->BooleanValue());
   11640   }
   11641 
   11642   // Test crankshaft external array loads
   11643   for (int i = 0; i < kElementCount; i++) {
   11644     array->set(i, static_cast<ElementType>(i));
   11645   }
   11646   result = CompileRun("function ee_load_test_func(sum) {"
   11647                       " for (var i = 0; i < 40; ++i)"
   11648                       "   sum += ext_array[i];"
   11649                       " return sum;"
   11650                       "}"
   11651                       "sum=0;"
   11652                       "for (var i=0;i<10000;++i) {"
   11653                       "  sum=ee_load_test_func(sum);"
   11654                       "}"
   11655                       "sum;");
   11656   CHECK_EQ(7800000, result->Int32Value());
   11657 
   11658   // Test crankshaft external array stores
   11659   result = CompileRun("function ee_store_test_func(sum) {"
   11660                       " for (var i = 0; i < 40; ++i)"
   11661                       "   sum += ext_array[i] = i;"
   11662                       " return sum;"
   11663                       "}"
   11664                       "sum=0;"
   11665                       "for (var i=0;i<10000;++i) {"
   11666                       "  sum=ee_store_test_func(sum);"
   11667                       "}"
   11668                       "sum;");
   11669   CHECK_EQ(7800000, result->Int32Value());
   11670 
   11671   for (int i = 0; i < kElementCount; i++) {
   11672     array->set(i, static_cast<ElementType>(i));
   11673   }
   11674   // Test complex assignments
   11675   result = CompileRun("function ee_op_test_complex_func(sum) {"
   11676                       " for (var i = 0; i < 40; ++i) {"
   11677                       "   sum += (ext_array[i] += 1);"
   11678                       "   sum += (ext_array[i] -= 1);"
   11679                       " } "
   11680                       " return sum;"
   11681                       "}"
   11682                       "sum=0;"
   11683                       "for (var i=0;i<10000;++i) {"
   11684                       "  sum=ee_op_test_complex_func(sum);"
   11685                       "}"
   11686                       "sum;");
   11687   CHECK_EQ(16000000, result->Int32Value());
   11688 
   11689   // Test count operations
   11690   result = CompileRun("function ee_op_test_count_func(sum) {"
   11691                       " for (var i = 0; i < 40; ++i) {"
   11692                       "   sum += (++ext_array[i]);"
   11693                       "   sum += (--ext_array[i]);"
   11694                       " } "
   11695                       " return sum;"
   11696                       "}"
   11697                       "sum=0;"
   11698                       "for (var i=0;i<10000;++i) {"
   11699                       "  sum=ee_op_test_count_func(sum);"
   11700                       "}"
   11701                       "sum;");
   11702   CHECK_EQ(16000000, result->Int32Value());
   11703 
   11704   result = CompileRun("ext_array[3] = 33;"
   11705                       "delete ext_array[3];"
   11706                       "ext_array[3];");
   11707   CHECK_EQ(33, result->Int32Value());
   11708 
   11709   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
   11710                       "ext_array[2] = 12; ext_array[3] = 13;"
   11711                       "ext_array.__defineGetter__('2',"
   11712                       "function() { return 120; });"
   11713                       "ext_array[2];");
   11714   CHECK_EQ(12, result->Int32Value());
   11715 
   11716   result = CompileRun("var js_array = new Array(40);"
   11717                       "js_array[0] = 77;"
   11718                       "js_array;");
   11719   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   11720 
   11721   result = CompileRun("ext_array[1] = 23;"
   11722                       "ext_array.__proto__ = [];"
   11723                       "js_array.__proto__ = ext_array;"
   11724                       "js_array.concat(ext_array);");
   11725   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   11726   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   11727 
   11728   result = CompileRun("ext_array[1] = 23;");
   11729   CHECK_EQ(23, result->Int32Value());
   11730 
   11731   // Test more complex manipulations which cause eax to contain values
   11732   // that won't be completely overwritten by loads from the arrays.
   11733   // This catches bugs in the instructions used for the KeyedLoadIC
   11734   // for byte and word types.
   11735   {
   11736     const int kXSize = 300;
   11737     const int kYSize = 300;
   11738     const int kLargeElementCount = kXSize * kYSize * 4;
   11739     ElementType* large_array_data =
   11740         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
   11741     i::Handle<ExternalArrayClass> large_array =
   11742         i::Handle<ExternalArrayClass>::cast(
   11743             FACTORY->NewExternalArray(kLargeElementCount,
   11744                                          array_type,
   11745                                          array_data));
   11746     v8::Handle<v8::Object> large_obj = v8::Object::New();
   11747     // Set the elements to be the external array.
   11748     large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
   11749                                                        array_type,
   11750                                                        kLargeElementCount);
   11751     context->Global()->Set(v8_str("large_array"), large_obj);
   11752     // Initialize contents of a few rows.
   11753     for (int x = 0; x < 300; x++) {
   11754       int row = 0;
   11755       int offset = row * 300 * 4;
   11756       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   11757       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   11758       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   11759       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   11760       row = 150;
   11761       offset = row * 300 * 4;
   11762       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   11763       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   11764       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   11765       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   11766       row = 298;
   11767       offset = row * 300 * 4;
   11768       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   11769       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   11770       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   11771       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   11772     }
   11773     // The goal of the code below is to make "offset" large enough
   11774     // that the computation of the index (which goes into eax) has
   11775     // high bits set which will not be overwritten by a byte or short
   11776     // load.
   11777     result = CompileRun("var failed = false;"
   11778                         "var offset = 0;"
   11779                         "for (var i = 0; i < 300; i++) {"
   11780                         "  if (large_array[4 * i] != 127 ||"
   11781                         "      large_array[4 * i + 1] != 0 ||"
   11782                         "      large_array[4 * i + 2] != 0 ||"
   11783                         "      large_array[4 * i + 3] != 127) {"
   11784                         "    failed = true;"
   11785                         "  }"
   11786                         "}"
   11787                         "offset = 150 * 300 * 4;"
   11788                         "for (var i = 0; i < 300; i++) {"
   11789                         "  if (large_array[offset + 4 * i] != 127 ||"
   11790                         "      large_array[offset + 4 * i + 1] != 0 ||"
   11791                         "      large_array[offset + 4 * i + 2] != 0 ||"
   11792                         "      large_array[offset + 4 * i + 3] != 127) {"
   11793                         "    failed = true;"
   11794                         "  }"
   11795                         "}"
   11796                         "offset = 298 * 300 * 4;"
   11797                         "for (var i = 0; i < 300; i++) {"
   11798                         "  if (large_array[offset + 4 * i] != 127 ||"
   11799                         "      large_array[offset + 4 * i + 1] != 0 ||"
   11800                         "      large_array[offset + 4 * i + 2] != 0 ||"
   11801                         "      large_array[offset + 4 * i + 3] != 127) {"
   11802                         "    failed = true;"
   11803                         "  }"
   11804                         "}"
   11805                         "!failed;");
   11806     CHECK_EQ(true, result->BooleanValue());
   11807     free(large_array_data);
   11808   }
   11809 
   11810   // The "" property descriptor is overloaded to store information about
   11811   // the external array. Ensure that setting and accessing the "" property
   11812   // works (it should overwrite the information cached about the external
   11813   // array in the DescriptorArray) in various situations.
   11814   result = CompileRun("ext_array[''] = 23; ext_array['']");
   11815   CHECK_EQ(23, result->Int32Value());
   11816 
   11817   // Property "" set after the external array is associated with the object.
   11818   {
   11819     v8::Handle<v8::Object> obj2 = v8::Object::New();
   11820     obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
   11821     obj2->Set(v8_str(""), v8::Int32::New(1503));
   11822     // Set the elements to be the external array.
   11823     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   11824                                                   array_type,
   11825                                                   kElementCount);
   11826     context->Global()->Set(v8_str("ext_array"), obj2);
   11827     result = CompileRun("ext_array['']");
   11828     CHECK_EQ(1503, result->Int32Value());
   11829   }
   11830 
   11831   // Property "" set after the external array is associated with the object.
   11832   {
   11833     v8::Handle<v8::Object> obj2 = v8::Object::New();
   11834     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
   11835     // Set the elements to be the external array.
   11836     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   11837                                                   array_type,
   11838                                                   kElementCount);
   11839     obj2->Set(v8_str(""), v8::Int32::New(1503));
   11840     context->Global()->Set(v8_str("ext_array"), obj2);
   11841     result = CompileRun("ext_array['']");
   11842     CHECK_EQ(1503, result->Int32Value());
   11843   }
   11844 
   11845   // Should reuse the map from previous test.
   11846   {
   11847     v8::Handle<v8::Object> obj2 = v8::Object::New();
   11848     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
   11849     // Set the elements to be the external array. Should re-use the map
   11850     // from previous test.
   11851     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   11852                                                   array_type,
   11853                                                   kElementCount);
   11854     context->Global()->Set(v8_str("ext_array"), obj2);
   11855     result = CompileRun("ext_array['']");
   11856   }
   11857 
   11858   // Property "" is a constant function that shouldn't not be interfered with
   11859   // when an external array is set.
   11860   {
   11861     v8::Handle<v8::Object> obj2 = v8::Object::New();
   11862     // Start
   11863     obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
   11864 
   11865     // Add a constant function to an object.
   11866     context->Global()->Set(v8_str("ext_array"), obj2);
   11867     result = CompileRun("ext_array[''] = function() {return 1503;};"
   11868                         "ext_array['']();");
   11869 
   11870     // Add an external array transition to the same map that
   11871     // has the constant transition.
   11872     v8::Handle<v8::Object> obj3 = v8::Object::New();
   11873     obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
   11874     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   11875                                                   array_type,
   11876                                                   kElementCount);
   11877     context->Global()->Set(v8_str("ext_array"), obj3);
   11878   }
   11879 
   11880   // If a external array transition is in the map, it should get clobbered
   11881   // by a constant function.
   11882   {
   11883     // Add an external array transition.
   11884     v8::Handle<v8::Object> obj3 = v8::Object::New();
   11885     obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
   11886     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   11887                                                   array_type,
   11888                                                   kElementCount);
   11889 
   11890     // Add a constant function to the same map that just got an external array
   11891     // transition.
   11892     v8::Handle<v8::Object> obj2 = v8::Object::New();
   11893     obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
   11894     context->Global()->Set(v8_str("ext_array"), obj2);
   11895     result = CompileRun("ext_array[''] = function() {return 1503;};"
   11896                         "ext_array['']();");
   11897   }
   11898 
   11899   free(array_data);
   11900 }
   11901 
   11902 
   11903 THREADED_TEST(ExternalByteArray) {
   11904   ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
   11905       v8::kExternalByteArray,
   11906       -128,
   11907       127);
   11908 }
   11909 
   11910 
   11911 THREADED_TEST(ExternalUnsignedByteArray) {
   11912   ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
   11913       v8::kExternalUnsignedByteArray,
   11914       0,
   11915       255);
   11916 }
   11917 
   11918 
   11919 THREADED_TEST(ExternalPixelArray) {
   11920   ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
   11921       v8::kExternalPixelArray,
   11922       0,
   11923       255);
   11924 }
   11925 
   11926 
   11927 THREADED_TEST(ExternalShortArray) {
   11928   ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
   11929       v8::kExternalShortArray,
   11930       -32768,
   11931       32767);
   11932 }
   11933 
   11934 
   11935 THREADED_TEST(ExternalUnsignedShortArray) {
   11936   ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
   11937       v8::kExternalUnsignedShortArray,
   11938       0,
   11939       65535);
   11940 }
   11941 
   11942 
   11943 THREADED_TEST(ExternalIntArray) {
   11944   ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
   11945       v8::kExternalIntArray,
   11946       INT_MIN,   // -2147483648
   11947       INT_MAX);  //  2147483647
   11948 }
   11949 
   11950 
   11951 THREADED_TEST(ExternalUnsignedIntArray) {
   11952   ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
   11953       v8::kExternalUnsignedIntArray,
   11954       0,
   11955       UINT_MAX);  // 4294967295
   11956 }
   11957 
   11958 
   11959 THREADED_TEST(ExternalFloatArray) {
   11960   ExternalArrayTestHelper<i::ExternalFloatArray, float>(
   11961       v8::kExternalFloatArray,
   11962       -500,
   11963       500);
   11964 }
   11965 
   11966 
   11967 THREADED_TEST(ExternalArrays) {
   11968   TestExternalByteArray();
   11969   TestExternalUnsignedByteArray();
   11970   TestExternalShortArray();
   11971   TestExternalUnsignedShortArray();
   11972   TestExternalIntArray();
   11973   TestExternalUnsignedIntArray();
   11974   TestExternalFloatArray();
   11975 }
   11976 
   11977 
   11978 void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
   11979   v8::HandleScope scope;
   11980   LocalContext context;
   11981   for (int size = 0; size < 100; size += 10) {
   11982     int element_size = ExternalArrayElementSize(array_type);
   11983     void* external_data = malloc(size * element_size);
   11984     v8::Handle<v8::Object> obj = v8::Object::New();
   11985     obj->SetIndexedPropertiesToExternalArrayData(
   11986         external_data, array_type, size);
   11987     CHECK(obj->HasIndexedPropertiesInExternalArrayData());
   11988     CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
   11989     CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
   11990     CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
   11991     free(external_data);
   11992   }
   11993 }
   11994 
   11995 
   11996 THREADED_TEST(ExternalArrayInfo) {
   11997   ExternalArrayInfoTestHelper(v8::kExternalByteArray);
   11998   ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
   11999   ExternalArrayInfoTestHelper(v8::kExternalShortArray);
   12000   ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
   12001   ExternalArrayInfoTestHelper(v8::kExternalIntArray);
   12002   ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
   12003   ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
   12004   ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
   12005 }
   12006 
   12007 
   12008 THREADED_TEST(ScriptContextDependence) {
   12009   v8::HandleScope scope;
   12010   LocalContext c1;
   12011   const char *source = "foo";
   12012   v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
   12013   v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
   12014   c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
   12015   CHECK_EQ(dep->Run()->Int32Value(), 100);
   12016   CHECK_EQ(indep->Run()->Int32Value(), 100);
   12017   LocalContext c2;
   12018   c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
   12019   CHECK_EQ(dep->Run()->Int32Value(), 100);
   12020   CHECK_EQ(indep->Run()->Int32Value(), 101);
   12021 }
   12022 
   12023 
   12024 THREADED_TEST(StackTrace) {
   12025   v8::HandleScope scope;
   12026   LocalContext context;
   12027   v8::TryCatch try_catch;
   12028   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   12029   v8::Handle<v8::String> src = v8::String::New(source);
   12030   v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
   12031   v8::Script::New(src, origin)->Run();
   12032   CHECK(try_catch.HasCaught());
   12033   v8::String::Utf8Value stack(try_catch.StackTrace());
   12034   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
   12035 }
   12036 
   12037 
   12038 // Checks that a StackFrame has certain expected values.
   12039 void checkStackFrame(const char* expected_script_name,
   12040     const char* expected_func_name, int expected_line_number,
   12041     int expected_column, bool is_eval, bool is_constructor,
   12042     v8::Handle<v8::StackFrame> frame) {
   12043   v8::HandleScope scope;
   12044   v8::String::Utf8Value func_name(frame->GetFunctionName());
   12045   v8::String::Utf8Value script_name(frame->GetScriptName());
   12046   if (*script_name == NULL) {
   12047     // The situation where there is no associated script, like for evals.
   12048     CHECK(expected_script_name == NULL);
   12049   } else {
   12050     CHECK(strstr(*script_name, expected_script_name) != NULL);
   12051   }
   12052   CHECK(strstr(*func_name, expected_func_name) != NULL);
   12053   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   12054   CHECK_EQ(expected_column, frame->GetColumn());
   12055   CHECK_EQ(is_eval, frame->IsEval());
   12056   CHECK_EQ(is_constructor, frame->IsConstructor());
   12057 }
   12058 
   12059 
   12060 v8::Handle<Value> AnalyzeStackInNativeCode(const v8::Arguments& args) {
   12061   v8::HandleScope scope;
   12062   const char* origin = "capture-stack-trace-test";
   12063   const int kOverviewTest = 1;
   12064   const int kDetailedTest = 2;
   12065 
   12066   ASSERT(args.Length() == 1);
   12067 
   12068   int testGroup = args[0]->Int32Value();
   12069   if (testGroup == kOverviewTest) {
   12070     v8::Handle<v8::StackTrace> stackTrace =
   12071         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
   12072     CHECK_EQ(4, stackTrace->GetFrameCount());
   12073     checkStackFrame(origin, "bar", 2, 10, false, false,
   12074                     stackTrace->GetFrame(0));
   12075     checkStackFrame(origin, "foo", 6, 3, false, false,
   12076                     stackTrace->GetFrame(1));
   12077     checkStackFrame(NULL, "", 1, 1, false, false,
   12078                     stackTrace->GetFrame(2));
   12079     // The last frame is an anonymous function that has the initial call.
   12080     checkStackFrame(origin, "", 8, 7, false, false,
   12081                     stackTrace->GetFrame(3));
   12082 
   12083     CHECK(stackTrace->AsArray()->IsArray());
   12084   } else if (testGroup == kDetailedTest) {
   12085     v8::Handle<v8::StackTrace> stackTrace =
   12086         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
   12087     CHECK_EQ(4, stackTrace->GetFrameCount());
   12088     checkStackFrame(origin, "bat", 4, 22, false, false,
   12089                     stackTrace->GetFrame(0));
   12090     checkStackFrame(origin, "baz", 8, 3, false, true,
   12091                     stackTrace->GetFrame(1));
   12092 #ifdef ENABLE_DEBUGGER_SUPPORT
   12093     bool is_eval = true;
   12094 #else  // ENABLE_DEBUGGER_SUPPORT
   12095     bool is_eval = false;
   12096 #endif  // ENABLE_DEBUGGER_SUPPORT
   12097 
   12098     checkStackFrame(NULL, "", 1, 1, is_eval, false,
   12099                     stackTrace->GetFrame(2));
   12100     // The last frame is an anonymous function that has the initial call to foo.
   12101     checkStackFrame(origin, "", 10, 1, false, false,
   12102                     stackTrace->GetFrame(3));
   12103 
   12104     CHECK(stackTrace->AsArray()->IsArray());
   12105   }
   12106   return v8::Undefined();
   12107 }
   12108 
   12109 
   12110 // Tests the C++ StackTrace API.
   12111 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   12112 // THREADED_TEST(CaptureStackTrace) {
   12113 TEST(CaptureStackTrace) {
   12114   v8::HandleScope scope;
   12115   v8::Handle<v8::String> origin = v8::String::New("capture-stack-trace-test");
   12116   Local<ObjectTemplate> templ = ObjectTemplate::New();
   12117   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   12118              v8::FunctionTemplate::New(AnalyzeStackInNativeCode));
   12119   LocalContext context(0, templ);
   12120 
   12121   // Test getting OVERVIEW information. Should ignore information that is not
   12122   // script name, function name, line number, and column offset.
   12123   const char *overview_source =
   12124     "function bar() {\n"
   12125     "  var y; AnalyzeStackInNativeCode(1);\n"
   12126     "}\n"
   12127     "function foo() {\n"
   12128     "\n"
   12129     "  bar();\n"
   12130     "}\n"
   12131     "var x;eval('new foo();');";
   12132   v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
   12133   v8::Handle<Value> overview_result =
   12134       v8::Script::New(overview_src, origin)->Run();
   12135   ASSERT(!overview_result.IsEmpty());
   12136   ASSERT(overview_result->IsObject());
   12137 
   12138   // Test getting DETAILED information.
   12139   const char *detailed_source =
   12140     "function bat() {AnalyzeStackInNativeCode(2);\n"
   12141     "}\n"
   12142     "\n"
   12143     "function baz() {\n"
   12144     "  bat();\n"
   12145     "}\n"
   12146     "eval('new baz();');";
   12147   v8::Handle<v8::String> detailed_src = v8::String::New(detailed_source);
   12148   // Make the script using a non-zero line and column offset.
   12149   v8::Handle<v8::Integer> line_offset = v8::Integer::New(3);
   12150   v8::Handle<v8::Integer> column_offset = v8::Integer::New(5);
   12151   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   12152   v8::Handle<v8::Script> detailed_script(
   12153       v8::Script::New(detailed_src, &detailed_origin));
   12154   v8::Handle<Value> detailed_result = detailed_script->Run();
   12155   ASSERT(!detailed_result.IsEmpty());
   12156   ASSERT(detailed_result->IsObject());
   12157 }
   12158 
   12159 
   12160 static void StackTraceForUncaughtExceptionListener(
   12161     v8::Handle<v8::Message> message,
   12162     v8::Handle<Value>) {
   12163   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   12164   CHECK_EQ(2, stack_trace->GetFrameCount());
   12165   checkStackFrame("origin", "foo", 2, 3, false, false,
   12166                   stack_trace->GetFrame(0));
   12167   checkStackFrame("origin", "bar", 5, 3, false, false,
   12168                   stack_trace->GetFrame(1));
   12169 }
   12170 
   12171 TEST(CaptureStackTraceForUncaughtException) {
   12172   report_count = 0;
   12173   v8::HandleScope scope;
   12174   LocalContext env;
   12175   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
   12176   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   12177 
   12178   Script::Compile(v8_str("function foo() {\n"
   12179                          "  throw 1;\n"
   12180                          "};\n"
   12181                          "function bar() {\n"
   12182                          "  foo();\n"
   12183                          "};"),
   12184                   v8_str("origin"))->Run();
   12185   v8::Local<v8::Object> global = env->Global();
   12186   Local<Value> trouble = global->Get(v8_str("bar"));
   12187   CHECK(trouble->IsFunction());
   12188   Function::Cast(*trouble)->Call(global, 0, NULL);
   12189   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   12190   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   12191 }
   12192 
   12193 
   12194 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   12195   v8::HandleScope scope;
   12196   LocalContext env;
   12197   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
   12198                                                     1024,
   12199                                                     v8::StackTrace::kDetailed);
   12200 
   12201   CompileRun(
   12202       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   12203       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   12204       "    'isConstructor'];\n"
   12205       "for (var i = 0; i < setters.length; i++) {\n"
   12206       "  var prop = setters[i];\n"
   12207       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   12208       "}\n");
   12209   CompileRun("throw 'exception';");
   12210   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   12211 }
   12212 
   12213 
   12214 v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) {
   12215   v8::HandleScope scope;
   12216   v8::Handle<v8::StackTrace> stackTrace =
   12217       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
   12218   CHECK_EQ(5, stackTrace->GetFrameCount());
   12219   v8::Handle<v8::String> url = v8_str("eval_url");
   12220   for (int i = 0; i < 3; i++) {
   12221     v8::Handle<v8::String> name =
   12222         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   12223     CHECK(!name.IsEmpty());
   12224     CHECK_EQ(url, name);
   12225   }
   12226   return v8::Undefined();
   12227 }
   12228 
   12229 
   12230 TEST(SourceURLInStackTrace) {
   12231   v8::HandleScope scope;
   12232   Local<ObjectTemplate> templ = ObjectTemplate::New();
   12233   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   12234              v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
   12235   LocalContext context(0, templ);
   12236 
   12237   const char *source =
   12238     "function outer() {\n"
   12239     "function bar() {\n"
   12240     "  AnalyzeStackOfEvalWithSourceURL();\n"
   12241     "}\n"
   12242     "function foo() {\n"
   12243     "\n"
   12244     "  bar();\n"
   12245     "}\n"
   12246     "foo();\n"
   12247     "}\n"
   12248     "eval('(' + outer +')()//@ sourceURL=eval_url');";
   12249   CHECK(CompileRun(source)->IsUndefined());
   12250 }
   12251 
   12252 
   12253 // Test that idle notification can be handled and eventually returns true.
   12254 THREADED_TEST(IdleNotification) {
   12255   bool rv = false;
   12256   for (int i = 0; i < 100; i++) {
   12257     rv = v8::V8::IdleNotification();
   12258     if (rv)
   12259       break;
   12260   }
   12261   CHECK(rv == true);
   12262 }
   12263 
   12264 
   12265 static uint32_t* stack_limit;
   12266 
   12267 static v8::Handle<Value> GetStackLimitCallback(const v8::Arguments& args) {
   12268   stack_limit = reinterpret_cast<uint32_t*>(
   12269       i::Isolate::Current()->stack_guard()->real_climit());
   12270   return v8::Undefined();
   12271 }
   12272 
   12273 
   12274 // Uses the address of a local variable to determine the stack top now.
   12275 // Given a size, returns an address that is that far from the current
   12276 // top of stack.
   12277 static uint32_t* ComputeStackLimit(uint32_t size) {
   12278   uint32_t* answer = &size - (size / sizeof(size));
   12279   // If the size is very large and the stack is very near the bottom of
   12280   // memory then the calculation above may wrap around and give an address
   12281   // that is above the (downwards-growing) stack.  In that case we return
   12282   // a very low address.
   12283   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   12284   return answer;
   12285 }
   12286 
   12287 
   12288 TEST(SetResourceConstraints) {
   12289   static const int K = 1024;
   12290   uint32_t* set_limit = ComputeStackLimit(128 * K);
   12291 
   12292   // Set stack limit.
   12293   v8::ResourceConstraints constraints;
   12294   constraints.set_stack_limit(set_limit);
   12295   CHECK(v8::SetResourceConstraints(&constraints));
   12296 
   12297   // Execute a script.
   12298   v8::HandleScope scope;
   12299   LocalContext env;
   12300   Local<v8::FunctionTemplate> fun_templ =
   12301       v8::FunctionTemplate::New(GetStackLimitCallback);
   12302   Local<Function> fun = fun_templ->GetFunction();
   12303   env->Global()->Set(v8_str("get_stack_limit"), fun);
   12304   CompileRun("get_stack_limit();");
   12305 
   12306   CHECK(stack_limit == set_limit);
   12307 }
   12308 
   12309 
   12310 TEST(SetResourceConstraintsInThread) {
   12311   uint32_t* set_limit;
   12312   {
   12313     v8::Locker locker;
   12314     static const int K = 1024;
   12315     set_limit = ComputeStackLimit(128 * K);
   12316 
   12317     // Set stack limit.
   12318     v8::ResourceConstraints constraints;
   12319     constraints.set_stack_limit(set_limit);
   12320     CHECK(v8::SetResourceConstraints(&constraints));
   12321 
   12322     // Execute a script.
   12323     v8::HandleScope scope;
   12324     LocalContext env;
   12325     Local<v8::FunctionTemplate> fun_templ =
   12326         v8::FunctionTemplate::New(GetStackLimitCallback);
   12327     Local<Function> fun = fun_templ->GetFunction();
   12328     env->Global()->Set(v8_str("get_stack_limit"), fun);
   12329     CompileRun("get_stack_limit();");
   12330 
   12331     CHECK(stack_limit == set_limit);
   12332   }
   12333   {
   12334     v8::Locker locker;
   12335     CHECK(stack_limit == set_limit);
   12336   }
   12337 }
   12338 
   12339 
   12340 THREADED_TEST(GetHeapStatistics) {
   12341   v8::HandleScope scope;
   12342   LocalContext c1;
   12343   v8::HeapStatistics heap_statistics;
   12344   CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
   12345   CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
   12346   v8::V8::GetHeapStatistics(&heap_statistics);
   12347   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   12348   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   12349 }
   12350 
   12351 
   12352 static double DoubleFromBits(uint64_t value) {
   12353   double target;
   12354   memcpy(&target, &value, sizeof(target));
   12355   return target;
   12356 }
   12357 
   12358 
   12359 static uint64_t DoubleToBits(double value) {
   12360   uint64_t target;
   12361   memcpy(&target, &value, sizeof(target));
   12362   return target;
   12363 }
   12364 
   12365 
   12366 static double DoubleToDateTime(double input) {
   12367   double date_limit = 864e13;
   12368   if (IsNaN(input) || input < -date_limit || input > date_limit) {
   12369     return i::OS::nan_value();
   12370   }
   12371   return (input < 0) ? -(floor(-input)) : floor(input);
   12372 }
   12373 
   12374 // We don't have a consistent way to write 64-bit constants syntactically, so we
   12375 // split them into two 32-bit constants and combine them programmatically.
   12376 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   12377   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   12378 }
   12379 
   12380 
   12381 THREADED_TEST(QuietSignalingNaNs) {
   12382   v8::HandleScope scope;
   12383   LocalContext context;
   12384   v8::TryCatch try_catch;
   12385 
   12386   // Special double values.
   12387   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
   12388   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
   12389   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
   12390   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
   12391   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   12392   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
   12393   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   12394 
   12395   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   12396   // on either side of the epoch.
   12397   double date_limit = 864e13;
   12398 
   12399   double test_values[] = {
   12400       snan,
   12401       qnan,
   12402       infinity,
   12403       max_normal,
   12404       date_limit + 1,
   12405       date_limit,
   12406       min_normal,
   12407       max_denormal,
   12408       min_denormal,
   12409       0,
   12410       -0,
   12411       -min_denormal,
   12412       -max_denormal,
   12413       -min_normal,
   12414       -date_limit,
   12415       -date_limit - 1,
   12416       -max_normal,
   12417       -infinity,
   12418       -qnan,
   12419       -snan
   12420   };
   12421   int num_test_values = 20;
   12422 
   12423   for (int i = 0; i < num_test_values; i++) {
   12424     double test_value = test_values[i];
   12425 
   12426     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   12427     v8::Handle<v8::Value> number = v8::Number::New(test_value);
   12428     double stored_number = number->NumberValue();
   12429     if (!IsNaN(test_value)) {
   12430       CHECK_EQ(test_value, stored_number);
   12431     } else {
   12432       uint64_t stored_bits = DoubleToBits(stored_number);
   12433       // Check if quiet nan (bits 51..62 all set).
   12434       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   12435     }
   12436 
   12437     // Check that Date::New preserves non-NaNs in the date range and
   12438     // quiets SNaNs.
   12439     v8::Handle<v8::Value> date = v8::Date::New(test_value);
   12440     double expected_stored_date = DoubleToDateTime(test_value);
   12441     double stored_date = date->NumberValue();
   12442     if (!IsNaN(expected_stored_date)) {
   12443       CHECK_EQ(expected_stored_date, stored_date);
   12444     } else {
   12445       uint64_t stored_bits = DoubleToBits(stored_date);
   12446       // Check if quiet nan (bits 51..62 all set).
   12447       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   12448     }
   12449   }
   12450 }
   12451 
   12452 
   12453 static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) {
   12454   v8::HandleScope scope;
   12455   v8::TryCatch tc;
   12456   v8::Handle<v8::String> str = args[0]->ToString();
   12457   if (tc.HasCaught())
   12458     return tc.ReThrow();
   12459   return v8::Undefined();
   12460 }
   12461 
   12462 
   12463 // Test that an exception can be propagated down through a spaghetti
   12464 // stack using ReThrow.
   12465 THREADED_TEST(SpaghettiStackReThrow) {
   12466   v8::HandleScope scope;
   12467   LocalContext context;
   12468   context->Global()->Set(
   12469       v8::String::New("s"),
   12470       v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
   12471   v8::TryCatch try_catch;
   12472   CompileRun(
   12473       "var i = 0;"
   12474       "var o = {"
   12475       "  toString: function () {"
   12476       "    if (i == 10) {"
   12477       "      throw 'Hey!';"
   12478       "    } else {"
   12479       "      i++;"
   12480       "      return s(o);"
   12481       "    }"
   12482       "  }"
   12483       "};"
   12484       "s(o);");
   12485   CHECK(try_catch.HasCaught());
   12486   v8::String::Utf8Value value(try_catch.Exception());
   12487   CHECK_EQ(0, strcmp(*value, "Hey!"));
   12488 }
   12489 
   12490 
   12491 TEST(Regress528) {
   12492   v8::V8::Initialize();
   12493 
   12494   v8::HandleScope scope;
   12495   v8::Persistent<Context> context;
   12496   v8::Persistent<Context> other_context;
   12497   int gc_count;
   12498 
   12499   // Create a context used to keep the code from aging in the compilation
   12500   // cache.
   12501   other_context = Context::New();
   12502 
   12503   // Context-dependent context data creates reference from the compilation
   12504   // cache to the global object.
   12505   const char* source_simple = "1";
   12506   context = Context::New();
   12507   {
   12508     v8::HandleScope scope;
   12509 
   12510     context->Enter();
   12511     Local<v8::String> obj = v8::String::New("");
   12512     context->SetData(obj);
   12513     CompileRun(source_simple);
   12514     context->Exit();
   12515   }
   12516   context.Dispose();
   12517   for (gc_count = 1; gc_count < 10; gc_count++) {
   12518     other_context->Enter();
   12519     CompileRun(source_simple);
   12520     other_context->Exit();
   12521     HEAP->CollectAllGarbage(false);
   12522     if (GetGlobalObjectsCount() == 1) break;
   12523   }
   12524   CHECK_GE(2, gc_count);
   12525   CHECK_EQ(1, GetGlobalObjectsCount());
   12526 
   12527   // Eval in a function creates reference from the compilation cache to the
   12528   // global object.
   12529   const char* source_eval = "function f(){eval('1')}; f()";
   12530   context = Context::New();
   12531   {
   12532     v8::HandleScope scope;
   12533 
   12534     context->Enter();
   12535     CompileRun(source_eval);
   12536     context->Exit();
   12537   }
   12538   context.Dispose();
   12539   for (gc_count = 1; gc_count < 10; gc_count++) {
   12540     other_context->Enter();
   12541     CompileRun(source_eval);
   12542     other_context->Exit();
   12543     HEAP->CollectAllGarbage(false);
   12544     if (GetGlobalObjectsCount() == 1) break;
   12545   }
   12546   CHECK_GE(2, gc_count);
   12547   CHECK_EQ(1, GetGlobalObjectsCount());
   12548 
   12549   // Looking up the line number for an exception creates reference from the
   12550   // compilation cache to the global object.
   12551   const char* source_exception = "function f(){throw 1;} f()";
   12552   context = Context::New();
   12553   {
   12554     v8::HandleScope scope;
   12555 
   12556     context->Enter();
   12557     v8::TryCatch try_catch;
   12558     CompileRun(source_exception);
   12559     CHECK(try_catch.HasCaught());
   12560     v8::Handle<v8::Message> message = try_catch.Message();
   12561     CHECK(!message.IsEmpty());
   12562     CHECK_EQ(1, message->GetLineNumber());
   12563     context->Exit();
   12564   }
   12565   context.Dispose();
   12566   for (gc_count = 1; gc_count < 10; gc_count++) {
   12567     other_context->Enter();
   12568     CompileRun(source_exception);
   12569     other_context->Exit();
   12570     HEAP->CollectAllGarbage(false);
   12571     if (GetGlobalObjectsCount() == 1) break;
   12572   }
   12573   CHECK_GE(2, gc_count);
   12574   CHECK_EQ(1, GetGlobalObjectsCount());
   12575 
   12576   other_context.Dispose();
   12577 }
   12578 
   12579 
   12580 THREADED_TEST(ScriptOrigin) {
   12581   v8::HandleScope scope;
   12582   LocalContext env;
   12583   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
   12584   v8::Handle<v8::String> script = v8::String::New(
   12585       "function f() {}\n\nfunction g() {}");
   12586   v8::Script::Compile(script, &origin)->Run();
   12587   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   12588       env->Global()->Get(v8::String::New("f")));
   12589   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   12590       env->Global()->Get(v8::String::New("g")));
   12591 
   12592   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   12593   CHECK_EQ("test", *v8::String::AsciiValue(script_origin_f.ResourceName()));
   12594   CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
   12595 
   12596   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   12597   CHECK_EQ("test", *v8::String::AsciiValue(script_origin_g.ResourceName()));
   12598   CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
   12599 }
   12600 
   12601 
   12602 THREADED_TEST(ScriptLineNumber) {
   12603   v8::HandleScope scope;
   12604   LocalContext env;
   12605   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
   12606   v8::Handle<v8::String> script = v8::String::New(
   12607       "function f() {}\n\nfunction g() {}");
   12608   v8::Script::Compile(script, &origin)->Run();
   12609   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   12610       env->Global()->Get(v8::String::New("f")));
   12611   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   12612       env->Global()->Get(v8::String::New("g")));
   12613   CHECK_EQ(0, f->GetScriptLineNumber());
   12614   CHECK_EQ(2, g->GetScriptLineNumber());
   12615 }
   12616 
   12617 
   12618 static v8::Handle<Value> GetterWhichReturns42(Local<String> name,
   12619                                               const AccessorInfo& info) {
   12620   return v8_num(42);
   12621 }
   12622 
   12623 
   12624 static void SetterWhichSetsYOnThisTo23(Local<String> name,
   12625                                        Local<Value> value,
   12626                                        const AccessorInfo& info) {
   12627   info.This()->Set(v8_str("y"), v8_num(23));
   12628 }
   12629 
   12630 
   12631 TEST(SetterOnConstructorPrototype) {
   12632   v8::HandleScope scope;
   12633   Local<ObjectTemplate> templ = ObjectTemplate::New();
   12634   templ->SetAccessor(v8_str("x"),
   12635                      GetterWhichReturns42,
   12636                      SetterWhichSetsYOnThisTo23);
   12637   LocalContext context;
   12638   context->Global()->Set(v8_str("P"), templ->NewInstance());
   12639   CompileRun("function C1() {"
   12640              "  this.x = 23;"
   12641              "};"
   12642              "C1.prototype = P;"
   12643              "function C2() {"
   12644              "  this.x = 23"
   12645              "};"
   12646              "C2.prototype = { };"
   12647              "C2.prototype.__proto__ = P;");
   12648 
   12649   v8::Local<v8::Script> script;
   12650   script = v8::Script::Compile(v8_str("new C1();"));
   12651   for (int i = 0; i < 10; i++) {
   12652     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   12653     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   12654     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   12655   }
   12656 
   12657   script = v8::Script::Compile(v8_str("new C2();"));
   12658   for (int i = 0; i < 10; i++) {
   12659     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   12660     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
   12661     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
   12662   }
   12663 }
   12664 
   12665 
   12666 static v8::Handle<Value> NamedPropertyGetterWhichReturns42(
   12667     Local<String> name, const AccessorInfo& info) {
   12668   return v8_num(42);
   12669 }
   12670 
   12671 
   12672 static v8::Handle<Value> NamedPropertySetterWhichSetsYOnThisTo23(
   12673     Local<String> name, Local<Value> value, const AccessorInfo& info) {
   12674   if (name->Equals(v8_str("x"))) {
   12675     info.This()->Set(v8_str("y"), v8_num(23));
   12676   }
   12677   return v8::Handle<Value>();
   12678 }
   12679 
   12680 
   12681 THREADED_TEST(InterceptorOnConstructorPrototype) {
   12682   v8::HandleScope scope;
   12683   Local<ObjectTemplate> templ = ObjectTemplate::New();
   12684   templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
   12685                                  NamedPropertySetterWhichSetsYOnThisTo23);
   12686   LocalContext context;
   12687   context->Global()->Set(v8_str("P"), templ->NewInstance());
   12688   CompileRun("function C1() {"
   12689              "  this.x = 23;"
   12690              "};"
   12691              "C1.prototype = P;"
   12692              "function C2() {"
   12693              "  this.x = 23"
   12694              "};"
   12695              "C2.prototype = { };"
   12696              "C2.prototype.__proto__ = P;");
   12697 
   12698   v8::Local<v8::Script> script;
   12699   script = v8::Script::Compile(v8_str("new C1();"));
   12700   for (int i = 0; i < 10; i++) {
   12701     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   12702     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   12703     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   12704   }
   12705 
   12706   script = v8::Script::Compile(v8_str("new C2();"));
   12707   for (int i = 0; i < 10; i++) {
   12708     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   12709     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
   12710     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
   12711   }
   12712 }
   12713 
   12714 
   12715 TEST(Bug618) {
   12716   const char* source = "function C1() {"
   12717                        "  this.x = 23;"
   12718                        "};"
   12719                        "C1.prototype = P;";
   12720 
   12721   v8::HandleScope scope;
   12722   LocalContext context;
   12723   v8::Local<v8::Script> script;
   12724 
   12725   // Use a simple object as prototype.
   12726   v8::Local<v8::Object> prototype = v8::Object::New();
   12727   prototype->Set(v8_str("y"), v8_num(42));
   12728   context->Global()->Set(v8_str("P"), prototype);
   12729 
   12730   // This compile will add the code to the compilation cache.
   12731   CompileRun(source);
   12732 
   12733   script = v8::Script::Compile(v8_str("new C1();"));
   12734   // Allow enough iterations for the inobject slack tracking logic
   12735   // to finalize instance size and install the fast construct stub.
   12736   for (int i = 0; i < 256; i++) {
   12737     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   12738     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   12739     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   12740   }
   12741 
   12742   // Use an API object with accessors as prototype.
   12743   Local<ObjectTemplate> templ = ObjectTemplate::New();
   12744   templ->SetAccessor(v8_str("x"),
   12745                      GetterWhichReturns42,
   12746                      SetterWhichSetsYOnThisTo23);
   12747   context->Global()->Set(v8_str("P"), templ->NewInstance());
   12748 
   12749   // This compile will get the code from the compilation cache.
   12750   CompileRun(source);
   12751 
   12752   script = v8::Script::Compile(v8_str("new C1();"));
   12753   for (int i = 0; i < 10; i++) {
   12754     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   12755     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   12756     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   12757   }
   12758 }
   12759 
   12760 int prologue_call_count = 0;
   12761 int epilogue_call_count = 0;
   12762 int prologue_call_count_second = 0;
   12763 int epilogue_call_count_second = 0;
   12764 
   12765 void PrologueCallback(v8::GCType, v8::GCCallbackFlags) {
   12766   ++prologue_call_count;
   12767 }
   12768 
   12769 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags) {
   12770   ++epilogue_call_count;
   12771 }
   12772 
   12773 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
   12774   ++prologue_call_count_second;
   12775 }
   12776 
   12777 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
   12778   ++epilogue_call_count_second;
   12779 }
   12780 
   12781 TEST(GCCallbacks) {
   12782   LocalContext context;
   12783 
   12784   v8::V8::AddGCPrologueCallback(PrologueCallback);
   12785   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
   12786   CHECK_EQ(0, prologue_call_count);
   12787   CHECK_EQ(0, epilogue_call_count);
   12788   HEAP->CollectAllGarbage(false);
   12789   CHECK_EQ(1, prologue_call_count);
   12790   CHECK_EQ(1, epilogue_call_count);
   12791   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
   12792   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
   12793   HEAP->CollectAllGarbage(false);
   12794   CHECK_EQ(2, prologue_call_count);
   12795   CHECK_EQ(2, epilogue_call_count);
   12796   CHECK_EQ(1, prologue_call_count_second);
   12797   CHECK_EQ(1, epilogue_call_count_second);
   12798   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
   12799   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
   12800   HEAP->CollectAllGarbage(false);
   12801   CHECK_EQ(2, prologue_call_count);
   12802   CHECK_EQ(2, epilogue_call_count);
   12803   CHECK_EQ(2, prologue_call_count_second);
   12804   CHECK_EQ(2, epilogue_call_count_second);
   12805   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
   12806   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   12807   HEAP->CollectAllGarbage(false);
   12808   CHECK_EQ(2, prologue_call_count);
   12809   CHECK_EQ(2, epilogue_call_count);
   12810   CHECK_EQ(2, prologue_call_count_second);
   12811   CHECK_EQ(2, epilogue_call_count_second);
   12812 }
   12813 
   12814 
   12815 THREADED_TEST(AddToJSFunctionResultCache) {
   12816   i::FLAG_allow_natives_syntax = true;
   12817   v8::HandleScope scope;
   12818 
   12819   LocalContext context;
   12820 
   12821   const char* code =
   12822       "(function() {"
   12823       "  var key0 = 'a';"
   12824       "  var key1 = 'b';"
   12825       "  var r0 = %_GetFromCache(0, key0);"
   12826       "  var r1 = %_GetFromCache(0, key1);"
   12827       "  var r0_ = %_GetFromCache(0, key0);"
   12828       "  if (r0 !== r0_)"
   12829       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
   12830       "  var r1_ = %_GetFromCache(0, key1);"
   12831       "  if (r1 !== r1_)"
   12832       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
   12833       "  return 'PASSED';"
   12834       "})()";
   12835   HEAP->ClearJSFunctionResultCaches();
   12836   ExpectString(code, "PASSED");
   12837 }
   12838 
   12839 
   12840 static const int k0CacheSize = 16;
   12841 
   12842 THREADED_TEST(FillJSFunctionResultCache) {
   12843   i::FLAG_allow_natives_syntax = true;
   12844   v8::HandleScope scope;
   12845 
   12846   LocalContext context;
   12847 
   12848   const char* code =
   12849       "(function() {"
   12850       "  var k = 'a';"
   12851       "  var r = %_GetFromCache(0, k);"
   12852       "  for (var i = 0; i < 16; i++) {"
   12853       "    %_GetFromCache(0, 'a' + i);"
   12854       "  };"
   12855       "  if (r === %_GetFromCache(0, k))"
   12856       "    return 'FAILED: k0CacheSize is too small';"
   12857       "  return 'PASSED';"
   12858       "})()";
   12859   HEAP->ClearJSFunctionResultCaches();
   12860   ExpectString(code, "PASSED");
   12861 }
   12862 
   12863 
   12864 THREADED_TEST(RoundRobinGetFromCache) {
   12865   i::FLAG_allow_natives_syntax = true;
   12866   v8::HandleScope scope;
   12867 
   12868   LocalContext context;
   12869 
   12870   const char* code =
   12871       "(function() {"
   12872       "  var keys = [];"
   12873       "  for (var i = 0; i < 16; i++) keys.push(i);"
   12874       "  var values = [];"
   12875       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   12876       "  for (var i = 0; i < 16; i++) {"
   12877       "    var v = %_GetFromCache(0, keys[i]);"
   12878       "    if (v !== values[i])"
   12879       "      return 'Wrong value for ' + "
   12880       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   12881       "  };"
   12882       "  return 'PASSED';"
   12883       "})()";
   12884   HEAP->ClearJSFunctionResultCaches();
   12885   ExpectString(code, "PASSED");
   12886 }
   12887 
   12888 
   12889 THREADED_TEST(ReverseGetFromCache) {
   12890   i::FLAG_allow_natives_syntax = true;
   12891   v8::HandleScope scope;
   12892 
   12893   LocalContext context;
   12894 
   12895   const char* code =
   12896       "(function() {"
   12897       "  var keys = [];"
   12898       "  for (var i = 0; i < 16; i++) keys.push(i);"
   12899       "  var values = [];"
   12900       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   12901       "  for (var i = 15; i >= 16; i--) {"
   12902       "    var v = %_GetFromCache(0, keys[i]);"
   12903       "    if (v !== values[i])"
   12904       "      return 'Wrong value for ' + "
   12905       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   12906       "  };"
   12907       "  return 'PASSED';"
   12908       "})()";
   12909   HEAP->ClearJSFunctionResultCaches();
   12910   ExpectString(code, "PASSED");
   12911 }
   12912 
   12913 
   12914 THREADED_TEST(TestEviction) {
   12915   i::FLAG_allow_natives_syntax = true;
   12916   v8::HandleScope scope;
   12917 
   12918   LocalContext context;
   12919 
   12920   const char* code =
   12921       "(function() {"
   12922       "  for (var i = 0; i < 2*16; i++) {"
   12923       "    %_GetFromCache(0, 'a' + i);"
   12924       "  };"
   12925       "  return 'PASSED';"
   12926       "})()";
   12927   HEAP->ClearJSFunctionResultCaches();
   12928   ExpectString(code, "PASSED");
   12929 }
   12930 
   12931 
   12932 THREADED_TEST(TwoByteStringInAsciiCons) {
   12933   // See Chromium issue 47824.
   12934   v8::HandleScope scope;
   12935 
   12936   LocalContext context;
   12937   const char* init_code =
   12938       "var str1 = 'abelspendabel';"
   12939       "var str2 = str1 + str1 + str1;"
   12940       "str2;";
   12941   Local<Value> result = CompileRun(init_code);
   12942 
   12943   CHECK(result->IsString());
   12944   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   12945   int length = string->length();
   12946   CHECK(string->IsAsciiRepresentation());
   12947 
   12948   FlattenString(string);
   12949   i::Handle<i::String> flat_string = FlattenGetString(string);
   12950 
   12951   CHECK(string->IsAsciiRepresentation());
   12952   CHECK(flat_string->IsAsciiRepresentation());
   12953 
   12954   // Create external resource.
   12955   uint16_t* uc16_buffer = new uint16_t[length + 1];
   12956 
   12957   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   12958   uc16_buffer[length] = 0;
   12959 
   12960   TestResource resource(uc16_buffer);
   12961 
   12962   flat_string->MakeExternal(&resource);
   12963 
   12964   CHECK(flat_string->IsTwoByteRepresentation());
   12965 
   12966   // At this point, we should have a Cons string which is flat and ASCII,
   12967   // with a first half that is a two-byte string (although it only contains
   12968   // ASCII characters). This is a valid sequence of steps, and it can happen
   12969   // in real pages.
   12970 
   12971   CHECK(string->IsAsciiRepresentation());
   12972   i::ConsString* cons = i::ConsString::cast(*string);
   12973   CHECK_EQ(0, cons->second()->length());
   12974   CHECK(cons->first()->IsTwoByteRepresentation());
   12975 
   12976   // Check that some string operations work.
   12977 
   12978   // Atom RegExp.
   12979   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   12980   CHECK_EQ(6, reresult->Int32Value());
   12981 
   12982   // Nonatom RegExp.
   12983   reresult = CompileRun("str2.match(/abe./g).length;");
   12984   CHECK_EQ(6, reresult->Int32Value());
   12985 
   12986   reresult = CompileRun("str2.search(/bel/g);");
   12987   CHECK_EQ(1, reresult->Int32Value());
   12988 
   12989   reresult = CompileRun("str2.search(/be./g);");
   12990   CHECK_EQ(1, reresult->Int32Value());
   12991 
   12992   ExpectTrue("/bel/g.test(str2);");
   12993 
   12994   ExpectTrue("/be./g.test(str2);");
   12995 
   12996   reresult = CompileRun("/bel/g.exec(str2);");
   12997   CHECK(!reresult->IsNull());
   12998 
   12999   reresult = CompileRun("/be./g.exec(str2);");
   13000   CHECK(!reresult->IsNull());
   13001 
   13002   ExpectString("str2.substring(2, 10);", "elspenda");
   13003 
   13004   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   13005 
   13006   ExpectString("str2.charAt(2);", "e");
   13007 
   13008   reresult = CompileRun("str2.charCodeAt(2);");
   13009   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
   13010 }
   13011 
   13012 
   13013 // Failed access check callback that performs a GC on each invocation.
   13014 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   13015                                  v8::AccessType type,
   13016                                  Local<v8::Value> data) {
   13017   HEAP->CollectAllGarbage(true);
   13018 }
   13019 
   13020 
   13021 TEST(GCInFailedAccessCheckCallback) {
   13022   // Install a failed access check callback that performs a GC on each
   13023   // invocation. Then force the callback to be called from va
   13024 
   13025   v8::V8::Initialize();
   13026   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   13027 
   13028   v8::HandleScope scope;
   13029 
   13030   // Create an ObjectTemplate for global objects and install access
   13031   // check callbacks that will block access.
   13032   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   13033   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   13034                                            IndexedGetAccessBlocker,
   13035                                            v8::Handle<v8::Value>(),
   13036                                            false);
   13037 
   13038   // Create a context and set an x property on it's global object.
   13039   LocalContext context0(NULL, global_template);
   13040   context0->Global()->Set(v8_str("x"), v8_num(42));
   13041   v8::Handle<v8::Object> global0 = context0->Global();
   13042 
   13043   // Create a context with a different security token so that the
   13044   // failed access check callback will be called on each access.
   13045   LocalContext context1(NULL, global_template);
   13046   context1->Global()->Set(v8_str("other"), global0);
   13047 
   13048   // Get property with failed access check.
   13049   ExpectUndefined("other.x");
   13050 
   13051   // Get element with failed access check.
   13052   ExpectUndefined("other[0]");
   13053 
   13054   // Set property with failed access check.
   13055   v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
   13056   CHECK(result->IsObject());
   13057 
   13058   // Set element with failed access check.
   13059   result = CompileRun("other[0] = new Object()");
   13060   CHECK(result->IsObject());
   13061 
   13062   // Get property attribute with failed access check.
   13063   ExpectFalse("\'x\' in other");
   13064 
   13065   // Get property attribute for element with failed access check.
   13066   ExpectFalse("0 in other");
   13067 
   13068   // Delete property.
   13069   ExpectFalse("delete other.x");
   13070 
   13071   // Delete element.
   13072   CHECK_EQ(false, global0->Delete(0));
   13073 
   13074   // DefineAccessor.
   13075   CHECK_EQ(false,
   13076            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
   13077 
   13078   // Define JavaScript accessor.
   13079   ExpectUndefined("Object.prototype.__defineGetter__.call("
   13080                   "    other, \'x\', function() { return 42; })");
   13081 
   13082   // LookupAccessor.
   13083   ExpectUndefined("Object.prototype.__lookupGetter__.call("
   13084                   "    other, \'x\')");
   13085 
   13086   // HasLocalElement.
   13087   ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
   13088 
   13089   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
   13090   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
   13091   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
   13092 
   13093   // Reset the failed access check callback so it does not influence
   13094   // the other tests.
   13095   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
   13096 }
   13097 
   13098 TEST(DefaultIsolateGetCurrent) {
   13099   CHECK(v8::Isolate::GetCurrent() != NULL);
   13100   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   13101   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   13102   printf("*** %s\n", "DefaultIsolateGetCurrent success");
   13103 }
   13104 
   13105 TEST(IsolateNewDispose) {
   13106   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
   13107   v8::Isolate* isolate = v8::Isolate::New();
   13108   CHECK(isolate != NULL);
   13109   CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   13110   CHECK(current_isolate != isolate);
   13111   CHECK(current_isolate == v8::Isolate::GetCurrent());
   13112 
   13113   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   13114   last_location = last_message = NULL;
   13115   isolate->Dispose();
   13116   CHECK_EQ(last_location, NULL);
   13117   CHECK_EQ(last_message, NULL);
   13118 }
   13119 
   13120 TEST(IsolateEnterExitDefault) {
   13121   v8::HandleScope scope;
   13122   LocalContext context;
   13123   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
   13124   CHECK(current_isolate != NULL);  // Default isolate.
   13125   ExpectString("'hello'", "hello");
   13126   current_isolate->Enter();
   13127   ExpectString("'still working'", "still working");
   13128   current_isolate->Exit();
   13129   ExpectString("'still working 2'", "still working 2");
   13130   current_isolate->Exit();
   13131   // Default isolate is always, well, 'default current'.
   13132   CHECK_EQ(v8::Isolate::GetCurrent(), current_isolate);
   13133   // Still working since default isolate is auto-entering any thread
   13134   // that has no isolate and attempts to execute V8 APIs.
   13135   ExpectString("'still working 3'", "still working 3");
   13136 }
   13137 
   13138 TEST(DisposeDefaultIsolate) {
   13139   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   13140 
   13141   // Run some V8 code to trigger default isolate to become 'current'.
   13142   v8::HandleScope scope;
   13143   LocalContext context;
   13144   ExpectString("'run some V8'", "run some V8");
   13145 
   13146   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   13147   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   13148   last_location = last_message = NULL;
   13149   isolate->Dispose();
   13150   // It is not possible to dispose default isolate via Isolate API.
   13151   CHECK_NE(last_location, NULL);
   13152   CHECK_NE(last_message, NULL);
   13153 }
   13154 
   13155 TEST(RunDefaultAndAnotherIsolate) {
   13156   v8::HandleScope scope;
   13157   LocalContext context;
   13158 
   13159   // Enter new isolate.
   13160   v8::Isolate* isolate = v8::Isolate::New();
   13161   CHECK(isolate);
   13162   isolate->Enter();
   13163   { // Need this block because subsequent Exit() will deallocate Heap,
   13164     // so we need all scope objects to be deconstructed when it happens.
   13165     v8::HandleScope scope_new;
   13166     LocalContext context_new;
   13167 
   13168     // Run something in new isolate.
   13169     CompileRun("var foo = 153;");
   13170     ExpectTrue("function f() { return foo == 153; }; f()");
   13171   }
   13172   isolate->Exit();
   13173 
   13174   // This runs automatically in default isolate.
   13175   // Variables in another isolate should be not available.
   13176   ExpectTrue("function f() {"
   13177              "  try {"
   13178              "    foo;"
   13179              "    return false;"
   13180              "  } catch(e) {"
   13181              "    return true;"
   13182              "  }"
   13183              "};"
   13184              "var bar = 371;"
   13185              "f()");
   13186 
   13187   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   13188   last_location = last_message = NULL;
   13189   isolate->Dispose();
   13190   CHECK_EQ(last_location, NULL);
   13191   CHECK_EQ(last_message, NULL);
   13192 
   13193   // Check that default isolate still runs.
   13194   ExpectTrue("function f() { return bar == 371; }; f()");
   13195 }
   13196 
   13197 TEST(DisposeIsolateWhenInUse) {
   13198   v8::Isolate* isolate = v8::Isolate::New();
   13199   CHECK(isolate);
   13200   isolate->Enter();
   13201   v8::HandleScope scope;
   13202   LocalContext context;
   13203   // Run something in this isolate.
   13204   ExpectTrue("true");
   13205   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   13206   last_location = last_message = NULL;
   13207   // Still entered, should fail.
   13208   isolate->Dispose();
   13209   CHECK_NE(last_location, NULL);
   13210   CHECK_NE(last_message, NULL);
   13211 }
   13212 
   13213 TEST(RunTwoIsolatesOnSingleThread) {
   13214   // Run isolate 1.
   13215   v8::Isolate* isolate1 = v8::Isolate::New();
   13216   isolate1->Enter();
   13217   v8::Persistent<v8::Context> context1 = v8::Context::New();
   13218 
   13219   {
   13220     v8::Context::Scope cscope(context1);
   13221     v8::HandleScope scope;
   13222     // Run something in new isolate.
   13223     CompileRun("var foo = 'isolate 1';");
   13224     ExpectString("function f() { return foo; }; f()", "isolate 1");
   13225   }
   13226 
   13227   // Run isolate 2.
   13228   v8::Isolate* isolate2 = v8::Isolate::New();
   13229   v8::Persistent<v8::Context> context2;
   13230 
   13231   {
   13232     v8::Isolate::Scope iscope(isolate2);
   13233     context2 = v8::Context::New();
   13234     v8::Context::Scope cscope(context2);
   13235     v8::HandleScope scope;
   13236 
   13237     // Run something in new isolate.
   13238     CompileRun("var foo = 'isolate 2';");
   13239     ExpectString("function f() { return foo; }; f()", "isolate 2");
   13240   }
   13241 
   13242   {
   13243     v8::Context::Scope cscope(context1);
   13244     v8::HandleScope scope;
   13245     // Now again in isolate 1
   13246     ExpectString("function f() { return foo; }; f()", "isolate 1");
   13247   }
   13248 
   13249   isolate1->Exit();
   13250 
   13251   // Run some stuff in default isolate.
   13252   v8::Persistent<v8::Context> context_default = v8::Context::New();
   13253 
   13254   {
   13255     v8::Context::Scope cscope(context_default);
   13256     v8::HandleScope scope;
   13257     // Variables in other isolates should be not available, verify there
   13258     // is an exception.
   13259     ExpectTrue("function f() {"
   13260                "  try {"
   13261                "    foo;"
   13262                "    return false;"
   13263                "  } catch(e) {"
   13264                "    return true;"
   13265                "  }"
   13266                "};"
   13267                "var isDefaultIsolate = true;"
   13268                "f()");
   13269   }
   13270 
   13271   isolate1->Enter();
   13272 
   13273   {
   13274     v8::Isolate::Scope iscope(isolate2);
   13275     v8::Context::Scope cscope(context2);
   13276     v8::HandleScope scope;
   13277     ExpectString("function f() { return foo; }; f()", "isolate 2");
   13278   }
   13279 
   13280   {
   13281     v8::Context::Scope cscope(context1);
   13282     v8::HandleScope scope;
   13283     ExpectString("function f() { return foo; }; f()", "isolate 1");
   13284   }
   13285 
   13286   {
   13287     v8::Isolate::Scope iscope(isolate2);
   13288     context2.Dispose();
   13289   }
   13290 
   13291   context1.Dispose();
   13292   isolate1->Exit();
   13293 
   13294   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   13295   last_location = last_message = NULL;
   13296 
   13297   isolate1->Dispose();
   13298   CHECK_EQ(last_location, NULL);
   13299   CHECK_EQ(last_message, NULL);
   13300 
   13301   isolate2->Dispose();
   13302   CHECK_EQ(last_location, NULL);
   13303   CHECK_EQ(last_message, NULL);
   13304 
   13305   // Check that default isolate still runs.
   13306   {
   13307     v8::Context::Scope cscope(context_default);
   13308     v8::HandleScope scope;
   13309     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   13310   }
   13311 }
   13312 
   13313 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   13314   v8::Isolate::Scope isolate_scope(isolate);
   13315   v8::HandleScope scope;
   13316   LocalContext context;
   13317   i::ScopedVector<char> code(1024);
   13318   i::OS::SNPrintF(code, "function fib(n) {"
   13319                         "  if (n <= 2) return 1;"
   13320                         "  return fib(n-1) + fib(n-2);"
   13321                         "}"
   13322                         "fib(%d)", limit);
   13323   Local<Value> value = CompileRun(code.start());
   13324   CHECK(value->IsNumber());
   13325   return static_cast<int>(value->NumberValue());
   13326 }
   13327 
   13328 class IsolateThread : public v8::internal::Thread {
   13329  public:
   13330   explicit IsolateThread(v8::Isolate* isolate, int fib_limit)
   13331       : Thread(NULL, "IsolateThread"),
   13332         isolate_(isolate),
   13333         fib_limit_(fib_limit),
   13334         result_(0) { }
   13335 
   13336   void Run() {
   13337     result_ = CalcFibonacci(isolate_, fib_limit_);
   13338   }
   13339 
   13340   int result() { return result_; }
   13341 
   13342  private:
   13343   v8::Isolate* isolate_;
   13344   int fib_limit_;
   13345   int result_;
   13346 };
   13347 
   13348 TEST(MultipleIsolatesOnIndividualThreads) {
   13349   v8::Isolate* isolate1 = v8::Isolate::New();
   13350   v8::Isolate* isolate2 = v8::Isolate::New();
   13351 
   13352   IsolateThread thread1(isolate1, 21);
   13353   IsolateThread thread2(isolate2, 12);
   13354 
   13355   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   13356   thread1.Start();
   13357   thread2.Start();
   13358 
   13359   int result1 = CalcFibonacci(v8::Isolate::GetCurrent(), 21);
   13360   int result2 = CalcFibonacci(v8::Isolate::GetCurrent(), 12);
   13361 
   13362   thread1.Join();
   13363   thread2.Join();
   13364 
   13365   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   13366   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   13367   CHECK_EQ(result1, 10946);
   13368   CHECK_EQ(result2, 144);
   13369   CHECK_EQ(result1, thread1.result());
   13370   CHECK_EQ(result2, thread2.result());
   13371 
   13372   isolate1->Dispose();
   13373   isolate2->Dispose();
   13374 }
   13375 
   13376 
   13377 class InitDefaultIsolateThread : public v8::internal::Thread {
   13378  public:
   13379   enum TestCase {
   13380     IgnoreOOM,
   13381     SetResourceConstraints,
   13382     SetFatalHandler,
   13383     SetCounterFunction,
   13384     SetCreateHistogramFunction,
   13385     SetAddHistogramSampleFunction
   13386   };
   13387 
   13388   explicit InitDefaultIsolateThread(TestCase testCase)
   13389       : Thread(NULL, "InitDefaultIsolateThread"),
   13390         testCase_(testCase),
   13391         result_(false) { }
   13392 
   13393   void Run() {
   13394     switch (testCase_) {
   13395     case IgnoreOOM:
   13396       v8::V8::IgnoreOutOfMemoryException();
   13397       break;
   13398 
   13399     case SetResourceConstraints: {
   13400       static const int K = 1024;
   13401       v8::ResourceConstraints constraints;
   13402       constraints.set_max_young_space_size(256 * K);
   13403       constraints.set_max_old_space_size(4 * K * K);
   13404       v8::SetResourceConstraints(&constraints);
   13405       break;
   13406     }
   13407 
   13408     case SetFatalHandler:
   13409       v8::V8::SetFatalErrorHandler(NULL);
   13410       break;
   13411 
   13412     case SetCounterFunction:
   13413       v8::V8::SetCounterFunction(NULL);
   13414       break;
   13415 
   13416     case SetCreateHistogramFunction:
   13417       v8::V8::SetCreateHistogramFunction(NULL);
   13418       break;
   13419 
   13420     case SetAddHistogramSampleFunction:
   13421       v8::V8::SetAddHistogramSampleFunction(NULL);
   13422       break;
   13423     }
   13424     result_ = true;
   13425   }
   13426 
   13427   bool result() { return result_; }
   13428 
   13429  private:
   13430   TestCase testCase_;
   13431   bool result_;
   13432 };
   13433 
   13434 
   13435 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   13436   InitDefaultIsolateThread thread(testCase);
   13437   thread.Start();
   13438   thread.Join();
   13439   CHECK_EQ(thread.result(), true);
   13440 }
   13441 
   13442 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
   13443   InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
   13444 }
   13445 
   13446 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
   13447   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
   13448 }
   13449 
   13450 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
   13451   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   13452 }
   13453 
   13454 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
   13455   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   13456 }
   13457 
   13458 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
   13459   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   13460 }
   13461 
   13462 TEST(InitializeDefaultIsolateOnSecondaryThread6) {
   13463   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   13464 }
   13465 
   13466 
   13467 TEST(StringCheckMultipleContexts) {
   13468   const char* code =
   13469       "(function() { return \"a\".charAt(0); })()";
   13470 
   13471   {
   13472     // Run the code twice in the first context to initialize the call IC.
   13473     v8::HandleScope scope;
   13474     LocalContext context1;
   13475     ExpectString(code, "a");
   13476     ExpectString(code, "a");
   13477   }
   13478 
   13479   {
   13480     // Change the String.prototype in the second context and check
   13481     // that the right function gets called.
   13482     v8::HandleScope scope;
   13483     LocalContext context2;
   13484     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   13485     ExpectString(code, "not a");
   13486   }
   13487 }
   13488 
   13489 
   13490 TEST(NumberCheckMultipleContexts) {
   13491   const char* code =
   13492       "(function() { return (42).toString(); })()";
   13493 
   13494   {
   13495     // Run the code twice in the first context to initialize the call IC.
   13496     v8::HandleScope scope;
   13497     LocalContext context1;
   13498     ExpectString(code, "42");
   13499     ExpectString(code, "42");
   13500   }
   13501 
   13502   {
   13503     // Change the Number.prototype in the second context and check
   13504     // that the right function gets called.
   13505     v8::HandleScope scope;
   13506     LocalContext context2;
   13507     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   13508     ExpectString(code, "not 42");
   13509   }
   13510 }
   13511 
   13512 
   13513 TEST(BooleanCheckMultipleContexts) {
   13514   const char* code =
   13515       "(function() { return true.toString(); })()";
   13516 
   13517   {
   13518     // Run the code twice in the first context to initialize the call IC.
   13519     v8::HandleScope scope;
   13520     LocalContext context1;
   13521     ExpectString(code, "true");
   13522     ExpectString(code, "true");
   13523   }
   13524 
   13525   {
   13526     // Change the Boolean.prototype in the second context and check
   13527     // that the right function gets called.
   13528     v8::HandleScope scope;
   13529     LocalContext context2;
   13530     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   13531     ExpectString(code, "");
   13532   }
   13533 }
   13534 
   13535 
   13536 TEST(DontDeleteCellLoadIC) {
   13537   const char* function_code =
   13538       "function readCell() { while (true) { return cell; } }";
   13539 
   13540   {
   13541     // Run the code twice in the first context to initialize the load
   13542     // IC for a don't delete cell.
   13543     v8::HandleScope scope;
   13544     LocalContext context1;
   13545     CompileRun("var cell = \"first\";");
   13546     ExpectBoolean("delete cell", false);
   13547     CompileRun(function_code);
   13548     ExpectString("readCell()", "first");
   13549     ExpectString("readCell()", "first");
   13550   }
   13551 
   13552   {
   13553     // Use a deletable cell in the second context.
   13554     v8::HandleScope scope;
   13555     LocalContext context2;
   13556     CompileRun("cell = \"second\";");
   13557     CompileRun(function_code);
   13558     ExpectString("readCell()", "second");
   13559     ExpectBoolean("delete cell", true);
   13560     ExpectString("(function() {"
   13561                  "  try {"
   13562                  "    return readCell();"
   13563                  "  } catch(e) {"
   13564                  "    return e.toString();"
   13565                  "  }"
   13566                  "})()",
   13567                  "ReferenceError: cell is not defined");
   13568     CompileRun("cell = \"new_second\";");
   13569     HEAP->CollectAllGarbage(true);
   13570     ExpectString("readCell()", "new_second");
   13571     ExpectString("readCell()", "new_second");
   13572   }
   13573 }
   13574 
   13575 
   13576 TEST(DontDeleteCellLoadICForceDelete) {
   13577   const char* function_code =
   13578       "function readCell() { while (true) { return cell; } }";
   13579 
   13580   // Run the code twice to initialize the load IC for a don't delete
   13581   // cell.
   13582   v8::HandleScope scope;
   13583   LocalContext context;
   13584   CompileRun("var cell = \"value\";");
   13585   ExpectBoolean("delete cell", false);
   13586   CompileRun(function_code);
   13587   ExpectString("readCell()", "value");
   13588   ExpectString("readCell()", "value");
   13589 
   13590   // Delete the cell using the API and check the inlined code works
   13591   // correctly.
   13592   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   13593   ExpectString("(function() {"
   13594                "  try {"
   13595                "    return readCell();"
   13596                "  } catch(e) {"
   13597                "    return e.toString();"
   13598                "  }"
   13599                "})()",
   13600                "ReferenceError: cell is not defined");
   13601 }
   13602 
   13603 
   13604 TEST(DontDeleteCellLoadICAPI) {
   13605   const char* function_code =
   13606       "function readCell() { while (true) { return cell; } }";
   13607 
   13608   // Run the code twice to initialize the load IC for a don't delete
   13609   // cell created using the API.
   13610   v8::HandleScope scope;
   13611   LocalContext context;
   13612   context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
   13613   ExpectBoolean("delete cell", false);
   13614   CompileRun(function_code);
   13615   ExpectString("readCell()", "value");
   13616   ExpectString("readCell()", "value");
   13617 
   13618   // Delete the cell using the API and check the inlined code works
   13619   // correctly.
   13620   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   13621   ExpectString("(function() {"
   13622                "  try {"
   13623                "    return readCell();"
   13624                "  } catch(e) {"
   13625                "    return e.toString();"
   13626                "  }"
   13627                "})()",
   13628                "ReferenceError: cell is not defined");
   13629 }
   13630 
   13631 
   13632 TEST(GlobalLoadICGC) {
   13633   const char* function_code =
   13634       "function readCell() { while (true) { return cell; } }";
   13635 
   13636   // Check inline load code for a don't delete cell is cleared during
   13637   // GC.
   13638   {
   13639     v8::HandleScope scope;
   13640     LocalContext context;
   13641     CompileRun("var cell = \"value\";");
   13642     ExpectBoolean("delete cell", false);
   13643     CompileRun(function_code);
   13644     ExpectString("readCell()", "value");
   13645     ExpectString("readCell()", "value");
   13646   }
   13647   {
   13648     v8::HandleScope scope;
   13649     LocalContext context2;
   13650     // Hold the code object in the second context.
   13651     CompileRun(function_code);
   13652     CheckSurvivingGlobalObjectsCount(1);
   13653   }
   13654 
   13655   // Check inline load code for a deletable cell is cleared during GC.
   13656   {
   13657     v8::HandleScope scope;
   13658     LocalContext context;
   13659     CompileRun("cell = \"value\";");
   13660     CompileRun(function_code);
   13661     ExpectString("readCell()", "value");
   13662     ExpectString("readCell()", "value");
   13663   }
   13664   {
   13665     v8::HandleScope scope;
   13666     LocalContext context2;
   13667     // Hold the code object in the second context.
   13668     CompileRun(function_code);
   13669     CheckSurvivingGlobalObjectsCount(1);
   13670   }
   13671 }
   13672 
   13673 
   13674 TEST(RegExp) {
   13675   v8::HandleScope scope;
   13676   LocalContext context;
   13677 
   13678   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
   13679   CHECK(re->IsRegExp());
   13680   CHECK(re->GetSource()->Equals(v8_str("foo")));
   13681   CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
   13682 
   13683   re = v8::RegExp::New(v8_str("bar"),
   13684                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   13685                                                       v8::RegExp::kGlobal));
   13686   CHECK(re->IsRegExp());
   13687   CHECK(re->GetSource()->Equals(v8_str("bar")));
   13688   CHECK_EQ(static_cast<int>(re->GetFlags()),
   13689            v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal);
   13690 
   13691   re = v8::RegExp::New(v8_str("baz"),
   13692                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   13693                                                       v8::RegExp::kMultiline));
   13694   CHECK(re->IsRegExp());
   13695   CHECK(re->GetSource()->Equals(v8_str("baz")));
   13696   CHECK_EQ(static_cast<int>(re->GetFlags()),
   13697            v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
   13698 
   13699   re = CompileRun("/quux/").As<v8::RegExp>();
   13700   CHECK(re->IsRegExp());
   13701   CHECK(re->GetSource()->Equals(v8_str("quux")));
   13702   CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
   13703 
   13704   re = CompileRun("/quux/gm").As<v8::RegExp>();
   13705   CHECK(re->IsRegExp());
   13706   CHECK(re->GetSource()->Equals(v8_str("quux")));
   13707   CHECK_EQ(static_cast<int>(re->GetFlags()),
   13708            v8::RegExp::kGlobal | v8::RegExp::kMultiline);
   13709 
   13710   // Override the RegExp constructor and check the API constructor
   13711   // still works.
   13712   CompileRun("RegExp = function() {}");
   13713 
   13714   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
   13715   CHECK(re->IsRegExp());
   13716   CHECK(re->GetSource()->Equals(v8_str("foobar")));
   13717   CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
   13718 
   13719   re = v8::RegExp::New(v8_str("foobarbaz"),
   13720                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   13721                                                       v8::RegExp::kMultiline));
   13722   CHECK(re->IsRegExp());
   13723   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
   13724   CHECK_EQ(static_cast<int>(re->GetFlags()),
   13725            v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
   13726 
   13727   context->Global()->Set(v8_str("re"), re);
   13728   ExpectTrue("re.test('FoobarbaZ')");
   13729 
   13730   v8::TryCatch try_catch;
   13731   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
   13732   CHECK(re.IsEmpty());
   13733   CHECK(try_catch.HasCaught());
   13734   context->Global()->Set(v8_str("ex"), try_catch.Exception());
   13735   ExpectTrue("ex instanceof SyntaxError");
   13736 }
   13737 
   13738 
   13739 THREADED_TEST(Equals) {
   13740   v8::HandleScope handleScope;
   13741   LocalContext localContext;
   13742 
   13743   v8::Handle<v8::Object> globalProxy = localContext->Global();
   13744   v8::Handle<Value> global = globalProxy->GetPrototype();
   13745 
   13746   CHECK(global->StrictEquals(global));
   13747   CHECK(!global->StrictEquals(globalProxy));
   13748   CHECK(!globalProxy->StrictEquals(global));
   13749   CHECK(globalProxy->StrictEquals(globalProxy));
   13750 
   13751   CHECK(global->Equals(global));
   13752   CHECK(!global->Equals(globalProxy));
   13753   CHECK(!globalProxy->Equals(global));
   13754   CHECK(globalProxy->Equals(globalProxy));
   13755 }
   13756 
   13757 
   13758 static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
   13759                                     const v8::AccessorInfo& info ) {
   13760   return v8_str("42!");
   13761 }
   13762 
   13763 
   13764 static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo& info) {
   13765   v8::Handle<v8::Array> result = v8::Array::New();
   13766   result->Set(0, v8_str("universalAnswer"));
   13767   return result;
   13768 }
   13769 
   13770 
   13771 TEST(NamedEnumeratorAndForIn) {
   13772   v8::HandleScope handle_scope;
   13773   LocalContext context;
   13774   v8::Context::Scope context_scope(context.local());
   13775 
   13776   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
   13777   tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
   13778   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
   13779   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   13780         "var result = []; for (var k in o) result.push(k); result"));
   13781   CHECK_EQ(1, result->Length());
   13782   CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
   13783 }
   13784 
   13785 
   13786 TEST(DefinePropertyPostDetach) {
   13787   v8::HandleScope scope;
   13788   LocalContext context;
   13789   v8::Handle<v8::Object> proxy = context->Global();
   13790   v8::Handle<v8::Function> define_property =
   13791       CompileRun("(function() {"
   13792                  "  Object.defineProperty("
   13793                  "    this,"
   13794                  "    1,"
   13795                  "    { configurable: true, enumerable: true, value: 3 });"
   13796                  "})").As<Function>();
   13797   context->DetachGlobal();
   13798   define_property->Call(proxy, 0, NULL);
   13799 }
   13800 
   13801 
   13802 static void InstallContextId(v8::Handle<Context> context, int id) {
   13803   Context::Scope scope(context);
   13804   CompileRun("Object.prototype").As<Object>()->
   13805       Set(v8_str("context_id"), v8::Integer::New(id));
   13806 }
   13807 
   13808 
   13809 static void CheckContextId(v8::Handle<Object> object, int expected) {
   13810   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
   13811 }
   13812 
   13813 
   13814 THREADED_TEST(CreationContext) {
   13815   HandleScope handle_scope;
   13816   Persistent<Context> context1 = Context::New();
   13817   InstallContextId(context1, 1);
   13818   Persistent<Context> context2 = Context::New();
   13819   InstallContextId(context2, 2);
   13820   Persistent<Context> context3 = Context::New();
   13821   InstallContextId(context3, 3);
   13822 
   13823   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
   13824 
   13825   Local<Object> object1;
   13826   Local<Function> func1;
   13827   {
   13828     Context::Scope scope(context1);
   13829     object1 = Object::New();
   13830     func1 = tmpl->GetFunction();
   13831   }
   13832 
   13833   Local<Object> object2;
   13834   Local<Function> func2;
   13835   {
   13836     Context::Scope scope(context2);
   13837     object2 = Object::New();
   13838     func2 = tmpl->GetFunction();
   13839   }
   13840 
   13841   Local<Object> instance1;
   13842   Local<Object> instance2;
   13843 
   13844   {
   13845     Context::Scope scope(context3);
   13846     instance1 = func1->NewInstance();
   13847     instance2 = func2->NewInstance();
   13848   }
   13849 
   13850   CHECK(object1->CreationContext() == context1);
   13851   CheckContextId(object1, 1);
   13852   CHECK(func1->CreationContext() == context1);
   13853   CheckContextId(func1, 1);
   13854   CHECK(instance1->CreationContext() == context1);
   13855   CheckContextId(instance1, 1);
   13856   CHECK(object2->CreationContext() == context2);
   13857   CheckContextId(object2, 2);
   13858   CHECK(func2->CreationContext() == context2);
   13859   CheckContextId(func2, 2);
   13860   CHECK(instance2->CreationContext() == context2);
   13861   CheckContextId(instance2, 2);
   13862 
   13863   {
   13864     Context::Scope scope(context1);
   13865     CHECK(object1->CreationContext() == context1);
   13866     CheckContextId(object1, 1);
   13867     CHECK(func1->CreationContext() == context1);
   13868     CheckContextId(func1, 1);
   13869     CHECK(instance1->CreationContext() == context1);
   13870     CheckContextId(instance1, 1);
   13871     CHECK(object2->CreationContext() == context2);
   13872     CheckContextId(object2, 2);
   13873     CHECK(func2->CreationContext() == context2);
   13874     CheckContextId(func2, 2);
   13875     CHECK(instance2->CreationContext() == context2);
   13876     CheckContextId(instance2, 2);
   13877   }
   13878 
   13879   {
   13880     Context::Scope scope(context2);
   13881     CHECK(object1->CreationContext() == context1);
   13882     CheckContextId(object1, 1);
   13883     CHECK(func1->CreationContext() == context1);
   13884     CheckContextId(func1, 1);
   13885     CHECK(instance1->CreationContext() == context1);
   13886     CheckContextId(instance1, 1);
   13887     CHECK(object2->CreationContext() == context2);
   13888     CheckContextId(object2, 2);
   13889     CHECK(func2->CreationContext() == context2);
   13890     CheckContextId(func2, 2);
   13891     CHECK(instance2->CreationContext() == context2);
   13892     CheckContextId(instance2, 2);
   13893   }
   13894 
   13895   context1.Dispose();
   13896   context2.Dispose();
   13897   context3.Dispose();
   13898 }
   13899