Home | History | Annotate | Download | only in cctest
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <limits.h>
     29 
     30 #include "v8.h"
     31 
     32 #include "api.h"
     33 #include "isolate.h"
     34 #include "compilation-cache.h"
     35 #include "execution.h"
     36 #include "snapshot.h"
     37 #include "platform.h"
     38 #include "utils.h"
     39 #include "cctest.h"
     40 #include "parser.h"
     41 #include "unicode-inl.h"
     42 
     43 static const bool kLogThreading = false;
     44 
     45 static bool IsNaN(double x) {
     46 #ifdef WIN32
     47   return _isnan(x);
     48 #else
     49   return isnan(x);
     50 #endif
     51 }
     52 
     53 using ::v8::AccessorInfo;
     54 using ::v8::Arguments;
     55 using ::v8::Context;
     56 using ::v8::Extension;
     57 using ::v8::Function;
     58 using ::v8::FunctionTemplate;
     59 using ::v8::Handle;
     60 using ::v8::HandleScope;
     61 using ::v8::Local;
     62 using ::v8::Message;
     63 using ::v8::MessageCallback;
     64 using ::v8::Object;
     65 using ::v8::ObjectTemplate;
     66 using ::v8::Persistent;
     67 using ::v8::Script;
     68 using ::v8::StackTrace;
     69 using ::v8::String;
     70 using ::v8::TryCatch;
     71 using ::v8::Undefined;
     72 using ::v8::V8;
     73 using ::v8::Value;
     74 
     75 
     76 static void ExpectString(const char* code, const char* expected) {
     77   Local<Value> result = CompileRun(code);
     78   CHECK(result->IsString());
     79   String::AsciiValue ascii(result);
     80   CHECK_EQ(expected, *ascii);
     81 }
     82 
     83 static void ExpectInt32(const char* code, int expected) {
     84   Local<Value> result = CompileRun(code);
     85   CHECK(result->IsInt32());
     86   CHECK_EQ(expected, result->Int32Value());
     87 }
     88 
     89 static void ExpectBoolean(const char* code, bool expected) {
     90   Local<Value> result = CompileRun(code);
     91   CHECK(result->IsBoolean());
     92   CHECK_EQ(expected, result->BooleanValue());
     93 }
     94 
     95 
     96 static void ExpectTrue(const char* code) {
     97   ExpectBoolean(code, true);
     98 }
     99 
    100 
    101 static void ExpectFalse(const char* code) {
    102   ExpectBoolean(code, false);
    103 }
    104 
    105 
    106 static void ExpectObject(const char* code, Local<Value> expected) {
    107   Local<Value> result = CompileRun(code);
    108   CHECK(result->Equals(expected));
    109 }
    110 
    111 
    112 static void ExpectUndefined(const char* code) {
    113   Local<Value> result = CompileRun(code);
    114   CHECK(result->IsUndefined());
    115 }
    116 
    117 
    118 static int signature_callback_count;
    119 static v8::Handle<Value> IncrementingSignatureCallback(
    120     const v8::Arguments& args) {
    121   ApiTestFuzzer::Fuzz();
    122   signature_callback_count++;
    123   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
    124   for (int i = 0; i < args.Length(); i++)
    125     result->Set(v8::Integer::New(i), args[i]);
    126   return result;
    127 }
    128 
    129 
    130 static v8::Handle<Value> SignatureCallback(const v8::Arguments& args) {
    131   ApiTestFuzzer::Fuzz();
    132   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
    133   for (int i = 0; i < args.Length(); i++) {
    134     result->Set(v8::Integer::New(i), args[i]);
    135   }
    136   return result;
    137 }
    138 
    139 
    140 THREADED_TEST(Handles) {
    141   v8::HandleScope scope;
    142   Local<Context> local_env;
    143   {
    144     LocalContext env;
    145     local_env = env.local();
    146   }
    147 
    148   // Local context should still be live.
    149   CHECK(!local_env.IsEmpty());
    150   local_env->Enter();
    151 
    152   v8::Handle<v8::Primitive> undef = v8::Undefined();
    153   CHECK(!undef.IsEmpty());
    154   CHECK(undef->IsUndefined());
    155 
    156   const char* c_source = "1 + 2 + 3";
    157   Local<String> source = String::New(c_source);
    158   Local<Script> script = Script::Compile(source);
    159   CHECK_EQ(6, script->Run()->Int32Value());
    160 
    161   local_env->Exit();
    162 }
    163 
    164 
    165 THREADED_TEST(ReceiverSignature) {
    166   v8::HandleScope scope;
    167   LocalContext env;
    168   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
    169   v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
    170   fun->PrototypeTemplate()->Set(
    171       v8_str("m"),
    172       v8::FunctionTemplate::New(IncrementingSignatureCallback,
    173                                 v8::Handle<Value>(),
    174                                 sig));
    175   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
    176   signature_callback_count = 0;
    177   CompileRun(
    178       "var o = new Fun();"
    179       "o.m();");
    180   CHECK_EQ(1, signature_callback_count);
    181   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
    182   sub_fun->Inherit(fun);
    183   env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction());
    184   CompileRun(
    185       "var o = new SubFun();"
    186       "o.m();");
    187   CHECK_EQ(2, signature_callback_count);
    188 
    189   v8::TryCatch try_catch;
    190   CompileRun(
    191       "var o = { };"
    192       "o.m = Fun.prototype.m;"
    193       "o.m();");
    194   CHECK_EQ(2, signature_callback_count);
    195   CHECK(try_catch.HasCaught());
    196   try_catch.Reset();
    197   v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
    198   sub_fun->Inherit(fun);
    199   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
    200   CompileRun(
    201       "var o = new UnrelFun();"
    202       "o.m = Fun.prototype.m;"
    203       "o.m();");
    204   CHECK_EQ(2, signature_callback_count);
    205   CHECK(try_catch.HasCaught());
    206 }
    207 
    208 
    209 THREADED_TEST(ArgumentSignature) {
    210   v8::HandleScope scope;
    211   LocalContext env;
    212   v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
    213   cons->SetClassName(v8_str("Cons"));
    214   v8::Handle<v8::Signature> sig =
    215       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
    216   v8::Handle<v8::FunctionTemplate> fun =
    217       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
    218   env->Global()->Set(v8_str("Cons"), cons->GetFunction());
    219   env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
    220 
    221   v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
    222   CHECK(value1->IsTrue());
    223 
    224   v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
    225   CHECK(value2->IsTrue());
    226 
    227   v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
    228   CHECK(value3->IsTrue());
    229 
    230   v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
    231   cons1->SetClassName(v8_str("Cons1"));
    232   v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
    233   cons2->SetClassName(v8_str("Cons2"));
    234   v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
    235   cons3->SetClassName(v8_str("Cons3"));
    236 
    237   v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
    238   v8::Handle<v8::Signature> wsig =
    239       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
    240   v8::Handle<v8::FunctionTemplate> fun2 =
    241       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
    242 
    243   env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
    244   env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
    245   env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
    246   env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
    247   v8::Handle<Value> value4 = CompileRun(
    248       "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
    249       "'[object Cons1],[object Cons2],[object Cons3]'");
    250   CHECK(value4->IsTrue());
    251 
    252   v8::Handle<Value> value5 = CompileRun(
    253       "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
    254   CHECK(value5->IsTrue());
    255 
    256   v8::Handle<Value> value6 = CompileRun(
    257       "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
    258   CHECK(value6->IsTrue());
    259 
    260   v8::Handle<Value> value7 = CompileRun(
    261       "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
    262       "'[object Cons1],[object Cons2],[object Cons3],d';");
    263   CHECK(value7->IsTrue());
    264 
    265   v8::Handle<Value> value8 = CompileRun(
    266       "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
    267   CHECK(value8->IsTrue());
    268 }
    269 
    270 
    271 THREADED_TEST(HulIgennem) {
    272   v8::HandleScope scope;
    273   LocalContext env;
    274   v8::Handle<v8::Primitive> undef = v8::Undefined();
    275   Local<String> undef_str = undef->ToString();
    276   char* value = i::NewArray<char>(undef_str->Length() + 1);
    277   undef_str->WriteAscii(value);
    278   CHECK_EQ(0, strcmp(value, "undefined"));
    279   i::DeleteArray(value);
    280 }
    281 
    282 
    283 THREADED_TEST(Access) {
    284   v8::HandleScope scope;
    285   LocalContext env;
    286   Local<v8::Object> obj = v8::Object::New();
    287   Local<Value> foo_before = obj->Get(v8_str("foo"));
    288   CHECK(foo_before->IsUndefined());
    289   Local<String> bar_str = v8_str("bar");
    290   obj->Set(v8_str("foo"), bar_str);
    291   Local<Value> foo_after = obj->Get(v8_str("foo"));
    292   CHECK(!foo_after->IsUndefined());
    293   CHECK(foo_after->IsString());
    294   CHECK_EQ(bar_str, foo_after);
    295 }
    296 
    297 
    298 THREADED_TEST(AccessElement) {
    299   v8::HandleScope scope;
    300   LocalContext env;
    301   Local<v8::Object> obj = v8::Object::New();
    302   Local<Value> before = obj->Get(1);
    303   CHECK(before->IsUndefined());
    304   Local<String> bar_str = v8_str("bar");
    305   obj->Set(1, bar_str);
    306   Local<Value> after = obj->Get(1);
    307   CHECK(!after->IsUndefined());
    308   CHECK(after->IsString());
    309   CHECK_EQ(bar_str, after);
    310 
    311   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
    312   CHECK_EQ(v8_str("a"), value->Get(0));
    313   CHECK_EQ(v8_str("b"), value->Get(1));
    314 }
    315 
    316 
    317 THREADED_TEST(Script) {
    318   v8::HandleScope scope;
    319   LocalContext env;
    320   const char* c_source = "1 + 2 + 3";
    321   Local<String> source = String::New(c_source);
    322   Local<Script> script = Script::Compile(source);
    323   CHECK_EQ(6, script->Run()->Int32Value());
    324 }
    325 
    326 
    327 static uint16_t* AsciiToTwoByteString(const char* source) {
    328   int array_length = i::StrLength(source) + 1;
    329   uint16_t* converted = i::NewArray<uint16_t>(array_length);
    330   for (int i = 0; i < array_length; i++) converted[i] = source[i];
    331   return converted;
    332 }
    333 
    334 
    335 class TestResource: public String::ExternalStringResource {
    336  public:
    337   explicit TestResource(uint16_t* data, int* counter = NULL)
    338     : data_(data), length_(0), counter_(counter) {
    339     while (data[length_]) ++length_;
    340   }
    341 
    342   ~TestResource() {
    343     i::DeleteArray(data_);
    344     if (counter_ != NULL) ++*counter_;
    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   int* counter_;
    358 };
    359 
    360 
    361 class TestAsciiResource: public String::ExternalAsciiStringResource {
    362  public:
    363   explicit TestAsciiResource(const char* data, int* counter = NULL)
    364     : data_(data), length_(strlen(data)), counter_(counter) { }
    365 
    366   ~TestAsciiResource() {
    367     i::DeleteArray(data_);
    368     if (counter_ != NULL) ++*counter_;
    369   }
    370 
    371   const char* data() const {
    372     return data_;
    373   }
    374 
    375   size_t length() const {
    376     return length_;
    377   }
    378  private:
    379   const char* data_;
    380   size_t length_;
    381   int* counter_;
    382 };
    383 
    384 
    385 THREADED_TEST(ScriptUsingStringResource) {
    386   int dispose_count = 0;
    387   const char* c_source = "1 + 2 * 3";
    388   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
    389   {
    390     v8::HandleScope scope;
    391     LocalContext env;
    392     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
    393     Local<String> source = String::NewExternal(resource);
    394     Local<Script> script = Script::Compile(source);
    395     Local<Value> value = script->Run();
    396     CHECK(value->IsNumber());
    397     CHECK_EQ(7, value->Int32Value());
    398     CHECK(source->IsExternal());
    399     CHECK_EQ(resource,
    400              static_cast<TestResource*>(source->GetExternalStringResource()));
    401     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    402     CHECK_EQ(0, dispose_count);
    403   }
    404   v8::internal::Isolate::Current()->compilation_cache()->Clear();
    405   HEAP->CollectAllAvailableGarbage();
    406   CHECK_EQ(1, dispose_count);
    407 }
    408 
    409 
    410 THREADED_TEST(ScriptUsingAsciiStringResource) {
    411   int dispose_count = 0;
    412   const char* c_source = "1 + 2 * 3";
    413   {
    414     v8::HandleScope scope;
    415     LocalContext env;
    416     Local<String> source =
    417         String::NewExternal(new TestAsciiResource(i::StrDup(c_source),
    418                                                   &dispose_count));
    419     Local<Script> script = Script::Compile(source);
    420     Local<Value> value = script->Run();
    421     CHECK(value->IsNumber());
    422     CHECK_EQ(7, value->Int32Value());
    423     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    424     CHECK_EQ(0, dispose_count);
    425   }
    426   i::Isolate::Current()->compilation_cache()->Clear();
    427   HEAP->CollectAllAvailableGarbage();
    428   CHECK_EQ(1, dispose_count);
    429 }
    430 
    431 
    432 THREADED_TEST(ScriptMakingExternalString) {
    433   int dispose_count = 0;
    434   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
    435   {
    436     v8::HandleScope scope;
    437     LocalContext env;
    438     Local<String> source = String::New(two_byte_source);
    439     // Trigger GCs so that the newly allocated string moves to old gen.
    440     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    441     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    442     bool success = source->MakeExternal(new TestResource(two_byte_source,
    443                                                          &dispose_count));
    444     CHECK(success);
    445     Local<Script> script = Script::Compile(source);
    446     Local<Value> value = script->Run();
    447     CHECK(value->IsNumber());
    448     CHECK_EQ(7, value->Int32Value());
    449     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    450     CHECK_EQ(0, dispose_count);
    451   }
    452   i::Isolate::Current()->compilation_cache()->Clear();
    453   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    454   CHECK_EQ(1, dispose_count);
    455 }
    456 
    457 
    458 THREADED_TEST(ScriptMakingExternalAsciiString) {
    459   int dispose_count = 0;
    460   const char* c_source = "1 + 2 * 3";
    461   {
    462     v8::HandleScope scope;
    463     LocalContext env;
    464     Local<String> source = v8_str(c_source);
    465     // Trigger GCs so that the newly allocated string moves to old gen.
    466     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    467     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    468     bool success = source->MakeExternal(
    469         new TestAsciiResource(i::StrDup(c_source), &dispose_count));
    470     CHECK(success);
    471     Local<Script> script = Script::Compile(source);
    472     Local<Value> value = script->Run();
    473     CHECK(value->IsNumber());
    474     CHECK_EQ(7, value->Int32Value());
    475     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    476     CHECK_EQ(0, dispose_count);
    477   }
    478   i::Isolate::Current()->compilation_cache()->Clear();
    479   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    480   CHECK_EQ(1, dispose_count);
    481 }
    482 
    483 
    484 TEST(MakingExternalStringConditions) {
    485   v8::HandleScope scope;
    486   LocalContext env;
    487 
    488   // Free some space in the new space so that we can check freshness.
    489   HEAP->CollectGarbage(i::NEW_SPACE);
    490   HEAP->CollectGarbage(i::NEW_SPACE);
    491 
    492   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
    493   Local<String> small_string = String::New(two_byte_string);
    494   i::DeleteArray(two_byte_string);
    495 
    496   // We should refuse to externalize newly created small string.
    497   CHECK(!small_string->CanMakeExternal());
    498   // Trigger GCs so that the newly allocated string moves to old gen.
    499   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    500   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    501   // Old space strings should be accepted.
    502   CHECK(small_string->CanMakeExternal());
    503 
    504   two_byte_string = AsciiToTwoByteString("small string 2");
    505   small_string = String::New(two_byte_string);
    506   i::DeleteArray(two_byte_string);
    507 
    508   // We should refuse externalizing newly created small string.
    509   CHECK(!small_string->CanMakeExternal());
    510   for (int i = 0; i < 100; i++) {
    511     String::Value value(small_string);
    512   }
    513   // Frequently used strings should be accepted.
    514   CHECK(small_string->CanMakeExternal());
    515 
    516   const int buf_size = 10 * 1024;
    517   char* buf = i::NewArray<char>(buf_size);
    518   memset(buf, 'a', buf_size);
    519   buf[buf_size - 1] = '\0';
    520 
    521   two_byte_string = AsciiToTwoByteString(buf);
    522   Local<String> large_string = String::New(two_byte_string);
    523   i::DeleteArray(buf);
    524   i::DeleteArray(two_byte_string);
    525   // Large strings should be immediately accepted.
    526   CHECK(large_string->CanMakeExternal());
    527 }
    528 
    529 
    530 TEST(MakingExternalAsciiStringConditions) {
    531   v8::HandleScope scope;
    532   LocalContext env;
    533 
    534   // Free some space in the new space so that we can check freshness.
    535   HEAP->CollectGarbage(i::NEW_SPACE);
    536   HEAP->CollectGarbage(i::NEW_SPACE);
    537 
    538   Local<String> small_string = String::New("s1");
    539   // We should refuse to externalize newly created small string.
    540   CHECK(!small_string->CanMakeExternal());
    541   // Trigger GCs so that the newly allocated string moves to old gen.
    542   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    543   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    544   // Old space strings should be accepted.
    545   CHECK(small_string->CanMakeExternal());
    546 
    547   small_string = String::New("small string 2");
    548   // We should refuse externalizing newly created small string.
    549   CHECK(!small_string->CanMakeExternal());
    550   for (int i = 0; i < 100; i++) {
    551     String::Value value(small_string);
    552   }
    553   // Frequently used strings should be accepted.
    554   CHECK(small_string->CanMakeExternal());
    555 
    556   const int buf_size = 10 * 1024;
    557   char* buf = i::NewArray<char>(buf_size);
    558   memset(buf, 'a', buf_size);
    559   buf[buf_size - 1] = '\0';
    560   Local<String> large_string = String::New(buf);
    561   i::DeleteArray(buf);
    562   // Large strings should be immediately accepted.
    563   CHECK(large_string->CanMakeExternal());
    564 }
    565 
    566 
    567 THREADED_TEST(UsingExternalString) {
    568   {
    569     v8::HandleScope scope;
    570     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    571     Local<String> string =
    572         String::NewExternal(new TestResource(two_byte_string));
    573     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    574     // Trigger GCs so that the newly allocated string moves to old gen.
    575     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    576     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    577     i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
    578     CHECK(isymbol->IsSymbol());
    579   }
    580   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    581   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    582 }
    583 
    584 
    585 THREADED_TEST(UsingExternalAsciiString) {
    586   {
    587     v8::HandleScope scope;
    588     const char* one_byte_string = "test string";
    589     Local<String> string = String::NewExternal(
    590         new TestAsciiResource(i::StrDup(one_byte_string)));
    591     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    592     // Trigger GCs so that the newly allocated string moves to old gen.
    593     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    594     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    595     i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
    596     CHECK(isymbol->IsSymbol());
    597   }
    598   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    599   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    600 }
    601 
    602 
    603 THREADED_TEST(ScavengeExternalString) {
    604   int dispose_count = 0;
    605   bool in_new_space = false;
    606   {
    607     v8::HandleScope scope;
    608     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    609     Local<String> string =
    610       String::NewExternal(new TestResource(two_byte_string,
    611                                            &dispose_count));
    612     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    613     HEAP->CollectGarbage(i::NEW_SPACE);
    614     in_new_space = HEAP->InNewSpace(*istring);
    615     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
    616     CHECK_EQ(0, dispose_count);
    617   }
    618   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    619   CHECK_EQ(1, dispose_count);
    620 }
    621 
    622 
    623 THREADED_TEST(ScavengeExternalAsciiString) {
    624   int dispose_count = 0;
    625   bool in_new_space = false;
    626   {
    627     v8::HandleScope scope;
    628     const char* one_byte_string = "test string";
    629     Local<String> string = String::NewExternal(
    630         new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
    631     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    632     HEAP->CollectGarbage(i::NEW_SPACE);
    633     in_new_space = HEAP->InNewSpace(*istring);
    634     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
    635     CHECK_EQ(0, dispose_count);
    636   }
    637   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    638   CHECK_EQ(1, dispose_count);
    639 }
    640 
    641 
    642 class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
    643  public:
    644   // Only used by non-threaded tests, so it can use static fields.
    645   static int dispose_calls;
    646   static int dispose_count;
    647 
    648   TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
    649       : TestAsciiResource(data, &dispose_count),
    650         dispose_(dispose) { }
    651 
    652   void Dispose() {
    653     ++dispose_calls;
    654     if (dispose_) delete this;
    655   }
    656  private:
    657   bool dispose_;
    658 };
    659 
    660 
    661 int TestAsciiResourceWithDisposeControl::dispose_count = 0;
    662 int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    663 
    664 
    665 TEST(ExternalStringWithDisposeHandling) {
    666   const char* c_source = "1 + 2 * 3";
    667 
    668   // Use a stack allocated external string resource allocated object.
    669   TestAsciiResourceWithDisposeControl::dispose_count = 0;
    670   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    671   TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
    672   {
    673     v8::HandleScope scope;
    674     LocalContext env;
    675     Local<String> source =  String::NewExternal(&res_stack);
    676     Local<Script> script = Script::Compile(source);
    677     Local<Value> value = script->Run();
    678     CHECK(value->IsNumber());
    679     CHECK_EQ(7, value->Int32Value());
    680     HEAP->CollectAllAvailableGarbage();
    681     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    682   }
    683   i::Isolate::Current()->compilation_cache()->Clear();
    684   HEAP->CollectAllAvailableGarbage();
    685   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
    686   CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    687 
    688   // Use a heap allocated external string resource allocated object.
    689   TestAsciiResourceWithDisposeControl::dispose_count = 0;
    690   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    691   TestAsciiResource* res_heap =
    692       new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
    693   {
    694     v8::HandleScope scope;
    695     LocalContext env;
    696     Local<String> source =  String::NewExternal(res_heap);
    697     Local<Script> script = Script::Compile(source);
    698     Local<Value> value = script->Run();
    699     CHECK(value->IsNumber());
    700     CHECK_EQ(7, value->Int32Value());
    701     HEAP->CollectAllAvailableGarbage();
    702     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    703   }
    704   i::Isolate::Current()->compilation_cache()->Clear();
    705   HEAP->CollectAllAvailableGarbage();
    706   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
    707   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
    708 }
    709 
    710 
    711 THREADED_TEST(StringConcat) {
    712   {
    713     v8::HandleScope scope;
    714     LocalContext env;
    715     const char* one_byte_string_1 = "function a_times_t";
    716     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
    717     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
    718     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
    719     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    720     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    721     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
    722     Local<String> left = v8_str(one_byte_string_1);
    723 
    724     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
    725     Local<String> right = String::New(two_byte_source);
    726     i::DeleteArray(two_byte_source);
    727 
    728     Local<String> source = String::Concat(left, right);
    729     right = String::NewExternal(
    730         new TestAsciiResource(i::StrDup(one_byte_extern_1)));
    731     source = String::Concat(source, right);
    732     right = String::NewExternal(
    733         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
    734     source = String::Concat(source, right);
    735     right = v8_str(one_byte_string_2);
    736     source = String::Concat(source, right);
    737 
    738     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
    739     right = String::New(two_byte_source);
    740     i::DeleteArray(two_byte_source);
    741 
    742     source = String::Concat(source, right);
    743     right = String::NewExternal(
    744         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
    745     source = String::Concat(source, right);
    746     Local<Script> script = Script::Compile(source);
    747     Local<Value> value = script->Run();
    748     CHECK(value->IsNumber());
    749     CHECK_EQ(68, value->Int32Value());
    750   }
    751   i::Isolate::Current()->compilation_cache()->Clear();
    752   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    753   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    754 }
    755 
    756 
    757 THREADED_TEST(GlobalProperties) {
    758   v8::HandleScope scope;
    759   LocalContext env;
    760   v8::Handle<v8::Object> global = env->Global();
    761   global->Set(v8_str("pi"), v8_num(3.1415926));
    762   Local<Value> pi = global->Get(v8_str("pi"));
    763   CHECK_EQ(3.1415926, pi->NumberValue());
    764 }
    765 
    766 
    767 static v8::Handle<Value> handle_call(const v8::Arguments& args) {
    768   ApiTestFuzzer::Fuzz();
    769   return v8_num(102);
    770 }
    771 
    772 
    773 static v8::Handle<Value> construct_call(const v8::Arguments& args) {
    774   ApiTestFuzzer::Fuzz();
    775   args.This()->Set(v8_str("x"), v8_num(1));
    776   args.This()->Set(v8_str("y"), v8_num(2));
    777   return args.This();
    778 }
    779 
    780 static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
    781   ApiTestFuzzer::Fuzz();
    782   return v8_num(239);
    783 }
    784 
    785 
    786 THREADED_TEST(FunctionTemplate) {
    787   v8::HandleScope scope;
    788   LocalContext env;
    789   {
    790     Local<v8::FunctionTemplate> fun_templ =
    791         v8::FunctionTemplate::New(handle_call);
    792     Local<Function> fun = fun_templ->GetFunction();
    793     env->Global()->Set(v8_str("obj"), fun);
    794     Local<Script> script = v8_compile("obj()");
    795     CHECK_EQ(102, script->Run()->Int32Value());
    796   }
    797   // Use SetCallHandler to initialize a function template, should work like the
    798   // previous one.
    799   {
    800     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
    801     fun_templ->SetCallHandler(handle_call);
    802     Local<Function> fun = fun_templ->GetFunction();
    803     env->Global()->Set(v8_str("obj"), fun);
    804     Local<Script> script = v8_compile("obj()");
    805     CHECK_EQ(102, script->Run()->Int32Value());
    806   }
    807   // Test constructor calls.
    808   {
    809     Local<v8::FunctionTemplate> fun_templ =
    810         v8::FunctionTemplate::New(construct_call);
    811     fun_templ->SetClassName(v8_str("funky"));
    812     fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), Return239);
    813     Local<Function> fun = fun_templ->GetFunction();
    814     env->Global()->Set(v8_str("obj"), fun);
    815     Local<Script> script = v8_compile("var s = new obj(); s.x");
    816     CHECK_EQ(1, script->Run()->Int32Value());
    817 
    818     Local<Value> result = v8_compile("(new obj()).toString()")->Run();
    819     CHECK_EQ(v8_str("[object funky]"), result);
    820 
    821     result = v8_compile("(new obj()).m")->Run();
    822     CHECK_EQ(239, result->Int32Value());
    823   }
    824 }
    825 
    826 
    827 static void* expected_ptr;
    828 static v8::Handle<v8::Value> callback(const v8::Arguments& args) {
    829   void* ptr = v8::External::Unwrap(args.Data());
    830   CHECK_EQ(expected_ptr, ptr);
    831   return v8::True();
    832 }
    833 
    834 
    835 static void TestExternalPointerWrapping() {
    836   v8::HandleScope scope;
    837   LocalContext env;
    838 
    839   v8::Handle<v8::Value> data = v8::External::Wrap(expected_ptr);
    840 
    841   v8::Handle<v8::Object> obj = v8::Object::New();
    842   obj->Set(v8_str("func"),
    843            v8::FunctionTemplate::New(callback, data)->GetFunction());
    844   env->Global()->Set(v8_str("obj"), obj);
    845 
    846   CHECK(CompileRun(
    847         "function foo() {\n"
    848         "  for (var i = 0; i < 13; i++) obj.func();\n"
    849         "}\n"
    850         "foo(), true")->BooleanValue());
    851 }
    852 
    853 
    854 THREADED_TEST(ExternalWrap) {
    855   // Check heap allocated object.
    856   int* ptr = new int;
    857   expected_ptr = ptr;
    858   TestExternalPointerWrapping();
    859   delete ptr;
    860 
    861   // Check stack allocated object.
    862   int foo;
    863   expected_ptr = &foo;
    864   TestExternalPointerWrapping();
    865 
    866   // Check not aligned addresses.
    867   const int n = 100;
    868   char* s = new char[n];
    869   for (int i = 0; i < n; i++) {
    870     expected_ptr = s + i;
    871     TestExternalPointerWrapping();
    872   }
    873 
    874   delete[] s;
    875 
    876   // Check several invalid addresses.
    877   expected_ptr = reinterpret_cast<void*>(1);
    878   TestExternalPointerWrapping();
    879 
    880   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
    881   TestExternalPointerWrapping();
    882 
    883   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
    884   TestExternalPointerWrapping();
    885 
    886 #if defined(V8_HOST_ARCH_X64)
    887   // Check a value with a leading 1 bit in x64 Smi encoding.
    888   expected_ptr = reinterpret_cast<void*>(0x400000000);
    889   TestExternalPointerWrapping();
    890 
    891   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
    892   TestExternalPointerWrapping();
    893 
    894   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
    895   TestExternalPointerWrapping();
    896 #endif
    897 }
    898 
    899 
    900 THREADED_TEST(FindInstanceInPrototypeChain) {
    901   v8::HandleScope scope;
    902   LocalContext env;
    903 
    904   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
    905   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
    906   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
    907   derived->Inherit(base);
    908 
    909   Local<v8::Function> base_function = base->GetFunction();
    910   Local<v8::Function> derived_function = derived->GetFunction();
    911   Local<v8::Function> other_function = other->GetFunction();
    912 
    913   Local<v8::Object> base_instance = base_function->NewInstance();
    914   Local<v8::Object> derived_instance = derived_function->NewInstance();
    915   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
    916   Local<v8::Object> other_instance = other_function->NewInstance();
    917   derived_instance2->Set(v8_str("__proto__"), derived_instance);
    918   other_instance->Set(v8_str("__proto__"), derived_instance2);
    919 
    920   // base_instance is only an instance of base.
    921   CHECK_EQ(base_instance,
    922            base_instance->FindInstanceInPrototypeChain(base));
    923   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
    924   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    925 
    926   // derived_instance is an instance of base and derived.
    927   CHECK_EQ(derived_instance,
    928            derived_instance->FindInstanceInPrototypeChain(base));
    929   CHECK_EQ(derived_instance,
    930            derived_instance->FindInstanceInPrototypeChain(derived));
    931   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    932 
    933   // other_instance is an instance of other and its immediate
    934   // prototype derived_instance2 is an instance of base and derived.
    935   // Note, derived_instance is an instance of base and derived too,
    936   // but it comes after derived_instance2 in the prototype chain of
    937   // other_instance.
    938   CHECK_EQ(derived_instance2,
    939            other_instance->FindInstanceInPrototypeChain(base));
    940   CHECK_EQ(derived_instance2,
    941            other_instance->FindInstanceInPrototypeChain(derived));
    942   CHECK_EQ(other_instance,
    943            other_instance->FindInstanceInPrototypeChain(other));
    944 }
    945 
    946 
    947 THREADED_TEST(TinyInteger) {
    948   v8::HandleScope scope;
    949   LocalContext env;
    950   int32_t value = 239;
    951   Local<v8::Integer> value_obj = v8::Integer::New(value);
    952   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    953 }
    954 
    955 
    956 THREADED_TEST(BigSmiInteger) {
    957   v8::HandleScope scope;
    958   LocalContext env;
    959   int32_t value = i::Smi::kMaxValue;
    960   // We cannot add one to a Smi::kMaxValue without wrapping.
    961   if (i::kSmiValueSize < 32) {
    962     CHECK(i::Smi::IsValid(value));
    963     CHECK(!i::Smi::IsValid(value + 1));
    964     Local<v8::Integer> value_obj = v8::Integer::New(value);
    965     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    966   }
    967 }
    968 
    969 
    970 THREADED_TEST(BigInteger) {
    971   v8::HandleScope scope;
    972   LocalContext env;
    973   // We cannot add one to a Smi::kMaxValue without wrapping.
    974   if (i::kSmiValueSize < 32) {
    975     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
    976     // The code will not be run in that case, due to the "if" guard.
    977     int32_t value =
    978         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
    979     CHECK(value > i::Smi::kMaxValue);
    980     CHECK(!i::Smi::IsValid(value));
    981     Local<v8::Integer> value_obj = v8::Integer::New(value);
    982     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    983   }
    984 }
    985 
    986 
    987 THREADED_TEST(TinyUnsignedInteger) {
    988   v8::HandleScope scope;
    989   LocalContext env;
    990   uint32_t value = 239;
    991   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
    992   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    993 }
    994 
    995 
    996 THREADED_TEST(BigUnsignedSmiInteger) {
    997   v8::HandleScope scope;
    998   LocalContext env;
    999   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
   1000   CHECK(i::Smi::IsValid(value));
   1001   CHECK(!i::Smi::IsValid(value + 1));
   1002   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1003   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1004 }
   1005 
   1006 
   1007 THREADED_TEST(BigUnsignedInteger) {
   1008   v8::HandleScope scope;
   1009   LocalContext env;
   1010   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
   1011   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
   1012   CHECK(!i::Smi::IsValid(value));
   1013   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1014   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1015 }
   1016 
   1017 
   1018 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
   1019   v8::HandleScope scope;
   1020   LocalContext env;
   1021   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
   1022   uint32_t value = INT32_MAX_AS_UINT + 1;
   1023   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
   1024   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1025   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1026 }
   1027 
   1028 
   1029 THREADED_TEST(IsNativeError) {
   1030   v8::HandleScope scope;
   1031   LocalContext env;
   1032   v8::Handle<Value> syntax_error = CompileRun(
   1033       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
   1034   CHECK(syntax_error->IsNativeError());
   1035   v8::Handle<Value> not_error = CompileRun("{a:42}");
   1036   CHECK(!not_error->IsNativeError());
   1037   v8::Handle<Value> not_object = CompileRun("42");
   1038   CHECK(!not_object->IsNativeError());
   1039 }
   1040 
   1041 
   1042 THREADED_TEST(StringObject) {
   1043   v8::HandleScope scope;
   1044   LocalContext env;
   1045   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
   1046   CHECK(boxed_string->IsStringObject());
   1047   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
   1048   CHECK(!unboxed_string->IsStringObject());
   1049   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
   1050   CHECK(!boxed_not_string->IsStringObject());
   1051   v8::Handle<Value> not_object = CompileRun("0");
   1052   CHECK(!not_object->IsStringObject());
   1053   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
   1054   CHECK(!as_boxed.IsEmpty());
   1055   Local<v8::String> the_string = as_boxed->StringValue();
   1056   CHECK(!the_string.IsEmpty());
   1057   ExpectObject("\"test\"", the_string);
   1058   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
   1059   CHECK(new_boxed_string->IsStringObject());
   1060   as_boxed = new_boxed_string.As<v8::StringObject>();
   1061   the_string = as_boxed->StringValue();
   1062   CHECK(!the_string.IsEmpty());
   1063   ExpectObject("\"test\"", the_string);
   1064 }
   1065 
   1066 
   1067 THREADED_TEST(NumberObject) {
   1068   v8::HandleScope scope;
   1069   LocalContext env;
   1070   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
   1071   CHECK(boxed_number->IsNumberObject());
   1072   v8::Handle<Value> unboxed_number = CompileRun("42");
   1073   CHECK(!unboxed_number->IsNumberObject());
   1074   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
   1075   CHECK(!boxed_not_number->IsNumberObject());
   1076   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
   1077   CHECK(!as_boxed.IsEmpty());
   1078   double the_number = as_boxed->NumberValue();
   1079   CHECK_EQ(42.0, the_number);
   1080   v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
   1081   CHECK(new_boxed_number->IsNumberObject());
   1082   as_boxed = new_boxed_number.As<v8::NumberObject>();
   1083   the_number = as_boxed->NumberValue();
   1084   CHECK_EQ(43.0, the_number);
   1085 }
   1086 
   1087 
   1088 THREADED_TEST(BooleanObject) {
   1089   v8::HandleScope scope;
   1090   LocalContext env;
   1091   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
   1092   CHECK(boxed_boolean->IsBooleanObject());
   1093   v8::Handle<Value> unboxed_boolean = CompileRun("true");
   1094   CHECK(!unboxed_boolean->IsBooleanObject());
   1095   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
   1096   CHECK(!boxed_not_boolean->IsBooleanObject());
   1097   v8::Handle<v8::BooleanObject> as_boxed =
   1098       boxed_boolean.As<v8::BooleanObject>();
   1099   CHECK(!as_boxed.IsEmpty());
   1100   bool the_boolean = as_boxed->BooleanValue();
   1101   CHECK_EQ(true, the_boolean);
   1102   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
   1103   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
   1104   CHECK(boxed_true->IsBooleanObject());
   1105   CHECK(boxed_false->IsBooleanObject());
   1106   as_boxed = boxed_true.As<v8::BooleanObject>();
   1107   CHECK_EQ(true, as_boxed->BooleanValue());
   1108   as_boxed = boxed_false.As<v8::BooleanObject>();
   1109   CHECK_EQ(false, as_boxed->BooleanValue());
   1110 }
   1111 
   1112 
   1113 THREADED_TEST(Number) {
   1114   v8::HandleScope scope;
   1115   LocalContext env;
   1116   double PI = 3.1415926;
   1117   Local<v8::Number> pi_obj = v8::Number::New(PI);
   1118   CHECK_EQ(PI, pi_obj->NumberValue());
   1119 }
   1120 
   1121 
   1122 THREADED_TEST(ToNumber) {
   1123   v8::HandleScope scope;
   1124   LocalContext env;
   1125   Local<String> str = v8_str("3.1415926");
   1126   CHECK_EQ(3.1415926, str->NumberValue());
   1127   v8::Handle<v8::Boolean> t = v8::True();
   1128   CHECK_EQ(1.0, t->NumberValue());
   1129   v8::Handle<v8::Boolean> f = v8::False();
   1130   CHECK_EQ(0.0, f->NumberValue());
   1131 }
   1132 
   1133 
   1134 THREADED_TEST(Date) {
   1135   v8::HandleScope scope;
   1136   LocalContext env;
   1137   double PI = 3.1415926;
   1138   Local<Value> date = v8::Date::New(PI);
   1139   CHECK_EQ(3.0, date->NumberValue());
   1140   date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42));
   1141   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
   1142 }
   1143 
   1144 
   1145 THREADED_TEST(Boolean) {
   1146   v8::HandleScope scope;
   1147   LocalContext env;
   1148   v8::Handle<v8::Boolean> t = v8::True();
   1149   CHECK(t->Value());
   1150   v8::Handle<v8::Boolean> f = v8::False();
   1151   CHECK(!f->Value());
   1152   v8::Handle<v8::Primitive> u = v8::Undefined();
   1153   CHECK(!u->BooleanValue());
   1154   v8::Handle<v8::Primitive> n = v8::Null();
   1155   CHECK(!n->BooleanValue());
   1156   v8::Handle<String> str1 = v8_str("");
   1157   CHECK(!str1->BooleanValue());
   1158   v8::Handle<String> str2 = v8_str("x");
   1159   CHECK(str2->BooleanValue());
   1160   CHECK(!v8::Number::New(0)->BooleanValue());
   1161   CHECK(v8::Number::New(-1)->BooleanValue());
   1162   CHECK(v8::Number::New(1)->BooleanValue());
   1163   CHECK(v8::Number::New(42)->BooleanValue());
   1164   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
   1165 }
   1166 
   1167 
   1168 static v8::Handle<Value> DummyCallHandler(const v8::Arguments& args) {
   1169   ApiTestFuzzer::Fuzz();
   1170   return v8_num(13.4);
   1171 }
   1172 
   1173 
   1174 static v8::Handle<Value> GetM(Local<String> name, const AccessorInfo&) {
   1175   ApiTestFuzzer::Fuzz();
   1176   return v8_num(876);
   1177 }
   1178 
   1179 
   1180 THREADED_TEST(GlobalPrototype) {
   1181   v8::HandleScope scope;
   1182   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
   1183   func_templ->PrototypeTemplate()->Set(
   1184       "dummy",
   1185       v8::FunctionTemplate::New(DummyCallHandler));
   1186   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
   1187   templ->Set("x", v8_num(200));
   1188   templ->SetAccessor(v8_str("m"), GetM);
   1189   LocalContext env(0, templ);
   1190   v8::Handle<Script> script(v8_compile("dummy()"));
   1191   v8::Handle<Value> result(script->Run());
   1192   CHECK_EQ(13.4, result->NumberValue());
   1193   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
   1194   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
   1195 }
   1196 
   1197 
   1198 THREADED_TEST(ObjectTemplate) {
   1199   v8::HandleScope scope;
   1200   Local<ObjectTemplate> templ1 = ObjectTemplate::New();
   1201   templ1->Set("x", v8_num(10));
   1202   templ1->Set("y", v8_num(13));
   1203   LocalContext env;
   1204   Local<v8::Object> instance1 = templ1->NewInstance();
   1205   env->Global()->Set(v8_str("p"), instance1);
   1206   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
   1207   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
   1208   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
   1209   fun->PrototypeTemplate()->Set("nirk", v8_num(123));
   1210   Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
   1211   templ2->Set("a", v8_num(12));
   1212   templ2->Set("b", templ1);
   1213   Local<v8::Object> instance2 = templ2->NewInstance();
   1214   env->Global()->Set(v8_str("q"), instance2);
   1215   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
   1216   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
   1217   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
   1218   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
   1219 }
   1220 
   1221 
   1222 static v8::Handle<Value> GetFlabby(const v8::Arguments& args) {
   1223   ApiTestFuzzer::Fuzz();
   1224   return v8_num(17.2);
   1225 }
   1226 
   1227 
   1228 static v8::Handle<Value> GetKnurd(Local<String> property, const AccessorInfo&) {
   1229   ApiTestFuzzer::Fuzz();
   1230   return v8_num(15.2);
   1231 }
   1232 
   1233 
   1234 THREADED_TEST(DescriptorInheritance) {
   1235   v8::HandleScope scope;
   1236   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
   1237   super->PrototypeTemplate()->Set("flabby",
   1238                                   v8::FunctionTemplate::New(GetFlabby));
   1239   super->PrototypeTemplate()->Set("PI", v8_num(3.14));
   1240 
   1241   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
   1242 
   1243   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
   1244   base1->Inherit(super);
   1245   base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
   1246 
   1247   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
   1248   base2->Inherit(super);
   1249   base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
   1250 
   1251   LocalContext env;
   1252 
   1253   env->Global()->Set(v8_str("s"), super->GetFunction());
   1254   env->Global()->Set(v8_str("base1"), base1->GetFunction());
   1255   env->Global()->Set(v8_str("base2"), base2->GetFunction());
   1256 
   1257   // Checks right __proto__ chain.
   1258   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
   1259   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
   1260 
   1261   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
   1262 
   1263   // Instance accessor should not be visible on function object or its prototype
   1264   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
   1265   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
   1266   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
   1267 
   1268   env->Global()->Set(v8_str("obj"),
   1269                      base1->GetFunction()->NewInstance());
   1270   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
   1271   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
   1272   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
   1273   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
   1274   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
   1275 
   1276   env->Global()->Set(v8_str("obj2"),
   1277                      base2->GetFunction()->NewInstance());
   1278   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
   1279   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
   1280   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
   1281   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
   1282   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
   1283 
   1284   // base1 and base2 cannot cross reference to each's prototype
   1285   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
   1286   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
   1287 }
   1288 
   1289 
   1290 int echo_named_call_count;
   1291 
   1292 
   1293 static v8::Handle<Value> EchoNamedProperty(Local<String> name,
   1294                                            const AccessorInfo& info) {
   1295   ApiTestFuzzer::Fuzz();
   1296   CHECK_EQ(v8_str("data"), info.Data());
   1297   echo_named_call_count++;
   1298   return name;
   1299 }
   1300 
   1301 // Helper functions for Interceptor/Accessor interaction tests
   1302 
   1303 Handle<Value> SimpleAccessorGetter(Local<String> name,
   1304                                    const AccessorInfo& info) {
   1305   Handle<Object> self = info.This();
   1306   return self->Get(String::Concat(v8_str("accessor_"), name));
   1307 }
   1308 
   1309 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
   1310                           const AccessorInfo& info) {
   1311   Handle<Object> self = info.This();
   1312   self->Set(String::Concat(v8_str("accessor_"), name), value);
   1313 }
   1314 
   1315 Handle<Value> EmptyInterceptorGetter(Local<String> name,
   1316                                      const AccessorInfo& info) {
   1317   return Handle<Value>();
   1318 }
   1319 
   1320 Handle<Value> EmptyInterceptorSetter(Local<String> name,
   1321                                      Local<Value> value,
   1322                                      const AccessorInfo& info) {
   1323   return Handle<Value>();
   1324 }
   1325 
   1326 Handle<Value> InterceptorGetter(Local<String> name,
   1327                                 const AccessorInfo& info) {
   1328   // Intercept names that start with 'interceptor_'.
   1329   String::AsciiValue ascii(name);
   1330   char* name_str = *ascii;
   1331   char prefix[] = "interceptor_";
   1332   int i;
   1333   for (i = 0; name_str[i] && prefix[i]; ++i) {
   1334     if (name_str[i] != prefix[i]) return Handle<Value>();
   1335   }
   1336   Handle<Object> self = info.This();
   1337   return self->GetHiddenValue(v8_str(name_str + i));
   1338 }
   1339 
   1340 Handle<Value> InterceptorSetter(Local<String> name,
   1341                                 Local<Value> value,
   1342                                 const AccessorInfo& info) {
   1343   // Intercept accesses that set certain integer values.
   1344   if (value->IsInt32() && value->Int32Value() < 10000) {
   1345     Handle<Object> self = info.This();
   1346     self->SetHiddenValue(name, value);
   1347     return value;
   1348   }
   1349   return Handle<Value>();
   1350 }
   1351 
   1352 void AddAccessor(Handle<FunctionTemplate> templ,
   1353                  Handle<String> name,
   1354                  v8::AccessorGetter getter,
   1355                  v8::AccessorSetter setter) {
   1356   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
   1357 }
   1358 
   1359 void AddInterceptor(Handle<FunctionTemplate> templ,
   1360                     v8::NamedPropertyGetter getter,
   1361                     v8::NamedPropertySetter setter) {
   1362   templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
   1363 }
   1364 
   1365 THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
   1366   v8::HandleScope scope;
   1367   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1368   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1369   child->Inherit(parent);
   1370   AddAccessor(parent, v8_str("age"),
   1371               SimpleAccessorGetter, SimpleAccessorSetter);
   1372   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1373   LocalContext env;
   1374   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1375   CompileRun("var child = new Child;"
   1376              "child.age = 10;");
   1377   ExpectBoolean("child.hasOwnProperty('age')", false);
   1378   ExpectInt32("child.age", 10);
   1379   ExpectInt32("child.accessor_age", 10);
   1380 }
   1381 
   1382 THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
   1383   v8::HandleScope scope;
   1384   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1385   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1386   child->Inherit(parent);
   1387   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1388   LocalContext env;
   1389   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1390   CompileRun("var child = new Child;"
   1391              "var parent = child.__proto__;"
   1392              "Object.defineProperty(parent, 'age', "
   1393              "  {get: function(){ return this.accessor_age; }, "
   1394              "   set: function(v){ this.accessor_age = v; }, "
   1395              "   enumerable: true, configurable: true});"
   1396              "child.age = 10;");
   1397   ExpectBoolean("child.hasOwnProperty('age')", false);
   1398   ExpectInt32("child.age", 10);
   1399   ExpectInt32("child.accessor_age", 10);
   1400 }
   1401 
   1402 THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
   1403   v8::HandleScope scope;
   1404   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1405   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1406   child->Inherit(parent);
   1407   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1408   LocalContext env;
   1409   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1410   CompileRun("var child = new Child;"
   1411              "var parent = child.__proto__;"
   1412              "parent.name = 'Alice';");
   1413   ExpectBoolean("child.hasOwnProperty('name')", false);
   1414   ExpectString("child.name", "Alice");
   1415   CompileRun("child.name = 'Bob';");
   1416   ExpectString("child.name", "Bob");
   1417   ExpectBoolean("child.hasOwnProperty('name')", true);
   1418   ExpectString("parent.name", "Alice");
   1419 }
   1420 
   1421 THREADED_TEST(SwitchFromInterceptorToAccessor) {
   1422   v8::HandleScope scope;
   1423   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   1424   AddAccessor(templ, v8_str("age"),
   1425               SimpleAccessorGetter, SimpleAccessorSetter);
   1426   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   1427   LocalContext env;
   1428   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   1429   CompileRun("var obj = new Obj;"
   1430              "function setAge(i){ obj.age = i; };"
   1431              "for(var i = 0; i <= 10000; i++) setAge(i);");
   1432   // All i < 10000 go to the interceptor.
   1433   ExpectInt32("obj.interceptor_age", 9999);
   1434   // The last i goes to the accessor.
   1435   ExpectInt32("obj.accessor_age", 10000);
   1436 }
   1437 
   1438 THREADED_TEST(SwitchFromAccessorToInterceptor) {
   1439   v8::HandleScope scope;
   1440   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   1441   AddAccessor(templ, v8_str("age"),
   1442               SimpleAccessorGetter, SimpleAccessorSetter);
   1443   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   1444   LocalContext env;
   1445   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   1446   CompileRun("var obj = new Obj;"
   1447              "function setAge(i){ obj.age = i; };"
   1448              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   1449   // All i >= 10000 go to the accessor.
   1450   ExpectInt32("obj.accessor_age", 10000);
   1451   // The last i goes to the interceptor.
   1452   ExpectInt32("obj.interceptor_age", 9999);
   1453 }
   1454 
   1455 THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
   1456   v8::HandleScope scope;
   1457   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1458   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1459   child->Inherit(parent);
   1460   AddAccessor(parent, v8_str("age"),
   1461               SimpleAccessorGetter, SimpleAccessorSetter);
   1462   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   1463   LocalContext env;
   1464   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1465   CompileRun("var child = new Child;"
   1466              "function setAge(i){ child.age = i; };"
   1467              "for(var i = 0; i <= 10000; i++) setAge(i);");
   1468   // All i < 10000 go to the interceptor.
   1469   ExpectInt32("child.interceptor_age", 9999);
   1470   // The last i goes to the accessor.
   1471   ExpectInt32("child.accessor_age", 10000);
   1472 }
   1473 
   1474 THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
   1475   v8::HandleScope scope;
   1476   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1477   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1478   child->Inherit(parent);
   1479   AddAccessor(parent, v8_str("age"),
   1480               SimpleAccessorGetter, SimpleAccessorSetter);
   1481   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   1482   LocalContext env;
   1483   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1484   CompileRun("var child = new Child;"
   1485              "function setAge(i){ child.age = i; };"
   1486              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   1487   // All i >= 10000 go to the accessor.
   1488   ExpectInt32("child.accessor_age", 10000);
   1489   // The last i goes to the interceptor.
   1490   ExpectInt32("child.interceptor_age", 9999);
   1491 }
   1492 
   1493 THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
   1494   v8::HandleScope scope;
   1495   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   1496   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   1497   LocalContext env;
   1498   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   1499   CompileRun("var obj = new Obj;"
   1500              "function setter(i) { this.accessor_age = i; };"
   1501              "function getter() { return this.accessor_age; };"
   1502              "function setAge(i) { obj.age = i; };"
   1503              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   1504              "for(var i = 0; i <= 10000; i++) setAge(i);");
   1505   // All i < 10000 go to the interceptor.
   1506   ExpectInt32("obj.interceptor_age", 9999);
   1507   // The last i goes to the JavaScript accessor.
   1508   ExpectInt32("obj.accessor_age", 10000);
   1509   // The installed JavaScript getter is still intact.
   1510   // This last part is a regression test for issue 1651 and relies on the fact
   1511   // that both interceptor and accessor are being installed on the same object.
   1512   ExpectInt32("obj.age", 10000);
   1513   ExpectBoolean("obj.hasOwnProperty('age')", true);
   1514   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
   1515 }
   1516 
   1517 THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
   1518   v8::HandleScope scope;
   1519   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   1520   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   1521   LocalContext env;
   1522   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   1523   CompileRun("var obj = new Obj;"
   1524              "function setter(i) { this.accessor_age = i; };"
   1525              "function getter() { return this.accessor_age; };"
   1526              "function setAge(i) { obj.age = i; };"
   1527              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   1528              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   1529   // All i >= 10000 go to the accessor.
   1530   ExpectInt32("obj.accessor_age", 10000);
   1531   // The last i goes to the interceptor.
   1532   ExpectInt32("obj.interceptor_age", 9999);
   1533   // The installed JavaScript getter is still intact.
   1534   // This last part is a regression test for issue 1651 and relies on the fact
   1535   // that both interceptor and accessor are being installed on the same object.
   1536   ExpectInt32("obj.age", 10000);
   1537   ExpectBoolean("obj.hasOwnProperty('age')", true);
   1538   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
   1539 }
   1540 
   1541 THREADED_TEST(SwitchFromInterceptorToProperty) {
   1542   v8::HandleScope scope;
   1543   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1544   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1545   child->Inherit(parent);
   1546   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   1547   LocalContext env;
   1548   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1549   CompileRun("var child = new Child;"
   1550              "function setAge(i){ child.age = i; };"
   1551              "for(var i = 0; i <= 10000; i++) setAge(i);");
   1552   // All i < 10000 go to the interceptor.
   1553   ExpectInt32("child.interceptor_age", 9999);
   1554   // The last i goes to child's own property.
   1555   ExpectInt32("child.age", 10000);
   1556 }
   1557 
   1558 THREADED_TEST(SwitchFromPropertyToInterceptor) {
   1559   v8::HandleScope scope;
   1560   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1561   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1562   child->Inherit(parent);
   1563   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   1564   LocalContext env;
   1565   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1566   CompileRun("var child = new Child;"
   1567              "function setAge(i){ child.age = i; };"
   1568              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   1569   // All i >= 10000 go to child's own property.
   1570   ExpectInt32("child.age", 10000);
   1571   // The last i goes to the interceptor.
   1572   ExpectInt32("child.interceptor_age", 9999);
   1573 }
   1574 
   1575 THREADED_TEST(NamedPropertyHandlerGetter) {
   1576   echo_named_call_count = 0;
   1577   v8::HandleScope scope;
   1578   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1579   templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
   1580                                                      0, 0, 0, 0,
   1581                                                      v8_str("data"));
   1582   LocalContext env;
   1583   env->Global()->Set(v8_str("obj"),
   1584                      templ->GetFunction()->NewInstance());
   1585   CHECK_EQ(echo_named_call_count, 0);
   1586   v8_compile("obj.x")->Run();
   1587   CHECK_EQ(echo_named_call_count, 1);
   1588   const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
   1589   v8::Handle<Value> str = CompileRun(code);
   1590   String::AsciiValue value(str);
   1591   CHECK_EQ(*value, "oddlepoddle");
   1592   // Check default behavior
   1593   CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
   1594   CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
   1595   CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
   1596 }
   1597 
   1598 
   1599 int echo_indexed_call_count = 0;
   1600 
   1601 
   1602 static v8::Handle<Value> EchoIndexedProperty(uint32_t index,
   1603                                              const AccessorInfo& info) {
   1604   ApiTestFuzzer::Fuzz();
   1605   CHECK_EQ(v8_num(637), info.Data());
   1606   echo_indexed_call_count++;
   1607   return v8_num(index);
   1608 }
   1609 
   1610 
   1611 THREADED_TEST(IndexedPropertyHandlerGetter) {
   1612   v8::HandleScope scope;
   1613   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1614   templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
   1615                                                        0, 0, 0, 0,
   1616                                                        v8_num(637));
   1617   LocalContext env;
   1618   env->Global()->Set(v8_str("obj"),
   1619                      templ->GetFunction()->NewInstance());
   1620   Local<Script> script = v8_compile("obj[900]");
   1621   CHECK_EQ(script->Run()->Int32Value(), 900);
   1622 }
   1623 
   1624 
   1625 v8::Handle<v8::Object> bottom;
   1626 
   1627 static v8::Handle<Value> CheckThisIndexedPropertyHandler(
   1628     uint32_t index,
   1629     const AccessorInfo& info) {
   1630   ApiTestFuzzer::Fuzz();
   1631   CHECK(info.This()->Equals(bottom));
   1632   return v8::Handle<Value>();
   1633 }
   1634 
   1635 static v8::Handle<Value> CheckThisNamedPropertyHandler(
   1636     Local<String> name,
   1637     const AccessorInfo& info) {
   1638   ApiTestFuzzer::Fuzz();
   1639   CHECK(info.This()->Equals(bottom));
   1640   return v8::Handle<Value>();
   1641 }
   1642 
   1643 
   1644 v8::Handle<Value> CheckThisIndexedPropertySetter(uint32_t index,
   1645                                                  Local<Value> value,
   1646                                                  const AccessorInfo& info) {
   1647   ApiTestFuzzer::Fuzz();
   1648   CHECK(info.This()->Equals(bottom));
   1649   return v8::Handle<Value>();
   1650 }
   1651 
   1652 
   1653 v8::Handle<Value> CheckThisNamedPropertySetter(Local<String> property,
   1654                                                Local<Value> value,
   1655                                                const AccessorInfo& info) {
   1656   ApiTestFuzzer::Fuzz();
   1657   CHECK(info.This()->Equals(bottom));
   1658   return v8::Handle<Value>();
   1659 }
   1660 
   1661 v8::Handle<v8::Integer> CheckThisIndexedPropertyQuery(
   1662     uint32_t index,
   1663     const AccessorInfo& info) {
   1664   ApiTestFuzzer::Fuzz();
   1665   CHECK(info.This()->Equals(bottom));
   1666   return v8::Handle<v8::Integer>();
   1667 }
   1668 
   1669 
   1670 v8::Handle<v8::Integer> CheckThisNamedPropertyQuery(Local<String> property,
   1671                                                     const AccessorInfo& info) {
   1672   ApiTestFuzzer::Fuzz();
   1673   CHECK(info.This()->Equals(bottom));
   1674   return v8::Handle<v8::Integer>();
   1675 }
   1676 
   1677 
   1678 v8::Handle<v8::Boolean> CheckThisIndexedPropertyDeleter(
   1679     uint32_t index,
   1680     const AccessorInfo& info) {
   1681   ApiTestFuzzer::Fuzz();
   1682   CHECK(info.This()->Equals(bottom));
   1683   return v8::Handle<v8::Boolean>();
   1684 }
   1685 
   1686 
   1687 v8::Handle<v8::Boolean> CheckThisNamedPropertyDeleter(
   1688     Local<String> property,
   1689     const AccessorInfo& info) {
   1690   ApiTestFuzzer::Fuzz();
   1691   CHECK(info.This()->Equals(bottom));
   1692   return v8::Handle<v8::Boolean>();
   1693 }
   1694 
   1695 
   1696 v8::Handle<v8::Array> CheckThisIndexedPropertyEnumerator(
   1697     const AccessorInfo& info) {
   1698   ApiTestFuzzer::Fuzz();
   1699   CHECK(info.This()->Equals(bottom));
   1700   return v8::Handle<v8::Array>();
   1701 }
   1702 
   1703 
   1704 v8::Handle<v8::Array> CheckThisNamedPropertyEnumerator(
   1705     const AccessorInfo& info) {
   1706   ApiTestFuzzer::Fuzz();
   1707   CHECK(info.This()->Equals(bottom));
   1708   return v8::Handle<v8::Array>();
   1709 }
   1710 
   1711 
   1712 THREADED_TEST(PropertyHandlerInPrototype) {
   1713   v8::HandleScope scope;
   1714   LocalContext env;
   1715 
   1716   // Set up a prototype chain with three interceptors.
   1717   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1718   templ->InstanceTemplate()->SetIndexedPropertyHandler(
   1719       CheckThisIndexedPropertyHandler,
   1720       CheckThisIndexedPropertySetter,
   1721       CheckThisIndexedPropertyQuery,
   1722       CheckThisIndexedPropertyDeleter,
   1723       CheckThisIndexedPropertyEnumerator);
   1724 
   1725   templ->InstanceTemplate()->SetNamedPropertyHandler(
   1726       CheckThisNamedPropertyHandler,
   1727       CheckThisNamedPropertySetter,
   1728       CheckThisNamedPropertyQuery,
   1729       CheckThisNamedPropertyDeleter,
   1730       CheckThisNamedPropertyEnumerator);
   1731 
   1732   bottom = templ->GetFunction()->NewInstance();
   1733   Local<v8::Object> top = templ->GetFunction()->NewInstance();
   1734   Local<v8::Object> middle = templ->GetFunction()->NewInstance();
   1735 
   1736   bottom->Set(v8_str("__proto__"), middle);
   1737   middle->Set(v8_str("__proto__"), top);
   1738   env->Global()->Set(v8_str("obj"), bottom);
   1739 
   1740   // Indexed and named get.
   1741   Script::Compile(v8_str("obj[0]"))->Run();
   1742   Script::Compile(v8_str("obj.x"))->Run();
   1743 
   1744   // Indexed and named set.
   1745   Script::Compile(v8_str("obj[1] = 42"))->Run();
   1746   Script::Compile(v8_str("obj.y = 42"))->Run();
   1747 
   1748   // Indexed and named query.
   1749   Script::Compile(v8_str("0 in obj"))->Run();
   1750   Script::Compile(v8_str("'x' in obj"))->Run();
   1751 
   1752   // Indexed and named deleter.
   1753   Script::Compile(v8_str("delete obj[0]"))->Run();
   1754   Script::Compile(v8_str("delete obj.x"))->Run();
   1755 
   1756   // Enumerators.
   1757   Script::Compile(v8_str("for (var p in obj) ;"))->Run();
   1758 }
   1759 
   1760 
   1761 static v8::Handle<Value> PrePropertyHandlerGet(Local<String> key,
   1762                                                const AccessorInfo& info) {
   1763   ApiTestFuzzer::Fuzz();
   1764   if (v8_str("pre")->Equals(key)) {
   1765     return v8_str("PrePropertyHandler: pre");
   1766   }
   1767   return v8::Handle<String>();
   1768 }
   1769 
   1770 
   1771 static v8::Handle<v8::Integer> PrePropertyHandlerQuery(Local<String> key,
   1772                                                        const AccessorInfo&) {
   1773   if (v8_str("pre")->Equals(key)) {
   1774     return v8::Integer::New(v8::None);
   1775   }
   1776 
   1777   return v8::Handle<v8::Integer>();  // do not intercept the call
   1778 }
   1779 
   1780 
   1781 THREADED_TEST(PrePropertyHandler) {
   1782   v8::HandleScope scope;
   1783   v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   1784   desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
   1785                                                     0,
   1786                                                     PrePropertyHandlerQuery);
   1787   LocalContext env(NULL, desc->InstanceTemplate());
   1788   Script::Compile(v8_str(
   1789       "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
   1790   v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
   1791   CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
   1792   v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
   1793   CHECK_EQ(v8_str("Object: on"), result_on);
   1794   v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
   1795   CHECK(result_post.IsEmpty());
   1796 }
   1797 
   1798 
   1799 THREADED_TEST(UndefinedIsNotEnumerable) {
   1800   v8::HandleScope scope;
   1801   LocalContext env;
   1802   v8::Handle<Value> result = Script::Compile(v8_str(
   1803       "this.propertyIsEnumerable(undefined)"))->Run();
   1804   CHECK(result->IsFalse());
   1805 }
   1806 
   1807 
   1808 v8::Handle<Script> call_recursively_script;
   1809 static const int kTargetRecursionDepth = 200;  // near maximum
   1810 
   1811 
   1812 static v8::Handle<Value> CallScriptRecursivelyCall(const v8::Arguments& args) {
   1813   ApiTestFuzzer::Fuzz();
   1814   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   1815   if (depth == kTargetRecursionDepth) return v8::Undefined();
   1816   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
   1817   return call_recursively_script->Run();
   1818 }
   1819 
   1820 
   1821 static v8::Handle<Value> CallFunctionRecursivelyCall(
   1822     const v8::Arguments& args) {
   1823   ApiTestFuzzer::Fuzz();
   1824   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   1825   if (depth == kTargetRecursionDepth) {
   1826     printf("[depth = %d]\n", depth);
   1827     return v8::Undefined();
   1828   }
   1829   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
   1830   v8::Handle<Value> function =
   1831       args.This()->Get(v8_str("callFunctionRecursively"));
   1832   return function.As<Function>()->Call(args.This(), 0, NULL);
   1833 }
   1834 
   1835 
   1836 THREADED_TEST(DeepCrossLanguageRecursion) {
   1837   v8::HandleScope scope;
   1838   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
   1839   global->Set(v8_str("callScriptRecursively"),
   1840               v8::FunctionTemplate::New(CallScriptRecursivelyCall));
   1841   global->Set(v8_str("callFunctionRecursively"),
   1842               v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
   1843   LocalContext env(NULL, global);
   1844 
   1845   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
   1846   call_recursively_script = v8_compile("callScriptRecursively()");
   1847   call_recursively_script->Run();
   1848   call_recursively_script = v8::Handle<Script>();
   1849 
   1850   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
   1851   Script::Compile(v8_str("callFunctionRecursively()"))->Run();
   1852 }
   1853 
   1854 
   1855 static v8::Handle<Value>
   1856     ThrowingPropertyHandlerGet(Local<String> key, const AccessorInfo&) {
   1857   ApiTestFuzzer::Fuzz();
   1858   return v8::ThrowException(key);
   1859 }
   1860 
   1861 
   1862 static v8::Handle<Value> ThrowingPropertyHandlerSet(Local<String> key,
   1863                                                     Local<Value>,
   1864                                                     const AccessorInfo&) {
   1865   v8::ThrowException(key);
   1866   return v8::Undefined();  // not the same as v8::Handle<v8::Value>()
   1867 }
   1868 
   1869 
   1870 THREADED_TEST(CallbackExceptionRegression) {
   1871   v8::HandleScope scope;
   1872   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   1873   obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
   1874                                ThrowingPropertyHandlerSet);
   1875   LocalContext env;
   1876   env->Global()->Set(v8_str("obj"), obj->NewInstance());
   1877   v8::Handle<Value> otto = Script::Compile(v8_str(
   1878       "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
   1879   CHECK_EQ(v8_str("otto"), otto);
   1880   v8::Handle<Value> netto = Script::Compile(v8_str(
   1881       "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
   1882   CHECK_EQ(v8_str("netto"), netto);
   1883 }
   1884 
   1885 
   1886 THREADED_TEST(FunctionPrototype) {
   1887   v8::HandleScope scope;
   1888   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
   1889   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
   1890   LocalContext env;
   1891   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
   1892   Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
   1893   CHECK_EQ(script->Run()->Int32Value(), 321);
   1894 }
   1895 
   1896 
   1897 THREADED_TEST(InternalFields) {
   1898   v8::HandleScope scope;
   1899   LocalContext env;
   1900 
   1901   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1902   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   1903   instance_templ->SetInternalFieldCount(1);
   1904   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   1905   CHECK_EQ(1, obj->InternalFieldCount());
   1906   CHECK(obj->GetInternalField(0)->IsUndefined());
   1907   obj->SetInternalField(0, v8_num(17));
   1908   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
   1909 }
   1910 
   1911 
   1912 THREADED_TEST(GlobalObjectInternalFields) {
   1913   v8::HandleScope scope;
   1914   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   1915   global_template->SetInternalFieldCount(1);
   1916   LocalContext env(NULL, global_template);
   1917   v8::Handle<v8::Object> global_proxy = env->Global();
   1918   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
   1919   CHECK_EQ(1, global->InternalFieldCount());
   1920   CHECK(global->GetInternalField(0)->IsUndefined());
   1921   global->SetInternalField(0, v8_num(17));
   1922   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
   1923 }
   1924 
   1925 
   1926 THREADED_TEST(InternalFieldsNativePointers) {
   1927   v8::HandleScope scope;
   1928   LocalContext env;
   1929 
   1930   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1931   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   1932   instance_templ->SetInternalFieldCount(1);
   1933   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   1934   CHECK_EQ(1, obj->InternalFieldCount());
   1935   CHECK(obj->GetPointerFromInternalField(0) == NULL);
   1936 
   1937   char* data = new char[100];
   1938 
   1939   void* aligned = data;
   1940   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1));
   1941   void* unaligned = data + 1;
   1942   CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1));
   1943 
   1944   // Check reading and writing aligned pointers.
   1945   obj->SetPointerInInternalField(0, aligned);
   1946   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   1947   CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
   1948 
   1949   // Check reading and writing unaligned pointers.
   1950   obj->SetPointerInInternalField(0, unaligned);
   1951   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   1952   CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
   1953 
   1954   delete[] data;
   1955 }
   1956 
   1957 
   1958 THREADED_TEST(InternalFieldsNativePointersAndExternal) {
   1959   v8::HandleScope scope;
   1960   LocalContext env;
   1961 
   1962   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   1963   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   1964   instance_templ->SetInternalFieldCount(1);
   1965   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   1966   CHECK_EQ(1, obj->InternalFieldCount());
   1967   CHECK(obj->GetPointerFromInternalField(0) == NULL);
   1968 
   1969   char* data = new char[100];
   1970 
   1971   void* aligned = data;
   1972   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1));
   1973   void* unaligned = data + 1;
   1974   CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1));
   1975 
   1976   obj->SetPointerInInternalField(0, aligned);
   1977   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   1978   CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0)));
   1979 
   1980   obj->SetPointerInInternalField(0, unaligned);
   1981   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   1982   CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0)));
   1983 
   1984   obj->SetInternalField(0, v8::External::Wrap(aligned));
   1985   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   1986   CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
   1987 
   1988   obj->SetInternalField(0, v8::External::Wrap(unaligned));
   1989   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   1990   CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
   1991 
   1992   delete[] data;
   1993 }
   1994 
   1995 
   1996 THREADED_TEST(IdentityHash) {
   1997   v8::HandleScope scope;
   1998   LocalContext env;
   1999 
   2000   // Ensure that the test starts with an fresh heap to test whether the hash
   2001   // code is based on the address.
   2002   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2003   Local<v8::Object> obj = v8::Object::New();
   2004   int hash = obj->GetIdentityHash();
   2005   int hash1 = obj->GetIdentityHash();
   2006   CHECK_EQ(hash, hash1);
   2007   int hash2 = v8::Object::New()->GetIdentityHash();
   2008   // Since the identity hash is essentially a random number two consecutive
   2009   // objects should not be assigned the same hash code. If the test below fails
   2010   // the random number generator should be evaluated.
   2011   CHECK_NE(hash, hash2);
   2012   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2013   int hash3 = v8::Object::New()->GetIdentityHash();
   2014   // Make sure that the identity hash is not based on the initial address of
   2015   // the object alone. If the test below fails the random number generator
   2016   // should be evaluated.
   2017   CHECK_NE(hash, hash3);
   2018   int hash4 = obj->GetIdentityHash();
   2019   CHECK_EQ(hash, hash4);
   2020 
   2021   // Check identity hashes behaviour in the presence of JS accessors.
   2022   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
   2023   {
   2024     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
   2025     Local<v8::Object> o1 = v8::Object::New();
   2026     Local<v8::Object> o2 = v8::Object::New();
   2027     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2028   }
   2029   {
   2030     CompileRun(
   2031         "function cnst() { return 42; };\n"
   2032         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
   2033     Local<v8::Object> o1 = v8::Object::New();
   2034     Local<v8::Object> o2 = v8::Object::New();
   2035     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2036   }
   2037 }
   2038 
   2039 
   2040 THREADED_TEST(HiddenProperties) {
   2041   v8::HandleScope scope;
   2042   LocalContext env;
   2043 
   2044   v8::Local<v8::Object> obj = v8::Object::New();
   2045   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   2046   v8::Local<v8::String> empty = v8_str("");
   2047   v8::Local<v8::String> prop_name = v8_str("prop_name");
   2048 
   2049   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2050 
   2051   // Make sure delete of a non-existent hidden value works
   2052   CHECK(obj->DeleteHiddenValue(key));
   2053 
   2054   CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
   2055   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
   2056   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
   2057   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2058 
   2059   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2060 
   2061   // Make sure we do not find the hidden property.
   2062   CHECK(!obj->Has(empty));
   2063   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2064   CHECK(obj->Get(empty)->IsUndefined());
   2065   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2066   CHECK(obj->Set(empty, v8::Integer::New(2003)));
   2067   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2068   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
   2069 
   2070   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2071 
   2072   // Add another property and delete it afterwards to force the object in
   2073   // slow case.
   2074   CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
   2075   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2076   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
   2077   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2078   CHECK(obj->Delete(prop_name));
   2079   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2080 
   2081   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2082 
   2083   CHECK(obj->DeleteHiddenValue(key));
   2084   CHECK(obj->GetHiddenValue(key).IsEmpty());
   2085 }
   2086 
   2087 
   2088 THREADED_TEST(Regress97784) {
   2089   // Regression test for crbug.com/97784
   2090   // Messing with the Object.prototype should not have effect on
   2091   // hidden properties.
   2092   v8::HandleScope scope;
   2093   LocalContext env;
   2094 
   2095   v8::Local<v8::Object> obj = v8::Object::New();
   2096   v8::Local<v8::String> key = v8_str("hidden");
   2097 
   2098   CompileRun(
   2099       "set_called = false;"
   2100       "Object.defineProperty("
   2101       "    Object.prototype,"
   2102       "    'hidden',"
   2103       "    {get: function() { return 45; },"
   2104       "     set: function() { set_called = true; }})");
   2105 
   2106   CHECK(obj->GetHiddenValue(key).IsEmpty());
   2107   // Make sure that the getter and setter from Object.prototype is not invoked.
   2108   // If it did we would have full access to the hidden properties in
   2109   // the accessor.
   2110   CHECK(obj->SetHiddenValue(key, v8::Integer::New(42)));
   2111   ExpectFalse("set_called");
   2112   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
   2113 }
   2114 
   2115 
   2116 static bool interceptor_for_hidden_properties_called;
   2117 static v8::Handle<Value> InterceptorForHiddenProperties(
   2118     Local<String> name, const AccessorInfo& info) {
   2119   interceptor_for_hidden_properties_called = true;
   2120   return v8::Handle<Value>();
   2121 }
   2122 
   2123 
   2124 THREADED_TEST(HiddenPropertiesWithInterceptors) {
   2125   v8::HandleScope scope;
   2126   LocalContext context;
   2127 
   2128   interceptor_for_hidden_properties_called = false;
   2129 
   2130   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   2131 
   2132   // Associate an interceptor with an object and start setting hidden values.
   2133   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   2134   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   2135   instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
   2136   Local<v8::Function> function = fun_templ->GetFunction();
   2137   Local<v8::Object> obj = function->NewInstance();
   2138   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
   2139   CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
   2140   CHECK(!interceptor_for_hidden_properties_called);
   2141 }
   2142 
   2143 
   2144 THREADED_TEST(External) {
   2145   v8::HandleScope scope;
   2146   int x = 3;
   2147   Local<v8::External> ext = v8::External::New(&x);
   2148   LocalContext env;
   2149   env->Global()->Set(v8_str("ext"), ext);
   2150   Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
   2151   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
   2152   int* ptr = static_cast<int*>(reext->Value());
   2153   CHECK_EQ(x, 3);
   2154   *ptr = 10;
   2155   CHECK_EQ(x, 10);
   2156 
   2157   // Make sure unaligned pointers are wrapped properly.
   2158   char* data = i::StrDup("0123456789");
   2159   Local<v8::Value> zero = v8::External::Wrap(&data[0]);
   2160   Local<v8::Value> one = v8::External::Wrap(&data[1]);
   2161   Local<v8::Value> two = v8::External::Wrap(&data[2]);
   2162   Local<v8::Value> three = v8::External::Wrap(&data[3]);
   2163 
   2164   char* char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(zero));
   2165   CHECK_EQ('0', *char_ptr);
   2166   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(one));
   2167   CHECK_EQ('1', *char_ptr);
   2168   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(two));
   2169   CHECK_EQ('2', *char_ptr);
   2170   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(three));
   2171   CHECK_EQ('3', *char_ptr);
   2172   i::DeleteArray(data);
   2173 }
   2174 
   2175 
   2176 THREADED_TEST(GlobalHandle) {
   2177   v8::Persistent<String> global;
   2178   {
   2179     v8::HandleScope scope;
   2180     Local<String> str = v8_str("str");
   2181     global = v8::Persistent<String>::New(str);
   2182   }
   2183   CHECK_EQ(global->Length(), 3);
   2184   global.Dispose();
   2185 }
   2186 
   2187 
   2188 class WeakCallCounter {
   2189  public:
   2190   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
   2191   int id() { return id_; }
   2192   void increment() { number_of_weak_calls_++; }
   2193   int NumberOfWeakCalls() { return number_of_weak_calls_; }
   2194  private:
   2195   int id_;
   2196   int number_of_weak_calls_;
   2197 };
   2198 
   2199 
   2200 static void WeakPointerCallback(Persistent<Value> handle, void* id) {
   2201   WeakCallCounter* counter = reinterpret_cast<WeakCallCounter*>(id);
   2202   CHECK_EQ(1234, counter->id());
   2203   counter->increment();
   2204   handle.Dispose();
   2205 }
   2206 
   2207 
   2208 THREADED_TEST(ApiObjectGroups) {
   2209   HandleScope scope;
   2210   LocalContext env;
   2211 
   2212   Persistent<Object> g1s1;
   2213   Persistent<Object> g1s2;
   2214   Persistent<Object> g1c1;
   2215   Persistent<Object> g2s1;
   2216   Persistent<Object> g2s2;
   2217   Persistent<Object> g2c1;
   2218 
   2219   WeakCallCounter counter(1234);
   2220 
   2221   {
   2222     HandleScope scope;
   2223     g1s1 = Persistent<Object>::New(Object::New());
   2224     g1s2 = Persistent<Object>::New(Object::New());
   2225     g1c1 = Persistent<Object>::New(Object::New());
   2226     g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2227     g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2228     g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2229 
   2230     g2s1 = Persistent<Object>::New(Object::New());
   2231     g2s2 = Persistent<Object>::New(Object::New());
   2232     g2c1 = Persistent<Object>::New(Object::New());
   2233     g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2234     g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2235     g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2236   }
   2237 
   2238   Persistent<Object> root = Persistent<Object>::New(g1s1);  // make a root.
   2239 
   2240   // Connect group 1 and 2, make a cycle.
   2241   CHECK(g1s2->Set(0, g2s2));
   2242   CHECK(g2s1->Set(0, g1s1));
   2243 
   2244   {
   2245     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
   2246     Persistent<Value> g1_children[] = { g1c1 };
   2247     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
   2248     Persistent<Value> g2_children[] = { g2c1 };
   2249     V8::AddObjectGroup(g1_objects, 2);
   2250     V8::AddImplicitReferences(g1s1, g1_children, 1);
   2251     V8::AddObjectGroup(g2_objects, 2);
   2252     V8::AddImplicitReferences(g2s2, g2_children, 1);
   2253   }
   2254   // Do a single full GC, ensure incremental marking is stopped.
   2255   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   2256 
   2257   // All object should be alive.
   2258   CHECK_EQ(0, counter.NumberOfWeakCalls());
   2259 
   2260   // Weaken the root.
   2261   root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2262   // But make children strong roots---all the objects (except for children)
   2263   // should be collectable now.
   2264   g1c1.ClearWeak();
   2265   g2c1.ClearWeak();
   2266 
   2267   // Groups are deleted, rebuild groups.
   2268   {
   2269     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
   2270     Persistent<Value> g1_children[] = { g1c1 };
   2271     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
   2272     Persistent<Value> g2_children[] = { g2c1 };
   2273     V8::AddObjectGroup(g1_objects, 2);
   2274     V8::AddImplicitReferences(g1s1, g1_children, 1);
   2275     V8::AddObjectGroup(g2_objects, 2);
   2276     V8::AddImplicitReferences(g2s2, g2_children, 1);
   2277   }
   2278 
   2279   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   2280 
   2281   // All objects should be gone. 5 global handles in total.
   2282   CHECK_EQ(5, counter.NumberOfWeakCalls());
   2283 
   2284   // And now make children weak again and collect them.
   2285   g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2286   g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2287 
   2288   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   2289   CHECK_EQ(7, counter.NumberOfWeakCalls());
   2290 }
   2291 
   2292 
   2293 THREADED_TEST(ApiObjectGroupsCycle) {
   2294   HandleScope scope;
   2295   LocalContext env;
   2296 
   2297   WeakCallCounter counter(1234);
   2298 
   2299   Persistent<Object> g1s1;
   2300   Persistent<Object> g1s2;
   2301   Persistent<Object> g2s1;
   2302   Persistent<Object> g2s2;
   2303   Persistent<Object> g3s1;
   2304   Persistent<Object> g3s2;
   2305 
   2306   {
   2307     HandleScope scope;
   2308     g1s1 = Persistent<Object>::New(Object::New());
   2309     g1s2 = Persistent<Object>::New(Object::New());
   2310     g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2311     g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2312 
   2313     g2s1 = Persistent<Object>::New(Object::New());
   2314     g2s2 = Persistent<Object>::New(Object::New());
   2315     g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2316     g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2317 
   2318     g3s1 = Persistent<Object>::New(Object::New());
   2319     g3s2 = Persistent<Object>::New(Object::New());
   2320     g3s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2321     g3s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2322   }
   2323 
   2324   Persistent<Object> root = Persistent<Object>::New(g1s1);  // make a root.
   2325 
   2326   // Connect groups.  We're building the following cycle:
   2327   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   2328   // groups.
   2329   {
   2330     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
   2331     Persistent<Value> g1_children[] = { g2s1 };
   2332     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
   2333     Persistent<Value> g2_children[] = { g3s1 };
   2334     Persistent<Value> g3_objects[] = { g3s1, g3s2 };
   2335     Persistent<Value> g3_children[] = { g1s1 };
   2336     V8::AddObjectGroup(g1_objects, 2);
   2337     V8::AddImplicitReferences(g1s1, g1_children, 1);
   2338     V8::AddObjectGroup(g2_objects, 2);
   2339     V8::AddImplicitReferences(g2s1, g2_children, 1);
   2340     V8::AddObjectGroup(g3_objects, 2);
   2341     V8::AddImplicitReferences(g3s1, g3_children, 1);
   2342   }
   2343   // Do a single full GC
   2344   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   2345 
   2346   // All object should be alive.
   2347   CHECK_EQ(0, counter.NumberOfWeakCalls());
   2348 
   2349   // Weaken the root.
   2350   root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
   2351 
   2352   // Groups are deleted, rebuild groups.
   2353   {
   2354     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
   2355     Persistent<Value> g1_children[] = { g2s1 };
   2356     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
   2357     Persistent<Value> g2_children[] = { g3s1 };
   2358     Persistent<Value> g3_objects[] = { g3s1, g3s2 };
   2359     Persistent<Value> g3_children[] = { g1s1 };
   2360     V8::AddObjectGroup(g1_objects, 2);
   2361     V8::AddImplicitReferences(g1s1, g1_children, 1);
   2362     V8::AddObjectGroup(g2_objects, 2);
   2363     V8::AddImplicitReferences(g2s1, g2_children, 1);
   2364     V8::AddObjectGroup(g3_objects, 2);
   2365     V8::AddImplicitReferences(g3s1, g3_children, 1);
   2366   }
   2367 
   2368   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   2369 
   2370   // All objects should be gone. 7 global handles in total.
   2371   CHECK_EQ(7, counter.NumberOfWeakCalls());
   2372 }
   2373 
   2374 
   2375 THREADED_TEST(ScriptException) {
   2376   v8::HandleScope scope;
   2377   LocalContext env;
   2378   Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
   2379   v8::TryCatch try_catch;
   2380   Local<Value> result = script->Run();
   2381   CHECK(result.IsEmpty());
   2382   CHECK(try_catch.HasCaught());
   2383   String::AsciiValue exception_value(try_catch.Exception());
   2384   CHECK_EQ(*exception_value, "panama!");
   2385 }
   2386 
   2387 
   2388 bool message_received;
   2389 
   2390 
   2391 static void check_message(v8::Handle<v8::Message> message,
   2392                           v8::Handle<Value> data) {
   2393   CHECK_EQ(5.76, data->NumberValue());
   2394   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   2395   CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
   2396   message_received = true;
   2397 }
   2398 
   2399 
   2400 THREADED_TEST(MessageHandlerData) {
   2401   message_received = false;
   2402   v8::HandleScope scope;
   2403   CHECK(!message_received);
   2404   v8::V8::AddMessageListener(check_message, v8_num(5.76));
   2405   LocalContext context;
   2406   v8::ScriptOrigin origin =
   2407       v8::ScriptOrigin(v8_str("6.75"));
   2408   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   2409                                                   &origin);
   2410   script->SetData(v8_str("7.56"));
   2411   script->Run();
   2412   CHECK(message_received);
   2413   // clear out the message listener
   2414   v8::V8::RemoveMessageListeners(check_message);
   2415 }
   2416 
   2417 
   2418 THREADED_TEST(GetSetProperty) {
   2419   v8::HandleScope scope;
   2420   LocalContext context;
   2421   context->Global()->Set(v8_str("foo"), v8_num(14));
   2422   context->Global()->Set(v8_str("12"), v8_num(92));
   2423   context->Global()->Set(v8::Integer::New(16), v8_num(32));
   2424   context->Global()->Set(v8_num(13), v8_num(56));
   2425   Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
   2426   CHECK_EQ(14, foo->Int32Value());
   2427   Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
   2428   CHECK_EQ(92, twelve->Int32Value());
   2429   Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
   2430   CHECK_EQ(32, sixteen->Int32Value());
   2431   Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
   2432   CHECK_EQ(56, thirteen->Int32Value());
   2433   CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
   2434   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
   2435   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
   2436   CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
   2437   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
   2438   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
   2439   CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
   2440   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
   2441   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
   2442 }
   2443 
   2444 
   2445 THREADED_TEST(PropertyAttributes) {
   2446   v8::HandleScope scope;
   2447   LocalContext context;
   2448   // none
   2449   Local<String> prop = v8_str("none");
   2450   context->Global()->Set(prop, v8_num(7));
   2451   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   2452   // read-only
   2453   prop = v8_str("read_only");
   2454   context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
   2455   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   2456   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
   2457   Script::Compile(v8_str("read_only = 9"))->Run();
   2458   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   2459   context->Global()->Set(prop, v8_num(10));
   2460   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   2461   // dont-delete
   2462   prop = v8_str("dont_delete");
   2463   context->Global()->Set(prop, v8_num(13), v8::DontDelete);
   2464   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   2465   Script::Compile(v8_str("delete dont_delete"))->Run();
   2466   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   2467   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
   2468   // dont-enum
   2469   prop = v8_str("dont_enum");
   2470   context->Global()->Set(prop, v8_num(28), v8::DontEnum);
   2471   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
   2472   // absent
   2473   prop = v8_str("absent");
   2474   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   2475   Local<Value> fake_prop = v8_num(1);
   2476   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
   2477   // exception
   2478   TryCatch try_catch;
   2479   Local<Value> exception =
   2480       CompileRun("({ toString: function() { throw 'exception';} })");
   2481   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
   2482   CHECK(try_catch.HasCaught());
   2483   String::AsciiValue exception_value(try_catch.Exception());
   2484   CHECK_EQ("exception", *exception_value);
   2485   try_catch.Reset();
   2486 }
   2487 
   2488 
   2489 THREADED_TEST(Array) {
   2490   v8::HandleScope scope;
   2491   LocalContext context;
   2492   Local<v8::Array> array = v8::Array::New();
   2493   CHECK_EQ(0, array->Length());
   2494   CHECK(array->Get(0)->IsUndefined());
   2495   CHECK(!array->Has(0));
   2496   CHECK(array->Get(100)->IsUndefined());
   2497   CHECK(!array->Has(100));
   2498   array->Set(2, v8_num(7));
   2499   CHECK_EQ(3, array->Length());
   2500   CHECK(!array->Has(0));
   2501   CHECK(!array->Has(1));
   2502   CHECK(array->Has(2));
   2503   CHECK_EQ(7, array->Get(2)->Int32Value());
   2504   Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
   2505   Local<v8::Array> arr = obj.As<v8::Array>();
   2506   CHECK_EQ(3, arr->Length());
   2507   CHECK_EQ(1, arr->Get(0)->Int32Value());
   2508   CHECK_EQ(2, arr->Get(1)->Int32Value());
   2509   CHECK_EQ(3, arr->Get(2)->Int32Value());
   2510   array = v8::Array::New(27);
   2511   CHECK_EQ(27, array->Length());
   2512   array = v8::Array::New(-27);
   2513   CHECK_EQ(0, array->Length());
   2514 }
   2515 
   2516 
   2517 v8::Handle<Value> HandleF(const v8::Arguments& args) {
   2518   v8::HandleScope scope;
   2519   ApiTestFuzzer::Fuzz();
   2520   Local<v8::Array> result = v8::Array::New(args.Length());
   2521   for (int i = 0; i < args.Length(); i++)
   2522     result->Set(i, args[i]);
   2523   return scope.Close(result);
   2524 }
   2525 
   2526 
   2527 THREADED_TEST(Vector) {
   2528   v8::HandleScope scope;
   2529   Local<ObjectTemplate> global = ObjectTemplate::New();
   2530   global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
   2531   LocalContext context(0, global);
   2532 
   2533   const char* fun = "f()";
   2534   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
   2535   CHECK_EQ(0, a0->Length());
   2536 
   2537   const char* fun2 = "f(11)";
   2538   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
   2539   CHECK_EQ(1, a1->Length());
   2540   CHECK_EQ(11, a1->Get(0)->Int32Value());
   2541 
   2542   const char* fun3 = "f(12, 13)";
   2543   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
   2544   CHECK_EQ(2, a2->Length());
   2545   CHECK_EQ(12, a2->Get(0)->Int32Value());
   2546   CHECK_EQ(13, a2->Get(1)->Int32Value());
   2547 
   2548   const char* fun4 = "f(14, 15, 16)";
   2549   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
   2550   CHECK_EQ(3, a3->Length());
   2551   CHECK_EQ(14, a3->Get(0)->Int32Value());
   2552   CHECK_EQ(15, a3->Get(1)->Int32Value());
   2553   CHECK_EQ(16, a3->Get(2)->Int32Value());
   2554 
   2555   const char* fun5 = "f(17, 18, 19, 20)";
   2556   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
   2557   CHECK_EQ(4, a4->Length());
   2558   CHECK_EQ(17, a4->Get(0)->Int32Value());
   2559   CHECK_EQ(18, a4->Get(1)->Int32Value());
   2560   CHECK_EQ(19, a4->Get(2)->Int32Value());
   2561   CHECK_EQ(20, a4->Get(3)->Int32Value());
   2562 }
   2563 
   2564 
   2565 THREADED_TEST(FunctionCall) {
   2566   v8::HandleScope scope;
   2567   LocalContext context;
   2568   CompileRun(
   2569     "function Foo() {"
   2570     "  var result = [];"
   2571     "  for (var i = 0; i < arguments.length; i++) {"
   2572     "    result.push(arguments[i]);"
   2573     "  }"
   2574     "  return result;"
   2575     "}");
   2576   Local<Function> Foo =
   2577       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   2578 
   2579   v8::Handle<Value>* args0 = NULL;
   2580   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
   2581   CHECK_EQ(0, a0->Length());
   2582 
   2583   v8::Handle<Value> args1[] = { v8_num(1.1) };
   2584   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
   2585   CHECK_EQ(1, a1->Length());
   2586   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
   2587 
   2588   v8::Handle<Value> args2[] = { v8_num(2.2),
   2589                                 v8_num(3.3) };
   2590   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
   2591   CHECK_EQ(2, a2->Length());
   2592   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
   2593   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
   2594 
   2595   v8::Handle<Value> args3[] = { v8_num(4.4),
   2596                                 v8_num(5.5),
   2597                                 v8_num(6.6) };
   2598   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
   2599   CHECK_EQ(3, a3->Length());
   2600   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
   2601   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
   2602   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
   2603 
   2604   v8::Handle<Value> args4[] = { v8_num(7.7),
   2605                                 v8_num(8.8),
   2606                                 v8_num(9.9),
   2607                                 v8_num(10.11) };
   2608   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
   2609   CHECK_EQ(4, a4->Length());
   2610   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
   2611   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   2612   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   2613   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
   2614 }
   2615 
   2616 
   2617 static const char* js_code_causing_out_of_memory =
   2618     "var a = new Array(); while(true) a.push(a);";
   2619 
   2620 
   2621 // These tests run for a long time and prevent us from running tests
   2622 // that come after them so they cannot run in parallel.
   2623 TEST(OutOfMemory) {
   2624   // It's not possible to read a snapshot into a heap with different dimensions.
   2625   if (i::Snapshot::IsEnabled()) return;
   2626   // Set heap limits.
   2627   static const int K = 1024;
   2628   v8::ResourceConstraints constraints;
   2629   constraints.set_max_young_space_size(256 * K);
   2630   constraints.set_max_old_space_size(4 * K * K);
   2631   v8::SetResourceConstraints(&constraints);
   2632 
   2633   // Execute a script that causes out of memory.
   2634   v8::HandleScope scope;
   2635   LocalContext context;
   2636   v8::V8::IgnoreOutOfMemoryException();
   2637   Local<Script> script =
   2638       Script::Compile(String::New(js_code_causing_out_of_memory));
   2639   Local<Value> result = script->Run();
   2640 
   2641   // Check for out of memory state.
   2642   CHECK(result.IsEmpty());
   2643   CHECK(context->HasOutOfMemoryException());
   2644 }
   2645 
   2646 
   2647 v8::Handle<Value> ProvokeOutOfMemory(const v8::Arguments& args) {
   2648   ApiTestFuzzer::Fuzz();
   2649 
   2650   v8::HandleScope scope;
   2651   LocalContext context;
   2652   Local<Script> script =
   2653       Script::Compile(String::New(js_code_causing_out_of_memory));
   2654   Local<Value> result = script->Run();
   2655 
   2656   // Check for out of memory state.
   2657   CHECK(result.IsEmpty());
   2658   CHECK(context->HasOutOfMemoryException());
   2659 
   2660   return result;
   2661 }
   2662 
   2663 
   2664 TEST(OutOfMemoryNested) {
   2665   // It's not possible to read a snapshot into a heap with different dimensions.
   2666   if (i::Snapshot::IsEnabled()) return;
   2667   // Set heap limits.
   2668   static const int K = 1024;
   2669   v8::ResourceConstraints constraints;
   2670   constraints.set_max_young_space_size(256 * K);
   2671   constraints.set_max_old_space_size(4 * K * K);
   2672   v8::SetResourceConstraints(&constraints);
   2673 
   2674   v8::HandleScope scope;
   2675   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2676   templ->Set(v8_str("ProvokeOutOfMemory"),
   2677              v8::FunctionTemplate::New(ProvokeOutOfMemory));
   2678   LocalContext context(0, templ);
   2679   v8::V8::IgnoreOutOfMemoryException();
   2680   Local<Value> result = CompileRun(
   2681     "var thrown = false;"
   2682     "try {"
   2683     "  ProvokeOutOfMemory();"
   2684     "} catch (e) {"
   2685     "  thrown = true;"
   2686     "}");
   2687   // Check for out of memory state.
   2688   CHECK(result.IsEmpty());
   2689   CHECK(context->HasOutOfMemoryException());
   2690 }
   2691 
   2692 
   2693 TEST(HugeConsStringOutOfMemory) {
   2694   // It's not possible to read a snapshot into a heap with different dimensions.
   2695   if (i::Snapshot::IsEnabled()) return;
   2696   // Set heap limits.
   2697   static const int K = 1024;
   2698   v8::ResourceConstraints constraints;
   2699   constraints.set_max_young_space_size(256 * K);
   2700   constraints.set_max_old_space_size(2 * K * K);
   2701   v8::SetResourceConstraints(&constraints);
   2702 
   2703   // Execute a script that causes out of memory.
   2704   v8::V8::IgnoreOutOfMemoryException();
   2705 
   2706   v8::HandleScope scope;
   2707   LocalContext context;
   2708 
   2709   // Build huge string. This should fail with out of memory exception.
   2710   Local<Value> result = CompileRun(
   2711     "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
   2712     "for (var i = 0; i < 22; i++) { str = str + str; }");
   2713 
   2714   // Check for out of memory state.
   2715   CHECK(result.IsEmpty());
   2716   CHECK(context->HasOutOfMemoryException());
   2717 }
   2718 
   2719 
   2720 THREADED_TEST(ConstructCall) {
   2721   v8::HandleScope scope;
   2722   LocalContext context;
   2723   CompileRun(
   2724     "function Foo() {"
   2725     "  var result = [];"
   2726     "  for (var i = 0; i < arguments.length; i++) {"
   2727     "    result.push(arguments[i]);"
   2728     "  }"
   2729     "  return result;"
   2730     "}");
   2731   Local<Function> Foo =
   2732       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   2733 
   2734   v8::Handle<Value>* args0 = NULL;
   2735   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
   2736   CHECK_EQ(0, a0->Length());
   2737 
   2738   v8::Handle<Value> args1[] = { v8_num(1.1) };
   2739   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
   2740   CHECK_EQ(1, a1->Length());
   2741   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
   2742 
   2743   v8::Handle<Value> args2[] = { v8_num(2.2),
   2744                                 v8_num(3.3) };
   2745   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
   2746   CHECK_EQ(2, a2->Length());
   2747   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
   2748   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
   2749 
   2750   v8::Handle<Value> args3[] = { v8_num(4.4),
   2751                                 v8_num(5.5),
   2752                                 v8_num(6.6) };
   2753   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
   2754   CHECK_EQ(3, a3->Length());
   2755   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
   2756   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
   2757   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
   2758 
   2759   v8::Handle<Value> args4[] = { v8_num(7.7),
   2760                                 v8_num(8.8),
   2761                                 v8_num(9.9),
   2762                                 v8_num(10.11) };
   2763   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
   2764   CHECK_EQ(4, a4->Length());
   2765   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
   2766   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   2767   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   2768   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
   2769 }
   2770 
   2771 
   2772 static void CheckUncle(v8::TryCatch* try_catch) {
   2773   CHECK(try_catch->HasCaught());
   2774   String::AsciiValue str_value(try_catch->Exception());
   2775   CHECK_EQ(*str_value, "uncle?");
   2776   try_catch->Reset();
   2777 }
   2778 
   2779 
   2780 THREADED_TEST(ConversionNumber) {
   2781   v8::HandleScope scope;
   2782   LocalContext env;
   2783   // Very large number.
   2784   CompileRun("var obj = Math.pow(2,32) * 1237;");
   2785   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   2786   CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
   2787   CHECK_EQ(0, obj->ToInt32()->Value());
   2788   CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
   2789   // Large number.
   2790   CompileRun("var obj = -1234567890123;");
   2791   obj = env->Global()->Get(v8_str("obj"));
   2792   CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
   2793   CHECK_EQ(-1912276171, obj->ToInt32()->Value());
   2794   CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
   2795   // Small positive integer.
   2796   CompileRun("var obj = 42;");
   2797   obj = env->Global()->Get(v8_str("obj"));
   2798   CHECK_EQ(42.0, obj->ToNumber()->Value());
   2799   CHECK_EQ(42, obj->ToInt32()->Value());
   2800   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   2801   // Negative integer.
   2802   CompileRun("var obj = -37;");
   2803   obj = env->Global()->Get(v8_str("obj"));
   2804   CHECK_EQ(-37.0, obj->ToNumber()->Value());
   2805   CHECK_EQ(-37, obj->ToInt32()->Value());
   2806   CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
   2807   // Positive non-int32 integer.
   2808   CompileRun("var obj = 0x81234567;");
   2809   obj = env->Global()->Get(v8_str("obj"));
   2810   CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
   2811   CHECK_EQ(-2128394905, obj->ToInt32()->Value());
   2812   CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
   2813   // Fraction.
   2814   CompileRun("var obj = 42.3;");
   2815   obj = env->Global()->Get(v8_str("obj"));
   2816   CHECK_EQ(42.3, obj->ToNumber()->Value());
   2817   CHECK_EQ(42, obj->ToInt32()->Value());
   2818   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   2819   // Large negative fraction.
   2820   CompileRun("var obj = -5726623061.75;");
   2821   obj = env->Global()->Get(v8_str("obj"));
   2822   CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
   2823   CHECK_EQ(-1431655765, obj->ToInt32()->Value());
   2824   CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
   2825 }
   2826 
   2827 
   2828 THREADED_TEST(isNumberType) {
   2829   v8::HandleScope scope;
   2830   LocalContext env;
   2831   // Very large number.
   2832   CompileRun("var obj = Math.pow(2,32) * 1237;");
   2833   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   2834   CHECK(!obj->IsInt32());
   2835   CHECK(!obj->IsUint32());
   2836   // Large negative number.
   2837   CompileRun("var obj = -1234567890123;");
   2838   obj = env->Global()->Get(v8_str("obj"));
   2839   CHECK(!obj->IsInt32());
   2840   CHECK(!obj->IsUint32());
   2841   // Small positive integer.
   2842   CompileRun("var obj = 42;");
   2843   obj = env->Global()->Get(v8_str("obj"));
   2844   CHECK(obj->IsInt32());
   2845   CHECK(obj->IsUint32());
   2846   // Negative integer.
   2847   CompileRun("var obj = -37;");
   2848   obj = env->Global()->Get(v8_str("obj"));
   2849   CHECK(obj->IsInt32());
   2850   CHECK(!obj->IsUint32());
   2851   // Positive non-int32 integer.
   2852   CompileRun("var obj = 0x81234567;");
   2853   obj = env->Global()->Get(v8_str("obj"));
   2854   CHECK(!obj->IsInt32());
   2855   CHECK(obj->IsUint32());
   2856   // Fraction.
   2857   CompileRun("var obj = 42.3;");
   2858   obj = env->Global()->Get(v8_str("obj"));
   2859   CHECK(!obj->IsInt32());
   2860   CHECK(!obj->IsUint32());
   2861   // Large negative fraction.
   2862   CompileRun("var obj = -5726623061.75;");
   2863   obj = env->Global()->Get(v8_str("obj"));
   2864   CHECK(!obj->IsInt32());
   2865   CHECK(!obj->IsUint32());
   2866   // Positive zero
   2867   CompileRun("var obj = 0.0;");
   2868   obj = env->Global()->Get(v8_str("obj"));
   2869   CHECK(obj->IsInt32());
   2870   CHECK(obj->IsUint32());
   2871   // Positive zero
   2872   CompileRun("var obj = -0.0;");
   2873   obj = env->Global()->Get(v8_str("obj"));
   2874   CHECK(!obj->IsInt32());
   2875   CHECK(!obj->IsUint32());
   2876 }
   2877 
   2878 
   2879 THREADED_TEST(ConversionException) {
   2880   v8::HandleScope scope;
   2881   LocalContext env;
   2882   CompileRun(
   2883     "function TestClass() { };"
   2884     "TestClass.prototype.toString = function () { throw 'uncle?'; };"
   2885     "var obj = new TestClass();");
   2886   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   2887 
   2888   v8::TryCatch try_catch;
   2889 
   2890   Local<Value> to_string_result = obj->ToString();
   2891   CHECK(to_string_result.IsEmpty());
   2892   CheckUncle(&try_catch);
   2893 
   2894   Local<Value> to_number_result = obj->ToNumber();
   2895   CHECK(to_number_result.IsEmpty());
   2896   CheckUncle(&try_catch);
   2897 
   2898   Local<Value> to_integer_result = obj->ToInteger();
   2899   CHECK(to_integer_result.IsEmpty());
   2900   CheckUncle(&try_catch);
   2901 
   2902   Local<Value> to_uint32_result = obj->ToUint32();
   2903   CHECK(to_uint32_result.IsEmpty());
   2904   CheckUncle(&try_catch);
   2905 
   2906   Local<Value> to_int32_result = obj->ToInt32();
   2907   CHECK(to_int32_result.IsEmpty());
   2908   CheckUncle(&try_catch);
   2909 
   2910   Local<Value> to_object_result = v8::Undefined()->ToObject();
   2911   CHECK(to_object_result.IsEmpty());
   2912   CHECK(try_catch.HasCaught());
   2913   try_catch.Reset();
   2914 
   2915   int32_t int32_value = obj->Int32Value();
   2916   CHECK_EQ(0, int32_value);
   2917   CheckUncle(&try_catch);
   2918 
   2919   uint32_t uint32_value = obj->Uint32Value();
   2920   CHECK_EQ(0, uint32_value);
   2921   CheckUncle(&try_catch);
   2922 
   2923   double number_value = obj->NumberValue();
   2924   CHECK_NE(0, IsNaN(number_value));
   2925   CheckUncle(&try_catch);
   2926 
   2927   int64_t integer_value = obj->IntegerValue();
   2928   CHECK_EQ(0.0, static_cast<double>(integer_value));
   2929   CheckUncle(&try_catch);
   2930 }
   2931 
   2932 
   2933 v8::Handle<Value> ThrowFromC(const v8::Arguments& args) {
   2934   ApiTestFuzzer::Fuzz();
   2935   return v8::ThrowException(v8_str("konto"));
   2936 }
   2937 
   2938 
   2939 v8::Handle<Value> CCatcher(const v8::Arguments& args) {
   2940   if (args.Length() < 1) return v8::False();
   2941   v8::HandleScope scope;
   2942   v8::TryCatch try_catch;
   2943   Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
   2944   CHECK(!try_catch.HasCaught() || result.IsEmpty());
   2945   return v8::Boolean::New(try_catch.HasCaught());
   2946 }
   2947 
   2948 
   2949 THREADED_TEST(APICatch) {
   2950   v8::HandleScope scope;
   2951   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2952   templ->Set(v8_str("ThrowFromC"),
   2953              v8::FunctionTemplate::New(ThrowFromC));
   2954   LocalContext context(0, templ);
   2955   CompileRun(
   2956     "var thrown = false;"
   2957     "try {"
   2958     "  ThrowFromC();"
   2959     "} catch (e) {"
   2960     "  thrown = true;"
   2961     "}");
   2962   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
   2963   CHECK(thrown->BooleanValue());
   2964 }
   2965 
   2966 
   2967 THREADED_TEST(APIThrowTryCatch) {
   2968   v8::HandleScope scope;
   2969   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2970   templ->Set(v8_str("ThrowFromC"),
   2971              v8::FunctionTemplate::New(ThrowFromC));
   2972   LocalContext context(0, templ);
   2973   v8::TryCatch try_catch;
   2974   CompileRun("ThrowFromC();");
   2975   CHECK(try_catch.HasCaught());
   2976 }
   2977 
   2978 
   2979 // Test that a try-finally block doesn't shadow a try-catch block
   2980 // when setting up an external handler.
   2981 //
   2982 // BUG(271): Some of the exception propagation does not work on the
   2983 // ARM simulator because the simulator separates the C++ stack and the
   2984 // JS stack.  This test therefore fails on the simulator.  The test is
   2985 // not threaded to allow the threading tests to run on the simulator.
   2986 TEST(TryCatchInTryFinally) {
   2987   v8::HandleScope scope;
   2988   Local<ObjectTemplate> templ = ObjectTemplate::New();
   2989   templ->Set(v8_str("CCatcher"),
   2990              v8::FunctionTemplate::New(CCatcher));
   2991   LocalContext context(0, templ);
   2992   Local<Value> result = CompileRun("try {"
   2993                                    "  try {"
   2994                                    "    CCatcher('throw 7;');"
   2995                                    "  } finally {"
   2996                                    "  }"
   2997                                    "} catch (e) {"
   2998                                    "}");
   2999   CHECK(result->IsTrue());
   3000 }
   3001 
   3002 
   3003 static void check_reference_error_message(
   3004     v8::Handle<v8::Message> message,
   3005     v8::Handle<v8::Value> data) {
   3006   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
   3007   CHECK(message->Get()->Equals(v8_str(reference_error)));
   3008 }
   3009 
   3010 
   3011 static v8::Handle<Value> Fail(const v8::Arguments& args) {
   3012   ApiTestFuzzer::Fuzz();
   3013   CHECK(false);
   3014   return v8::Undefined();
   3015 }
   3016 
   3017 
   3018 // Test that overwritten methods are not invoked on uncaught exception
   3019 // formatting. However, they are invoked when performing normal error
   3020 // string conversions.
   3021 TEST(APIThrowMessageOverwrittenToString) {
   3022   v8::HandleScope scope;
   3023   v8::V8::AddMessageListener(check_reference_error_message);
   3024   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3025   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
   3026   LocalContext context(NULL, templ);
   3027   CompileRun("asdf;");
   3028   CompileRun("var limit = {};"
   3029              "limit.valueOf = fail;"
   3030              "Error.stackTraceLimit = limit;");
   3031   CompileRun("asdf");
   3032   CompileRun("Array.prototype.pop = fail;");
   3033   CompileRun("Object.prototype.hasOwnProperty = fail;");
   3034   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
   3035   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
   3036   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
   3037   CompileRun("ReferenceError.prototype.toString ="
   3038              "  function() { return 'Whoops' }");
   3039   CompileRun("asdf;");
   3040   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
   3041   CompileRun("asdf;");
   3042   CompileRun("ReferenceError.prototype.constructor = void 0;");
   3043   CompileRun("asdf;");
   3044   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
   3045   CompileRun("asdf;");
   3046   CompileRun("ReferenceError.prototype = new Object();");
   3047   CompileRun("asdf;");
   3048   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
   3049   CHECK(string->Equals(v8_str("Whoops")));
   3050   CompileRun("ReferenceError.prototype.constructor = new Object();"
   3051              "ReferenceError.prototype.constructor.name = 1;"
   3052              "Number.prototype.toString = function() { return 'Whoops'; };"
   3053              "ReferenceError.prototype.toString = Object.prototype.toString;");
   3054   CompileRun("asdf;");
   3055   v8::V8::RemoveMessageListeners(check_message);
   3056 }
   3057 
   3058 
   3059 static void receive_message(v8::Handle<v8::Message> message,
   3060                             v8::Handle<v8::Value> data) {
   3061   message->Get();
   3062   message_received = true;
   3063 }
   3064 
   3065 
   3066 TEST(APIThrowMessage) {
   3067   message_received = false;
   3068   v8::HandleScope scope;
   3069   v8::V8::AddMessageListener(receive_message);
   3070   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3071   templ->Set(v8_str("ThrowFromC"),
   3072              v8::FunctionTemplate::New(ThrowFromC));
   3073   LocalContext context(0, templ);
   3074   CompileRun("ThrowFromC();");
   3075   CHECK(message_received);
   3076   v8::V8::RemoveMessageListeners(check_message);
   3077 }
   3078 
   3079 
   3080 TEST(APIThrowMessageAndVerboseTryCatch) {
   3081   message_received = false;
   3082   v8::HandleScope scope;
   3083   v8::V8::AddMessageListener(receive_message);
   3084   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3085   templ->Set(v8_str("ThrowFromC"),
   3086              v8::FunctionTemplate::New(ThrowFromC));
   3087   LocalContext context(0, templ);
   3088   v8::TryCatch try_catch;
   3089   try_catch.SetVerbose(true);
   3090   Local<Value> result = CompileRun("ThrowFromC();");
   3091   CHECK(try_catch.HasCaught());
   3092   CHECK(result.IsEmpty());
   3093   CHECK(message_received);
   3094   v8::V8::RemoveMessageListeners(check_message);
   3095 }
   3096 
   3097 
   3098 TEST(APIStackOverflowAndVerboseTryCatch) {
   3099   message_received = false;
   3100   v8::HandleScope scope;
   3101   v8::V8::AddMessageListener(receive_message);
   3102   LocalContext context;
   3103   v8::TryCatch try_catch;
   3104   try_catch.SetVerbose(true);
   3105   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
   3106   CHECK(try_catch.HasCaught());
   3107   CHECK(result.IsEmpty());
   3108   CHECK(message_received);
   3109   v8::V8::RemoveMessageListeners(receive_message);
   3110 }
   3111 
   3112 
   3113 THREADED_TEST(ExternalScriptException) {
   3114   v8::HandleScope scope;
   3115   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3116   templ->Set(v8_str("ThrowFromC"),
   3117              v8::FunctionTemplate::New(ThrowFromC));
   3118   LocalContext context(0, templ);
   3119 
   3120   v8::TryCatch try_catch;
   3121   Local<Script> script
   3122       = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
   3123   Local<Value> result = script->Run();
   3124   CHECK(result.IsEmpty());
   3125   CHECK(try_catch.HasCaught());
   3126   String::AsciiValue exception_value(try_catch.Exception());
   3127   CHECK_EQ("konto", *exception_value);
   3128 }
   3129 
   3130 
   3131 
   3132 v8::Handle<Value> CThrowCountDown(const v8::Arguments& args) {
   3133   ApiTestFuzzer::Fuzz();
   3134   CHECK_EQ(4, args.Length());
   3135   int count = args[0]->Int32Value();
   3136   int cInterval = args[2]->Int32Value();
   3137   if (count == 0) {
   3138     return v8::ThrowException(v8_str("FromC"));
   3139   } else {
   3140     Local<v8::Object> global = Context::GetCurrent()->Global();
   3141     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
   3142     v8::Handle<Value> argv[] = { v8_num(count - 1),
   3143                                  args[1],
   3144                                  args[2],
   3145                                  args[3] };
   3146     if (count % cInterval == 0) {
   3147       v8::TryCatch try_catch;
   3148       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
   3149       int expected = args[3]->Int32Value();
   3150       if (try_catch.HasCaught()) {
   3151         CHECK_EQ(expected, count);
   3152         CHECK(result.IsEmpty());
   3153         CHECK(!i::Isolate::Current()->has_scheduled_exception());
   3154       } else {
   3155         CHECK_NE(expected, count);
   3156       }
   3157       return result;
   3158     } else {
   3159       return fun.As<Function>()->Call(global, 4, argv);
   3160     }
   3161   }
   3162 }
   3163 
   3164 
   3165 v8::Handle<Value> JSCheck(const v8::Arguments& args) {
   3166   ApiTestFuzzer::Fuzz();
   3167   CHECK_EQ(3, args.Length());
   3168   bool equality = args[0]->BooleanValue();
   3169   int count = args[1]->Int32Value();
   3170   int expected = args[2]->Int32Value();
   3171   if (equality) {
   3172     CHECK_EQ(count, expected);
   3173   } else {
   3174     CHECK_NE(count, expected);
   3175   }
   3176   return v8::Undefined();
   3177 }
   3178 
   3179 
   3180 THREADED_TEST(EvalInTryFinally) {
   3181   v8::HandleScope scope;
   3182   LocalContext context;
   3183   v8::TryCatch try_catch;
   3184   CompileRun("(function() {"
   3185              "  try {"
   3186              "    eval('asldkf (*&^&*^');"
   3187              "  } finally {"
   3188              "    return;"
   3189              "  }"
   3190              "})()");
   3191   CHECK(!try_catch.HasCaught());
   3192 }
   3193 
   3194 
   3195 // This test works by making a stack of alternating JavaScript and C
   3196 // activations.  These activations set up exception handlers with regular
   3197 // intervals, one interval for C activations and another for JavaScript
   3198 // activations.  When enough activations have been created an exception is
   3199 // thrown and we check that the right activation catches the exception and that
   3200 // no other activations do.  The right activation is always the topmost one with
   3201 // a handler, regardless of whether it is in JavaScript or C.
   3202 //
   3203 // The notation used to describe a test case looks like this:
   3204 //
   3205 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
   3206 //
   3207 // Each entry is an activation, either JS or C.  The index is the count at that
   3208 // level.  Stars identify activations with exception handlers, the @ identifies
   3209 // the exception handler that should catch the exception.
   3210 //
   3211 // BUG(271): Some of the exception propagation does not work on the
   3212 // ARM simulator because the simulator separates the C++ stack and the
   3213 // JS stack.  This test therefore fails on the simulator.  The test is
   3214 // not threaded to allow the threading tests to run on the simulator.
   3215 TEST(ExceptionOrder) {
   3216   v8::HandleScope scope;
   3217   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3218   templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
   3219   templ->Set(v8_str("CThrowCountDown"),
   3220              v8::FunctionTemplate::New(CThrowCountDown));
   3221   LocalContext context(0, templ);
   3222   CompileRun(
   3223     "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
   3224     "  if (count == 0) throw 'FromJS';"
   3225     "  if (count % jsInterval == 0) {"
   3226     "    try {"
   3227     "      var value = CThrowCountDown(count - 1,"
   3228     "                                  jsInterval,"
   3229     "                                  cInterval,"
   3230     "                                  expected);"
   3231     "      check(false, count, expected);"
   3232     "      return value;"
   3233     "    } catch (e) {"
   3234     "      check(true, count, expected);"
   3235     "    }"
   3236     "  } else {"
   3237     "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
   3238     "  }"
   3239     "}");
   3240   Local<Function> fun =
   3241       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
   3242 
   3243   const int argc = 4;
   3244   //                             count      jsInterval cInterval  expected
   3245 
   3246   // *JS[4] *C[3] @JS[2] C[1] JS[0]
   3247   v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
   3248   fun->Call(fun, argc, a0);
   3249 
   3250   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
   3251   v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
   3252   fun->Call(fun, argc, a1);
   3253 
   3254   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
   3255   v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
   3256   fun->Call(fun, argc, a2);
   3257 
   3258   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
   3259   v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
   3260   fun->Call(fun, argc, a3);
   3261 
   3262   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
   3263   v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
   3264   fun->Call(fun, argc, a4);
   3265 
   3266   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
   3267   v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
   3268   fun->Call(fun, argc, a5);
   3269 }
   3270 
   3271 
   3272 v8::Handle<Value> ThrowValue(const v8::Arguments& args) {
   3273   ApiTestFuzzer::Fuzz();
   3274   CHECK_EQ(1, args.Length());
   3275   return v8::ThrowException(args[0]);
   3276 }
   3277 
   3278 
   3279 THREADED_TEST(ThrowValues) {
   3280   v8::HandleScope scope;
   3281   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3282   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
   3283   LocalContext context(0, templ);
   3284   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   3285     "function Run(obj) {"
   3286     "  try {"
   3287     "    Throw(obj);"
   3288     "  } catch (e) {"
   3289     "    return e;"
   3290     "  }"
   3291     "  return 'no exception';"
   3292     "}"
   3293     "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
   3294   CHECK_EQ(5, result->Length());
   3295   CHECK(result->Get(v8::Integer::New(0))->IsString());
   3296   CHECK(result->Get(v8::Integer::New(1))->IsNumber());
   3297   CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
   3298   CHECK(result->Get(v8::Integer::New(2))->IsNumber());
   3299   CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
   3300   CHECK(result->Get(v8::Integer::New(3))->IsNull());
   3301   CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
   3302 }
   3303 
   3304 
   3305 THREADED_TEST(CatchZero) {
   3306   v8::HandleScope scope;
   3307   LocalContext context;
   3308   v8::TryCatch try_catch;
   3309   CHECK(!try_catch.HasCaught());
   3310   Script::Compile(v8_str("throw 10"))->Run();
   3311   CHECK(try_catch.HasCaught());
   3312   CHECK_EQ(10, try_catch.Exception()->Int32Value());
   3313   try_catch.Reset();
   3314   CHECK(!try_catch.HasCaught());
   3315   Script::Compile(v8_str("throw 0"))->Run();
   3316   CHECK(try_catch.HasCaught());
   3317   CHECK_EQ(0, try_catch.Exception()->Int32Value());
   3318 }
   3319 
   3320 
   3321 THREADED_TEST(CatchExceptionFromWith) {
   3322   v8::HandleScope scope;
   3323   LocalContext context;
   3324   v8::TryCatch try_catch;
   3325   CHECK(!try_catch.HasCaught());
   3326   Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
   3327   CHECK(try_catch.HasCaught());
   3328 }
   3329 
   3330 
   3331 THREADED_TEST(TryCatchAndFinallyHidingException) {
   3332   v8::HandleScope scope;
   3333   LocalContext context;
   3334   v8::TryCatch try_catch;
   3335   CHECK(!try_catch.HasCaught());
   3336   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
   3337   CompileRun("f({toString: function() { throw 42; }});");
   3338   CHECK(!try_catch.HasCaught());
   3339 }
   3340 
   3341 
   3342 v8::Handle<v8::Value> WithTryCatch(const v8::Arguments& args) {
   3343   v8::TryCatch try_catch;
   3344   return v8::Undefined();
   3345 }
   3346 
   3347 
   3348 THREADED_TEST(TryCatchAndFinally) {
   3349   v8::HandleScope scope;
   3350   LocalContext context;
   3351   context->Global()->Set(
   3352       v8_str("native_with_try_catch"),
   3353       v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
   3354   v8::TryCatch try_catch;
   3355   CHECK(!try_catch.HasCaught());
   3356   CompileRun(
   3357       "try {\n"
   3358       "  throw new Error('a');\n"
   3359       "} finally {\n"
   3360       "  native_with_try_catch();\n"
   3361       "}\n");
   3362   CHECK(try_catch.HasCaught());
   3363 }
   3364 
   3365 
   3366 THREADED_TEST(Equality) {
   3367   v8::HandleScope scope;
   3368   LocalContext context;
   3369   // Check that equality works at all before relying on CHECK_EQ
   3370   CHECK(v8_str("a")->Equals(v8_str("a")));
   3371   CHECK(!v8_str("a")->Equals(v8_str("b")));
   3372 
   3373   CHECK_EQ(v8_str("a"), v8_str("a"));
   3374   CHECK_NE(v8_str("a"), v8_str("b"));
   3375   CHECK_EQ(v8_num(1), v8_num(1));
   3376   CHECK_EQ(v8_num(1.00), v8_num(1));
   3377   CHECK_NE(v8_num(1), v8_num(2));
   3378 
   3379   // Assume String is not symbol.
   3380   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
   3381   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
   3382   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   3383   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   3384   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
   3385   CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
   3386   Local<Value> not_a_number = v8_num(i::OS::nan_value());
   3387   CHECK(!not_a_number->StrictEquals(not_a_number));
   3388   CHECK(v8::False()->StrictEquals(v8::False()));
   3389   CHECK(!v8::False()->StrictEquals(v8::Undefined()));
   3390 
   3391   v8::Handle<v8::Object> obj = v8::Object::New();
   3392   v8::Persistent<v8::Object> alias = v8::Persistent<v8::Object>::New(obj);
   3393   CHECK(alias->StrictEquals(obj));
   3394   alias.Dispose();
   3395 }
   3396 
   3397 
   3398 THREADED_TEST(MultiRun) {
   3399   v8::HandleScope scope;
   3400   LocalContext context;
   3401   Local<Script> script = Script::Compile(v8_str("x"));
   3402   for (int i = 0; i < 10; i++)
   3403     script->Run();
   3404 }
   3405 
   3406 
   3407 static v8::Handle<Value> GetXValue(Local<String> name,
   3408                                    const AccessorInfo& info) {
   3409   ApiTestFuzzer::Fuzz();
   3410   CHECK_EQ(info.Data(), v8_str("donut"));
   3411   CHECK_EQ(name, v8_str("x"));
   3412   return name;
   3413 }
   3414 
   3415 
   3416 THREADED_TEST(SimplePropertyRead) {
   3417   v8::HandleScope scope;
   3418   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3419   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   3420   LocalContext context;
   3421   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3422   Local<Script> script = Script::Compile(v8_str("obj.x"));
   3423   for (int i = 0; i < 10; i++) {
   3424     Local<Value> result = script->Run();
   3425     CHECK_EQ(result, v8_str("x"));
   3426   }
   3427 }
   3428 
   3429 THREADED_TEST(DefinePropertyOnAPIAccessor) {
   3430   v8::HandleScope scope;
   3431   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3432   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   3433   LocalContext context;
   3434   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3435 
   3436   // Uses getOwnPropertyDescriptor to check the configurable status
   3437   Local<Script> script_desc
   3438     = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
   3439                              "obj, 'x');"
   3440                              "prop.configurable;"));
   3441   Local<Value> result = script_desc->Run();
   3442   CHECK_EQ(result->BooleanValue(), true);
   3443 
   3444   // Redefine get - but still configurable
   3445   Local<Script> script_define
   3446     = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
   3447                              "            configurable: true };"
   3448                              "Object.defineProperty(obj, 'x', desc);"
   3449                              "obj.x"));
   3450   result = script_define->Run();
   3451   CHECK_EQ(result, v8_num(42));
   3452 
   3453   // Check that the accessor is still configurable
   3454   result = script_desc->Run();
   3455   CHECK_EQ(result->BooleanValue(), true);
   3456 
   3457   // Redefine to a non-configurable
   3458   script_define
   3459     = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
   3460                              "             configurable: false };"
   3461                              "Object.defineProperty(obj, 'x', desc);"
   3462                              "obj.x"));
   3463   result = script_define->Run();
   3464   CHECK_EQ(result, v8_num(43));
   3465   result = script_desc->Run();
   3466   CHECK_EQ(result->BooleanValue(), false);
   3467 
   3468   // Make sure that it is not possible to redefine again
   3469   v8::TryCatch try_catch;
   3470   result = script_define->Run();
   3471   CHECK(try_catch.HasCaught());
   3472   String::AsciiValue exception_value(try_catch.Exception());
   3473   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   3474 }
   3475 
   3476 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
   3477   v8::HandleScope scope;
   3478   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3479   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   3480   LocalContext context;
   3481   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3482 
   3483   Local<Script> script_desc = Script::Compile(v8_str("var prop ="
   3484                                     "Object.getOwnPropertyDescriptor( "
   3485                                     "obj, 'x');"
   3486                                     "prop.configurable;"));
   3487   Local<Value> result = script_desc->Run();
   3488   CHECK_EQ(result->BooleanValue(), true);
   3489 
   3490   Local<Script> script_define =
   3491     Script::Compile(v8_str("var desc = {get: function(){return 42; },"
   3492                            "            configurable: true };"
   3493                            "Object.defineProperty(obj, 'x', desc);"
   3494                            "obj.x"));
   3495   result = script_define->Run();
   3496   CHECK_EQ(result, v8_num(42));
   3497 
   3498 
   3499   result = script_desc->Run();
   3500   CHECK_EQ(result->BooleanValue(), true);
   3501 
   3502 
   3503   script_define =
   3504     Script::Compile(v8_str("var desc = {get: function(){return 43; },"
   3505                            "            configurable: false };"
   3506                            "Object.defineProperty(obj, 'x', desc);"
   3507                            "obj.x"));
   3508   result = script_define->Run();
   3509   CHECK_EQ(result, v8_num(43));
   3510   result = script_desc->Run();
   3511 
   3512   CHECK_EQ(result->BooleanValue(), false);
   3513 
   3514   v8::TryCatch try_catch;
   3515   result = script_define->Run();
   3516   CHECK(try_catch.HasCaught());
   3517   String::AsciiValue exception_value(try_catch.Exception());
   3518   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   3519 }
   3520 
   3521 
   3522 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
   3523                                                 char const* name) {
   3524   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
   3525 }
   3526 
   3527 
   3528 THREADED_TEST(DefineAPIAccessorOnObject) {
   3529   v8::HandleScope scope;
   3530   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3531   LocalContext context;
   3532 
   3533   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   3534   CompileRun("var obj2 = {};");
   3535 
   3536   CHECK(CompileRun("obj1.x")->IsUndefined());
   3537   CHECK(CompileRun("obj2.x")->IsUndefined());
   3538 
   3539   CHECK(GetGlobalProperty(&context, "obj1")->
   3540       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3541 
   3542   ExpectString("obj1.x", "x");
   3543   CHECK(CompileRun("obj2.x")->IsUndefined());
   3544 
   3545   CHECK(GetGlobalProperty(&context, "obj2")->
   3546       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3547 
   3548   ExpectString("obj1.x", "x");
   3549   ExpectString("obj2.x", "x");
   3550 
   3551   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3552   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3553 
   3554   CompileRun("Object.defineProperty(obj1, 'x',"
   3555              "{ get: function() { return 'y'; }, configurable: true })");
   3556 
   3557   ExpectString("obj1.x", "y");
   3558   ExpectString("obj2.x", "x");
   3559 
   3560   CompileRun("Object.defineProperty(obj2, 'x',"
   3561              "{ get: function() { return 'y'; }, configurable: true })");
   3562 
   3563   ExpectString("obj1.x", "y");
   3564   ExpectString("obj2.x", "y");
   3565 
   3566   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3567   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3568 
   3569   CHECK(GetGlobalProperty(&context, "obj1")->
   3570       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3571   CHECK(GetGlobalProperty(&context, "obj2")->
   3572       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3573 
   3574   ExpectString("obj1.x", "x");
   3575   ExpectString("obj2.x", "x");
   3576 
   3577   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3578   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3579 
   3580   // Define getters/setters, but now make them not configurable.
   3581   CompileRun("Object.defineProperty(obj1, 'x',"
   3582              "{ get: function() { return 'z'; }, configurable: false })");
   3583   CompileRun("Object.defineProperty(obj2, 'x',"
   3584              "{ get: function() { return 'z'; }, configurable: false })");
   3585 
   3586   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3587   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3588 
   3589   ExpectString("obj1.x", "z");
   3590   ExpectString("obj2.x", "z");
   3591 
   3592   CHECK(!GetGlobalProperty(&context, "obj1")->
   3593       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3594   CHECK(!GetGlobalProperty(&context, "obj2")->
   3595       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3596 
   3597   ExpectString("obj1.x", "z");
   3598   ExpectString("obj2.x", "z");
   3599 }
   3600 
   3601 
   3602 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   3603   v8::HandleScope scope;
   3604   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3605   LocalContext context;
   3606 
   3607   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   3608   CompileRun("var obj2 = {};");
   3609 
   3610   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   3611         v8_str("x"),
   3612         GetXValue, NULL,
   3613         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   3614   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   3615         v8_str("x"),
   3616         GetXValue, NULL,
   3617         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   3618 
   3619   ExpectString("obj1.x", "x");
   3620   ExpectString("obj2.x", "x");
   3621 
   3622   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   3623   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   3624 
   3625   CHECK(!GetGlobalProperty(&context, "obj1")->
   3626       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3627   CHECK(!GetGlobalProperty(&context, "obj2")->
   3628       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   3629 
   3630   {
   3631     v8::TryCatch try_catch;
   3632     CompileRun("Object.defineProperty(obj1, 'x',"
   3633         "{get: function() { return 'func'; }})");
   3634     CHECK(try_catch.HasCaught());
   3635     String::AsciiValue exception_value(try_catch.Exception());
   3636     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   3637   }
   3638   {
   3639     v8::TryCatch try_catch;
   3640     CompileRun("Object.defineProperty(obj2, 'x',"
   3641         "{get: function() { return 'func'; }})");
   3642     CHECK(try_catch.HasCaught());
   3643     String::AsciiValue exception_value(try_catch.Exception());
   3644     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   3645   }
   3646 }
   3647 
   3648 
   3649 static v8::Handle<Value> Get239Value(Local<String> name,
   3650                                      const AccessorInfo& info) {
   3651   ApiTestFuzzer::Fuzz();
   3652   CHECK_EQ(info.Data(), v8_str("donut"));
   3653   CHECK_EQ(name, v8_str("239"));
   3654   return name;
   3655 }
   3656 
   3657 
   3658 THREADED_TEST(ElementAPIAccessor) {
   3659   v8::HandleScope scope;
   3660   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3661   LocalContext context;
   3662 
   3663   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   3664   CompileRun("var obj2 = {};");
   3665 
   3666   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   3667         v8_str("239"),
   3668         Get239Value, NULL,
   3669         v8_str("donut")));
   3670   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   3671         v8_str("239"),
   3672         Get239Value, NULL,
   3673         v8_str("donut")));
   3674 
   3675   ExpectString("obj1[239]", "239");
   3676   ExpectString("obj2[239]", "239");
   3677   ExpectString("obj1['239']", "239");
   3678   ExpectString("obj2['239']", "239");
   3679 }
   3680 
   3681 
   3682 v8::Persistent<Value> xValue;
   3683 
   3684 
   3685 static void SetXValue(Local<String> name,
   3686                       Local<Value> value,
   3687                       const AccessorInfo& info) {
   3688   CHECK_EQ(value, v8_num(4));
   3689   CHECK_EQ(info.Data(), v8_str("donut"));
   3690   CHECK_EQ(name, v8_str("x"));
   3691   CHECK(xValue.IsEmpty());
   3692   xValue = v8::Persistent<Value>::New(value);
   3693 }
   3694 
   3695 
   3696 THREADED_TEST(SimplePropertyWrite) {
   3697   v8::HandleScope scope;
   3698   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3699   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
   3700   LocalContext context;
   3701   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3702   Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
   3703   for (int i = 0; i < 10; i++) {
   3704     CHECK(xValue.IsEmpty());
   3705     script->Run();
   3706     CHECK_EQ(v8_num(4), xValue);
   3707     xValue.Dispose();
   3708     xValue = v8::Persistent<Value>();
   3709   }
   3710 }
   3711 
   3712 
   3713 static v8::Handle<Value> XPropertyGetter(Local<String> property,
   3714                                          const AccessorInfo& info) {
   3715   ApiTestFuzzer::Fuzz();
   3716   CHECK(info.Data()->IsUndefined());
   3717   return property;
   3718 }
   3719 
   3720 
   3721 THREADED_TEST(NamedInterceptorPropertyRead) {
   3722   v8::HandleScope scope;
   3723   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3724   templ->SetNamedPropertyHandler(XPropertyGetter);
   3725   LocalContext context;
   3726   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3727   Local<Script> script = Script::Compile(v8_str("obj.x"));
   3728   for (int i = 0; i < 10; i++) {
   3729     Local<Value> result = script->Run();
   3730     CHECK_EQ(result, v8_str("x"));
   3731   }
   3732 }
   3733 
   3734 
   3735 THREADED_TEST(NamedInterceptorDictionaryIC) {
   3736   v8::HandleScope scope;
   3737   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3738   templ->SetNamedPropertyHandler(XPropertyGetter);
   3739   LocalContext context;
   3740   // Create an object with a named interceptor.
   3741   context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
   3742   Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
   3743   for (int i = 0; i < 10; i++) {
   3744     Local<Value> result = script->Run();
   3745     CHECK_EQ(result, v8_str("x"));
   3746   }
   3747   // Create a slow case object and a function accessing a property in
   3748   // that slow case object (with dictionary probing in generated
   3749   // code). Then force object with a named interceptor into slow-case,
   3750   // pass it to the function, and check that the interceptor is called
   3751   // instead of accessing the local property.
   3752   Local<Value> result =
   3753       CompileRun("function get_x(o) { return o.x; };"
   3754                  "var obj = { x : 42, y : 0 };"
   3755                  "delete obj.y;"
   3756                  "for (var i = 0; i < 10; i++) get_x(obj);"
   3757                  "interceptor_obj.x = 42;"
   3758                  "interceptor_obj.y = 10;"
   3759                  "delete interceptor_obj.y;"
   3760                  "get_x(interceptor_obj)");
   3761   CHECK_EQ(result, v8_str("x"));
   3762 }
   3763 
   3764 
   3765 THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
   3766   v8::HandleScope scope;
   3767 
   3768   v8::Persistent<Context> context1 = Context::New();
   3769 
   3770   context1->Enter();
   3771   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3772   templ->SetNamedPropertyHandler(XPropertyGetter);
   3773   // Create an object with a named interceptor.
   3774   v8::Local<v8::Object> object = templ->NewInstance();
   3775   context1->Global()->Set(v8_str("interceptor_obj"), object);
   3776 
   3777   // Force the object into the slow case.
   3778   CompileRun("interceptor_obj.y = 0;"
   3779              "delete interceptor_obj.y;");
   3780   context1->Exit();
   3781 
   3782   {
   3783     // Introduce the object into a different context.
   3784     // Repeat named loads to exercise ICs.
   3785     LocalContext context2;
   3786     context2->Global()->Set(v8_str("interceptor_obj"), object);
   3787     Local<Value> result =
   3788       CompileRun("function get_x(o) { return o.x; }"
   3789                  "interceptor_obj.x = 42;"
   3790                  "for (var i=0; i != 10; i++) {"
   3791                  "  get_x(interceptor_obj);"
   3792                  "}"
   3793                  "get_x(interceptor_obj)");
   3794     // Check that the interceptor was actually invoked.
   3795     CHECK_EQ(result, v8_str("x"));
   3796   }
   3797 
   3798   // Return to the original context and force some object to the slow case
   3799   // to cause the NormalizedMapCache to verify.
   3800   context1->Enter();
   3801   CompileRun("var obj = { x : 0 }; delete obj.x;");
   3802   context1->Exit();
   3803 
   3804   context1.Dispose();
   3805 }
   3806 
   3807 
   3808 static v8::Handle<Value> SetXOnPrototypeGetter(Local<String> property,
   3809                                                const AccessorInfo& info) {
   3810   // Set x on the prototype object and do not handle the get request.
   3811   v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
   3812   proto.As<v8::Object>()->Set(v8_str("x"), v8::Integer::New(23));
   3813   return v8::Handle<Value>();
   3814 }
   3815 
   3816 
   3817 // This is a regression test for http://crbug.com/20104. Map
   3818 // transitions should not interfere with post interceptor lookup.
   3819 THREADED_TEST(NamedInterceptorMapTransitionRead) {
   3820   v8::HandleScope scope;
   3821   Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
   3822   Local<v8::ObjectTemplate> instance_template
   3823       = function_template->InstanceTemplate();
   3824   instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
   3825   LocalContext context;
   3826   context->Global()->Set(v8_str("F"), function_template->GetFunction());
   3827   // Create an instance of F and introduce a map transition for x.
   3828   CompileRun("var o = new F(); o.x = 23;");
   3829   // Create an instance of F and invoke the getter. The result should be 23.
   3830   Local<Value> result = CompileRun("o = new F(); o.x");
   3831   CHECK_EQ(result->Int32Value(), 23);
   3832 }
   3833 
   3834 
   3835 static v8::Handle<Value> IndexedPropertyGetter(uint32_t index,
   3836                                                const AccessorInfo& info) {
   3837   ApiTestFuzzer::Fuzz();
   3838   if (index == 37) {
   3839     return v8::Handle<Value>(v8_num(625));
   3840   }
   3841   return v8::Handle<Value>();
   3842 }
   3843 
   3844 
   3845 static v8::Handle<Value> IndexedPropertySetter(uint32_t index,
   3846                                                Local<Value> value,
   3847                                                const AccessorInfo& info) {
   3848   ApiTestFuzzer::Fuzz();
   3849   if (index == 39) {
   3850     return value;
   3851   }
   3852   return v8::Handle<Value>();
   3853 }
   3854 
   3855 
   3856 THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
   3857   v8::HandleScope scope;
   3858   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3859   templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
   3860                                    IndexedPropertySetter);
   3861   LocalContext context;
   3862   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3863   Local<Script> getter_script = Script::Compile(v8_str(
   3864       "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
   3865   Local<Script> setter_script = Script::Compile(v8_str(
   3866       "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
   3867       "obj[17] = 23;"
   3868       "obj.foo;"));
   3869   Local<Script> interceptor_setter_script = Script::Compile(v8_str(
   3870       "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
   3871       "obj[39] = 47;"
   3872       "obj.foo;"));  // This setter should not run, due to the interceptor.
   3873   Local<Script> interceptor_getter_script = Script::Compile(v8_str(
   3874       "obj[37];"));
   3875   Local<Value> result = getter_script->Run();
   3876   CHECK_EQ(v8_num(5), result);
   3877   result = setter_script->Run();
   3878   CHECK_EQ(v8_num(23), result);
   3879   result = interceptor_setter_script->Run();
   3880   CHECK_EQ(v8_num(23), result);
   3881   result = interceptor_getter_script->Run();
   3882   CHECK_EQ(v8_num(625), result);
   3883 }
   3884 
   3885 
   3886 static v8::Handle<Value> UnboxedDoubleIndexedPropertyGetter(
   3887     uint32_t index,
   3888     const AccessorInfo& info) {
   3889   ApiTestFuzzer::Fuzz();
   3890   if (index < 25) {
   3891     return v8::Handle<Value>(v8_num(index));
   3892   }
   3893   return v8::Handle<Value>();
   3894 }
   3895 
   3896 
   3897 static v8::Handle<Value> UnboxedDoubleIndexedPropertySetter(
   3898     uint32_t index,
   3899     Local<Value> value,
   3900     const AccessorInfo& info) {
   3901   ApiTestFuzzer::Fuzz();
   3902   if (index < 25) {
   3903     return v8::Handle<Value>(v8_num(index));
   3904   }
   3905   return v8::Handle<Value>();
   3906 }
   3907 
   3908 
   3909 Handle<v8::Array> UnboxedDoubleIndexedPropertyEnumerator(
   3910     const AccessorInfo& info) {
   3911   // Force the list of returned keys to be stored in a FastDoubleArray.
   3912   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
   3913       "keys = new Array(); keys[125000] = 1;"
   3914       "for(i = 0; i < 80000; i++) { keys[i] = i; };"
   3915       "keys.length = 25; keys;"));
   3916   Local<Value> result = indexed_property_names_script->Run();
   3917   return Local<v8::Array>(::v8::Array::Cast(*result));
   3918 }
   3919 
   3920 
   3921 // Make sure that the the interceptor code in the runtime properly handles
   3922 // merging property name lists for double-array-backed arrays.
   3923 THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
   3924   v8::HandleScope scope;
   3925   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3926   templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
   3927                                    UnboxedDoubleIndexedPropertySetter,
   3928                                    0,
   3929                                    0,
   3930                                    UnboxedDoubleIndexedPropertyEnumerator);
   3931   LocalContext context;
   3932   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3933   // When obj is created, force it to be Stored in a FastDoubleArray.
   3934   Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
   3935       "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
   3936       "key_count = 0; "
   3937       "for (x in obj) {key_count++;};"
   3938       "obj;"));
   3939   Local<Value> result = create_unboxed_double_script->Run();
   3940   CHECK(result->ToObject()->HasRealIndexedProperty(2000));
   3941   Local<Script> key_count_check = Script::Compile(v8_str(
   3942       "key_count;"));
   3943   result = key_count_check->Run();
   3944   CHECK_EQ(v8_num(40013), result);
   3945 }
   3946 
   3947 
   3948 Handle<v8::Array> NonStrictArgsIndexedPropertyEnumerator(
   3949     const AccessorInfo& info) {
   3950   // Force the list of returned keys to be stored in a Arguments object.
   3951   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
   3952       "function f(w,x) {"
   3953       " return arguments;"
   3954       "}"
   3955       "keys = f(0, 1, 2, 3);"
   3956       "keys;"));
   3957   Local<Value> result = indexed_property_names_script->Run();
   3958   return Local<v8::Array>(static_cast<v8::Array*>(::v8::Object::Cast(*result)));
   3959 }
   3960 
   3961 
   3962 static v8::Handle<Value> NonStrictIndexedPropertyGetter(
   3963     uint32_t index,
   3964     const AccessorInfo& info) {
   3965   ApiTestFuzzer::Fuzz();
   3966   if (index < 4) {
   3967     return v8::Handle<Value>(v8_num(index));
   3968   }
   3969   return v8::Handle<Value>();
   3970 }
   3971 
   3972 
   3973 // Make sure that the the interceptor code in the runtime properly handles
   3974 // merging property name lists for non-string arguments arrays.
   3975 THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
   3976   v8::HandleScope scope;
   3977   Local<ObjectTemplate> templ = ObjectTemplate::New();
   3978   templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
   3979                                    0,
   3980                                    0,
   3981                                    0,
   3982                                    NonStrictArgsIndexedPropertyEnumerator);
   3983   LocalContext context;
   3984   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   3985   Local<Script> create_args_script =
   3986       Script::Compile(v8_str(
   3987           "var key_count = 0;"
   3988           "for (x in obj) {key_count++;} key_count;"));
   3989   Local<Value> result = create_args_script->Run();
   3990   CHECK_EQ(v8_num(4), result);
   3991 }
   3992 
   3993 
   3994 static v8::Handle<Value> IdentityIndexedPropertyGetter(
   3995     uint32_t index,
   3996     const AccessorInfo& info) {
   3997   return v8::Integer::NewFromUnsigned(index);
   3998 }
   3999 
   4000 
   4001 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
   4002   v8::HandleScope scope;
   4003   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4004   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4005 
   4006   LocalContext context;
   4007   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   4008 
   4009   // Check fast object case.
   4010   const char* fast_case_code =
   4011       "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
   4012   ExpectString(fast_case_code, "0");
   4013 
   4014   // Check slow case.
   4015   const char* slow_case_code =
   4016       "obj.x = 1; delete obj.x;"
   4017       "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
   4018   ExpectString(slow_case_code, "1");
   4019 }
   4020 
   4021 
   4022 THREADED_TEST(IndexedInterceptorWithNoSetter) {
   4023   v8::HandleScope scope;
   4024   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4025   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4026 
   4027   LocalContext context;
   4028   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   4029 
   4030   const char* code =
   4031       "try {"
   4032       "  obj[0] = 239;"
   4033       "  for (var i = 0; i < 100; i++) {"
   4034       "    var v = obj[0];"
   4035       "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4036       "  }"
   4037       "  'PASSED'"
   4038       "} catch(e) {"
   4039       "  e"
   4040       "}";
   4041   ExpectString(code, "PASSED");
   4042 }
   4043 
   4044 
   4045 THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
   4046   v8::HandleScope scope;
   4047   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4048   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4049 
   4050   LocalContext context;
   4051   Local<v8::Object> obj = templ->NewInstance();
   4052   obj->TurnOnAccessCheck();
   4053   context->Global()->Set(v8_str("obj"), obj);
   4054 
   4055   const char* code =
   4056       "try {"
   4057       "  for (var i = 0; i < 100; i++) {"
   4058       "    var v = obj[0];"
   4059       "    if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4060       "  }"
   4061       "  'PASSED'"
   4062       "} catch(e) {"
   4063       "  e"
   4064       "}";
   4065   ExpectString(code, "PASSED");
   4066 }
   4067 
   4068 
   4069 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
   4070   i::FLAG_allow_natives_syntax = true;
   4071   v8::HandleScope scope;
   4072   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4073   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4074 
   4075   LocalContext context;
   4076   Local<v8::Object> obj = templ->NewInstance();
   4077   context->Global()->Set(v8_str("obj"), obj);
   4078 
   4079   const char* code =
   4080       "try {"
   4081       "  for (var i = 0; i < 100; i++) {"
   4082       "    var expected = i;"
   4083       "    if (i == 5) {"
   4084       "      %EnableAccessChecks(obj);"
   4085       "      expected = undefined;"
   4086       "    }"
   4087       "    var v = obj[i];"
   4088       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4089       "    if (i == 5) %DisableAccessChecks(obj);"
   4090       "  }"
   4091       "  'PASSED'"
   4092       "} catch(e) {"
   4093       "  e"
   4094       "}";
   4095   ExpectString(code, "PASSED");
   4096 }
   4097 
   4098 
   4099 THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
   4100   v8::HandleScope scope;
   4101   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4102   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4103 
   4104   LocalContext context;
   4105   Local<v8::Object> obj = templ->NewInstance();
   4106   context->Global()->Set(v8_str("obj"), obj);
   4107 
   4108   const char* code =
   4109       "try {"
   4110       "  for (var i = 0; i < 100; i++) {"
   4111       "    var v = obj[i];"
   4112       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4113       "  }"
   4114       "  'PASSED'"
   4115       "} catch(e) {"
   4116       "  e"
   4117       "}";
   4118   ExpectString(code, "PASSED");
   4119 }
   4120 
   4121 
   4122 THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
   4123   v8::HandleScope scope;
   4124   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4125   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4126 
   4127   LocalContext context;
   4128   Local<v8::Object> obj = templ->NewInstance();
   4129   context->Global()->Set(v8_str("obj"), obj);
   4130 
   4131   const char* code =
   4132       "try {"
   4133       "  for (var i = 0; i < 100; i++) {"
   4134       "    var expected = i;"
   4135       "    var key = i;"
   4136       "    if (i == 25) {"
   4137       "       key = -1;"
   4138       "       expected = undefined;"
   4139       "    }"
   4140       "    if (i == 50) {"
   4141       "       /* probe minimal Smi number on 32-bit platforms */"
   4142       "       key = -(1 << 30);"
   4143       "       expected = undefined;"
   4144       "    }"
   4145       "    if (i == 75) {"
   4146       "       /* probe minimal Smi number on 64-bit platforms */"
   4147       "       key = 1 << 31;"
   4148       "       expected = undefined;"
   4149       "    }"
   4150       "    var v = obj[key];"
   4151       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4152       "  }"
   4153       "  'PASSED'"
   4154       "} catch(e) {"
   4155       "  e"
   4156       "}";
   4157   ExpectString(code, "PASSED");
   4158 }
   4159 
   4160 
   4161 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
   4162   v8::HandleScope scope;
   4163   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4164   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4165 
   4166   LocalContext context;
   4167   Local<v8::Object> obj = templ->NewInstance();
   4168   context->Global()->Set(v8_str("obj"), obj);
   4169 
   4170   const char* code =
   4171       "try {"
   4172       "  for (var i = 0; i < 100; i++) {"
   4173       "    var expected = i;"
   4174       "    var key = i;"
   4175       "    if (i == 50) {"
   4176       "       key = 'foobar';"
   4177       "       expected = undefined;"
   4178       "    }"
   4179       "    var v = obj[key];"
   4180       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4181       "  }"
   4182       "  'PASSED'"
   4183       "} catch(e) {"
   4184       "  e"
   4185       "}";
   4186   ExpectString(code, "PASSED");
   4187 }
   4188 
   4189 
   4190 THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
   4191   v8::HandleScope scope;
   4192   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4193   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4194 
   4195   LocalContext context;
   4196   Local<v8::Object> obj = templ->NewInstance();
   4197   context->Global()->Set(v8_str("obj"), obj);
   4198 
   4199   const char* code =
   4200       "var original = obj;"
   4201       "try {"
   4202       "  for (var i = 0; i < 100; i++) {"
   4203       "    var expected = i;"
   4204       "    if (i == 50) {"
   4205       "       obj = {50: 'foobar'};"
   4206       "       expected = 'foobar';"
   4207       "    }"
   4208       "    var v = obj[i];"
   4209       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4210       "    if (i == 50) obj = original;"
   4211       "  }"
   4212       "  'PASSED'"
   4213       "} catch(e) {"
   4214       "  e"
   4215       "}";
   4216   ExpectString(code, "PASSED");
   4217 }
   4218 
   4219 
   4220 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
   4221   v8::HandleScope scope;
   4222   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4223   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4224 
   4225   LocalContext context;
   4226   Local<v8::Object> obj = templ->NewInstance();
   4227   context->Global()->Set(v8_str("obj"), obj);
   4228 
   4229   const char* code =
   4230       "var original = obj;"
   4231       "try {"
   4232       "  for (var i = 0; i < 100; i++) {"
   4233       "    var expected = i;"
   4234       "    if (i == 5) {"
   4235       "       obj = 239;"
   4236       "       expected = undefined;"
   4237       "    }"
   4238       "    var v = obj[i];"
   4239       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4240       "    if (i == 5) obj = original;"
   4241       "  }"
   4242       "  'PASSED'"
   4243       "} catch(e) {"
   4244       "  e"
   4245       "}";
   4246   ExpectString(code, "PASSED");
   4247 }
   4248 
   4249 
   4250 THREADED_TEST(IndexedInterceptorOnProto) {
   4251   v8::HandleScope scope;
   4252   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4253   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   4254 
   4255   LocalContext context;
   4256   Local<v8::Object> obj = templ->NewInstance();
   4257   context->Global()->Set(v8_str("obj"), obj);
   4258 
   4259   const char* code =
   4260       "var o = {__proto__: obj};"
   4261       "try {"
   4262       "  for (var i = 0; i < 100; i++) {"
   4263       "    var v = o[i];"
   4264       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   4265       "  }"
   4266       "  'PASSED'"
   4267       "} catch(e) {"
   4268       "  e"
   4269       "}";
   4270   ExpectString(code, "PASSED");
   4271 }
   4272 
   4273 
   4274 THREADED_TEST(MultiContexts) {
   4275   v8::HandleScope scope;
   4276   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
   4277   templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
   4278 
   4279   Local<String> password = v8_str("Password");
   4280 
   4281   // Create an environment
   4282   LocalContext context0(0, templ);
   4283   context0->SetSecurityToken(password);
   4284   v8::Handle<v8::Object> global0 = context0->Global();
   4285   global0->Set(v8_str("custom"), v8_num(1234));
   4286   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   4287 
   4288   // Create an independent environment
   4289   LocalContext context1(0, templ);
   4290   context1->SetSecurityToken(password);
   4291   v8::Handle<v8::Object> global1 = context1->Global();
   4292   global1->Set(v8_str("custom"), v8_num(1234));
   4293   CHECK_NE(global0, global1);
   4294   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   4295   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
   4296 
   4297   // Now create a new context with the old global
   4298   LocalContext context2(0, templ, global1);
   4299   context2->SetSecurityToken(password);
   4300   v8::Handle<v8::Object> global2 = context2->Global();
   4301   CHECK_EQ(global1, global2);
   4302   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
   4303   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
   4304 }
   4305 
   4306 
   4307 THREADED_TEST(FunctionPrototypeAcrossContexts) {
   4308   // Make sure that functions created by cloning boilerplates cannot
   4309   // communicate through their __proto__ field.
   4310 
   4311   v8::HandleScope scope;
   4312 
   4313   LocalContext env0;
   4314   v8::Handle<v8::Object> global0 =
   4315       env0->Global();
   4316   v8::Handle<v8::Object> object0 =
   4317       global0->Get(v8_str("Object")).As<v8::Object>();
   4318   v8::Handle<v8::Object> tostring0 =
   4319       object0->Get(v8_str("toString")).As<v8::Object>();
   4320   v8::Handle<v8::Object> proto0 =
   4321       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
   4322   proto0->Set(v8_str("custom"), v8_num(1234));
   4323 
   4324   LocalContext env1;
   4325   v8::Handle<v8::Object> global1 =
   4326       env1->Global();
   4327   v8::Handle<v8::Object> object1 =
   4328       global1->Get(v8_str("Object")).As<v8::Object>();
   4329   v8::Handle<v8::Object> tostring1 =
   4330       object1->Get(v8_str("toString")).As<v8::Object>();
   4331   v8::Handle<v8::Object> proto1 =
   4332       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
   4333   CHECK(!proto1->Has(v8_str("custom")));
   4334 }
   4335 
   4336 
   4337 THREADED_TEST(Regress892105) {
   4338   // Make sure that object and array literals created by cloning
   4339   // boilerplates cannot communicate through their __proto__
   4340   // field. This is rather difficult to check, but we try to add stuff
   4341   // to Object.prototype and Array.prototype and create a new
   4342   // environment. This should succeed.
   4343 
   4344   v8::HandleScope scope;
   4345 
   4346   Local<String> source = v8_str("Object.prototype.obj = 1234;"
   4347                                 "Array.prototype.arr = 4567;"
   4348                                 "8901");
   4349 
   4350   LocalContext env0;
   4351   Local<Script> script0 = Script::Compile(source);
   4352   CHECK_EQ(8901.0, script0->Run()->NumberValue());
   4353 
   4354   LocalContext env1;
   4355   Local<Script> script1 = Script::Compile(source);
   4356   CHECK_EQ(8901.0, script1->Run()->NumberValue());
   4357 }
   4358 
   4359 
   4360 THREADED_TEST(UndetectableObject) {
   4361   v8::HandleScope scope;
   4362   LocalContext env;
   4363 
   4364   Local<v8::FunctionTemplate> desc =
   4365       v8::FunctionTemplate::New(0, v8::Handle<Value>());
   4366   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   4367 
   4368   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   4369   env->Global()->Set(v8_str("undetectable"), obj);
   4370 
   4371   ExpectString("undetectable.toString()", "[object Object]");
   4372   ExpectString("typeof undetectable", "undefined");
   4373   ExpectString("typeof(undetectable)", "undefined");
   4374   ExpectBoolean("typeof undetectable == 'undefined'", true);
   4375   ExpectBoolean("typeof undetectable == 'object'", false);
   4376   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   4377   ExpectBoolean("!undetectable", true);
   4378 
   4379   ExpectObject("true&&undetectable", obj);
   4380   ExpectBoolean("false&&undetectable", false);
   4381   ExpectBoolean("true||undetectable", true);
   4382   ExpectObject("false||undetectable", obj);
   4383 
   4384   ExpectObject("undetectable&&true", obj);
   4385   ExpectObject("undetectable&&false", obj);
   4386   ExpectBoolean("undetectable||true", true);
   4387   ExpectBoolean("undetectable||false", false);
   4388 
   4389   ExpectBoolean("undetectable==null", true);
   4390   ExpectBoolean("null==undetectable", true);
   4391   ExpectBoolean("undetectable==undefined", true);
   4392   ExpectBoolean("undefined==undetectable", true);
   4393   ExpectBoolean("undetectable==undetectable", true);
   4394 
   4395 
   4396   ExpectBoolean("undetectable===null", false);
   4397   ExpectBoolean("null===undetectable", false);
   4398   ExpectBoolean("undetectable===undefined", false);
   4399   ExpectBoolean("undefined===undetectable", false);
   4400   ExpectBoolean("undetectable===undetectable", true);
   4401 }
   4402 
   4403 
   4404 THREADED_TEST(VoidLiteral) {
   4405   v8::HandleScope scope;
   4406   LocalContext env;
   4407 
   4408   Local<v8::FunctionTemplate> desc =
   4409       v8::FunctionTemplate::New(0, v8::Handle<Value>());
   4410   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   4411 
   4412   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   4413   env->Global()->Set(v8_str("undetectable"), obj);
   4414 
   4415   ExpectBoolean("undefined == void 0", true);
   4416   ExpectBoolean("undetectable == void 0", true);
   4417   ExpectBoolean("null == void 0", true);
   4418   ExpectBoolean("undefined === void 0", true);
   4419   ExpectBoolean("undetectable === void 0", false);
   4420   ExpectBoolean("null === void 0", false);
   4421 
   4422   ExpectBoolean("void 0 == undefined", true);
   4423   ExpectBoolean("void 0 == undetectable", true);
   4424   ExpectBoolean("void 0 == null", true);
   4425   ExpectBoolean("void 0 === undefined", true);
   4426   ExpectBoolean("void 0 === undetectable", false);
   4427   ExpectBoolean("void 0 === null", false);
   4428 
   4429   ExpectString("(function() {"
   4430                "  try {"
   4431                "    return x === void 0;"
   4432                "  } catch(e) {"
   4433                "    return e.toString();"
   4434                "  }"
   4435                "})()",
   4436                "ReferenceError: x is not defined");
   4437   ExpectString("(function() {"
   4438                "  try {"
   4439                "    return void 0 === x;"
   4440                "  } catch(e) {"
   4441                "    return e.toString();"
   4442                "  }"
   4443                "})()",
   4444                "ReferenceError: x is not defined");
   4445 }
   4446 
   4447 
   4448 THREADED_TEST(ExtensibleOnUndetectable) {
   4449   v8::HandleScope scope;
   4450   LocalContext env;
   4451 
   4452   Local<v8::FunctionTemplate> desc =
   4453       v8::FunctionTemplate::New(0, v8::Handle<Value>());
   4454   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   4455 
   4456   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   4457   env->Global()->Set(v8_str("undetectable"), obj);
   4458 
   4459   Local<String> source = v8_str("undetectable.x = 42;"
   4460                                 "undetectable.x");
   4461 
   4462   Local<Script> script = Script::Compile(source);
   4463 
   4464   CHECK_EQ(v8::Integer::New(42), script->Run());
   4465 
   4466   ExpectBoolean("Object.isExtensible(undetectable)", true);
   4467 
   4468   source = v8_str("Object.preventExtensions(undetectable);");
   4469   script = Script::Compile(source);
   4470   script->Run();
   4471   ExpectBoolean("Object.isExtensible(undetectable)", false);
   4472 
   4473   source = v8_str("undetectable.y = 2000;");
   4474   script = Script::Compile(source);
   4475   script->Run();
   4476   ExpectBoolean("undetectable.y == undefined", true);
   4477 }
   4478 
   4479 
   4480 
   4481 THREADED_TEST(UndetectableString) {
   4482   v8::HandleScope scope;
   4483   LocalContext env;
   4484 
   4485   Local<String> obj = String::NewUndetectable("foo");
   4486   env->Global()->Set(v8_str("undetectable"), obj);
   4487 
   4488   ExpectString("undetectable", "foo");
   4489   ExpectString("typeof undetectable", "undefined");
   4490   ExpectString("typeof(undetectable)", "undefined");
   4491   ExpectBoolean("typeof undetectable == 'undefined'", true);
   4492   ExpectBoolean("typeof undetectable == 'string'", false);
   4493   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   4494   ExpectBoolean("!undetectable", true);
   4495 
   4496   ExpectObject("true&&undetectable", obj);
   4497   ExpectBoolean("false&&undetectable", false);
   4498   ExpectBoolean("true||undetectable", true);
   4499   ExpectObject("false||undetectable", obj);
   4500 
   4501   ExpectObject("undetectable&&true", obj);
   4502   ExpectObject("undetectable&&false", obj);
   4503   ExpectBoolean("undetectable||true", true);
   4504   ExpectBoolean("undetectable||false", false);
   4505 
   4506   ExpectBoolean("undetectable==null", true);
   4507   ExpectBoolean("null==undetectable", true);
   4508   ExpectBoolean("undetectable==undefined", true);
   4509   ExpectBoolean("undefined==undetectable", true);
   4510   ExpectBoolean("undetectable==undetectable", true);
   4511 
   4512 
   4513   ExpectBoolean("undetectable===null", false);
   4514   ExpectBoolean("null===undetectable", false);
   4515   ExpectBoolean("undetectable===undefined", false);
   4516   ExpectBoolean("undefined===undetectable", false);
   4517   ExpectBoolean("undetectable===undetectable", true);
   4518 }
   4519 
   4520 
   4521 TEST(UndetectableOptimized) {
   4522   i::FLAG_allow_natives_syntax = true;
   4523   v8::HandleScope scope;
   4524   LocalContext env;
   4525 
   4526   Local<String> obj = String::NewUndetectable("foo");
   4527   env->Global()->Set(v8_str("undetectable"), obj);
   4528   env->Global()->Set(v8_str("detectable"), v8_str("bar"));
   4529 
   4530   ExpectString(
   4531       "function testBranch() {"
   4532       "  if (!%_IsUndetectableObject(undetectable)) throw 1;"
   4533       "  if (%_IsUndetectableObject(detectable)) throw 2;"
   4534       "}\n"
   4535       "function testBool() {"
   4536       "  var b1 = !%_IsUndetectableObject(undetectable);"
   4537       "  var b2 = %_IsUndetectableObject(detectable);"
   4538       "  if (b1) throw 3;"
   4539       "  if (b2) throw 4;"
   4540       "  return b1 == b2;"
   4541       "}\n"
   4542       "%OptimizeFunctionOnNextCall(testBranch);"
   4543       "%OptimizeFunctionOnNextCall(testBool);"
   4544       "for (var i = 0; i < 10; i++) {"
   4545       "  testBranch();"
   4546       "  testBool();"
   4547       "}\n"
   4548       "\"PASS\"",
   4549       "PASS");
   4550 }
   4551 
   4552 
   4553 template <typename T> static void USE(T) { }
   4554 
   4555 
   4556 // This test is not intended to be run, just type checked.
   4557 static inline void PersistentHandles() {
   4558   USE(PersistentHandles);
   4559   Local<String> str = v8_str("foo");
   4560   v8::Persistent<String> p_str = v8::Persistent<String>::New(str);
   4561   USE(p_str);
   4562   Local<Script> scr = Script::Compile(v8_str(""));
   4563   v8::Persistent<Script> p_scr = v8::Persistent<Script>::New(scr);
   4564   USE(p_scr);
   4565   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4566   v8::Persistent<ObjectTemplate> p_templ =
   4567     v8::Persistent<ObjectTemplate>::New(templ);
   4568   USE(p_templ);
   4569 }
   4570 
   4571 
   4572 static v8::Handle<Value> HandleLogDelegator(const v8::Arguments& args) {
   4573   ApiTestFuzzer::Fuzz();
   4574   return v8::Undefined();
   4575 }
   4576 
   4577 
   4578 THREADED_TEST(GlobalObjectTemplate) {
   4579   v8::HandleScope handle_scope;
   4580   Local<ObjectTemplate> global_template = ObjectTemplate::New();
   4581   global_template->Set(v8_str("JSNI_Log"),
   4582                        v8::FunctionTemplate::New(HandleLogDelegator));
   4583   v8::Persistent<Context> context = Context::New(0, global_template);
   4584   Context::Scope context_scope(context);
   4585   Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
   4586   context.Dispose();
   4587 }
   4588 
   4589 
   4590 static const char* kSimpleExtensionSource =
   4591   "function Foo() {"
   4592   "  return 4;"
   4593   "}";
   4594 
   4595 
   4596 THREADED_TEST(SimpleExtensions) {
   4597   v8::HandleScope handle_scope;
   4598   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
   4599   const char* extension_names[] = { "simpletest" };
   4600   v8::ExtensionConfiguration extensions(1, extension_names);
   4601   v8::Handle<Context> context = Context::New(&extensions);
   4602   Context::Scope lock(context);
   4603   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
   4604   CHECK_EQ(result, v8::Integer::New(4));
   4605 }
   4606 
   4607 
   4608 static const char* kEmbeddedExtensionSource =
   4609     "function Ret54321(){return 54321;}~~@@$"
   4610     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
   4611 static const int kEmbeddedExtensionSourceValidLen = 34;
   4612 
   4613 
   4614 THREADED_TEST(ExtensionMissingSourceLength) {
   4615   v8::HandleScope handle_scope;
   4616   v8::RegisterExtension(new Extension("srclentest_fail",
   4617                                       kEmbeddedExtensionSource));
   4618   const char* extension_names[] = { "srclentest_fail" };
   4619   v8::ExtensionConfiguration extensions(1, extension_names);
   4620   v8::Handle<Context> context = Context::New(&extensions);
   4621   CHECK_EQ(0, *context);
   4622 }
   4623 
   4624 
   4625 THREADED_TEST(ExtensionWithSourceLength) {
   4626   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
   4627        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
   4628     v8::HandleScope handle_scope;
   4629     i::ScopedVector<char> extension_name(32);
   4630     i::OS::SNPrintF(extension_name, "ext #%d", source_len);
   4631     v8::RegisterExtension(new Extension(extension_name.start(),
   4632                                         kEmbeddedExtensionSource, 0, 0,
   4633                                         source_len));
   4634     const char* extension_names[1] = { extension_name.start() };
   4635     v8::ExtensionConfiguration extensions(1, extension_names);
   4636     v8::Handle<Context> context = Context::New(&extensions);
   4637     if (source_len == kEmbeddedExtensionSourceValidLen) {
   4638       Context::Scope lock(context);
   4639       v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
   4640       CHECK_EQ(v8::Integer::New(54321), result);
   4641     } else {
   4642       // Anything but exactly the right length should fail to compile.
   4643       CHECK_EQ(0, *context);
   4644     }
   4645   }
   4646 }
   4647 
   4648 
   4649 static const char* kEvalExtensionSource1 =
   4650   "function UseEval1() {"
   4651   "  var x = 42;"
   4652   "  return eval('x');"
   4653   "}";
   4654 
   4655 
   4656 static const char* kEvalExtensionSource2 =
   4657   "(function() {"
   4658   "  var x = 42;"
   4659   "  function e() {"
   4660   "    return eval('x');"
   4661   "  }"
   4662   "  this.UseEval2 = e;"
   4663   "})()";
   4664 
   4665 
   4666 THREADED_TEST(UseEvalFromExtension) {
   4667   v8::HandleScope handle_scope;
   4668   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
   4669   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
   4670   const char* extension_names[] = { "evaltest1", "evaltest2" };
   4671   v8::ExtensionConfiguration extensions(2, extension_names);
   4672   v8::Handle<Context> context = Context::New(&extensions);
   4673   Context::Scope lock(context);
   4674   v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
   4675   CHECK_EQ(result, v8::Integer::New(42));
   4676   result = Script::Compile(v8_str("UseEval2()"))->Run();
   4677   CHECK_EQ(result, v8::Integer::New(42));
   4678 }
   4679 
   4680 
   4681 static const char* kWithExtensionSource1 =
   4682   "function UseWith1() {"
   4683   "  var x = 42;"
   4684   "  with({x:87}) { return x; }"
   4685   "}";
   4686 
   4687 
   4688 
   4689 static const char* kWithExtensionSource2 =
   4690   "(function() {"
   4691   "  var x = 42;"
   4692   "  function e() {"
   4693   "    with ({x:87}) { return x; }"
   4694   "  }"
   4695   "  this.UseWith2 = e;"
   4696   "})()";
   4697 
   4698 
   4699 THREADED_TEST(UseWithFromExtension) {
   4700   v8::HandleScope handle_scope;
   4701   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
   4702   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
   4703   const char* extension_names[] = { "withtest1", "withtest2" };
   4704   v8::ExtensionConfiguration extensions(2, extension_names);
   4705   v8::Handle<Context> context = Context::New(&extensions);
   4706   Context::Scope lock(context);
   4707   v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
   4708   CHECK_EQ(result, v8::Integer::New(87));
   4709   result = Script::Compile(v8_str("UseWith2()"))->Run();
   4710   CHECK_EQ(result, v8::Integer::New(87));
   4711 }
   4712 
   4713 
   4714 THREADED_TEST(AutoExtensions) {
   4715   v8::HandleScope handle_scope;
   4716   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
   4717   extension->set_auto_enable(true);
   4718   v8::RegisterExtension(extension);
   4719   v8::Handle<Context> context = Context::New();
   4720   Context::Scope lock(context);
   4721   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
   4722   CHECK_EQ(result, v8::Integer::New(4));
   4723 }
   4724 
   4725 
   4726 static const char* kSyntaxErrorInExtensionSource =
   4727     "[";
   4728 
   4729 
   4730 // Test that a syntax error in an extension does not cause a fatal
   4731 // error but results in an empty context.
   4732 THREADED_TEST(SyntaxErrorExtensions) {
   4733   v8::HandleScope handle_scope;
   4734   v8::RegisterExtension(new Extension("syntaxerror",
   4735                                       kSyntaxErrorInExtensionSource));
   4736   const char* extension_names[] = { "syntaxerror" };
   4737   v8::ExtensionConfiguration extensions(1, extension_names);
   4738   v8::Handle<Context> context = Context::New(&extensions);
   4739   CHECK(context.IsEmpty());
   4740 }
   4741 
   4742 
   4743 static const char* kExceptionInExtensionSource =
   4744     "throw 42";
   4745 
   4746 
   4747 // Test that an exception when installing an extension does not cause
   4748 // a fatal error but results in an empty context.
   4749 THREADED_TEST(ExceptionExtensions) {
   4750   v8::HandleScope handle_scope;
   4751   v8::RegisterExtension(new Extension("exception",
   4752                                       kExceptionInExtensionSource));
   4753   const char* extension_names[] = { "exception" };
   4754   v8::ExtensionConfiguration extensions(1, extension_names);
   4755   v8::Handle<Context> context = Context::New(&extensions);
   4756   CHECK(context.IsEmpty());
   4757 }
   4758 
   4759 
   4760 static const char* kNativeCallInExtensionSource =
   4761     "function call_runtime_last_index_of(x) {"
   4762     "  return %StringLastIndexOf(x, 'bob', 10);"
   4763     "}";
   4764 
   4765 
   4766 static const char* kNativeCallTest =
   4767     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
   4768 
   4769 // Test that a native runtime calls are supported in extensions.
   4770 THREADED_TEST(NativeCallInExtensions) {
   4771   v8::HandleScope handle_scope;
   4772   v8::RegisterExtension(new Extension("nativecall",
   4773                                       kNativeCallInExtensionSource));
   4774   const char* extension_names[] = { "nativecall" };
   4775   v8::ExtensionConfiguration extensions(1, extension_names);
   4776   v8::Handle<Context> context = Context::New(&extensions);
   4777   Context::Scope lock(context);
   4778   v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
   4779   CHECK_EQ(result, v8::Integer::New(3));
   4780 }
   4781 
   4782 
   4783 class NativeFunctionExtension : public Extension {
   4784  public:
   4785   NativeFunctionExtension(const char* name,
   4786                           const char* source,
   4787                           v8::InvocationCallback fun = &Echo)
   4788       : Extension(name, source),
   4789         function_(fun) { }
   4790 
   4791   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
   4792       v8::Handle<v8::String> name) {
   4793     return v8::FunctionTemplate::New(function_);
   4794   }
   4795 
   4796   static v8::Handle<v8::Value> Echo(const v8::Arguments& args) {
   4797     if (args.Length() >= 1) return (args[0]);
   4798     return v8::Undefined();
   4799   }
   4800  private:
   4801   v8::InvocationCallback function_;
   4802 };
   4803 
   4804 
   4805 THREADED_TEST(NativeFunctionDeclaration) {
   4806   v8::HandleScope handle_scope;
   4807   const char* name = "nativedecl";
   4808   v8::RegisterExtension(new NativeFunctionExtension(name,
   4809                                                     "native function foo();"));
   4810   const char* extension_names[] = { name };
   4811   v8::ExtensionConfiguration extensions(1, extension_names);
   4812   v8::Handle<Context> context = Context::New(&extensions);
   4813   Context::Scope lock(context);
   4814   v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
   4815   CHECK_EQ(result, v8::Integer::New(42));
   4816 }
   4817 
   4818 
   4819 THREADED_TEST(NativeFunctionDeclarationError) {
   4820   v8::HandleScope handle_scope;
   4821   const char* name = "nativedeclerr";
   4822   // Syntax error in extension code.
   4823   v8::RegisterExtension(new NativeFunctionExtension(name,
   4824                                                     "native\nfunction foo();"));
   4825   const char* extension_names[] = { name };
   4826   v8::ExtensionConfiguration extensions(1, extension_names);
   4827   v8::Handle<Context> context(Context::New(&extensions));
   4828   CHECK(context.IsEmpty());
   4829 }
   4830 
   4831 
   4832 THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
   4833   v8::HandleScope handle_scope;
   4834   const char* name = "nativedeclerresc";
   4835   // Syntax error in extension code - escape code in "native" means that
   4836   // it's not treated as a keyword.
   4837   v8::RegisterExtension(new NativeFunctionExtension(
   4838       name,
   4839       "nativ\\u0065 function foo();"));
   4840   const char* extension_names[] = { name };
   4841   v8::ExtensionConfiguration extensions(1, extension_names);
   4842   v8::Handle<Context> context(Context::New(&extensions));
   4843   CHECK(context.IsEmpty());
   4844 }
   4845 
   4846 
   4847 static void CheckDependencies(const char* name, const char* expected) {
   4848   v8::HandleScope handle_scope;
   4849   v8::ExtensionConfiguration config(1, &name);
   4850   LocalContext context(&config);
   4851   CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
   4852 }
   4853 
   4854 
   4855 /*
   4856  * Configuration:
   4857  *
   4858  *     /-- B <--\
   4859  * A <-          -- D <-- E
   4860  *     \-- C <--/
   4861  */
   4862 THREADED_TEST(ExtensionDependency) {
   4863   static const char* kEDeps[] = { "D" };
   4864   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
   4865   static const char* kDDeps[] = { "B", "C" };
   4866   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
   4867   static const char* kBCDeps[] = { "A" };
   4868   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
   4869   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
   4870   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
   4871   CheckDependencies("A", "undefinedA");
   4872   CheckDependencies("B", "undefinedAB");
   4873   CheckDependencies("C", "undefinedAC");
   4874   CheckDependencies("D", "undefinedABCD");
   4875   CheckDependencies("E", "undefinedABCDE");
   4876   v8::HandleScope handle_scope;
   4877   static const char* exts[2] = { "C", "E" };
   4878   v8::ExtensionConfiguration config(2, exts);
   4879   LocalContext context(&config);
   4880   CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
   4881 }
   4882 
   4883 
   4884 static const char* kExtensionTestScript =
   4885   "native function A();"
   4886   "native function B();"
   4887   "native function C();"
   4888   "function Foo(i) {"
   4889   "  if (i == 0) return A();"
   4890   "  if (i == 1) return B();"
   4891   "  if (i == 2) return C();"
   4892   "}";
   4893 
   4894 
   4895 static v8::Handle<Value> CallFun(const v8::Arguments& args) {
   4896   ApiTestFuzzer::Fuzz();
   4897   if (args.IsConstructCall()) {
   4898     args.This()->Set(v8_str("data"), args.Data());
   4899     return v8::Null();
   4900   }
   4901   return args.Data();
   4902 }
   4903 
   4904 
   4905 class FunctionExtension : public Extension {
   4906  public:
   4907   FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
   4908   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
   4909       v8::Handle<String> name);
   4910 };
   4911 
   4912 
   4913 static int lookup_count = 0;
   4914 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
   4915       v8::Handle<String> name) {
   4916   lookup_count++;
   4917   if (name->Equals(v8_str("A"))) {
   4918     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
   4919   } else if (name->Equals(v8_str("B"))) {
   4920     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
   4921   } else if (name->Equals(v8_str("C"))) {
   4922     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
   4923   } else {
   4924     return v8::Handle<v8::FunctionTemplate>();
   4925   }
   4926 }
   4927 
   4928 
   4929 THREADED_TEST(FunctionLookup) {
   4930   v8::RegisterExtension(new FunctionExtension());
   4931   v8::HandleScope handle_scope;
   4932   static const char* exts[1] = { "functiontest" };
   4933   v8::ExtensionConfiguration config(1, exts);
   4934   LocalContext context(&config);
   4935   CHECK_EQ(3, lookup_count);
   4936   CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
   4937   CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
   4938   CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
   4939 }
   4940 
   4941 
   4942 THREADED_TEST(NativeFunctionConstructCall) {
   4943   v8::RegisterExtension(new FunctionExtension());
   4944   v8::HandleScope handle_scope;
   4945   static const char* exts[1] = { "functiontest" };
   4946   v8::ExtensionConfiguration config(1, exts);
   4947   LocalContext context(&config);
   4948   for (int i = 0; i < 10; i++) {
   4949     // Run a few times to ensure that allocation of objects doesn't
   4950     // change behavior of a constructor function.
   4951     CHECK_EQ(v8::Integer::New(8),
   4952              Script::Compile(v8_str("(new A()).data"))->Run());
   4953     CHECK_EQ(v8::Integer::New(7),
   4954              Script::Compile(v8_str("(new B()).data"))->Run());
   4955     CHECK_EQ(v8::Integer::New(6),
   4956              Script::Compile(v8_str("(new C()).data"))->Run());
   4957   }
   4958 }
   4959 
   4960 
   4961 static const char* last_location;
   4962 static const char* last_message;
   4963 void StoringErrorCallback(const char* location, const char* message) {
   4964   if (last_location == NULL) {
   4965     last_location = location;
   4966     last_message = message;
   4967   }
   4968 }
   4969 
   4970 
   4971 // ErrorReporting creates a circular extensions configuration and
   4972 // tests that the fatal error handler gets called.  This renders V8
   4973 // unusable and therefore this test cannot be run in parallel.
   4974 TEST(ErrorReporting) {
   4975   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   4976   static const char* aDeps[] = { "B" };
   4977   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
   4978   static const char* bDeps[] = { "A" };
   4979   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
   4980   last_location = NULL;
   4981   v8::ExtensionConfiguration config(1, bDeps);
   4982   v8::Handle<Context> context = Context::New(&config);
   4983   CHECK(context.IsEmpty());
   4984   CHECK_NE(last_location, NULL);
   4985 }
   4986 
   4987 
   4988 static const char* js_code_causing_huge_string_flattening =
   4989     "var str = 'X';"
   4990     "for (var i = 0; i < 30; i++) {"
   4991     "  str = str + str;"
   4992     "}"
   4993     "str.match(/X/);";
   4994 
   4995 
   4996 void OOMCallback(const char* location, const char* message) {
   4997   exit(0);
   4998 }
   4999 
   5000 
   5001 TEST(RegexpOutOfMemory) {
   5002   // Execute a script that causes out of memory when flattening a string.
   5003   v8::HandleScope scope;
   5004   v8::V8::SetFatalErrorHandler(OOMCallback);
   5005   LocalContext context;
   5006   Local<Script> script =
   5007       Script::Compile(String::New(js_code_causing_huge_string_flattening));
   5008   last_location = NULL;
   5009   script->Run();
   5010 
   5011   CHECK(false);  // Should not return.
   5012 }
   5013 
   5014 
   5015 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
   5016                                              v8::Handle<Value> data) {
   5017   CHECK_EQ(v8::Undefined(), data);
   5018   CHECK(message->GetScriptResourceName()->IsUndefined());
   5019   CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
   5020   message->GetLineNumber();
   5021   message->GetSourceLine();
   5022 }
   5023 
   5024 
   5025 THREADED_TEST(ErrorWithMissingScriptInfo) {
   5026   v8::HandleScope scope;
   5027   LocalContext context;
   5028   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
   5029   Script::Compile(v8_str("throw Error()"))->Run();
   5030   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
   5031 }
   5032 
   5033 
   5034 int global_index = 0;
   5035 
   5036 class Snorkel {
   5037  public:
   5038   Snorkel() { index_ = global_index++; }
   5039   int index_;
   5040 };
   5041 
   5042 class Whammy {
   5043  public:
   5044   Whammy() {
   5045     cursor_ = 0;
   5046   }
   5047   ~Whammy() {
   5048     script_.Dispose();
   5049   }
   5050   v8::Handle<Script> getScript() {
   5051     if (script_.IsEmpty())
   5052       script_ = v8::Persistent<Script>::New(v8_compile("({}).blammo"));
   5053     return Local<Script>(*script_);
   5054   }
   5055 
   5056  public:
   5057   static const int kObjectCount = 256;
   5058   int cursor_;
   5059   v8::Persistent<v8::Object> objects_[kObjectCount];
   5060   v8::Persistent<Script> script_;
   5061 };
   5062 
   5063 static void HandleWeakReference(v8::Persistent<v8::Value> obj, void* data) {
   5064   Snorkel* snorkel = reinterpret_cast<Snorkel*>(data);
   5065   delete snorkel;
   5066   obj.ClearWeak();
   5067 }
   5068 
   5069 v8::Handle<Value> WhammyPropertyGetter(Local<String> name,
   5070                                        const AccessorInfo& info) {
   5071   Whammy* whammy =
   5072     static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
   5073 
   5074   v8::Persistent<v8::Object> prev = whammy->objects_[whammy->cursor_];
   5075 
   5076   v8::Handle<v8::Object> obj = v8::Object::New();
   5077   v8::Persistent<v8::Object> global = v8::Persistent<v8::Object>::New(obj);
   5078   if (!prev.IsEmpty()) {
   5079     prev->Set(v8_str("next"), obj);
   5080     prev.MakeWeak(new Snorkel(), &HandleWeakReference);
   5081     whammy->objects_[whammy->cursor_].Clear();
   5082   }
   5083   whammy->objects_[whammy->cursor_] = global;
   5084   whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
   5085   return whammy->getScript()->Run();
   5086 }
   5087 
   5088 THREADED_TEST(WeakReference) {
   5089   v8::HandleScope handle_scope;
   5090   v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
   5091   Whammy* whammy = new Whammy();
   5092   templ->SetNamedPropertyHandler(WhammyPropertyGetter,
   5093                                  0, 0, 0, 0,
   5094                                  v8::External::New(whammy));
   5095   const char* extension_list[] = { "v8/gc" };
   5096   v8::ExtensionConfiguration extensions(1, extension_list);
   5097   v8::Persistent<Context> context = Context::New(&extensions);
   5098   Context::Scope context_scope(context);
   5099 
   5100   v8::Handle<v8::Object> interceptor = templ->NewInstance();
   5101   context->Global()->Set(v8_str("whammy"), interceptor);
   5102   const char* code =
   5103       "var last;"
   5104       "for (var i = 0; i < 10000; i++) {"
   5105       "  var obj = whammy.length;"
   5106       "  if (last) last.next = obj;"
   5107       "  last = obj;"
   5108       "}"
   5109       "gc();"
   5110       "4";
   5111   v8::Handle<Value> result = CompileRun(code);
   5112   CHECK_EQ(4.0, result->NumberValue());
   5113   delete whammy;
   5114   context.Dispose();
   5115 }
   5116 
   5117 
   5118 static void DisposeAndSetFlag(v8::Persistent<v8::Value> obj, void* data) {
   5119   obj.Dispose();
   5120   obj.Clear();
   5121   *(reinterpret_cast<bool*>(data)) = true;
   5122 }
   5123 
   5124 
   5125 THREADED_TEST(IndependentWeakHandle) {
   5126   v8::Persistent<Context> context = Context::New();
   5127   Context::Scope context_scope(context);
   5128 
   5129   v8::Persistent<v8::Object> object_a;
   5130 
   5131   {
   5132     v8::HandleScope handle_scope;
   5133     object_a = v8::Persistent<v8::Object>::New(v8::Object::New());
   5134   }
   5135 
   5136   bool object_a_disposed = false;
   5137   object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag);
   5138   object_a.MarkIndependent();
   5139   HEAP->PerformScavenge();
   5140   CHECK(object_a_disposed);
   5141 }
   5142 
   5143 
   5144 static void InvokeScavenge() {
   5145   HEAP->PerformScavenge();
   5146 }
   5147 
   5148 
   5149 static void InvokeMarkSweep() {
   5150   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   5151 }
   5152 
   5153 
   5154 static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) {
   5155   obj.Dispose();
   5156   obj.Clear();
   5157   *(reinterpret_cast<bool*>(data)) = true;
   5158   InvokeScavenge();
   5159 }
   5160 
   5161 
   5162 static void ForceMarkSweep(v8::Persistent<v8::Value> obj, void* data) {
   5163   obj.Dispose();
   5164   obj.Clear();
   5165   *(reinterpret_cast<bool*>(data)) = true;
   5166   InvokeMarkSweep();
   5167 }
   5168 
   5169 
   5170 THREADED_TEST(GCFromWeakCallbacks) {
   5171   v8::Persistent<Context> context = Context::New();
   5172   Context::Scope context_scope(context);
   5173 
   5174   static const int kNumberOfGCTypes = 2;
   5175   v8::WeakReferenceCallback gc_forcing_callback[kNumberOfGCTypes] =
   5176       {&ForceScavenge, &ForceMarkSweep};
   5177 
   5178   typedef void (*GCInvoker)();
   5179   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
   5180 
   5181   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
   5182     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
   5183       v8::Persistent<v8::Object> object;
   5184       {
   5185         v8::HandleScope handle_scope;
   5186         object = v8::Persistent<v8::Object>::New(v8::Object::New());
   5187       }
   5188       bool disposed = false;
   5189       object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]);
   5190       object.MarkIndependent();
   5191       invoke_gc[outer_gc]();
   5192       CHECK(disposed);
   5193     }
   5194   }
   5195 }
   5196 
   5197 
   5198 static void RevivingCallback(v8::Persistent<v8::Value> obj, void* data) {
   5199   obj.ClearWeak();
   5200   *(reinterpret_cast<bool*>(data)) = true;
   5201 }
   5202 
   5203 
   5204 THREADED_TEST(IndependentHandleRevival) {
   5205   v8::Persistent<Context> context = Context::New();
   5206   Context::Scope context_scope(context);
   5207 
   5208   v8::Persistent<v8::Object> object;
   5209   {
   5210     v8::HandleScope handle_scope;
   5211     object = v8::Persistent<v8::Object>::New(v8::Object::New());
   5212     object->Set(v8_str("x"), v8::Integer::New(1));
   5213     v8::Local<String> y_str = v8_str("y");
   5214     object->Set(y_str, y_str);
   5215   }
   5216   bool revived = false;
   5217   object.MakeWeak(&revived, &RevivingCallback);
   5218   object.MarkIndependent();
   5219   HEAP->PerformScavenge();
   5220   CHECK(revived);
   5221   HEAP->CollectAllGarbage(true);
   5222   {
   5223     v8::HandleScope handle_scope;
   5224     v8::Local<String> y_str = v8_str("y");
   5225     CHECK_EQ(v8::Integer::New(1), object->Get(v8_str("x")));
   5226     CHECK(object->Get(y_str)->Equals(y_str));
   5227   }
   5228 }
   5229 
   5230 
   5231 v8::Handle<Function> args_fun;
   5232 
   5233 
   5234 static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) {
   5235   ApiTestFuzzer::Fuzz();
   5236   CHECK_EQ(args_fun, args.Callee());
   5237   CHECK_EQ(3, args.Length());
   5238   CHECK_EQ(v8::Integer::New(1), args[0]);
   5239   CHECK_EQ(v8::Integer::New(2), args[1]);
   5240   CHECK_EQ(v8::Integer::New(3), args[2]);
   5241   CHECK_EQ(v8::Undefined(), args[3]);
   5242   v8::HandleScope scope;
   5243   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   5244   return v8::Undefined();
   5245 }
   5246 
   5247 
   5248 THREADED_TEST(Arguments) {
   5249   v8::HandleScope scope;
   5250   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
   5251   global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
   5252   LocalContext context(NULL, global);
   5253   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
   5254   v8_compile("f(1, 2, 3)")->Run();
   5255 }
   5256 
   5257 
   5258 static v8::Handle<Value> NoBlockGetterX(Local<String> name,
   5259                                         const AccessorInfo&) {
   5260   return v8::Handle<Value>();
   5261 }
   5262 
   5263 
   5264 static v8::Handle<Value> NoBlockGetterI(uint32_t index,
   5265                                         const AccessorInfo&) {
   5266   return v8::Handle<Value>();
   5267 }
   5268 
   5269 
   5270 static v8::Handle<v8::Boolean> PDeleter(Local<String> name,
   5271                                         const AccessorInfo&) {
   5272   if (!name->Equals(v8_str("foo"))) {
   5273     return v8::Handle<v8::Boolean>();  // not intercepted
   5274   }
   5275 
   5276   return v8::False();  // intercepted, and don't delete the property
   5277 }
   5278 
   5279 
   5280 static v8::Handle<v8::Boolean> IDeleter(uint32_t index, const AccessorInfo&) {
   5281   if (index != 2) {
   5282     return v8::Handle<v8::Boolean>();  // not intercepted
   5283   }
   5284 
   5285   return v8::False();  // intercepted, and don't delete the property
   5286 }
   5287 
   5288 
   5289 THREADED_TEST(Deleter) {
   5290   v8::HandleScope scope;
   5291   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   5292   obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
   5293   obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
   5294   LocalContext context;
   5295   context->Global()->Set(v8_str("k"), obj->NewInstance());
   5296   CompileRun(
   5297     "k.foo = 'foo';"
   5298     "k.bar = 'bar';"
   5299     "k[2] = 2;"
   5300     "k[4] = 4;");
   5301   CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
   5302   CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
   5303 
   5304   CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
   5305   CHECK(v8_compile("k.bar")->Run()->IsUndefined());
   5306 
   5307   CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
   5308   CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
   5309 
   5310   CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
   5311   CHECK(v8_compile("k[4]")->Run()->IsUndefined());
   5312 }
   5313 
   5314 
   5315 static v8::Handle<Value> GetK(Local<String> name, const AccessorInfo&) {
   5316   ApiTestFuzzer::Fuzz();
   5317   if (name->Equals(v8_str("foo")) ||
   5318       name->Equals(v8_str("bar")) ||
   5319       name->Equals(v8_str("baz"))) {
   5320     return v8::Undefined();
   5321   }
   5322   return v8::Handle<Value>();
   5323 }
   5324 
   5325 
   5326 static v8::Handle<Value> IndexedGetK(uint32_t index, const AccessorInfo&) {
   5327   ApiTestFuzzer::Fuzz();
   5328   if (index == 0 || index == 1) return v8::Undefined();
   5329   return v8::Handle<Value>();
   5330 }
   5331 
   5332 
   5333 static v8::Handle<v8::Array> NamedEnum(const AccessorInfo&) {
   5334   ApiTestFuzzer::Fuzz();
   5335   v8::Handle<v8::Array> result = v8::Array::New(3);
   5336   result->Set(v8::Integer::New(0), v8_str("foo"));
   5337   result->Set(v8::Integer::New(1), v8_str("bar"));
   5338   result->Set(v8::Integer::New(2), v8_str("baz"));
   5339   return result;
   5340 }
   5341 
   5342 
   5343 static v8::Handle<v8::Array> IndexedEnum(const AccessorInfo&) {
   5344   ApiTestFuzzer::Fuzz();
   5345   v8::Handle<v8::Array> result = v8::Array::New(2);
   5346   result->Set(v8::Integer::New(0), v8_str("0"));
   5347   result->Set(v8::Integer::New(1), v8_str("1"));
   5348   return result;
   5349 }
   5350 
   5351 
   5352 THREADED_TEST(Enumerators) {
   5353   v8::HandleScope scope;
   5354   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   5355   obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
   5356   obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
   5357   LocalContext context;
   5358   context->Global()->Set(v8_str("k"), obj->NewInstance());
   5359   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   5360     "k[10] = 0;"
   5361     "k.a = 0;"
   5362     "k[5] = 0;"
   5363     "k.b = 0;"
   5364     "k[4294967295] = 0;"
   5365     "k.c = 0;"
   5366     "k[4294967296] = 0;"
   5367     "k.d = 0;"
   5368     "k[140000] = 0;"
   5369     "k.e = 0;"
   5370     "k[30000000000] = 0;"
   5371     "k.f = 0;"
   5372     "var result = [];"
   5373     "for (var prop in k) {"
   5374     "  result.push(prop);"
   5375     "}"
   5376     "result"));
   5377   // Check that we get all the property names returned including the
   5378   // ones from the enumerators in the right order: indexed properties
   5379   // in numerical order, indexed interceptor properties, named
   5380   // properties in insertion order, named interceptor properties.
   5381   // This order is not mandated by the spec, so this test is just
   5382   // documenting our behavior.
   5383   CHECK_EQ(17, result->Length());
   5384   // Indexed properties in numerical order.
   5385   CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
   5386   CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
   5387   CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
   5388   CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
   5389   // Indexed interceptor properties in the order they are returned
   5390   // from the enumerator interceptor.
   5391   CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
   5392   CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
   5393   // Named properties in insertion order.
   5394   CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
   5395   CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
   5396   CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
   5397   CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
   5398   CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
   5399   CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
   5400   CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
   5401   CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
   5402   // Named interceptor properties.
   5403   CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
   5404   CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
   5405   CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
   5406 }
   5407 
   5408 
   5409 int p_getter_count;
   5410 int p_getter_count2;
   5411 
   5412 
   5413 static v8::Handle<Value> PGetter(Local<String> name, const AccessorInfo& info) {
   5414   ApiTestFuzzer::Fuzz();
   5415   p_getter_count++;
   5416   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
   5417   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   5418   if (name->Equals(v8_str("p1"))) {
   5419     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   5420   } else if (name->Equals(v8_str("p2"))) {
   5421     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   5422   } else if (name->Equals(v8_str("p3"))) {
   5423     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   5424   } else if (name->Equals(v8_str("p4"))) {
   5425     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   5426   }
   5427   return v8::Undefined();
   5428 }
   5429 
   5430 
   5431 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
   5432   ApiTestFuzzer::Fuzz();
   5433   LocalContext context;
   5434   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   5435   CompileRun(
   5436     "o1.__proto__ = { };"
   5437     "var o2 = { __proto__: o1 };"
   5438     "var o3 = { __proto__: o2 };"
   5439     "var o4 = { __proto__: o3 };"
   5440     "for (var i = 0; i < 10; i++) o4.p4;"
   5441     "for (var i = 0; i < 10; i++) o3.p3;"
   5442     "for (var i = 0; i < 10; i++) o2.p2;"
   5443     "for (var i = 0; i < 10; i++) o1.p1;");
   5444 }
   5445 
   5446 
   5447 static v8::Handle<Value> PGetter2(Local<String> name,
   5448                                   const AccessorInfo& info) {
   5449   ApiTestFuzzer::Fuzz();
   5450   p_getter_count2++;
   5451   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
   5452   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   5453   if (name->Equals(v8_str("p1"))) {
   5454     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   5455   } else if (name->Equals(v8_str("p2"))) {
   5456     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   5457   } else if (name->Equals(v8_str("p3"))) {
   5458     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   5459   } else if (name->Equals(v8_str("p4"))) {
   5460     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   5461   }
   5462   return v8::Undefined();
   5463 }
   5464 
   5465 
   5466 THREADED_TEST(GetterHolders) {
   5467   v8::HandleScope scope;
   5468   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   5469   obj->SetAccessor(v8_str("p1"), PGetter);
   5470   obj->SetAccessor(v8_str("p2"), PGetter);
   5471   obj->SetAccessor(v8_str("p3"), PGetter);
   5472   obj->SetAccessor(v8_str("p4"), PGetter);
   5473   p_getter_count = 0;
   5474   RunHolderTest(obj);
   5475   CHECK_EQ(40, p_getter_count);
   5476 }
   5477 
   5478 
   5479 THREADED_TEST(PreInterceptorHolders) {
   5480   v8::HandleScope scope;
   5481   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   5482   obj->SetNamedPropertyHandler(PGetter2);
   5483   p_getter_count2 = 0;
   5484   RunHolderTest(obj);
   5485   CHECK_EQ(40, p_getter_count2);
   5486 }
   5487 
   5488 
   5489 THREADED_TEST(ObjectInstantiation) {
   5490   v8::HandleScope scope;
   5491   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   5492   templ->SetAccessor(v8_str("t"), PGetter2);
   5493   LocalContext context;
   5494   context->Global()->Set(v8_str("o"), templ->NewInstance());
   5495   for (int i = 0; i < 100; i++) {
   5496     v8::HandleScope inner_scope;
   5497     v8::Handle<v8::Object> obj = templ->NewInstance();
   5498     CHECK_NE(obj, context->Global()->Get(v8_str("o")));
   5499     context->Global()->Set(v8_str("o2"), obj);
   5500     v8::Handle<Value> value =
   5501         Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
   5502     CHECK_EQ(v8::True(), value);
   5503     context->Global()->Set(v8_str("o"), obj);
   5504   }
   5505 }
   5506 
   5507 
   5508 static int StrCmp16(uint16_t* a, uint16_t* b) {
   5509   while (true) {
   5510     if (*a == 0 && *b == 0) return 0;
   5511     if (*a != *b) return 0 + *a - *b;
   5512     a++;
   5513     b++;
   5514   }
   5515 }
   5516 
   5517 
   5518 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
   5519   while (true) {
   5520     if (n-- == 0) return 0;
   5521     if (*a == 0 && *b == 0) return 0;
   5522     if (*a != *b) return 0 + *a - *b;
   5523     a++;
   5524     b++;
   5525   }
   5526 }
   5527 
   5528 
   5529 int GetUtf8Length(Handle<String> str) {
   5530   int len = str->Utf8Length();
   5531   if (len < 0) {
   5532     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
   5533     i::FlattenString(istr);
   5534     len = str->Utf8Length();
   5535   }
   5536   return len;
   5537 }
   5538 
   5539 
   5540 THREADED_TEST(StringWrite) {
   5541   LocalContext context;
   5542   v8::HandleScope scope;
   5543   v8::Handle<String> str = v8_str("abcde");
   5544   // abc<Icelandic eth><Unicode snowman>.
   5545   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
   5546   const int kStride = 4;  // Must match stride in for loops in JS below.
   5547   CompileRun(
   5548       "var left = '';"
   5549       "for (var i = 0; i < 0xd800; i += 4) {"
   5550       "  left = left + String.fromCharCode(i);"
   5551       "}");
   5552   CompileRun(
   5553       "var right = '';"
   5554       "for (var i = 0; i < 0xd800; i += 4) {"
   5555       "  right = String.fromCharCode(i) + right;"
   5556       "}");
   5557   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
   5558   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
   5559   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
   5560 
   5561   CHECK_EQ(5, str2->Length());
   5562   CHECK_EQ(0xd800 / kStride, left_tree->Length());
   5563   CHECK_EQ(0xd800 / kStride, right_tree->Length());
   5564 
   5565   char buf[100];
   5566   char utf8buf[0xd800 * 3];
   5567   uint16_t wbuf[100];
   5568   int len;
   5569   int charlen;
   5570 
   5571   memset(utf8buf, 0x1, 1000);
   5572   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   5573   CHECK_EQ(9, len);
   5574   CHECK_EQ(5, charlen);
   5575   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   5576 
   5577   memset(utf8buf, 0x1, 1000);
   5578   len = str2->WriteUtf8(utf8buf, 8, &charlen);
   5579   CHECK_EQ(8, len);
   5580   CHECK_EQ(5, charlen);
   5581   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
   5582 
   5583   memset(utf8buf, 0x1, 1000);
   5584   len = str2->WriteUtf8(utf8buf, 7, &charlen);
   5585   CHECK_EQ(5, len);
   5586   CHECK_EQ(4, charlen);
   5587   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   5588 
   5589   memset(utf8buf, 0x1, 1000);
   5590   len = str2->WriteUtf8(utf8buf, 6, &charlen);
   5591   CHECK_EQ(5, len);
   5592   CHECK_EQ(4, charlen);
   5593   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   5594 
   5595   memset(utf8buf, 0x1, 1000);
   5596   len = str2->WriteUtf8(utf8buf, 5, &charlen);
   5597   CHECK_EQ(5, len);
   5598   CHECK_EQ(4, charlen);
   5599   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   5600 
   5601   memset(utf8buf, 0x1, 1000);
   5602   len = str2->WriteUtf8(utf8buf, 4, &charlen);
   5603   CHECK_EQ(3, len);
   5604   CHECK_EQ(3, charlen);
   5605   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   5606 
   5607   memset(utf8buf, 0x1, 1000);
   5608   len = str2->WriteUtf8(utf8buf, 3, &charlen);
   5609   CHECK_EQ(3, len);
   5610   CHECK_EQ(3, charlen);
   5611   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   5612 
   5613   memset(utf8buf, 0x1, 1000);
   5614   len = str2->WriteUtf8(utf8buf, 2, &charlen);
   5615   CHECK_EQ(2, len);
   5616   CHECK_EQ(2, charlen);
   5617   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
   5618 
   5619   memset(utf8buf, 0x1, sizeof(utf8buf));
   5620   len = GetUtf8Length(left_tree);
   5621   int utf8_expected =
   5622       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
   5623   CHECK_EQ(utf8_expected, len);
   5624   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   5625   CHECK_EQ(utf8_expected, len);
   5626   CHECK_EQ(0xd800 / kStride, charlen);
   5627   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
   5628   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
   5629   CHECK_EQ(0xc0 - kStride,
   5630            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
   5631   CHECK_EQ(1, utf8buf[utf8_expected]);
   5632 
   5633   memset(utf8buf, 0x1, sizeof(utf8buf));
   5634   len = GetUtf8Length(right_tree);
   5635   CHECK_EQ(utf8_expected, len);
   5636   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   5637   CHECK_EQ(utf8_expected, len);
   5638   CHECK_EQ(0xd800 / kStride, charlen);
   5639   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
   5640   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
   5641   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
   5642   CHECK_EQ(1, utf8buf[utf8_expected]);
   5643 
   5644   memset(buf, 0x1, sizeof(buf));
   5645   memset(wbuf, 0x1, sizeof(wbuf));
   5646   len = str->WriteAscii(buf);
   5647   CHECK_EQ(5, len);
   5648   len = str->Write(wbuf);
   5649   CHECK_EQ(5, len);
   5650   CHECK_EQ(0, strcmp("abcde", buf));
   5651   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   5652   CHECK_EQ(0, StrCmp16(answer1, wbuf));
   5653 
   5654   memset(buf, 0x1, sizeof(buf));
   5655   memset(wbuf, 0x1, sizeof(wbuf));
   5656   len = str->WriteAscii(buf, 0, 4);
   5657   CHECK_EQ(4, len);
   5658   len = str->Write(wbuf, 0, 4);
   5659   CHECK_EQ(4, len);
   5660   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
   5661   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
   5662   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
   5663 
   5664   memset(buf, 0x1, sizeof(buf));
   5665   memset(wbuf, 0x1, sizeof(wbuf));
   5666   len = str->WriteAscii(buf, 0, 5);
   5667   CHECK_EQ(5, len);
   5668   len = str->Write(wbuf, 0, 5);
   5669   CHECK_EQ(5, len);
   5670   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
   5671   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
   5672   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
   5673 
   5674   memset(buf, 0x1, sizeof(buf));
   5675   memset(wbuf, 0x1, sizeof(wbuf));
   5676   len = str->WriteAscii(buf, 0, 6);
   5677   CHECK_EQ(5, len);
   5678   len = str->Write(wbuf, 0, 6);
   5679   CHECK_EQ(5, len);
   5680   CHECK_EQ(0, strcmp("abcde", buf));
   5681   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   5682   CHECK_EQ(0, StrCmp16(answer4, wbuf));
   5683 
   5684   memset(buf, 0x1, sizeof(buf));
   5685   memset(wbuf, 0x1, sizeof(wbuf));
   5686   len = str->WriteAscii(buf, 4, -1);
   5687   CHECK_EQ(1, len);
   5688   len = str->Write(wbuf, 4, -1);
   5689   CHECK_EQ(1, len);
   5690   CHECK_EQ(0, strcmp("e", buf));
   5691   uint16_t answer5[] = {'e', '\0'};
   5692   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   5693 
   5694   memset(buf, 0x1, sizeof(buf));
   5695   memset(wbuf, 0x1, sizeof(wbuf));
   5696   len = str->WriteAscii(buf, 4, 6);
   5697   CHECK_EQ(1, len);
   5698   len = str->Write(wbuf, 4, 6);
   5699   CHECK_EQ(1, len);
   5700   CHECK_EQ(0, strcmp("e", buf));
   5701   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   5702 
   5703   memset(buf, 0x1, sizeof(buf));
   5704   memset(wbuf, 0x1, sizeof(wbuf));
   5705   len = str->WriteAscii(buf, 4, 1);
   5706   CHECK_EQ(1, len);
   5707   len = str->Write(wbuf, 4, 1);
   5708   CHECK_EQ(1, len);
   5709   CHECK_EQ(0, strncmp("e\1", buf, 2));
   5710   uint16_t answer6[] = {'e', 0x101};
   5711   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
   5712 
   5713   memset(buf, 0x1, sizeof(buf));
   5714   memset(wbuf, 0x1, sizeof(wbuf));
   5715   len = str->WriteAscii(buf, 3, 1);
   5716   CHECK_EQ(1, len);
   5717   len = str->Write(wbuf, 3, 1);
   5718   CHECK_EQ(1, len);
   5719   CHECK_EQ(0, strncmp("d\1", buf, 2));
   5720   uint16_t answer7[] = {'d', 0x101};
   5721   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
   5722 
   5723   memset(wbuf, 0x1, sizeof(wbuf));
   5724   wbuf[5] = 'X';
   5725   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
   5726   CHECK_EQ(5, len);
   5727   CHECK_EQ('X', wbuf[5]);
   5728   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
   5729   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   5730   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
   5731   CHECK_NE(0, StrCmp16(answer8b, wbuf));
   5732   wbuf[5] = '\0';
   5733   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
   5734 
   5735   memset(buf, 0x1, sizeof(buf));
   5736   buf[5] = 'X';
   5737   len = str->WriteAscii(buf, 0, 6, String::NO_NULL_TERMINATION);
   5738   CHECK_EQ(5, len);
   5739   CHECK_EQ('X', buf[5]);
   5740   CHECK_EQ(0, strncmp("abcde", buf, 5));
   5741   CHECK_NE(0, strcmp("abcde", buf));
   5742   buf[5] = '\0';
   5743   CHECK_EQ(0, strcmp("abcde", buf));
   5744 
   5745   memset(utf8buf, 0x1, sizeof(utf8buf));
   5746   utf8buf[8] = 'X';
   5747   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   5748                         String::NO_NULL_TERMINATION);
   5749   CHECK_EQ(8, len);
   5750   CHECK_EQ('X', utf8buf[8]);
   5751   CHECK_EQ(5, charlen);
   5752   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
   5753   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   5754   utf8buf[8] = '\0';
   5755   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   5756 }
   5757 
   5758 
   5759 static void Utf16Helper(
   5760     LocalContext& context,
   5761     const char* name,
   5762     const char* lengths_name,
   5763     int len) {
   5764   Local<v8::Array> a =
   5765       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
   5766   Local<v8::Array> alens =
   5767       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
   5768   for (int i = 0; i < len; i++) {
   5769     Local<v8::String> string =
   5770       Local<v8::String>::Cast(a->Get(i));
   5771     Local<v8::Number> expected_len =
   5772       Local<v8::Number>::Cast(alens->Get(i));
   5773     CHECK_EQ(expected_len->Value() != string->Length(),
   5774              string->MayContainNonAscii());
   5775     int length = GetUtf8Length(string);
   5776     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
   5777   }
   5778 }
   5779 
   5780 
   5781 static uint16_t StringGet(Handle<String> str, int index) {
   5782   i::Handle<i::String> istring =
   5783       v8::Utils::OpenHandle(String::Cast(*str));
   5784   return istring->Get(index);
   5785 }
   5786 
   5787 
   5788 static void WriteUtf8Helper(
   5789     LocalContext& context,
   5790     const char* name,
   5791     const char* lengths_name,
   5792     int len) {
   5793   Local<v8::Array> b =
   5794       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
   5795   Local<v8::Array> alens =
   5796       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
   5797   char buffer[1000];
   5798   char buffer2[1000];
   5799   for (int i = 0; i < len; i++) {
   5800     Local<v8::String> string =
   5801       Local<v8::String>::Cast(b->Get(i));
   5802     Local<v8::Number> expected_len =
   5803       Local<v8::Number>::Cast(alens->Get(i));
   5804     int utf8_length = static_cast<int>(expected_len->Value());
   5805     for (int j = utf8_length + 1; j >= 0; j--) {
   5806       memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
   5807       memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
   5808       int nchars;
   5809       int utf8_written =
   5810           string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
   5811       int utf8_written2 =
   5812           string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
   5813       CHECK_GE(utf8_length + 1, utf8_written);
   5814       CHECK_GE(utf8_length, utf8_written2);
   5815       for (int k = 0; k < utf8_written2; k++) {
   5816         CHECK_EQ(buffer[k], buffer2[k]);
   5817       }
   5818       CHECK(nchars * 3 >= utf8_written - 1);
   5819       CHECK(nchars <= utf8_written);
   5820       if (j == utf8_length + 1) {
   5821         CHECK_EQ(utf8_written2, utf8_length);
   5822         CHECK_EQ(utf8_written2 + 1, utf8_written);
   5823       }
   5824       CHECK_EQ(buffer[utf8_written], 42);
   5825       if (j > utf8_length) {
   5826         if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
   5827         if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
   5828         Handle<String> roundtrip = v8_str(buffer);
   5829         CHECK(roundtrip->Equals(string));
   5830       } else {
   5831         if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
   5832       }
   5833       if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
   5834       if (nchars >= 2) {
   5835         uint16_t trail = StringGet(string, nchars - 1);
   5836         uint16_t lead = StringGet(string, nchars - 2);
   5837         if (((lead & 0xfc00) == 0xd800) &&
   5838             ((trail & 0xfc00) == 0xdc00)) {
   5839           unsigned char u1 = buffer2[utf8_written2 - 4];
   5840           unsigned char u2 = buffer2[utf8_written2 - 3];
   5841           unsigned char u3 = buffer2[utf8_written2 - 2];
   5842           unsigned char u4 = buffer2[utf8_written2 - 1];
   5843           CHECK_EQ((u1 & 0xf8), 0xf0);
   5844           CHECK_EQ((u2 & 0xc0), 0x80);
   5845           CHECK_EQ((u3 & 0xc0), 0x80);
   5846           CHECK_EQ((u4 & 0xc0), 0x80);
   5847           uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
   5848           CHECK_EQ((u4 & 0x3f), (c & 0x3f));
   5849           CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
   5850           CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
   5851           CHECK_EQ((u1 & 0x3), c >> 18);
   5852         }
   5853       }
   5854     }
   5855   }
   5856 }
   5857 
   5858 
   5859 THREADED_TEST(Utf16) {
   5860   LocalContext context;
   5861   v8::HandleScope scope;
   5862   CompileRun(
   5863       "var pad = '01234567890123456789';"
   5864       "var p = [];"
   5865       "var plens = [20, 3, 3];"
   5866       "p.push('01234567890123456789');"
   5867       "var lead = 0xd800;"
   5868       "var trail = 0xdc00;"
   5869       "p.push(String.fromCharCode(0xd800));"
   5870       "p.push(String.fromCharCode(0xdc00));"
   5871       "var a = [];"
   5872       "var b = [];"
   5873       "var c = [];"
   5874       "var alens = [];"
   5875       "for (var i = 0; i < 3; i++) {"
   5876       "  p[1] = String.fromCharCode(lead++);"
   5877       "  for (var j = 0; j < 3; j++) {"
   5878       "    p[2] = String.fromCharCode(trail++);"
   5879       "    a.push(p[i] + p[j]);"
   5880       "    b.push(p[i] + p[j]);"
   5881       "    c.push(p[i] + p[j]);"
   5882       "    alens.push(plens[i] + plens[j]);"
   5883       "  }"
   5884       "}"
   5885       "alens[5] -= 2;"  // Here the surrogate pairs match up.
   5886       "var a2 = [];"
   5887       "var b2 = [];"
   5888       "var c2 = [];"
   5889       "var a2lens = [];"
   5890       "for (var m = 0; m < 9; m++) {"
   5891       "  for (var n = 0; n < 9; n++) {"
   5892       "    a2.push(a[m] + a[n]);"
   5893       "    b2.push(b[m] + b[n]);"
   5894       "    var newc = 'x' + c[m] + c[n] + 'y';"
   5895       "    c2.push(newc.substring(1, newc.length - 1));"
   5896       "    var utf = alens[m] + alens[n];"  // And here.
   5897            // The 'n's that start with 0xdc.. are 6-8
   5898            // The 'm's that end with 0xd8.. are 1, 4 and 7
   5899       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
   5900       "    a2lens.push(utf);"
   5901       "  }"
   5902       "}");
   5903   Utf16Helper(context, "a", "alens", 9);
   5904   Utf16Helper(context, "a2", "a2lens", 81);
   5905   WriteUtf8Helper(context, "b", "alens", 9);
   5906   WriteUtf8Helper(context, "b2", "a2lens", 81);
   5907   WriteUtf8Helper(context, "c2", "a2lens", 81);
   5908 }
   5909 
   5910 
   5911 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
   5912   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
   5913   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
   5914   return *is1 == *is2;
   5915 }
   5916 
   5917 
   5918 static void SameSymbolHelper(const char* a, const char* b) {
   5919   Handle<String> symbol1 = v8::String::NewSymbol(a);
   5920   Handle<String> symbol2 = v8::String::NewSymbol(b);
   5921   CHECK(SameSymbol(symbol1, symbol2));
   5922 }
   5923 
   5924 
   5925 THREADED_TEST(Utf16Symbol) {
   5926   LocalContext context;
   5927   v8::HandleScope scope;
   5928 
   5929   Handle<String> symbol1 = v8::String::NewSymbol("abc");
   5930   Handle<String> symbol2 = v8::String::NewSymbol("abc");
   5931   CHECK(SameSymbol(symbol1, symbol2));
   5932 
   5933   SameSymbolHelper("\360\220\220\205",  // 4 byte encoding.
   5934                    "\355\240\201\355\260\205");  // 2 3-byte surrogates.
   5935   SameSymbolHelper("\355\240\201\355\260\206",  // 2 3-byte surrogates.
   5936                    "\360\220\220\206");  // 4 byte encoding.
   5937   SameSymbolHelper("x\360\220\220\205",  // 4 byte encoding.
   5938                    "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
   5939   SameSymbolHelper("x\355\240\201\355\260\206",  // 2 3-byte surrogates.
   5940                    "x\360\220\220\206");  // 4 byte encoding.
   5941   CompileRun(
   5942       "var sym0 = 'benedictus';"
   5943       "var sym0b = 'S\303\270ren';"
   5944       "var sym1 = '\355\240\201\355\260\207';"
   5945       "var sym2 = '\360\220\220\210';"
   5946       "var sym3 = 'x\355\240\201\355\260\207';"
   5947       "var sym4 = 'x\360\220\220\210';"
   5948       "if (sym1.length != 2) throw sym1;"
   5949       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
   5950       "if (sym2.length != 2) throw sym2;"
   5951       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
   5952       "if (sym3.length != 3) throw sym3;"
   5953       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
   5954       "if (sym4.length != 3) throw sym4;"
   5955       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
   5956   Handle<String> sym0 = v8::String::NewSymbol("benedictus");
   5957   Handle<String> sym0b = v8::String::NewSymbol("S\303\270ren");
   5958   Handle<String> sym1 = v8::String::NewSymbol("\355\240\201\355\260\207");
   5959   Handle<String> sym2 = v8::String::NewSymbol("\360\220\220\210");
   5960   Handle<String> sym3 = v8::String::NewSymbol("x\355\240\201\355\260\207");
   5961   Handle<String> sym4 = v8::String::NewSymbol("x\360\220\220\210");
   5962   v8::Local<v8::Object> global = context->Global();
   5963   Local<Value> s0 = global->Get(v8_str("sym0"));
   5964   Local<Value> s0b = global->Get(v8_str("sym0b"));
   5965   Local<Value> s1 = global->Get(v8_str("sym1"));
   5966   Local<Value> s2 = global->Get(v8_str("sym2"));
   5967   Local<Value> s3 = global->Get(v8_str("sym3"));
   5968   Local<Value> s4 = global->Get(v8_str("sym4"));
   5969   CHECK(SameSymbol(sym0, Handle<String>(String::Cast(*s0))));
   5970   CHECK(SameSymbol(sym0b, Handle<String>(String::Cast(*s0b))));
   5971   CHECK(SameSymbol(sym1, Handle<String>(String::Cast(*s1))));
   5972   CHECK(SameSymbol(sym2, Handle<String>(String::Cast(*s2))));
   5973   CHECK(SameSymbol(sym3, Handle<String>(String::Cast(*s3))));
   5974   CHECK(SameSymbol(sym4, Handle<String>(String::Cast(*s4))));
   5975 }
   5976 
   5977 
   5978 THREADED_TEST(ToArrayIndex) {
   5979   v8::HandleScope scope;
   5980   LocalContext context;
   5981 
   5982   v8::Handle<String> str = v8_str("42");
   5983   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
   5984   CHECK(!index.IsEmpty());
   5985   CHECK_EQ(42.0, index->Uint32Value());
   5986   str = v8_str("42asdf");
   5987   index = str->ToArrayIndex();
   5988   CHECK(index.IsEmpty());
   5989   str = v8_str("-42");
   5990   index = str->ToArrayIndex();
   5991   CHECK(index.IsEmpty());
   5992   str = v8_str("4294967295");
   5993   index = str->ToArrayIndex();
   5994   CHECK(!index.IsEmpty());
   5995   CHECK_EQ(4294967295.0, index->Uint32Value());
   5996   v8::Handle<v8::Number> num = v8::Number::New(1);
   5997   index = num->ToArrayIndex();
   5998   CHECK(!index.IsEmpty());
   5999   CHECK_EQ(1.0, index->Uint32Value());
   6000   num = v8::Number::New(-1);
   6001   index = num->ToArrayIndex();
   6002   CHECK(index.IsEmpty());
   6003   v8::Handle<v8::Object> obj = v8::Object::New();
   6004   index = obj->ToArrayIndex();
   6005   CHECK(index.IsEmpty());
   6006 }
   6007 
   6008 
   6009 THREADED_TEST(ErrorConstruction) {
   6010   v8::HandleScope scope;
   6011   LocalContext context;
   6012 
   6013   v8::Handle<String> foo = v8_str("foo");
   6014   v8::Handle<String> message = v8_str("message");
   6015   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
   6016   CHECK(range_error->IsObject());
   6017   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
   6018   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
   6019   CHECK(reference_error->IsObject());
   6020   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
   6021   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
   6022   CHECK(syntax_error->IsObject());
   6023   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
   6024   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
   6025   CHECK(type_error->IsObject());
   6026   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
   6027   v8::Handle<Value> error = v8::Exception::Error(foo);
   6028   CHECK(error->IsObject());
   6029   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
   6030 }
   6031 
   6032 
   6033 static v8::Handle<Value> YGetter(Local<String> name, const AccessorInfo& info) {
   6034   ApiTestFuzzer::Fuzz();
   6035   return v8_num(10);
   6036 }
   6037 
   6038 
   6039 static void YSetter(Local<String> name,
   6040                     Local<Value> value,
   6041                     const AccessorInfo& info) {
   6042   if (info.This()->Has(name)) {
   6043     info.This()->Delete(name);
   6044   }
   6045   info.This()->Set(name, value);
   6046 }
   6047 
   6048 
   6049 THREADED_TEST(DeleteAccessor) {
   6050   v8::HandleScope scope;
   6051   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   6052   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
   6053   LocalContext context;
   6054   v8::Handle<v8::Object> holder = obj->NewInstance();
   6055   context->Global()->Set(v8_str("holder"), holder);
   6056   v8::Handle<Value> result = CompileRun(
   6057       "holder.y = 11; holder.y = 12; holder.y");
   6058   CHECK_EQ(12, result->Uint32Value());
   6059 }
   6060 
   6061 
   6062 THREADED_TEST(TypeSwitch) {
   6063   v8::HandleScope scope;
   6064   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
   6065   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
   6066   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
   6067   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
   6068   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
   6069   LocalContext context;
   6070   v8::Handle<v8::Object> obj0 = v8::Object::New();
   6071   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
   6072   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
   6073   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
   6074   for (int i = 0; i < 10; i++) {
   6075     CHECK_EQ(0, type_switch->match(obj0));
   6076     CHECK_EQ(1, type_switch->match(obj1));
   6077     CHECK_EQ(2, type_switch->match(obj2));
   6078     CHECK_EQ(3, type_switch->match(obj3));
   6079     CHECK_EQ(3, type_switch->match(obj3));
   6080     CHECK_EQ(2, type_switch->match(obj2));
   6081     CHECK_EQ(1, type_switch->match(obj1));
   6082     CHECK_EQ(0, type_switch->match(obj0));
   6083   }
   6084 }
   6085 
   6086 
   6087 // For use within the TestSecurityHandler() test.
   6088 static bool g_security_callback_result = false;
   6089 static bool NamedSecurityTestCallback(Local<v8::Object> global,
   6090                                       Local<Value> name,
   6091                                       v8::AccessType type,
   6092                                       Local<Value> data) {
   6093   // Always allow read access.
   6094   if (type == v8::ACCESS_GET)
   6095     return true;
   6096 
   6097   // Sometimes allow other access.
   6098   return g_security_callback_result;
   6099 }
   6100 
   6101 
   6102 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
   6103                                         uint32_t key,
   6104                                         v8::AccessType type,
   6105                                         Local<Value> data) {
   6106   // Always allow read access.
   6107   if (type == v8::ACCESS_GET)
   6108     return true;
   6109 
   6110   // Sometimes allow other access.
   6111   return g_security_callback_result;
   6112 }
   6113 
   6114 
   6115 static int trouble_nesting = 0;
   6116 static v8::Handle<Value> TroubleCallback(const v8::Arguments& args) {
   6117   ApiTestFuzzer::Fuzz();
   6118   trouble_nesting++;
   6119 
   6120   // Call a JS function that throws an uncaught exception.
   6121   Local<v8::Object> arg_this = Context::GetCurrent()->Global();
   6122   Local<Value> trouble_callee = (trouble_nesting == 3) ?
   6123     arg_this->Get(v8_str("trouble_callee")) :
   6124     arg_this->Get(v8_str("trouble_caller"));
   6125   CHECK(trouble_callee->IsFunction());
   6126   return Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL);
   6127 }
   6128 
   6129 
   6130 static int report_count = 0;
   6131 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
   6132                                              v8::Handle<Value>) {
   6133   report_count++;
   6134 }
   6135 
   6136 
   6137 // Counts uncaught exceptions, but other tests running in parallel
   6138 // also have uncaught exceptions.
   6139 TEST(ApiUncaughtException) {
   6140   report_count = 0;
   6141   v8::HandleScope scope;
   6142   LocalContext env;
   6143   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
   6144 
   6145   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
   6146   v8::Local<v8::Object> global = env->Global();
   6147   global->Set(v8_str("trouble"), fun->GetFunction());
   6148 
   6149   Script::Compile(v8_str("function trouble_callee() {"
   6150                          "  var x = null;"
   6151                          "  return x.foo;"
   6152                          "};"
   6153                          "function trouble_caller() {"
   6154                          "  trouble();"
   6155                          "};"))->Run();
   6156   Local<Value> trouble = global->Get(v8_str("trouble"));
   6157   CHECK(trouble->IsFunction());
   6158   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
   6159   CHECK(trouble_callee->IsFunction());
   6160   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
   6161   CHECK(trouble_caller->IsFunction());
   6162   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
   6163   CHECK_EQ(1, report_count);
   6164   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
   6165 }
   6166 
   6167 static const char* script_resource_name = "ExceptionInNativeScript.js";
   6168 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
   6169                                                 v8::Handle<Value>) {
   6170   v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
   6171   CHECK(!name_val.IsEmpty() && name_val->IsString());
   6172   v8::String::AsciiValue name(message->GetScriptResourceName());
   6173   CHECK_EQ(script_resource_name, *name);
   6174   CHECK_EQ(3, message->GetLineNumber());
   6175   v8::String::AsciiValue source_line(message->GetSourceLine());
   6176   CHECK_EQ("  new o.foo();", *source_line);
   6177 }
   6178 
   6179 TEST(ExceptionInNativeScript) {
   6180   v8::HandleScope scope;
   6181   LocalContext env;
   6182   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
   6183 
   6184   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
   6185   v8::Local<v8::Object> global = env->Global();
   6186   global->Set(v8_str("trouble"), fun->GetFunction());
   6187 
   6188   Script::Compile(v8_str("function trouble() {\n"
   6189                          "  var o = {};\n"
   6190                          "  new o.foo();\n"
   6191                          "};"), v8::String::New(script_resource_name))->Run();
   6192   Local<Value> trouble = global->Get(v8_str("trouble"));
   6193   CHECK(trouble->IsFunction());
   6194   Function::Cast(*trouble)->Call(global, 0, NULL);
   6195   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
   6196 }
   6197 
   6198 
   6199 TEST(CompilationErrorUsingTryCatchHandler) {
   6200   v8::HandleScope scope;
   6201   LocalContext env;
   6202   v8::TryCatch try_catch;
   6203   Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
   6204   CHECK_NE(NULL, *try_catch.Exception());
   6205   CHECK(try_catch.HasCaught());
   6206 }
   6207 
   6208 
   6209 TEST(TryCatchFinallyUsingTryCatchHandler) {
   6210   v8::HandleScope scope;
   6211   LocalContext env;
   6212   v8::TryCatch try_catch;
   6213   Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
   6214   CHECK(!try_catch.HasCaught());
   6215   Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
   6216   CHECK(try_catch.HasCaught());
   6217   try_catch.Reset();
   6218   Script::Compile(v8_str("(function() {"
   6219                          "try { throw ''; } finally { return; }"
   6220                          "})()"))->Run();
   6221   CHECK(!try_catch.HasCaught());
   6222   Script::Compile(v8_str("(function()"
   6223                          "  { try { throw ''; } finally { throw 0; }"
   6224                          "})()"))->Run();
   6225   CHECK(try_catch.HasCaught());
   6226 }
   6227 
   6228 
   6229 // SecurityHandler can't be run twice
   6230 TEST(SecurityHandler) {
   6231   v8::HandleScope scope0;
   6232   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   6233   global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
   6234                                            IndexedSecurityTestCallback);
   6235   // Create an environment
   6236   v8::Persistent<Context> context0 =
   6237     Context::New(NULL, global_template);
   6238   context0->Enter();
   6239 
   6240   v8::Handle<v8::Object> global0 = context0->Global();
   6241   v8::Handle<Script> script0 = v8_compile("foo = 111");
   6242   script0->Run();
   6243   global0->Set(v8_str("0"), v8_num(999));
   6244   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
   6245   CHECK_EQ(111, foo0->Int32Value());
   6246   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
   6247   CHECK_EQ(999, z0->Int32Value());
   6248 
   6249   // Create another environment, should fail security checks.
   6250   v8::HandleScope scope1;
   6251 
   6252   v8::Persistent<Context> context1 =
   6253     Context::New(NULL, global_template);
   6254   context1->Enter();
   6255 
   6256   v8::Handle<v8::Object> global1 = context1->Global();
   6257   global1->Set(v8_str("othercontext"), global0);
   6258   // This set will fail the security check.
   6259   v8::Handle<Script> script1 =
   6260     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
   6261   script1->Run();
   6262   // This read will pass the security check.
   6263   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
   6264   CHECK_EQ(111, foo1->Int32Value());
   6265   // This read will pass the security check.
   6266   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
   6267   CHECK_EQ(999, z1->Int32Value());
   6268 
   6269   // Create another environment, should pass security checks.
   6270   { g_security_callback_result = true;  // allow security handler to pass.
   6271     v8::HandleScope scope2;
   6272     LocalContext context2;
   6273     v8::Handle<v8::Object> global2 = context2->Global();
   6274     global2->Set(v8_str("othercontext"), global0);
   6275     v8::Handle<Script> script2 =
   6276         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
   6277     script2->Run();
   6278     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
   6279     CHECK_EQ(333, foo2->Int32Value());
   6280     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
   6281     CHECK_EQ(888, z2->Int32Value());
   6282   }
   6283 
   6284   context1->Exit();
   6285   context1.Dispose();
   6286 
   6287   context0->Exit();
   6288   context0.Dispose();
   6289 }
   6290 
   6291 
   6292 THREADED_TEST(SecurityChecks) {
   6293   v8::HandleScope handle_scope;
   6294   LocalContext env1;
   6295   v8::Persistent<Context> env2 = Context::New();
   6296 
   6297   Local<Value> foo = v8_str("foo");
   6298   Local<Value> bar = v8_str("bar");
   6299 
   6300   // Set to the same domain.
   6301   env1->SetSecurityToken(foo);
   6302 
   6303   // Create a function in env1.
   6304   Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
   6305   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
   6306   CHECK(spy->IsFunction());
   6307 
   6308   // Create another function accessing global objects.
   6309   Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
   6310   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
   6311   CHECK(spy2->IsFunction());
   6312 
   6313   // Switch to env2 in the same domain and invoke spy on env2.
   6314   {
   6315     env2->SetSecurityToken(foo);
   6316     // Enter env2
   6317     Context::Scope scope_env2(env2);
   6318     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
   6319     CHECK(result->IsFunction());
   6320   }
   6321 
   6322   {
   6323     env2->SetSecurityToken(bar);
   6324     Context::Scope scope_env2(env2);
   6325 
   6326     // Call cross_domain_call, it should throw an exception
   6327     v8::TryCatch try_catch;
   6328     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
   6329     CHECK(try_catch.HasCaught());
   6330   }
   6331 
   6332   env2.Dispose();
   6333 }
   6334 
   6335 
   6336 // Regression test case for issue 1183439.
   6337 THREADED_TEST(SecurityChecksForPrototypeChain) {
   6338   v8::HandleScope scope;
   6339   LocalContext current;
   6340   v8::Persistent<Context> other = Context::New();
   6341 
   6342   // Change context to be able to get to the Object function in the
   6343   // other context without hitting the security checks.
   6344   v8::Local<Value> other_object;
   6345   { Context::Scope scope(other);
   6346     other_object = other->Global()->Get(v8_str("Object"));
   6347     other->Global()->Set(v8_num(42), v8_num(87));
   6348   }
   6349 
   6350   current->Global()->Set(v8_str("other"), other->Global());
   6351   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
   6352 
   6353   // Make sure the security check fails here and we get an undefined
   6354   // result instead of getting the Object function. Repeat in a loop
   6355   // to make sure to exercise the IC code.
   6356   v8::Local<Script> access_other0 = v8_compile("other.Object");
   6357   v8::Local<Script> access_other1 = v8_compile("other[42]");
   6358   for (int i = 0; i < 5; i++) {
   6359     CHECK(!access_other0->Run()->Equals(other_object));
   6360     CHECK(access_other0->Run()->IsUndefined());
   6361     CHECK(!access_other1->Run()->Equals(v8_num(87)));
   6362     CHECK(access_other1->Run()->IsUndefined());
   6363   }
   6364 
   6365   // Create an object that has 'other' in its prototype chain and make
   6366   // sure we cannot access the Object function indirectly through
   6367   // that. Repeat in a loop to make sure to exercise the IC code.
   6368   v8_compile("function F() { };"
   6369              "F.prototype = other;"
   6370              "var f = new F();")->Run();
   6371   v8::Local<Script> access_f0 = v8_compile("f.Object");
   6372   v8::Local<Script> access_f1 = v8_compile("f[42]");
   6373   for (int j = 0; j < 5; j++) {
   6374     CHECK(!access_f0->Run()->Equals(other_object));
   6375     CHECK(access_f0->Run()->IsUndefined());
   6376     CHECK(!access_f1->Run()->Equals(v8_num(87)));
   6377     CHECK(access_f1->Run()->IsUndefined());
   6378   }
   6379 
   6380   // Now it gets hairy: Set the prototype for the other global object
   6381   // to be the current global object. The prototype chain for 'f' now
   6382   // goes through 'other' but ends up in the current global object.
   6383   { Context::Scope scope(other);
   6384     other->Global()->Set(v8_str("__proto__"), current->Global());
   6385   }
   6386   // Set a named and an index property on the current global
   6387   // object. To force the lookup to go through the other global object,
   6388   // the properties must not exist in the other global object.
   6389   current->Global()->Set(v8_str("foo"), v8_num(100));
   6390   current->Global()->Set(v8_num(99), v8_num(101));
   6391   // Try to read the properties from f and make sure that the access
   6392   // gets stopped by the security checks on the other global object.
   6393   Local<Script> access_f2 = v8_compile("f.foo");
   6394   Local<Script> access_f3 = v8_compile("f[99]");
   6395   for (int k = 0; k < 5; k++) {
   6396     CHECK(!access_f2->Run()->Equals(v8_num(100)));
   6397     CHECK(access_f2->Run()->IsUndefined());
   6398     CHECK(!access_f3->Run()->Equals(v8_num(101)));
   6399     CHECK(access_f3->Run()->IsUndefined());
   6400   }
   6401   other.Dispose();
   6402 }
   6403 
   6404 
   6405 THREADED_TEST(CrossDomainDelete) {
   6406   v8::HandleScope handle_scope;
   6407   LocalContext env1;
   6408   v8::Persistent<Context> env2 = Context::New();
   6409 
   6410   Local<Value> foo = v8_str("foo");
   6411   Local<Value> bar = v8_str("bar");
   6412 
   6413   // Set to the same domain.
   6414   env1->SetSecurityToken(foo);
   6415   env2->SetSecurityToken(foo);
   6416 
   6417   env1->Global()->Set(v8_str("prop"), v8_num(3));
   6418   env2->Global()->Set(v8_str("env1"), env1->Global());
   6419 
   6420   // Change env2 to a different domain and delete env1.prop.
   6421   env2->SetSecurityToken(bar);
   6422   {
   6423     Context::Scope scope_env2(env2);
   6424     Local<Value> result =
   6425         Script::Compile(v8_str("delete env1.prop"))->Run();
   6426     CHECK(result->IsFalse());
   6427   }
   6428 
   6429   // Check that env1.prop still exists.
   6430   Local<Value> v = env1->Global()->Get(v8_str("prop"));
   6431   CHECK(v->IsNumber());
   6432   CHECK_EQ(3, v->Int32Value());
   6433 
   6434   env2.Dispose();
   6435 }
   6436 
   6437 
   6438 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
   6439   v8::HandleScope handle_scope;
   6440   LocalContext env1;
   6441   v8::Persistent<Context> env2 = Context::New();
   6442 
   6443   Local<Value> foo = v8_str("foo");
   6444   Local<Value> bar = v8_str("bar");
   6445 
   6446   // Set to the same domain.
   6447   env1->SetSecurityToken(foo);
   6448   env2->SetSecurityToken(foo);
   6449 
   6450   env1->Global()->Set(v8_str("prop"), v8_num(3));
   6451   env2->Global()->Set(v8_str("env1"), env1->Global());
   6452 
   6453   // env1.prop is enumerable in env2.
   6454   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
   6455   {
   6456     Context::Scope scope_env2(env2);
   6457     Local<Value> result = Script::Compile(test)->Run();
   6458     CHECK(result->IsTrue());
   6459   }
   6460 
   6461   // Change env2 to a different domain and test again.
   6462   env2->SetSecurityToken(bar);
   6463   {
   6464     Context::Scope scope_env2(env2);
   6465     Local<Value> result = Script::Compile(test)->Run();
   6466     CHECK(result->IsFalse());
   6467   }
   6468 
   6469   env2.Dispose();
   6470 }
   6471 
   6472 
   6473 THREADED_TEST(CrossDomainForIn) {
   6474   v8::HandleScope handle_scope;
   6475   LocalContext env1;
   6476   v8::Persistent<Context> env2 = Context::New();
   6477 
   6478   Local<Value> foo = v8_str("foo");
   6479   Local<Value> bar = v8_str("bar");
   6480 
   6481   // Set to the same domain.
   6482   env1->SetSecurityToken(foo);
   6483   env2->SetSecurityToken(foo);
   6484 
   6485   env1->Global()->Set(v8_str("prop"), v8_num(3));
   6486   env2->Global()->Set(v8_str("env1"), env1->Global());
   6487 
   6488   // Change env2 to a different domain and set env1's global object
   6489   // as the __proto__ of an object in env2 and enumerate properties
   6490   // in for-in. It shouldn't enumerate properties on env1's global
   6491   // object.
   6492   env2->SetSecurityToken(bar);
   6493   {
   6494     Context::Scope scope_env2(env2);
   6495     Local<Value> result =
   6496         CompileRun("(function(){var obj = {'__proto__':env1};"
   6497                    "for (var p in obj)"
   6498                    "   if (p == 'prop') return false;"
   6499                    "return true;})()");
   6500     CHECK(result->IsTrue());
   6501   }
   6502   env2.Dispose();
   6503 }
   6504 
   6505 
   6506 TEST(ContextDetachGlobal) {
   6507   v8::HandleScope handle_scope;
   6508   LocalContext env1;
   6509   v8::Persistent<Context> env2 = Context::New();
   6510 
   6511   Local<v8::Object> global1 = env1->Global();
   6512 
   6513   Local<Value> foo = v8_str("foo");
   6514 
   6515   // Set to the same domain.
   6516   env1->SetSecurityToken(foo);
   6517   env2->SetSecurityToken(foo);
   6518 
   6519   // Enter env2
   6520   env2->Enter();
   6521 
   6522   // Create a function in env2 and add a reference to it in env1.
   6523   Local<v8::Object> global2 = env2->Global();
   6524   global2->Set(v8_str("prop"), v8::Integer::New(1));
   6525   CompileRun("function getProp() {return prop;}");
   6526 
   6527   env1->Global()->Set(v8_str("getProp"),
   6528                       global2->Get(v8_str("getProp")));
   6529 
   6530   // Detach env2's global, and reuse the global object of env2
   6531   env2->Exit();
   6532   env2->DetachGlobal();
   6533   // env2 has a new global object.
   6534   CHECK(!env2->Global()->Equals(global2));
   6535 
   6536   v8::Persistent<Context> env3 =
   6537       Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
   6538   env3->SetSecurityToken(v8_str("bar"));
   6539   env3->Enter();
   6540 
   6541   Local<v8::Object> global3 = env3->Global();
   6542   CHECK_EQ(global2, global3);
   6543   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
   6544   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
   6545   global3->Set(v8_str("prop"), v8::Integer::New(-1));
   6546   global3->Set(v8_str("prop2"), v8::Integer::New(2));
   6547   env3->Exit();
   6548 
   6549   // Call getProp in env1, and it should return the value 1
   6550   {
   6551     Local<Value> get_prop = global1->Get(v8_str("getProp"));
   6552     CHECK(get_prop->IsFunction());
   6553     v8::TryCatch try_catch;
   6554     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
   6555     CHECK(!try_catch.HasCaught());
   6556     CHECK_EQ(1, r->Int32Value());
   6557   }
   6558 
   6559   // Check that env3 is not accessible from env1
   6560   {
   6561     Local<Value> r = global3->Get(v8_str("prop2"));
   6562     CHECK(r->IsUndefined());
   6563   }
   6564 
   6565   env2.Dispose();
   6566   env3.Dispose();
   6567 }
   6568 
   6569 
   6570 TEST(DetachAndReattachGlobal) {
   6571   v8::HandleScope scope;
   6572   LocalContext env1;
   6573 
   6574   // Create second environment.
   6575   v8::Persistent<Context> env2 = Context::New();
   6576 
   6577   Local<Value> foo = v8_str("foo");
   6578 
   6579   // Set same security token for env1 and env2.
   6580   env1->SetSecurityToken(foo);
   6581   env2->SetSecurityToken(foo);
   6582 
   6583   // Create a property on the global object in env2.
   6584   {
   6585     v8::Context::Scope scope(env2);
   6586     env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
   6587   }
   6588 
   6589   // Create a reference to env2 global from env1 global.
   6590   env1->Global()->Set(v8_str("other"), env2->Global());
   6591 
   6592   // Check that we have access to other.p in env2 from env1.
   6593   Local<Value> result = CompileRun("other.p");
   6594   CHECK(result->IsInt32());
   6595   CHECK_EQ(42, result->Int32Value());
   6596 
   6597   // Hold on to global from env2 and detach global from env2.
   6598   Local<v8::Object> global2 = env2->Global();
   6599   env2->DetachGlobal();
   6600 
   6601   // Check that the global has been detached. No other.p property can
   6602   // be found.
   6603   result = CompileRun("other.p");
   6604   CHECK(result->IsUndefined());
   6605 
   6606   // Reuse global2 for env3.
   6607   v8::Persistent<Context> env3 =
   6608       Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
   6609   CHECK_EQ(global2, env3->Global());
   6610 
   6611   // Start by using the same security token for env3 as for env1 and env2.
   6612   env3->SetSecurityToken(foo);
   6613 
   6614   // Create a property on the global object in env3.
   6615   {
   6616     v8::Context::Scope scope(env3);
   6617     env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
   6618   }
   6619 
   6620   // Check that other.p is now the property in env3 and that we have access.
   6621   result = CompileRun("other.p");
   6622   CHECK(result->IsInt32());
   6623   CHECK_EQ(24, result->Int32Value());
   6624 
   6625   // Change security token for env3 to something different from env1 and env2.
   6626   env3->SetSecurityToken(v8_str("bar"));
   6627 
   6628   // Check that we do not have access to other.p in env1. |other| is now
   6629   // the global object for env3 which has a different security token,
   6630   // so access should be blocked.
   6631   result = CompileRun("other.p");
   6632   CHECK(result->IsUndefined());
   6633 
   6634   // Detach the global for env3 and reattach it to env2.
   6635   env3->DetachGlobal();
   6636   env2->ReattachGlobal(global2);
   6637 
   6638   // Check that we have access to other.p again in env1.  |other| is now
   6639   // the global object for env2 which has the same security token as env1.
   6640   result = CompileRun("other.p");
   6641   CHECK(result->IsInt32());
   6642   CHECK_EQ(42, result->Int32Value());
   6643 
   6644   env2.Dispose();
   6645   env3.Dispose();
   6646 }
   6647 
   6648 
   6649 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
   6650 static bool NamedAccessBlocker(Local<v8::Object> global,
   6651                                Local<Value> name,
   6652                                v8::AccessType type,
   6653                                Local<Value> data) {
   6654   return Context::GetCurrent()->Global()->Equals(global) ||
   6655       allowed_access_type[type];
   6656 }
   6657 
   6658 
   6659 static bool IndexedAccessBlocker(Local<v8::Object> global,
   6660                                  uint32_t key,
   6661                                  v8::AccessType type,
   6662                                  Local<Value> data) {
   6663   return Context::GetCurrent()->Global()->Equals(global) ||
   6664       allowed_access_type[type];
   6665 }
   6666 
   6667 
   6668 static int g_echo_value = -1;
   6669 static v8::Handle<Value> EchoGetter(Local<String> name,
   6670                                     const AccessorInfo& info) {
   6671   return v8_num(g_echo_value);
   6672 }
   6673 
   6674 
   6675 static void EchoSetter(Local<String> name,
   6676                        Local<Value> value,
   6677                        const AccessorInfo&) {
   6678   if (value->IsNumber())
   6679     g_echo_value = value->Int32Value();
   6680 }
   6681 
   6682 
   6683 static v8::Handle<Value> UnreachableGetter(Local<String> name,
   6684                                            const AccessorInfo& info) {
   6685   CHECK(false);  // This function should not be called..
   6686   return v8::Undefined();
   6687 }
   6688 
   6689 
   6690 static void UnreachableSetter(Local<String>, Local<Value>,
   6691                               const AccessorInfo&) {
   6692   CHECK(false);  // This function should nto be called.
   6693 }
   6694 
   6695 
   6696 TEST(AccessControl) {
   6697   v8::HandleScope handle_scope;
   6698   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   6699 
   6700   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   6701                                            IndexedAccessBlocker);
   6702 
   6703   // Add an accessor accessible by cross-domain JS code.
   6704   global_template->SetAccessor(
   6705       v8_str("accessible_prop"),
   6706       EchoGetter, EchoSetter,
   6707       v8::Handle<Value>(),
   6708       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   6709 
   6710   // Add an accessor that is not accessible by cross-domain JS code.
   6711   global_template->SetAccessor(v8_str("blocked_prop"),
   6712                                UnreachableGetter, UnreachableSetter,
   6713                                v8::Handle<Value>(),
   6714                                v8::DEFAULT);
   6715 
   6716   // Create an environment
   6717   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
   6718   context0->Enter();
   6719 
   6720   v8::Handle<v8::Object> global0 = context0->Global();
   6721 
   6722   // Define a property with JS getter and setter.
   6723   CompileRun(
   6724       "function getter() { return 'getter'; };\n"
   6725       "function setter() { return 'setter'; }\n"
   6726       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   6727 
   6728   Local<Value> getter = global0->Get(v8_str("getter"));
   6729   Local<Value> setter = global0->Get(v8_str("setter"));
   6730 
   6731   // And define normal element.
   6732   global0->Set(239, v8_str("239"));
   6733 
   6734   // Define an element with JS getter and setter.
   6735   CompileRun(
   6736       "function el_getter() { return 'el_getter'; };\n"
   6737       "function el_setter() { return 'el_setter'; };\n"
   6738       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   6739 
   6740   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
   6741   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
   6742 
   6743   v8::HandleScope scope1;
   6744 
   6745   v8::Persistent<Context> context1 = Context::New();
   6746   context1->Enter();
   6747 
   6748   v8::Handle<v8::Object> global1 = context1->Global();
   6749   global1->Set(v8_str("other"), global0);
   6750 
   6751   // Access blocked property.
   6752   CompileRun("other.blocked_prop = 1");
   6753 
   6754   ExpectUndefined("other.blocked_prop");
   6755   ExpectUndefined(
   6756       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
   6757   ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
   6758 
   6759   // Enable ACCESS_HAS
   6760   allowed_access_type[v8::ACCESS_HAS] = true;
   6761   ExpectUndefined("other.blocked_prop");
   6762   // ... and now we can get the descriptor...
   6763   ExpectUndefined(
   6764       "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
   6765   // ... and enumerate the property.
   6766   ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
   6767   allowed_access_type[v8::ACCESS_HAS] = false;
   6768 
   6769   // Access blocked element.
   6770   CompileRun("other[239] = 1");
   6771 
   6772   ExpectUndefined("other[239]");
   6773   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
   6774   ExpectFalse("propertyIsEnumerable.call(other, '239')");
   6775 
   6776   // Enable ACCESS_HAS
   6777   allowed_access_type[v8::ACCESS_HAS] = true;
   6778   ExpectUndefined("other[239]");
   6779   // ... and now we can get the descriptor...
   6780   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
   6781   // ... and enumerate the property.
   6782   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   6783   allowed_access_type[v8::ACCESS_HAS] = false;
   6784 
   6785   // Access a property with JS accessor.
   6786   CompileRun("other.js_accessor_p = 2");
   6787 
   6788   ExpectUndefined("other.js_accessor_p");
   6789   ExpectUndefined(
   6790       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
   6791 
   6792   // Enable ACCESS_HAS.
   6793   allowed_access_type[v8::ACCESS_HAS] = true;
   6794   ExpectUndefined("other.js_accessor_p");
   6795   ExpectUndefined(
   6796       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
   6797   ExpectUndefined(
   6798       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
   6799   ExpectUndefined(
   6800       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   6801   allowed_access_type[v8::ACCESS_HAS] = false;
   6802 
   6803   // Enable both ACCESS_HAS and ACCESS_GET.
   6804   allowed_access_type[v8::ACCESS_HAS] = true;
   6805   allowed_access_type[v8::ACCESS_GET] = true;
   6806 
   6807   ExpectString("other.js_accessor_p", "getter");
   6808   ExpectObject(
   6809       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   6810   ExpectUndefined(
   6811       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
   6812   ExpectUndefined(
   6813       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   6814 
   6815   allowed_access_type[v8::ACCESS_GET] = false;
   6816   allowed_access_type[v8::ACCESS_HAS] = false;
   6817 
   6818   // Enable both ACCESS_HAS and ACCESS_SET.
   6819   allowed_access_type[v8::ACCESS_HAS] = true;
   6820   allowed_access_type[v8::ACCESS_SET] = true;
   6821 
   6822   ExpectUndefined("other.js_accessor_p");
   6823   ExpectUndefined(
   6824       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
   6825   ExpectObject(
   6826       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   6827   ExpectUndefined(
   6828       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   6829 
   6830   allowed_access_type[v8::ACCESS_SET] = false;
   6831   allowed_access_type[v8::ACCESS_HAS] = false;
   6832 
   6833   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
   6834   allowed_access_type[v8::ACCESS_HAS] = true;
   6835   allowed_access_type[v8::ACCESS_GET] = true;
   6836   allowed_access_type[v8::ACCESS_SET] = true;
   6837 
   6838   ExpectString("other.js_accessor_p", "getter");
   6839   ExpectObject(
   6840       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   6841   ExpectObject(
   6842       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   6843   ExpectUndefined(
   6844       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   6845 
   6846   allowed_access_type[v8::ACCESS_SET] = false;
   6847   allowed_access_type[v8::ACCESS_GET] = false;
   6848   allowed_access_type[v8::ACCESS_HAS] = false;
   6849 
   6850   // Access an element with JS accessor.
   6851   CompileRun("other[42] = 2");
   6852 
   6853   ExpectUndefined("other[42]");
   6854   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
   6855 
   6856   // Enable ACCESS_HAS.
   6857   allowed_access_type[v8::ACCESS_HAS] = true;
   6858   ExpectUndefined("other[42]");
   6859   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
   6860   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
   6861   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   6862   allowed_access_type[v8::ACCESS_HAS] = false;
   6863 
   6864   // Enable both ACCESS_HAS and ACCESS_GET.
   6865   allowed_access_type[v8::ACCESS_HAS] = true;
   6866   allowed_access_type[v8::ACCESS_GET] = true;
   6867 
   6868   ExpectString("other[42]", "el_getter");
   6869   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   6870   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
   6871   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   6872 
   6873   allowed_access_type[v8::ACCESS_GET] = false;
   6874   allowed_access_type[v8::ACCESS_HAS] = false;
   6875 
   6876   // Enable both ACCESS_HAS and ACCESS_SET.
   6877   allowed_access_type[v8::ACCESS_HAS] = true;
   6878   allowed_access_type[v8::ACCESS_SET] = true;
   6879 
   6880   ExpectUndefined("other[42]");
   6881   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
   6882   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   6883   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   6884 
   6885   allowed_access_type[v8::ACCESS_SET] = false;
   6886   allowed_access_type[v8::ACCESS_HAS] = false;
   6887 
   6888   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
   6889   allowed_access_type[v8::ACCESS_HAS] = true;
   6890   allowed_access_type[v8::ACCESS_GET] = true;
   6891   allowed_access_type[v8::ACCESS_SET] = true;
   6892 
   6893   ExpectString("other[42]", "el_getter");
   6894   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   6895   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   6896   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   6897 
   6898   allowed_access_type[v8::ACCESS_SET] = false;
   6899   allowed_access_type[v8::ACCESS_GET] = false;
   6900   allowed_access_type[v8::ACCESS_HAS] = false;
   6901 
   6902   v8::Handle<Value> value;
   6903 
   6904   // Access accessible property
   6905   value = CompileRun("other.accessible_prop = 3");
   6906   CHECK(value->IsNumber());
   6907   CHECK_EQ(3, value->Int32Value());
   6908   CHECK_EQ(3, g_echo_value);
   6909 
   6910   value = CompileRun("other.accessible_prop");
   6911   CHECK(value->IsNumber());
   6912   CHECK_EQ(3, value->Int32Value());
   6913 
   6914   value = CompileRun(
   6915       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   6916   CHECK(value->IsNumber());
   6917   CHECK_EQ(3, value->Int32Value());
   6918 
   6919   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   6920   CHECK(value->IsTrue());
   6921 
   6922   // Enumeration doesn't enumerate accessors from inaccessible objects in
   6923   // the prototype chain even if the accessors are in themselves accessible.
   6924   value =
   6925       CompileRun("(function(){var obj = {'__proto__':other};"
   6926                  "for (var p in obj)"
   6927                  "   if (p == 'accessible_prop' || p == 'blocked_prop') {"
   6928                  "     return false;"
   6929                  "   }"
   6930                  "return true;})()");
   6931   CHECK(value->IsTrue());
   6932 
   6933   context1->Exit();
   6934   context0->Exit();
   6935   context1.Dispose();
   6936   context0.Dispose();
   6937 }
   6938 
   6939 
   6940 TEST(AccessControlES5) {
   6941   v8::HandleScope handle_scope;
   6942   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   6943 
   6944   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   6945                                            IndexedAccessBlocker);
   6946 
   6947   // Add accessible accessor.
   6948   global_template->SetAccessor(
   6949       v8_str("accessible_prop"),
   6950       EchoGetter, EchoSetter,
   6951       v8::Handle<Value>(),
   6952       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   6953 
   6954 
   6955   // Add an accessor that is not accessible by cross-domain JS code.
   6956   global_template->SetAccessor(v8_str("blocked_prop"),
   6957                                UnreachableGetter, UnreachableSetter,
   6958                                v8::Handle<Value>(),
   6959                                v8::DEFAULT);
   6960 
   6961   // Create an environment
   6962   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
   6963   context0->Enter();
   6964 
   6965   v8::Handle<v8::Object> global0 = context0->Global();
   6966 
   6967   v8::Persistent<Context> context1 = Context::New();
   6968   context1->Enter();
   6969   v8::Handle<v8::Object> global1 = context1->Global();
   6970   global1->Set(v8_str("other"), global0);
   6971 
   6972   // Regression test for issue 1154.
   6973   ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
   6974 
   6975   ExpectUndefined("other.blocked_prop");
   6976 
   6977   // Regression test for issue 1027.
   6978   CompileRun("Object.defineProperty(\n"
   6979              "  other, 'blocked_prop', {configurable: false})");
   6980   ExpectUndefined("other.blocked_prop");
   6981   ExpectUndefined(
   6982       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
   6983 
   6984   // Regression test for issue 1171.
   6985   ExpectTrue("Object.isExtensible(other)");
   6986   CompileRun("Object.preventExtensions(other)");
   6987   ExpectTrue("Object.isExtensible(other)");
   6988 
   6989   // Object.seal and Object.freeze.
   6990   CompileRun("Object.freeze(other)");
   6991   ExpectTrue("Object.isExtensible(other)");
   6992 
   6993   CompileRun("Object.seal(other)");
   6994   ExpectTrue("Object.isExtensible(other)");
   6995 
   6996   // Regression test for issue 1250.
   6997   // Make sure that we can set the accessible accessors value using normal
   6998   // assignment.
   6999   CompileRun("other.accessible_prop = 42");
   7000   CHECK_EQ(42, g_echo_value);
   7001 
   7002   v8::Handle<Value> value;
   7003   // We follow Safari in ignoring assignments to host object accessors.
   7004   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
   7005   value = CompileRun("other.accessible_prop == 42");
   7006   CHECK(value->IsTrue());
   7007 }
   7008 
   7009 
   7010 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
   7011                                             Local<Value> name,
   7012                                             v8::AccessType type,
   7013                                             Local<Value> data) {
   7014   return false;
   7015 }
   7016 
   7017 
   7018 static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
   7019                                               uint32_t key,
   7020                                               v8::AccessType type,
   7021                                               Local<Value> data) {
   7022   return false;
   7023 }
   7024 
   7025 
   7026 THREADED_TEST(AccessControlGetOwnPropertyNames) {
   7027   v8::HandleScope handle_scope;
   7028   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
   7029 
   7030   obj_template->Set(v8_str("x"), v8::Integer::New(42));
   7031   obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
   7032                                         GetOwnPropertyNamesIndexedBlocker);
   7033 
   7034   // Create an environment
   7035   v8::Persistent<Context> context0 = Context::New(NULL, obj_template);
   7036   context0->Enter();
   7037 
   7038   v8::Handle<v8::Object> global0 = context0->Global();
   7039 
   7040   v8::HandleScope scope1;
   7041 
   7042   v8::Persistent<Context> context1 = Context::New();
   7043   context1->Enter();
   7044 
   7045   v8::Handle<v8::Object> global1 = context1->Global();
   7046   global1->Set(v8_str("other"), global0);
   7047   global1->Set(v8_str("object"), obj_template->NewInstance());
   7048 
   7049   v8::Handle<Value> value;
   7050 
   7051   // Attempt to get the property names of the other global object and
   7052   // of an object that requires access checks.  Accessing the other
   7053   // global object should be blocked by access checks on the global
   7054   // proxy object.  Accessing the object that requires access checks
   7055   // is blocked by the access checks on the object itself.
   7056   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
   7057   CHECK(value->IsTrue());
   7058 
   7059   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
   7060   CHECK(value->IsTrue());
   7061 
   7062   context1->Exit();
   7063   context0->Exit();
   7064   context1.Dispose();
   7065   context0.Dispose();
   7066 }
   7067 
   7068 
   7069 static v8::Handle<v8::Array> NamedPropertyEnumerator(const AccessorInfo& info) {
   7070   v8::Handle<v8::Array> result = v8::Array::New(1);
   7071   result->Set(0, v8_str("x"));
   7072   return result;
   7073 }
   7074 
   7075 
   7076 THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
   7077   v8::HandleScope handle_scope;
   7078   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
   7079 
   7080   obj_template->Set(v8_str("x"), v8::Integer::New(42));
   7081   obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
   7082                                         NamedPropertyEnumerator);
   7083 
   7084   LocalContext context;
   7085   v8::Handle<v8::Object> global = context->Global();
   7086   global->Set(v8_str("object"), obj_template->NewInstance());
   7087 
   7088   v8::Handle<Value> value =
   7089       CompileRun("Object.getOwnPropertyNames(object).join(',')");
   7090   CHECK_EQ(v8_str("x"), value);
   7091 }
   7092 
   7093 
   7094 static v8::Handle<Value> ConstTenGetter(Local<String> name,
   7095                                         const AccessorInfo& info) {
   7096   return v8_num(10);
   7097 }
   7098 
   7099 
   7100 THREADED_TEST(CrossDomainAccessors) {
   7101   v8::HandleScope handle_scope;
   7102 
   7103   v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
   7104 
   7105   v8::Handle<v8::ObjectTemplate> global_template =
   7106       func_template->InstanceTemplate();
   7107 
   7108   v8::Handle<v8::ObjectTemplate> proto_template =
   7109       func_template->PrototypeTemplate();
   7110 
   7111   // Add an accessor to proto that's accessible by cross-domain JS code.
   7112   proto_template->SetAccessor(v8_str("accessible"),
   7113                               ConstTenGetter, 0,
   7114                               v8::Handle<Value>(),
   7115                               v8::ALL_CAN_READ);
   7116 
   7117   // Add an accessor that is not accessible by cross-domain JS code.
   7118   global_template->SetAccessor(v8_str("unreachable"),
   7119                                UnreachableGetter, 0,
   7120                                v8::Handle<Value>(),
   7121                                v8::DEFAULT);
   7122 
   7123   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
   7124   context0->Enter();
   7125 
   7126   Local<v8::Object> global = context0->Global();
   7127   // Add a normal property that shadows 'accessible'
   7128   global->Set(v8_str("accessible"), v8_num(11));
   7129 
   7130   // Enter a new context.
   7131   v8::HandleScope scope1;
   7132   v8::Persistent<Context> context1 = Context::New();
   7133   context1->Enter();
   7134 
   7135   v8::Handle<v8::Object> global1 = context1->Global();
   7136   global1->Set(v8_str("other"), global);
   7137 
   7138   // Should return 10, instead of 11
   7139   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
   7140   CHECK(value->IsNumber());
   7141   CHECK_EQ(10, value->Int32Value());
   7142 
   7143   value = v8_compile("other.unreachable")->Run();
   7144   CHECK(value->IsUndefined());
   7145 
   7146   context1->Exit();
   7147   context0->Exit();
   7148   context1.Dispose();
   7149   context0.Dispose();
   7150 }
   7151 
   7152 
   7153 static int named_access_count = 0;
   7154 static int indexed_access_count = 0;
   7155 
   7156 static bool NamedAccessCounter(Local<v8::Object> global,
   7157                                Local<Value> name,
   7158                                v8::AccessType type,
   7159                                Local<Value> data) {
   7160   named_access_count++;
   7161   return true;
   7162 }
   7163 
   7164 
   7165 static bool IndexedAccessCounter(Local<v8::Object> global,
   7166                                  uint32_t key,
   7167                                  v8::AccessType type,
   7168                                  Local<Value> data) {
   7169   indexed_access_count++;
   7170   return true;
   7171 }
   7172 
   7173 
   7174 // This one is too easily disturbed by other tests.
   7175 TEST(AccessControlIC) {
   7176   named_access_count = 0;
   7177   indexed_access_count = 0;
   7178 
   7179   v8::HandleScope handle_scope;
   7180 
   7181   // Create an environment.
   7182   v8::Persistent<Context> context0 = Context::New();
   7183   context0->Enter();
   7184 
   7185   // Create an object that requires access-check functions to be
   7186   // called for cross-domain access.
   7187   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   7188   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   7189                                            IndexedAccessCounter);
   7190   Local<v8::Object> object = object_template->NewInstance();
   7191 
   7192   v8::HandleScope scope1;
   7193 
   7194   // Create another environment.
   7195   v8::Persistent<Context> context1 = Context::New();
   7196   context1->Enter();
   7197 
   7198   // Make easy access to the object from the other environment.
   7199   v8::Handle<v8::Object> global1 = context1->Global();
   7200   global1->Set(v8_str("obj"), object);
   7201 
   7202   v8::Handle<Value> value;
   7203 
   7204   // Check that the named access-control function is called every time.
   7205   CompileRun("function testProp(obj) {"
   7206              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   7207              "  for (var j = 0; j < 10; j++) obj.prop;"
   7208              "  return obj.prop"
   7209              "}");
   7210   value = CompileRun("testProp(obj)");
   7211   CHECK(value->IsNumber());
   7212   CHECK_EQ(1, value->Int32Value());
   7213   CHECK_EQ(21, named_access_count);
   7214 
   7215   // Check that the named access-control function is called every time.
   7216   CompileRun("var p = 'prop';"
   7217              "function testKeyed(obj) {"
   7218              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   7219              "  for (var j = 0; j < 10; j++) obj[p];"
   7220              "  return obj[p];"
   7221              "}");
   7222   // Use obj which requires access checks.  No inline caching is used
   7223   // in that case.
   7224   value = CompileRun("testKeyed(obj)");
   7225   CHECK(value->IsNumber());
   7226   CHECK_EQ(1, value->Int32Value());
   7227   CHECK_EQ(42, named_access_count);
   7228   // Force the inline caches into generic state and try again.
   7229   CompileRun("testKeyed({ a: 0 })");
   7230   CompileRun("testKeyed({ b: 0 })");
   7231   value = CompileRun("testKeyed(obj)");
   7232   CHECK(value->IsNumber());
   7233   CHECK_EQ(1, value->Int32Value());
   7234   CHECK_EQ(63, named_access_count);
   7235 
   7236   // Check that the indexed access-control function is called every time.
   7237   CompileRun("function testIndexed(obj) {"
   7238              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   7239              "  for (var j = 0; j < 10; j++) obj[0];"
   7240              "  return obj[0]"
   7241              "}");
   7242   value = CompileRun("testIndexed(obj)");
   7243   CHECK(value->IsNumber());
   7244   CHECK_EQ(1, value->Int32Value());
   7245   CHECK_EQ(21, indexed_access_count);
   7246   // Force the inline caches into generic state.
   7247   CompileRun("testIndexed(new Array(1))");
   7248   // Test that the indexed access check is called.
   7249   value = CompileRun("testIndexed(obj)");
   7250   CHECK(value->IsNumber());
   7251   CHECK_EQ(1, value->Int32Value());
   7252   CHECK_EQ(42, indexed_access_count);
   7253 
   7254   // Check that the named access check is called when invoking
   7255   // functions on an object that requires access checks.
   7256   CompileRun("obj.f = function() {}");
   7257   CompileRun("function testCallNormal(obj) {"
   7258              "  for (var i = 0; i < 10; i++) obj.f();"
   7259              "}");
   7260   CompileRun("testCallNormal(obj)");
   7261   CHECK_EQ(74, named_access_count);
   7262 
   7263   // Force obj into slow case.
   7264   value = CompileRun("delete obj.prop");
   7265   CHECK(value->BooleanValue());
   7266   // Force inline caches into dictionary probing mode.
   7267   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   7268   // Test that the named access check is called.
   7269   value = CompileRun("testProp(obj);");
   7270   CHECK(value->IsNumber());
   7271   CHECK_EQ(1, value->Int32Value());
   7272   CHECK_EQ(96, named_access_count);
   7273 
   7274   // Force the call inline cache into dictionary probing mode.
   7275   CompileRun("o.f = function() {}; testCallNormal(o)");
   7276   // Test that the named access check is still called for each
   7277   // invocation of the function.
   7278   value = CompileRun("testCallNormal(obj)");
   7279   CHECK_EQ(106, named_access_count);
   7280 
   7281   context1->Exit();
   7282   context0->Exit();
   7283   context1.Dispose();
   7284   context0.Dispose();
   7285 }
   7286 
   7287 
   7288 static bool NamedAccessFlatten(Local<v8::Object> global,
   7289                                Local<Value> name,
   7290                                v8::AccessType type,
   7291                                Local<Value> data) {
   7292   char buf[100];
   7293   int len;
   7294 
   7295   CHECK(name->IsString());
   7296 
   7297   memset(buf, 0x1, sizeof(buf));
   7298   len = name.As<String>()->WriteAscii(buf);
   7299   CHECK_EQ(4, len);
   7300 
   7301   uint16_t buf2[100];
   7302 
   7303   memset(buf, 0x1, sizeof(buf));
   7304   len = name.As<String>()->Write(buf2);
   7305   CHECK_EQ(4, len);
   7306 
   7307   return true;
   7308 }
   7309 
   7310 
   7311 static bool IndexedAccessFlatten(Local<v8::Object> global,
   7312                                  uint32_t key,
   7313                                  v8::AccessType type,
   7314                                  Local<Value> data) {
   7315   return true;
   7316 }
   7317 
   7318 
   7319 // Regression test.  In access checks, operations that may cause
   7320 // garbage collection are not allowed.  It used to be the case that
   7321 // using the Write operation on a string could cause a garbage
   7322 // collection due to flattening of the string.  This is no longer the
   7323 // case.
   7324 THREADED_TEST(AccessControlFlatten) {
   7325   named_access_count = 0;
   7326   indexed_access_count = 0;
   7327 
   7328   v8::HandleScope handle_scope;
   7329 
   7330   // Create an environment.
   7331   v8::Persistent<Context> context0 = Context::New();
   7332   context0->Enter();
   7333 
   7334   // Create an object that requires access-check functions to be
   7335   // called for cross-domain access.
   7336   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   7337   object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
   7338                                            IndexedAccessFlatten);
   7339   Local<v8::Object> object = object_template->NewInstance();
   7340 
   7341   v8::HandleScope scope1;
   7342 
   7343   // Create another environment.
   7344   v8::Persistent<Context> context1 = Context::New();
   7345   context1->Enter();
   7346 
   7347   // Make easy access to the object from the other environment.
   7348   v8::Handle<v8::Object> global1 = context1->Global();
   7349   global1->Set(v8_str("obj"), object);
   7350 
   7351   v8::Handle<Value> value;
   7352 
   7353   value = v8_compile("var p = 'as' + 'df';")->Run();
   7354   value = v8_compile("obj[p];")->Run();
   7355 
   7356   context1->Exit();
   7357   context0->Exit();
   7358   context1.Dispose();
   7359   context0.Dispose();
   7360 }
   7361 
   7362 
   7363 static v8::Handle<Value> AccessControlNamedGetter(
   7364     Local<String>, const AccessorInfo&) {
   7365   return v8::Integer::New(42);
   7366 }
   7367 
   7368 
   7369 static v8::Handle<Value> AccessControlNamedSetter(
   7370     Local<String>, Local<Value> value, const AccessorInfo&) {
   7371   return value;
   7372 }
   7373 
   7374 
   7375 static v8::Handle<Value> AccessControlIndexedGetter(
   7376       uint32_t index,
   7377       const AccessorInfo& info) {
   7378   return v8_num(42);
   7379 }
   7380 
   7381 
   7382 static v8::Handle<Value> AccessControlIndexedSetter(
   7383     uint32_t, Local<Value> value, const AccessorInfo&) {
   7384   return value;
   7385 }
   7386 
   7387 
   7388 THREADED_TEST(AccessControlInterceptorIC) {
   7389   named_access_count = 0;
   7390   indexed_access_count = 0;
   7391 
   7392   v8::HandleScope handle_scope;
   7393 
   7394   // Create an environment.
   7395   v8::Persistent<Context> context0 = Context::New();
   7396   context0->Enter();
   7397 
   7398   // Create an object that requires access-check functions to be
   7399   // called for cross-domain access.  The object also has interceptors
   7400   // interceptor.
   7401   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   7402   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   7403                                            IndexedAccessCounter);
   7404   object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
   7405                                            AccessControlNamedSetter);
   7406   object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
   7407                                              AccessControlIndexedSetter);
   7408   Local<v8::Object> object = object_template->NewInstance();
   7409 
   7410   v8::HandleScope scope1;
   7411 
   7412   // Create another environment.
   7413   v8::Persistent<Context> context1 = Context::New();
   7414   context1->Enter();
   7415 
   7416   // Make easy access to the object from the other environment.
   7417   v8::Handle<v8::Object> global1 = context1->Global();
   7418   global1->Set(v8_str("obj"), object);
   7419 
   7420   v8::Handle<Value> value;
   7421 
   7422   // Check that the named access-control function is called every time
   7423   // eventhough there is an interceptor on the object.
   7424   value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
   7425   value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
   7426                      "obj.x")->Run();
   7427   CHECK(value->IsNumber());
   7428   CHECK_EQ(42, value->Int32Value());
   7429   CHECK_EQ(21, named_access_count);
   7430 
   7431   value = v8_compile("var p = 'x';")->Run();
   7432   value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
   7433   value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
   7434                      "obj[p]")->Run();
   7435   CHECK(value->IsNumber());
   7436   CHECK_EQ(42, value->Int32Value());
   7437   CHECK_EQ(42, named_access_count);
   7438 
   7439   // Check that the indexed access-control function is called every
   7440   // time eventhough there is an interceptor on the object.
   7441   value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
   7442   value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
   7443                      "obj[0]")->Run();
   7444   CHECK(value->IsNumber());
   7445   CHECK_EQ(42, value->Int32Value());
   7446   CHECK_EQ(21, indexed_access_count);
   7447 
   7448   context1->Exit();
   7449   context0->Exit();
   7450   context1.Dispose();
   7451   context0.Dispose();
   7452 }
   7453 
   7454 
   7455 THREADED_TEST(Version) {
   7456   v8::V8::GetVersion();
   7457 }
   7458 
   7459 
   7460 static v8::Handle<Value> InstanceFunctionCallback(const v8::Arguments& args) {
   7461   ApiTestFuzzer::Fuzz();
   7462   return v8_num(12);
   7463 }
   7464 
   7465 
   7466 THREADED_TEST(InstanceProperties) {
   7467   v8::HandleScope handle_scope;
   7468   LocalContext context;
   7469 
   7470   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   7471   Local<ObjectTemplate> instance = t->InstanceTemplate();
   7472 
   7473   instance->Set(v8_str("x"), v8_num(42));
   7474   instance->Set(v8_str("f"),
   7475                 v8::FunctionTemplate::New(InstanceFunctionCallback));
   7476 
   7477   Local<Value> o = t->GetFunction()->NewInstance();
   7478 
   7479   context->Global()->Set(v8_str("i"), o);
   7480   Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
   7481   CHECK_EQ(42, value->Int32Value());
   7482 
   7483   value = Script::Compile(v8_str("i.f()"))->Run();
   7484   CHECK_EQ(12, value->Int32Value());
   7485 }
   7486 
   7487 
   7488 static v8::Handle<Value>
   7489 GlobalObjectInstancePropertiesGet(Local<String> key, const AccessorInfo&) {
   7490   ApiTestFuzzer::Fuzz();
   7491   return v8::Handle<Value>();
   7492 }
   7493 
   7494 
   7495 THREADED_TEST(GlobalObjectInstanceProperties) {
   7496   v8::HandleScope handle_scope;
   7497 
   7498   Local<Value> global_object;
   7499 
   7500   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   7501   t->InstanceTemplate()->SetNamedPropertyHandler(
   7502       GlobalObjectInstancePropertiesGet);
   7503   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   7504   instance_template->Set(v8_str("x"), v8_num(42));
   7505   instance_template->Set(v8_str("f"),
   7506                          v8::FunctionTemplate::New(InstanceFunctionCallback));
   7507 
   7508   // The script to check how Crankshaft compiles missing global function
   7509   // invocations.  function g is not defined and should throw on call.
   7510   const char* script =
   7511       "function wrapper(call) {"
   7512       "  var x = 0, y = 1;"
   7513       "  for (var i = 0; i < 1000; i++) {"
   7514       "    x += i * 100;"
   7515       "    y += i * 100;"
   7516       "  }"
   7517       "  if (call) g();"
   7518       "}"
   7519       "for (var i = 0; i < 17; i++) wrapper(false);"
   7520       "var thrown = 0;"
   7521       "try { wrapper(true); } catch (e) { thrown = 1; };"
   7522       "thrown";
   7523 
   7524   {
   7525     LocalContext env(NULL, instance_template);
   7526     // Hold on to the global object so it can be used again in another
   7527     // environment initialization.
   7528     global_object = env->Global();
   7529 
   7530     Local<Value> value = Script::Compile(v8_str("x"))->Run();
   7531     CHECK_EQ(42, value->Int32Value());
   7532     value = Script::Compile(v8_str("f()"))->Run();
   7533     CHECK_EQ(12, value->Int32Value());
   7534     value = Script::Compile(v8_str(script))->Run();
   7535     CHECK_EQ(1, value->Int32Value());
   7536   }
   7537 
   7538   {
   7539     // Create new environment reusing the global object.
   7540     LocalContext env(NULL, instance_template, global_object);
   7541     Local<Value> value = Script::Compile(v8_str("x"))->Run();
   7542     CHECK_EQ(42, value->Int32Value());
   7543     value = Script::Compile(v8_str("f()"))->Run();
   7544     CHECK_EQ(12, value->Int32Value());
   7545     value = Script::Compile(v8_str(script))->Run();
   7546     CHECK_EQ(1, value->Int32Value());
   7547   }
   7548 }
   7549 
   7550 
   7551 THREADED_TEST(CallKnownGlobalReceiver) {
   7552   v8::HandleScope handle_scope;
   7553 
   7554   Local<Value> global_object;
   7555 
   7556   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   7557   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   7558 
   7559   // The script to check that we leave global object not
   7560   // global object proxy on stack when we deoptimize from inside
   7561   // arguments evaluation.
   7562   // To provoke error we need to both force deoptimization
   7563   // from arguments evaluation and to force CallIC to take
   7564   // CallIC_Miss code path that can't cope with global proxy.
   7565   const char* script =
   7566       "function bar(x, y) { try { } finally { } }"
   7567       "function baz(x) { try { } finally { } }"
   7568       "function bom(x) { try { } finally { } }"
   7569       "function foo(x) { bar([x], bom(2)); }"
   7570       "for (var i = 0; i < 10000; i++) foo(1);"
   7571       "foo";
   7572 
   7573   Local<Value> foo;
   7574   {
   7575     LocalContext env(NULL, instance_template);
   7576     // Hold on to the global object so it can be used again in another
   7577     // environment initialization.
   7578     global_object = env->Global();
   7579     foo = Script::Compile(v8_str(script))->Run();
   7580   }
   7581 
   7582   {
   7583     // Create new environment reusing the global object.
   7584     LocalContext env(NULL, instance_template, global_object);
   7585     env->Global()->Set(v8_str("foo"), foo);
   7586     Script::Compile(v8_str("foo()"))->Run();
   7587   }
   7588 }
   7589 
   7590 
   7591 static v8::Handle<Value> ShadowFunctionCallback(const v8::Arguments& args) {
   7592   ApiTestFuzzer::Fuzz();
   7593   return v8_num(42);
   7594 }
   7595 
   7596 
   7597 static int shadow_y;
   7598 static int shadow_y_setter_call_count;
   7599 static int shadow_y_getter_call_count;
   7600 
   7601 
   7602 static void ShadowYSetter(Local<String>, Local<Value>, const AccessorInfo&) {
   7603   shadow_y_setter_call_count++;
   7604   shadow_y = 42;
   7605 }
   7606 
   7607 
   7608 static v8::Handle<Value> ShadowYGetter(Local<String> name,
   7609                                        const AccessorInfo& info) {
   7610   ApiTestFuzzer::Fuzz();
   7611   shadow_y_getter_call_count++;
   7612   return v8_num(shadow_y);
   7613 }
   7614 
   7615 
   7616 static v8::Handle<Value> ShadowIndexedGet(uint32_t index,
   7617                                           const AccessorInfo& info) {
   7618   return v8::Handle<Value>();
   7619 }
   7620 
   7621 
   7622 static v8::Handle<Value> ShadowNamedGet(Local<String> key,
   7623                                         const AccessorInfo&) {
   7624   return v8::Handle<Value>();
   7625 }
   7626 
   7627 
   7628 THREADED_TEST(ShadowObject) {
   7629   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   7630   v8::HandleScope handle_scope;
   7631 
   7632   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
   7633   LocalContext context(NULL, global_template);
   7634 
   7635   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   7636   t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
   7637   t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
   7638   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   7639   Local<ObjectTemplate> instance = t->InstanceTemplate();
   7640 
   7641   // Only allow calls of f on instances of t.
   7642   Local<v8::Signature> signature = v8::Signature::New(t);
   7643   proto->Set(v8_str("f"),
   7644              v8::FunctionTemplate::New(ShadowFunctionCallback,
   7645                                        Local<Value>(),
   7646                                        signature));
   7647   proto->Set(v8_str("x"), v8_num(12));
   7648 
   7649   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   7650 
   7651   Local<Value> o = t->GetFunction()->NewInstance();
   7652   context->Global()->Set(v8_str("__proto__"), o);
   7653 
   7654   Local<Value> value =
   7655       Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
   7656   CHECK(value->IsBoolean());
   7657   CHECK(!value->BooleanValue());
   7658 
   7659   value = Script::Compile(v8_str("x"))->Run();
   7660   CHECK_EQ(12, value->Int32Value());
   7661 
   7662   value = Script::Compile(v8_str("f()"))->Run();
   7663   CHECK_EQ(42, value->Int32Value());
   7664 
   7665   Script::Compile(v8_str("y = 42"))->Run();
   7666   CHECK_EQ(1, shadow_y_setter_call_count);
   7667   value = Script::Compile(v8_str("y"))->Run();
   7668   CHECK_EQ(1, shadow_y_getter_call_count);
   7669   CHECK_EQ(42, value->Int32Value());
   7670 }
   7671 
   7672 
   7673 THREADED_TEST(HiddenPrototype) {
   7674   v8::HandleScope handle_scope;
   7675   LocalContext context;
   7676 
   7677   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
   7678   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   7679   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   7680   t1->SetHiddenPrototype(true);
   7681   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   7682   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   7683   t2->SetHiddenPrototype(true);
   7684   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   7685   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   7686   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   7687 
   7688   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   7689   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   7690   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   7691   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   7692 
   7693   // Setting the prototype on an object skips hidden prototypes.
   7694   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   7695   o0->Set(v8_str("__proto__"), o1);
   7696   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   7697   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   7698   o0->Set(v8_str("__proto__"), o2);
   7699   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   7700   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   7701   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   7702   o0->Set(v8_str("__proto__"), o3);
   7703   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   7704   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   7705   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   7706   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   7707 
   7708   // Getting the prototype of o0 should get the first visible one
   7709   // which is o3.  Therefore, z should not be defined on the prototype
   7710   // object.
   7711   Local<Value> proto = o0->Get(v8_str("__proto__"));
   7712   CHECK(proto->IsObject());
   7713   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
   7714 }
   7715 
   7716 
   7717 THREADED_TEST(SetPrototype) {
   7718   v8::HandleScope handle_scope;
   7719   LocalContext context;
   7720 
   7721   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
   7722   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   7723   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   7724   t1->SetHiddenPrototype(true);
   7725   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   7726   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   7727   t2->SetHiddenPrototype(true);
   7728   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   7729   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   7730   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   7731 
   7732   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   7733   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   7734   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   7735   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   7736 
   7737   // Setting the prototype on an object does not skip hidden prototypes.
   7738   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   7739   CHECK(o0->SetPrototype(o1));
   7740   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   7741   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   7742   CHECK(o1->SetPrototype(o2));
   7743   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   7744   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   7745   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   7746   CHECK(o2->SetPrototype(o3));
   7747   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   7748   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   7749   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   7750   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   7751 
   7752   // Getting the prototype of o0 should get the first visible one
   7753   // which is o3.  Therefore, z should not be defined on the prototype
   7754   // object.
   7755   Local<Value> proto = o0->Get(v8_str("__proto__"));
   7756   CHECK(proto->IsObject());
   7757   CHECK_EQ(proto.As<v8::Object>(), o3);
   7758 
   7759   // However, Object::GetPrototype ignores hidden prototype.
   7760   Local<Value> proto0 = o0->GetPrototype();
   7761   CHECK(proto0->IsObject());
   7762   CHECK_EQ(proto0.As<v8::Object>(), o1);
   7763 
   7764   Local<Value> proto1 = o1->GetPrototype();
   7765   CHECK(proto1->IsObject());
   7766   CHECK_EQ(proto1.As<v8::Object>(), o2);
   7767 
   7768   Local<Value> proto2 = o2->GetPrototype();
   7769   CHECK(proto2->IsObject());
   7770   CHECK_EQ(proto2.As<v8::Object>(), o3);
   7771 }
   7772 
   7773 
   7774 // Getting property names of an object with a prototype chain that
   7775 // triggers dictionary elements in GetLocalPropertyNames() shouldn't
   7776 // crash the runtime.
   7777 THREADED_TEST(Regress91517) {
   7778   i::FLAG_allow_natives_syntax = true;
   7779   v8::HandleScope handle_scope;
   7780   LocalContext context;
   7781 
   7782   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   7783   t1->SetHiddenPrototype(true);
   7784   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   7785   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   7786   t2->SetHiddenPrototype(true);
   7787   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   7788   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New());
   7789   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   7790   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   7791   t3->SetHiddenPrototype(true);
   7792   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   7793   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
   7794   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   7795 
   7796   // Force dictionary-based properties.
   7797   i::ScopedVector<char> name_buf(1024);
   7798   for (int i = 1; i <= 1000; i++) {
   7799     i::OS::SNPrintF(name_buf, "sdf%d", i);
   7800     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   7801   }
   7802 
   7803   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   7804   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   7805   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   7806   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
   7807 
   7808   // Create prototype chain of hidden prototypes.
   7809   CHECK(o4->SetPrototype(o3));
   7810   CHECK(o3->SetPrototype(o2));
   7811   CHECK(o2->SetPrototype(o1));
   7812 
   7813   // Call the runtime version of GetLocalPropertyNames() on the natively
   7814   // created object through JavaScript.
   7815   context->Global()->Set(v8_str("obj"), o4);
   7816   CompileRun("var names = %GetLocalPropertyNames(obj);");
   7817 
   7818   ExpectInt32("names.length", 1006);
   7819   ExpectTrue("names.indexOf(\"baz\") >= 0");
   7820   ExpectTrue("names.indexOf(\"boo\") >= 0");
   7821   ExpectTrue("names.indexOf(\"foo\") >= 0");
   7822   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
   7823   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   7824   ExpectFalse("names[1005] == undefined");
   7825 }
   7826 
   7827 
   7828 THREADED_TEST(FunctionReadOnlyPrototype) {
   7829   v8::HandleScope handle_scope;
   7830   LocalContext context;
   7831 
   7832   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   7833   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
   7834   t1->ReadOnlyPrototype();
   7835   context->Global()->Set(v8_str("func1"), t1->GetFunction());
   7836   // Configured value of ReadOnly flag.
   7837   CHECK(CompileRun(
   7838       "(function() {"
   7839       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   7840       "  return (descriptor['writable'] == false);"
   7841       "})()")->BooleanValue());
   7842   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
   7843   CHECK_EQ(42,
   7844            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
   7845 
   7846   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   7847   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
   7848   context->Global()->Set(v8_str("func2"), t2->GetFunction());
   7849   // Default value of ReadOnly flag.
   7850   CHECK(CompileRun(
   7851       "(function() {"
   7852       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   7853       "  return (descriptor['writable'] == true);"
   7854       "})()")->BooleanValue());
   7855   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
   7856 }
   7857 
   7858 
   7859 THREADED_TEST(SetPrototypeThrows) {
   7860   v8::HandleScope handle_scope;
   7861   LocalContext context;
   7862 
   7863   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   7864 
   7865   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
   7866   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
   7867 
   7868   CHECK(o0->SetPrototype(o1));
   7869   // If setting the prototype leads to the cycle, SetPrototype should
   7870   // return false and keep VM in sane state.
   7871   v8::TryCatch try_catch;
   7872   CHECK(!o1->SetPrototype(o0));
   7873   CHECK(!try_catch.HasCaught());
   7874   ASSERT(!i::Isolate::Current()->has_pending_exception());
   7875 
   7876   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
   7877 }
   7878 
   7879 
   7880 THREADED_TEST(GetterSetterExceptions) {
   7881   v8::HandleScope handle_scope;
   7882   LocalContext context;
   7883   CompileRun(
   7884     "function Foo() { };"
   7885     "function Throw() { throw 5; };"
   7886     "var x = { };"
   7887     "x.__defineSetter__('set', Throw);"
   7888     "x.__defineGetter__('get', Throw);");
   7889   Local<v8::Object> x =
   7890       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
   7891   v8::TryCatch try_catch;
   7892   x->Set(v8_str("set"), v8::Integer::New(8));
   7893   x->Get(v8_str("get"));
   7894   x->Set(v8_str("set"), v8::Integer::New(8));
   7895   x->Get(v8_str("get"));
   7896   x->Set(v8_str("set"), v8::Integer::New(8));
   7897   x->Get(v8_str("get"));
   7898   x->Set(v8_str("set"), v8::Integer::New(8));
   7899   x->Get(v8_str("get"));
   7900 }
   7901 
   7902 
   7903 THREADED_TEST(Constructor) {
   7904   v8::HandleScope handle_scope;
   7905   LocalContext context;
   7906   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   7907   templ->SetClassName(v8_str("Fun"));
   7908   Local<Function> cons = templ->GetFunction();
   7909   context->Global()->Set(v8_str("Fun"), cons);
   7910   Local<v8::Object> inst = cons->NewInstance();
   7911   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
   7912   CHECK(obj->IsJSObject());
   7913   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   7914   CHECK(value->BooleanValue());
   7915 }
   7916 
   7917 
   7918 static Handle<Value> ConstructorCallback(const Arguments& args) {
   7919   ApiTestFuzzer::Fuzz();
   7920   Local<Object> This;
   7921 
   7922   if (args.IsConstructCall()) {
   7923     Local<Object> Holder = args.Holder();
   7924     This = Object::New();
   7925     Local<Value> proto = Holder->GetPrototype();
   7926     if (proto->IsObject()) {
   7927       This->SetPrototype(proto);
   7928     }
   7929   } else {
   7930     This = args.This();
   7931   }
   7932 
   7933   This->Set(v8_str("a"), args[0]);
   7934   return This;
   7935 }
   7936 
   7937 
   7938 static Handle<Value> FakeConstructorCallback(const Arguments& args) {
   7939   ApiTestFuzzer::Fuzz();
   7940   return args[0];
   7941 }
   7942 
   7943 
   7944 THREADED_TEST(ConstructorForObject) {
   7945   v8::HandleScope handle_scope;
   7946   LocalContext context;
   7947 
   7948   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   7949     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
   7950     Local<Object> instance = instance_template->NewInstance();
   7951     context->Global()->Set(v8_str("obj"), instance);
   7952     v8::TryCatch try_catch;
   7953     Local<Value> value;
   7954     CHECK(!try_catch.HasCaught());
   7955 
   7956     // Call the Object's constructor with a 32-bit signed integer.
   7957     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
   7958     CHECK(!try_catch.HasCaught());
   7959     CHECK(value->IsInt32());
   7960     CHECK_EQ(28, value->Int32Value());
   7961 
   7962     Local<Value> args1[] = { v8_num(28) };
   7963     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
   7964     CHECK(value_obj1->IsObject());
   7965     Local<Object> object1 = Local<Object>::Cast(value_obj1);
   7966     value = object1->Get(v8_str("a"));
   7967     CHECK(value->IsInt32());
   7968     CHECK(!try_catch.HasCaught());
   7969     CHECK_EQ(28, value->Int32Value());
   7970 
   7971     // Call the Object's constructor with a String.
   7972     value = CompileRun(
   7973         "(function() { var o = new obj('tipli'); return o.a; })()");
   7974     CHECK(!try_catch.HasCaught());
   7975     CHECK(value->IsString());
   7976     String::AsciiValue string_value1(value->ToString());
   7977     CHECK_EQ("tipli", *string_value1);
   7978 
   7979     Local<Value> args2[] = { v8_str("tipli") };
   7980     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
   7981     CHECK(value_obj2->IsObject());
   7982     Local<Object> object2 = Local<Object>::Cast(value_obj2);
   7983     value = object2->Get(v8_str("a"));
   7984     CHECK(!try_catch.HasCaught());
   7985     CHECK(value->IsString());
   7986     String::AsciiValue string_value2(value->ToString());
   7987     CHECK_EQ("tipli", *string_value2);
   7988 
   7989     // Call the Object's constructor with a Boolean.
   7990     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
   7991     CHECK(!try_catch.HasCaught());
   7992     CHECK(value->IsBoolean());
   7993     CHECK_EQ(true, value->BooleanValue());
   7994 
   7995     Handle<Value> args3[] = { v8::True() };
   7996     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
   7997     CHECK(value_obj3->IsObject());
   7998     Local<Object> object3 = Local<Object>::Cast(value_obj3);
   7999     value = object3->Get(v8_str("a"));
   8000     CHECK(!try_catch.HasCaught());
   8001     CHECK(value->IsBoolean());
   8002     CHECK_EQ(true, value->BooleanValue());
   8003 
   8004     // Call the Object's constructor with undefined.
   8005     Handle<Value> args4[] = { v8::Undefined() };
   8006     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
   8007     CHECK(value_obj4->IsObject());
   8008     Local<Object> object4 = Local<Object>::Cast(value_obj4);
   8009     value = object4->Get(v8_str("a"));
   8010     CHECK(!try_catch.HasCaught());
   8011     CHECK(value->IsUndefined());
   8012 
   8013     // Call the Object's constructor with null.
   8014     Handle<Value> args5[] = { v8::Null() };
   8015     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
   8016     CHECK(value_obj5->IsObject());
   8017     Local<Object> object5 = Local<Object>::Cast(value_obj5);
   8018     value = object5->Get(v8_str("a"));
   8019     CHECK(!try_catch.HasCaught());
   8020     CHECK(value->IsNull());
   8021   }
   8022 
   8023   // Check exception handling when there is no constructor set for the Object.
   8024   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   8025     Local<Object> instance = instance_template->NewInstance();
   8026     context->Global()->Set(v8_str("obj2"), instance);
   8027     v8::TryCatch try_catch;
   8028     Local<Value> value;
   8029     CHECK(!try_catch.HasCaught());
   8030 
   8031     value = CompileRun("new obj2(28)");
   8032     CHECK(try_catch.HasCaught());
   8033     String::AsciiValue exception_value1(try_catch.Exception());
   8034     CHECK_EQ("TypeError: object is not a function", *exception_value1);
   8035     try_catch.Reset();
   8036 
   8037     Local<Value> args[] = { v8_num(29) };
   8038     value = instance->CallAsConstructor(1, args);
   8039     CHECK(try_catch.HasCaught());
   8040     String::AsciiValue exception_value2(try_catch.Exception());
   8041     CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
   8042     try_catch.Reset();
   8043   }
   8044 
   8045   // Check the case when constructor throws exception.
   8046   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   8047     instance_template->SetCallAsFunctionHandler(ThrowValue);
   8048     Local<Object> instance = instance_template->NewInstance();
   8049     context->Global()->Set(v8_str("obj3"), instance);
   8050     v8::TryCatch try_catch;
   8051     Local<Value> value;
   8052     CHECK(!try_catch.HasCaught());
   8053 
   8054     value = CompileRun("new obj3(22)");
   8055     CHECK(try_catch.HasCaught());
   8056     String::AsciiValue exception_value1(try_catch.Exception());
   8057     CHECK_EQ("22", *exception_value1);
   8058     try_catch.Reset();
   8059 
   8060     Local<Value> args[] = { v8_num(23) };
   8061     value = instance->CallAsConstructor(1, args);
   8062     CHECK(try_catch.HasCaught());
   8063     String::AsciiValue exception_value2(try_catch.Exception());
   8064     CHECK_EQ("23", *exception_value2);
   8065     try_catch.Reset();
   8066   }
   8067 
   8068   // Check whether constructor returns with an object or non-object.
   8069   { Local<FunctionTemplate> function_template =
   8070         FunctionTemplate::New(FakeConstructorCallback);
   8071     Local<Function> function = function_template->GetFunction();
   8072     Local<Object> instance1 = function;
   8073     context->Global()->Set(v8_str("obj4"), instance1);
   8074     v8::TryCatch try_catch;
   8075     Local<Value> value;
   8076     CHECK(!try_catch.HasCaught());
   8077 
   8078     CHECK(instance1->IsObject());
   8079     CHECK(instance1->IsFunction());
   8080 
   8081     value = CompileRun("new obj4(28)");
   8082     CHECK(!try_catch.HasCaught());
   8083     CHECK(value->IsObject());
   8084 
   8085     Local<Value> args1[] = { v8_num(28) };
   8086     value = instance1->CallAsConstructor(1, args1);
   8087     CHECK(!try_catch.HasCaught());
   8088     CHECK(value->IsObject());
   8089 
   8090     Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   8091     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
   8092     Local<Object> instance2 = instance_template->NewInstance();
   8093     context->Global()->Set(v8_str("obj5"), instance2);
   8094     CHECK(!try_catch.HasCaught());
   8095 
   8096     CHECK(instance2->IsObject());
   8097     CHECK(!instance2->IsFunction());
   8098 
   8099     value = CompileRun("new obj5(28)");
   8100     CHECK(!try_catch.HasCaught());
   8101     CHECK(!value->IsObject());
   8102 
   8103     Local<Value> args2[] = { v8_num(28) };
   8104     value = instance2->CallAsConstructor(1, args2);
   8105     CHECK(!try_catch.HasCaught());
   8106     CHECK(!value->IsObject());
   8107   }
   8108 }
   8109 
   8110 
   8111 THREADED_TEST(FunctionDescriptorException) {
   8112   v8::HandleScope handle_scope;
   8113   LocalContext context;
   8114   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   8115   templ->SetClassName(v8_str("Fun"));
   8116   Local<Function> cons = templ->GetFunction();
   8117   context->Global()->Set(v8_str("Fun"), cons);
   8118   Local<Value> value = CompileRun(
   8119     "function test() {"
   8120     "  try {"
   8121     "    (new Fun()).blah()"
   8122     "  } catch (e) {"
   8123     "    var str = String(e);"
   8124     "    if (str.indexOf('TypeError') == -1) return 1;"
   8125     "    if (str.indexOf('[object Fun]') != -1) return 2;"
   8126     "    if (str.indexOf('#<Fun>') == -1) return 3;"
   8127     "    return 0;"
   8128     "  }"
   8129     "  return 4;"
   8130     "}"
   8131     "test();");
   8132   CHECK_EQ(0, value->Int32Value());
   8133 }
   8134 
   8135 
   8136 THREADED_TEST(EvalAliasedDynamic) {
   8137   v8::HandleScope scope;
   8138   LocalContext current;
   8139 
   8140   // Tests where aliased eval can only be resolved dynamically.
   8141   Local<Script> script =
   8142       Script::Compile(v8_str("function f(x) { "
   8143                              "  var foo = 2;"
   8144                              "  with (x) { return eval('foo'); }"
   8145                              "}"
   8146                              "foo = 0;"
   8147                              "result1 = f(new Object());"
   8148                              "result2 = f(this);"
   8149                              "var x = new Object();"
   8150                              "x.eval = function(x) { return 1; };"
   8151                              "result3 = f(x);"));
   8152   script->Run();
   8153   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
   8154   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
   8155   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
   8156 
   8157   v8::TryCatch try_catch;
   8158   script =
   8159     Script::Compile(v8_str("function f(x) { "
   8160                            "  var bar = 2;"
   8161                            "  with (x) { return eval('bar'); }"
   8162                            "}"
   8163                            "result4 = f(this)"));
   8164   script->Run();
   8165   CHECK(!try_catch.HasCaught());
   8166   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
   8167 
   8168   try_catch.Reset();
   8169 }
   8170 
   8171 
   8172 THREADED_TEST(CrossEval) {
   8173   v8::HandleScope scope;
   8174   LocalContext other;
   8175   LocalContext current;
   8176 
   8177   Local<String> token = v8_str("<security token>");
   8178   other->SetSecurityToken(token);
   8179   current->SetSecurityToken(token);
   8180 
   8181   // Set up reference from current to other.
   8182   current->Global()->Set(v8_str("other"), other->Global());
   8183 
   8184   // Check that new variables are introduced in other context.
   8185   Local<Script> script =
   8186       Script::Compile(v8_str("other.eval('var foo = 1234')"));
   8187   script->Run();
   8188   Local<Value> foo = other->Global()->Get(v8_str("foo"));
   8189   CHECK_EQ(1234, foo->Int32Value());
   8190   CHECK(!current->Global()->Has(v8_str("foo")));
   8191 
   8192   // Check that writing to non-existing properties introduces them in
   8193   // the other context.
   8194   script =
   8195       Script::Compile(v8_str("other.eval('na = 1234')"));
   8196   script->Run();
   8197   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
   8198   CHECK(!current->Global()->Has(v8_str("na")));
   8199 
   8200   // Check that global variables in current context are not visible in other
   8201   // context.
   8202   v8::TryCatch try_catch;
   8203   script =
   8204       Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
   8205   Local<Value> result = script->Run();
   8206   CHECK(try_catch.HasCaught());
   8207   try_catch.Reset();
   8208 
   8209   // Check that local variables in current context are not visible in other
   8210   // context.
   8211   script =
   8212       Script::Compile(v8_str("(function() { "
   8213                              "  var baz = 87;"
   8214                              "  return other.eval('baz');"
   8215                              "})();"));
   8216   result = script->Run();
   8217   CHECK(try_catch.HasCaught());
   8218   try_catch.Reset();
   8219 
   8220   // Check that global variables in the other environment are visible
   8221   // when evaluting code.
   8222   other->Global()->Set(v8_str("bis"), v8_num(1234));
   8223   script = Script::Compile(v8_str("other.eval('bis')"));
   8224   CHECK_EQ(1234, script->Run()->Int32Value());
   8225   CHECK(!try_catch.HasCaught());
   8226 
   8227   // Check that the 'this' pointer points to the global object evaluating
   8228   // code.
   8229   other->Global()->Set(v8_str("t"), other->Global());
   8230   script = Script::Compile(v8_str("other.eval('this == t')"));
   8231   result = script->Run();
   8232   CHECK(result->IsTrue());
   8233   CHECK(!try_catch.HasCaught());
   8234 
   8235   // Check that variables introduced in with-statement are not visible in
   8236   // other context.
   8237   script =
   8238       Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
   8239   result = script->Run();
   8240   CHECK(try_catch.HasCaught());
   8241   try_catch.Reset();
   8242 
   8243   // Check that you cannot use 'eval.call' with another object than the
   8244   // current global object.
   8245   script =
   8246       Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
   8247   result = script->Run();
   8248   CHECK(try_catch.HasCaught());
   8249 }
   8250 
   8251 
   8252 // Test that calling eval in a context which has been detached from
   8253 // its global throws an exception.  This behavior is consistent with
   8254 // other JavaScript implementations.
   8255 THREADED_TEST(EvalInDetachedGlobal) {
   8256   v8::HandleScope scope;
   8257 
   8258   v8::Persistent<Context> context0 = Context::New();
   8259   v8::Persistent<Context> context1 = Context::New();
   8260 
   8261   // Set up function in context0 that uses eval from context0.
   8262   context0->Enter();
   8263   v8::Handle<v8::Value> fun =
   8264       CompileRun("var x = 42;"
   8265                  "(function() {"
   8266                  "  var e = eval;"
   8267                  "  return function(s) { return e(s); }"
   8268                  "})()");
   8269   context0->Exit();
   8270 
   8271   // Put the function into context1 and call it before and after
   8272   // detaching the global.  Before detaching, the call succeeds and
   8273   // after detaching and exception is thrown.
   8274   context1->Enter();
   8275   context1->Global()->Set(v8_str("fun"), fun);
   8276   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
   8277   CHECK_EQ(42, x_value->Int32Value());
   8278   context0->DetachGlobal();
   8279   v8::TryCatch catcher;
   8280   x_value = CompileRun("fun('x')");
   8281   CHECK(x_value.IsEmpty());
   8282   CHECK(catcher.HasCaught());
   8283   context1->Exit();
   8284 
   8285   context1.Dispose();
   8286   context0.Dispose();
   8287 }
   8288 
   8289 
   8290 THREADED_TEST(CrossLazyLoad) {
   8291   v8::HandleScope scope;
   8292   LocalContext other;
   8293   LocalContext current;
   8294 
   8295   Local<String> token = v8_str("<security token>");
   8296   other->SetSecurityToken(token);
   8297   current->SetSecurityToken(token);
   8298 
   8299   // Set up reference from current to other.
   8300   current->Global()->Set(v8_str("other"), other->Global());
   8301 
   8302   // Trigger lazy loading in other context.
   8303   Local<Script> script =
   8304       Script::Compile(v8_str("other.eval('new Date(42)')"));
   8305   Local<Value> value = script->Run();
   8306   CHECK_EQ(42.0, value->NumberValue());
   8307 }
   8308 
   8309 
   8310 static v8::Handle<Value> call_as_function(const v8::Arguments& args) {
   8311   ApiTestFuzzer::Fuzz();
   8312   if (args.IsConstructCall()) {
   8313     if (args[0]->IsInt32()) {
   8314        return v8_num(-args[0]->Int32Value());
   8315     }
   8316   }
   8317 
   8318   return args[0];
   8319 }
   8320 
   8321 
   8322 // Test that a call handler can be set for objects which will allow
   8323 // non-function objects created through the API to be called as
   8324 // functions.
   8325 THREADED_TEST(CallAsFunction) {
   8326   v8::HandleScope scope;
   8327   LocalContext context;
   8328 
   8329   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   8330     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   8331     instance_template->SetCallAsFunctionHandler(call_as_function);
   8332     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   8333     context->Global()->Set(v8_str("obj"), instance);
   8334     v8::TryCatch try_catch;
   8335     Local<Value> value;
   8336     CHECK(!try_catch.HasCaught());
   8337 
   8338     value = CompileRun("obj(42)");
   8339     CHECK(!try_catch.HasCaught());
   8340     CHECK_EQ(42, value->Int32Value());
   8341 
   8342     value = CompileRun("(function(o){return o(49)})(obj)");
   8343     CHECK(!try_catch.HasCaught());
   8344     CHECK_EQ(49, value->Int32Value());
   8345 
   8346     // test special case of call as function
   8347     value = CompileRun("[obj]['0'](45)");
   8348     CHECK(!try_catch.HasCaught());
   8349     CHECK_EQ(45, value->Int32Value());
   8350 
   8351     value = CompileRun("obj.call = Function.prototype.call;"
   8352                        "obj.call(null, 87)");
   8353     CHECK(!try_catch.HasCaught());
   8354     CHECK_EQ(87, value->Int32Value());
   8355 
   8356     // Regression tests for bug #1116356: Calling call through call/apply
   8357     // must work for non-function receivers.
   8358     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   8359     value = CompileRun(apply_99);
   8360     CHECK(!try_catch.HasCaught());
   8361     CHECK_EQ(99, value->Int32Value());
   8362 
   8363     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   8364     value = CompileRun(call_17);
   8365     CHECK(!try_catch.HasCaught());
   8366     CHECK_EQ(17, value->Int32Value());
   8367 
   8368     // Check that the call-as-function handler can be called through
   8369     // new.
   8370     value = CompileRun("new obj(43)");
   8371     CHECK(!try_catch.HasCaught());
   8372     CHECK_EQ(-43, value->Int32Value());
   8373 
   8374     // Check that the call-as-function handler can be called through
   8375     // the API.
   8376     v8::Handle<Value> args[] = { v8_num(28) };
   8377     value = instance->CallAsFunction(instance, 1, args);
   8378     CHECK(!try_catch.HasCaught());
   8379     CHECK_EQ(28, value->Int32Value());
   8380   }
   8381 
   8382   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   8383     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   8384     USE(instance_template);
   8385     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   8386     context->Global()->Set(v8_str("obj2"), instance);
   8387     v8::TryCatch try_catch;
   8388     Local<Value> value;
   8389     CHECK(!try_catch.HasCaught());
   8390 
   8391     // Call an object without call-as-function handler through the JS
   8392     value = CompileRun("obj2(28)");
   8393     CHECK(value.IsEmpty());
   8394     CHECK(try_catch.HasCaught());
   8395     String::AsciiValue exception_value1(try_catch.Exception());
   8396     CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
   8397              *exception_value1);
   8398     try_catch.Reset();
   8399 
   8400     // Call an object without call-as-function handler through the API
   8401     value = CompileRun("obj2(28)");
   8402     v8::Handle<Value> args[] = { v8_num(28) };
   8403     value = instance->CallAsFunction(instance, 1, args);
   8404     CHECK(value.IsEmpty());
   8405     CHECK(try_catch.HasCaught());
   8406     String::AsciiValue exception_value2(try_catch.Exception());
   8407     CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
   8408     try_catch.Reset();
   8409   }
   8410 
   8411   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   8412     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   8413     instance_template->SetCallAsFunctionHandler(ThrowValue);
   8414     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   8415     context->Global()->Set(v8_str("obj3"), instance);
   8416     v8::TryCatch try_catch;
   8417     Local<Value> value;
   8418     CHECK(!try_catch.HasCaught());
   8419 
   8420     // Catch the exception which is thrown by call-as-function handler
   8421     value = CompileRun("obj3(22)");
   8422     CHECK(try_catch.HasCaught());
   8423     String::AsciiValue exception_value1(try_catch.Exception());
   8424     CHECK_EQ("22", *exception_value1);
   8425     try_catch.Reset();
   8426 
   8427     v8::Handle<Value> args[] = { v8_num(23) };
   8428     value = instance->CallAsFunction(instance, 1, args);
   8429     CHECK(try_catch.HasCaught());
   8430     String::AsciiValue exception_value2(try_catch.Exception());
   8431     CHECK_EQ("23", *exception_value2);
   8432     try_catch.Reset();
   8433   }
   8434 }
   8435 
   8436 
   8437 // Check whether a non-function object is callable.
   8438 THREADED_TEST(CallableObject) {
   8439   v8::HandleScope scope;
   8440   LocalContext context;
   8441 
   8442   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   8443     instance_template->SetCallAsFunctionHandler(call_as_function);
   8444     Local<Object> instance = instance_template->NewInstance();
   8445     v8::TryCatch try_catch;
   8446 
   8447     CHECK(instance->IsCallable());
   8448     CHECK(!try_catch.HasCaught());
   8449   }
   8450 
   8451   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   8452     Local<Object> instance = instance_template->NewInstance();
   8453     v8::TryCatch try_catch;
   8454 
   8455     CHECK(!instance->IsCallable());
   8456     CHECK(!try_catch.HasCaught());
   8457   }
   8458 
   8459   { Local<FunctionTemplate> function_template =
   8460         FunctionTemplate::New(call_as_function);
   8461     Local<Function> function = function_template->GetFunction();
   8462     Local<Object> instance = function;
   8463     v8::TryCatch try_catch;
   8464 
   8465     CHECK(instance->IsCallable());
   8466     CHECK(!try_catch.HasCaught());
   8467   }
   8468 
   8469   { Local<FunctionTemplate> function_template = FunctionTemplate::New();
   8470     Local<Function> function = function_template->GetFunction();
   8471     Local<Object> instance = function;
   8472     v8::TryCatch try_catch;
   8473 
   8474     CHECK(instance->IsCallable());
   8475     CHECK(!try_catch.HasCaught());
   8476   }
   8477 }
   8478 
   8479 
   8480 static int CountHandles() {
   8481   return v8::HandleScope::NumberOfHandles();
   8482 }
   8483 
   8484 
   8485 static int Recurse(int depth, int iterations) {
   8486   v8::HandleScope scope;
   8487   if (depth == 0) return CountHandles();
   8488   for (int i = 0; i < iterations; i++) {
   8489     Local<v8::Number> n(v8::Integer::New(42));
   8490   }
   8491   return Recurse(depth - 1, iterations);
   8492 }
   8493 
   8494 
   8495 THREADED_TEST(HandleIteration) {
   8496   static const int kIterations = 500;
   8497   static const int kNesting = 200;
   8498   CHECK_EQ(0, CountHandles());
   8499   {
   8500     v8::HandleScope scope1;
   8501     CHECK_EQ(0, CountHandles());
   8502     for (int i = 0; i < kIterations; i++) {
   8503       Local<v8::Number> n(v8::Integer::New(42));
   8504       CHECK_EQ(i + 1, CountHandles());
   8505     }
   8506 
   8507     CHECK_EQ(kIterations, CountHandles());
   8508     {
   8509       v8::HandleScope scope2;
   8510       for (int j = 0; j < kIterations; j++) {
   8511         Local<v8::Number> n(v8::Integer::New(42));
   8512         CHECK_EQ(j + 1 + kIterations, CountHandles());
   8513       }
   8514     }
   8515     CHECK_EQ(kIterations, CountHandles());
   8516   }
   8517   CHECK_EQ(0, CountHandles());
   8518   CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
   8519 }
   8520 
   8521 
   8522 static v8::Handle<Value> InterceptorHasOwnPropertyGetter(
   8523     Local<String> name,
   8524     const AccessorInfo& info) {
   8525   ApiTestFuzzer::Fuzz();
   8526   return v8::Handle<Value>();
   8527 }
   8528 
   8529 
   8530 THREADED_TEST(InterceptorHasOwnProperty) {
   8531   v8::HandleScope scope;
   8532   LocalContext context;
   8533   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8534   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   8535   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
   8536   Local<Function> function = fun_templ->GetFunction();
   8537   context->Global()->Set(v8_str("constructor"), function);
   8538   v8::Handle<Value> value = CompileRun(
   8539       "var o = new constructor();"
   8540       "o.hasOwnProperty('ostehaps');");
   8541   CHECK_EQ(false, value->BooleanValue());
   8542   value = CompileRun(
   8543       "o.ostehaps = 42;"
   8544       "o.hasOwnProperty('ostehaps');");
   8545   CHECK_EQ(true, value->BooleanValue());
   8546   value = CompileRun(
   8547       "var p = new constructor();"
   8548       "p.hasOwnProperty('ostehaps');");
   8549   CHECK_EQ(false, value->BooleanValue());
   8550 }
   8551 
   8552 
   8553 static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC(
   8554     Local<String> name,
   8555     const AccessorInfo& info) {
   8556   ApiTestFuzzer::Fuzz();
   8557   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   8558   return v8::Handle<Value>();
   8559 }
   8560 
   8561 
   8562 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
   8563   v8::HandleScope scope;
   8564   LocalContext context;
   8565   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   8566   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   8567   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
   8568   Local<Function> function = fun_templ->GetFunction();
   8569   context->Global()->Set(v8_str("constructor"), function);
   8570   // Let's first make some stuff so we can be sure to get a good GC.
   8571   CompileRun(
   8572       "function makestr(size) {"
   8573       "  switch (size) {"
   8574       "    case 1: return 'f';"
   8575       "    case 2: return 'fo';"
   8576       "    case 3: return 'foo';"
   8577       "  }"
   8578       "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
   8579       "}"
   8580       "var x = makestr(12345);"
   8581       "x = makestr(31415);"
   8582       "x = makestr(23456);");
   8583   v8::Handle<Value> value = CompileRun(
   8584       "var o = new constructor();"
   8585       "o.__proto__ = new String(x);"
   8586       "o.hasOwnProperty('ostehaps');");
   8587   CHECK_EQ(false, value->BooleanValue());
   8588 }
   8589 
   8590 
   8591 typedef v8::Handle<Value> (*NamedPropertyGetter)(Local<String> property,
   8592                                                  const AccessorInfo& info);
   8593 
   8594 
   8595 static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
   8596                                    const char* source,
   8597                                    int expected) {
   8598   v8::HandleScope scope;
   8599   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8600   templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
   8601   LocalContext context;
   8602   context->Global()->Set(v8_str("o"), templ->NewInstance());
   8603   v8::Handle<Value> value = CompileRun(source);
   8604   CHECK_EQ(expected, value->Int32Value());
   8605 }
   8606 
   8607 
   8608 static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
   8609                                                  const AccessorInfo& info) {
   8610   ApiTestFuzzer::Fuzz();
   8611   CHECK_EQ(v8_str("data"), info.Data());
   8612   CHECK_EQ(v8_str("x"), name);
   8613   return v8::Integer::New(42);
   8614 }
   8615 
   8616 
   8617 // This test should hit the load IC for the interceptor case.
   8618 THREADED_TEST(InterceptorLoadIC) {
   8619   CheckInterceptorLoadIC(InterceptorLoadICGetter,
   8620     "var result = 0;"
   8621     "for (var i = 0; i < 1000; i++) {"
   8622     "  result = o.x;"
   8623     "}",
   8624     42);
   8625 }
   8626 
   8627 
   8628 // Below go several tests which verify that JITing for various
   8629 // configurations of interceptor and explicit fields works fine
   8630 // (those cases are special cased to get better performance).
   8631 
   8632 static v8::Handle<Value> InterceptorLoadXICGetter(Local<String> name,
   8633                                                  const AccessorInfo& info) {
   8634   ApiTestFuzzer::Fuzz();
   8635   return v8_str("x")->Equals(name)
   8636       ? v8::Integer::New(42) : v8::Handle<v8::Value>();
   8637 }
   8638 
   8639 
   8640 THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
   8641   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   8642     "var result = 0;"
   8643     "o.y = 239;"
   8644     "for (var i = 0; i < 1000; i++) {"
   8645     "  result = o.y;"
   8646     "}",
   8647     239);
   8648 }
   8649 
   8650 
   8651 THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
   8652   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   8653     "var result = 0;"
   8654     "o.__proto__ = { 'y': 239 };"
   8655     "for (var i = 0; i < 1000; i++) {"
   8656     "  result = o.y + o.x;"
   8657     "}",
   8658     239 + 42);
   8659 }
   8660 
   8661 
   8662 THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
   8663   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   8664     "var result = 0;"
   8665     "o.__proto__.y = 239;"
   8666     "for (var i = 0; i < 1000; i++) {"
   8667     "  result = o.y + o.x;"
   8668     "}",
   8669     239 + 42);
   8670 }
   8671 
   8672 
   8673 THREADED_TEST(InterceptorLoadICUndefined) {
   8674   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   8675     "var result = 0;"
   8676     "for (var i = 0; i < 1000; i++) {"
   8677     "  result = (o.y == undefined) ? 239 : 42;"
   8678     "}",
   8679     239);
   8680 }
   8681 
   8682 
   8683 THREADED_TEST(InterceptorLoadICWithOverride) {
   8684   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   8685     "fst = new Object();  fst.__proto__ = o;"
   8686     "snd = new Object();  snd.__proto__ = fst;"
   8687     "var result1 = 0;"
   8688     "for (var i = 0; i < 1000;  i++) {"
   8689     "  result1 = snd.x;"
   8690     "}"
   8691     "fst.x = 239;"
   8692     "var result = 0;"
   8693     "for (var i = 0; i < 1000; i++) {"
   8694     "  result = snd.x;"
   8695     "}"
   8696     "result + result1",
   8697     239 + 42);
   8698 }
   8699 
   8700 
   8701 // Test the case when we stored field into
   8702 // a stub, but interceptor produced value on its own.
   8703 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
   8704   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   8705     "proto = new Object();"
   8706     "o.__proto__ = proto;"
   8707     "proto.x = 239;"
   8708     "for (var i = 0; i < 1000; i++) {"
   8709     "  o.x;"
   8710     // Now it should be ICed and keep a reference to x defined on proto
   8711     "}"
   8712     "var result = 0;"
   8713     "for (var i = 0; i < 1000; i++) {"
   8714     "  result += o.x;"
   8715     "}"
   8716     "result;",
   8717     42 * 1000);
   8718 }
   8719 
   8720 
   8721 // Test the case when we stored field into
   8722 // a stub, but it got invalidated later on.
   8723 THREADED_TEST(InterceptorLoadICInvalidatedField) {
   8724   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   8725     "proto1 = new Object();"
   8726     "proto2 = new Object();"
   8727     "o.__proto__ = proto1;"
   8728     "proto1.__proto__ = proto2;"
   8729     "proto2.y = 239;"
   8730     "for (var i = 0; i < 1000; i++) {"
   8731     "  o.y;"
   8732     // Now it should be ICed and keep a reference to y defined on proto2
   8733     "}"
   8734     "proto1.y = 42;"
   8735     "var result = 0;"
   8736     "for (var i = 0; i < 1000; i++) {"
   8737     "  result += o.y;"
   8738     "}"
   8739     "result;",
   8740     42 * 1000);
   8741 }
   8742 
   8743 
   8744 static int interceptor_load_not_handled_calls = 0;
   8745 static v8::Handle<Value> InterceptorLoadNotHandled(Local<String> name,
   8746                                                    const AccessorInfo& info) {
   8747   ++interceptor_load_not_handled_calls;
   8748   return v8::Handle<v8::Value>();
   8749 }
   8750 
   8751 
   8752 // Test how post-interceptor lookups are done in the non-cacheable
   8753 // case: the interceptor should not be invoked during this lookup.
   8754 THREADED_TEST(InterceptorLoadICPostInterceptor) {
   8755   interceptor_load_not_handled_calls = 0;
   8756   CheckInterceptorLoadIC(InterceptorLoadNotHandled,
   8757     "receiver = new Object();"
   8758     "receiver.__proto__ = o;"
   8759     "proto = new Object();"
   8760     "/* Make proto a slow-case object. */"
   8761     "for (var i = 0; i < 1000; i++) {"
   8762     "  proto[\"xxxxxxxx\" + i] = [];"
   8763     "}"
   8764     "proto.x = 17;"
   8765     "o.__proto__ = proto;"
   8766     "var result = 0;"
   8767     "for (var i = 0; i < 1000; i++) {"
   8768     "  result += receiver.x;"
   8769     "}"
   8770     "result;",
   8771     17 * 1000);
   8772   CHECK_EQ(1000, interceptor_load_not_handled_calls);
   8773 }
   8774 
   8775 
   8776 // Test the case when we stored field into
   8777 // a stub, but it got invalidated later on due to override on
   8778 // global object which is between interceptor and fields' holders.
   8779 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
   8780   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   8781     "o.__proto__ = this;"  // set a global to be a proto of o.
   8782     "this.__proto__.y = 239;"
   8783     "for (var i = 0; i < 10; i++) {"
   8784     "  if (o.y != 239) throw 'oops: ' + o.y;"
   8785     // Now it should be ICed and keep a reference to y defined on field_holder.
   8786     "}"
   8787     "this.y = 42;"  // Assign on a global.
   8788     "var result = 0;"
   8789     "for (var i = 0; i < 10; i++) {"
   8790     "  result += o.y;"
   8791     "}"
   8792     "result;",
   8793     42 * 10);
   8794 }
   8795 
   8796 
   8797 static void SetOnThis(Local<String> name,
   8798                       Local<Value> value,
   8799                       const AccessorInfo& info) {
   8800   info.This()->ForceSet(name, value);
   8801 }
   8802 
   8803 
   8804 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
   8805   v8::HandleScope scope;
   8806   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8807   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   8808   templ->SetAccessor(v8_str("y"), Return239);
   8809   LocalContext context;
   8810   context->Global()->Set(v8_str("o"), templ->NewInstance());
   8811 
   8812   // Check the case when receiver and interceptor's holder
   8813   // are the same objects.
   8814   v8::Handle<Value> value = CompileRun(
   8815       "var result = 0;"
   8816       "for (var i = 0; i < 7; i++) {"
   8817       "  result = o.y;"
   8818       "}");
   8819   CHECK_EQ(239, value->Int32Value());
   8820 
   8821   // Check the case when interceptor's holder is in proto chain
   8822   // of receiver.
   8823   value = CompileRun(
   8824       "r = { __proto__: o };"
   8825       "var result = 0;"
   8826       "for (var i = 0; i < 7; i++) {"
   8827       "  result = r.y;"
   8828       "}");
   8829   CHECK_EQ(239, value->Int32Value());
   8830 }
   8831 
   8832 
   8833 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
   8834   v8::HandleScope scope;
   8835   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   8836   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   8837   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   8838   templ_p->SetAccessor(v8_str("y"), Return239);
   8839 
   8840   LocalContext context;
   8841   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   8842   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   8843 
   8844   // Check the case when receiver and interceptor's holder
   8845   // are the same objects.
   8846   v8::Handle<Value> value = CompileRun(
   8847       "o.__proto__ = p;"
   8848       "var result = 0;"
   8849       "for (var i = 0; i < 7; i++) {"
   8850       "  result = o.x + o.y;"
   8851       "}");
   8852   CHECK_EQ(239 + 42, value->Int32Value());
   8853 
   8854   // Check the case when interceptor's holder is in proto chain
   8855   // of receiver.
   8856   value = CompileRun(
   8857       "r = { __proto__: o };"
   8858       "var result = 0;"
   8859       "for (var i = 0; i < 7; i++) {"
   8860       "  result = r.x + r.y;"
   8861       "}");
   8862   CHECK_EQ(239 + 42, value->Int32Value());
   8863 }
   8864 
   8865 
   8866 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
   8867   v8::HandleScope scope;
   8868   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   8869   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   8870   templ->SetAccessor(v8_str("y"), Return239);
   8871 
   8872   LocalContext context;
   8873   context->Global()->Set(v8_str("o"), templ->NewInstance());
   8874 
   8875   v8::Handle<Value> value = CompileRun(
   8876     "fst = new Object();  fst.__proto__ = o;"
   8877     "snd = new Object();  snd.__proto__ = fst;"
   8878     "var result1 = 0;"
   8879     "for (var i = 0; i < 7;  i++) {"
   8880     "  result1 = snd.x;"
   8881     "}"
   8882     "fst.x = 239;"
   8883     "var result = 0;"
   8884     "for (var i = 0; i < 7; i++) {"
   8885     "  result = snd.x;"
   8886     "}"
   8887     "result + result1");
   8888   CHECK_EQ(239 + 42, value->Int32Value());
   8889 }
   8890 
   8891 
   8892 // Test the case when we stored callback into
   8893 // a stub, but interceptor produced value on its own.
   8894 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
   8895   v8::HandleScope scope;
   8896   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   8897   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   8898   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   8899   templ_p->SetAccessor(v8_str("y"), Return239);
   8900 
   8901   LocalContext context;
   8902   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   8903   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   8904 
   8905   v8::Handle<Value> value = CompileRun(
   8906     "o.__proto__ = p;"
   8907     "for (var i = 0; i < 7; i++) {"
   8908     "  o.x;"
   8909     // Now it should be ICed and keep a reference to x defined on p
   8910     "}"
   8911     "var result = 0;"
   8912     "for (var i = 0; i < 7; i++) {"
   8913     "  result += o.x;"
   8914     "}"
   8915     "result");
   8916   CHECK_EQ(42 * 7, value->Int32Value());
   8917 }
   8918 
   8919 
   8920 // Test the case when we stored callback into
   8921 // a stub, but it got invalidated later on.
   8922 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
   8923   v8::HandleScope scope;
   8924   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   8925   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   8926   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   8927   templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
   8928 
   8929   LocalContext context;
   8930   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   8931   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   8932 
   8933   v8::Handle<Value> value = CompileRun(
   8934     "inbetween = new Object();"
   8935     "o.__proto__ = inbetween;"
   8936     "inbetween.__proto__ = p;"
   8937     "for (var i = 0; i < 10; i++) {"
   8938     "  o.y;"
   8939     // Now it should be ICed and keep a reference to y defined on p
   8940     "}"
   8941     "inbetween.y = 42;"
   8942     "var result = 0;"
   8943     "for (var i = 0; i < 10; i++) {"
   8944     "  result += o.y;"
   8945     "}"
   8946     "result");
   8947   CHECK_EQ(42 * 10, value->Int32Value());
   8948 }
   8949 
   8950 
   8951 // Test the case when we stored callback into
   8952 // a stub, but it got invalidated later on due to override on
   8953 // global object which is between interceptor and callbacks' holders.
   8954 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
   8955   v8::HandleScope scope;
   8956   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   8957   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   8958   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   8959   templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
   8960 
   8961   LocalContext context;
   8962   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   8963   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   8964 
   8965   v8::Handle<Value> value = CompileRun(
   8966     "o.__proto__ = this;"
   8967     "this.__proto__ = p;"
   8968     "for (var i = 0; i < 10; i++) {"
   8969     "  if (o.y != 239) throw 'oops: ' + o.y;"
   8970     // Now it should be ICed and keep a reference to y defined on p
   8971     "}"
   8972     "this.y = 42;"
   8973     "var result = 0;"
   8974     "for (var i = 0; i < 10; i++) {"
   8975     "  result += o.y;"
   8976     "}"
   8977     "result");
   8978   CHECK_EQ(42 * 10, value->Int32Value());
   8979 }
   8980 
   8981 
   8982 static v8::Handle<Value> InterceptorLoadICGetter0(Local<String> name,
   8983                                                   const AccessorInfo& info) {
   8984   ApiTestFuzzer::Fuzz();
   8985   CHECK(v8_str("x")->Equals(name));
   8986   return v8::Integer::New(0);
   8987 }
   8988 
   8989 
   8990 THREADED_TEST(InterceptorReturningZero) {
   8991   CheckInterceptorLoadIC(InterceptorLoadICGetter0,
   8992      "o.x == undefined ? 1 : 0",
   8993      0);
   8994 }
   8995 
   8996 
   8997 static v8::Handle<Value> InterceptorStoreICSetter(
   8998     Local<String> key, Local<Value> value, const AccessorInfo&) {
   8999   CHECK(v8_str("x")->Equals(key));
   9000   CHECK_EQ(42, value->Int32Value());
   9001   return value;
   9002 }
   9003 
   9004 
   9005 // This test should hit the store IC for the interceptor case.
   9006 THREADED_TEST(InterceptorStoreIC) {
   9007   v8::HandleScope scope;
   9008   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9009   templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
   9010                                  InterceptorStoreICSetter,
   9011                                  0, 0, 0, v8_str("data"));
   9012   LocalContext context;
   9013   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9014   CompileRun(
   9015       "for (var i = 0; i < 1000; i++) {"
   9016       "  o.x = 42;"
   9017       "}");
   9018 }
   9019 
   9020 
   9021 THREADED_TEST(InterceptorStoreICWithNoSetter) {
   9022   v8::HandleScope scope;
   9023   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9024   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   9025   LocalContext context;
   9026   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9027   v8::Handle<Value> value = CompileRun(
   9028     "for (var i = 0; i < 1000; i++) {"
   9029     "  o.y = 239;"
   9030     "}"
   9031     "42 + o.y");
   9032   CHECK_EQ(239 + 42, value->Int32Value());
   9033 }
   9034 
   9035 
   9036 
   9037 
   9038 v8::Handle<Value> call_ic_function;
   9039 v8::Handle<Value> call_ic_function2;
   9040 v8::Handle<Value> call_ic_function3;
   9041 
   9042 static v8::Handle<Value> InterceptorCallICGetter(Local<String> name,
   9043                                                  const AccessorInfo& info) {
   9044   ApiTestFuzzer::Fuzz();
   9045   CHECK(v8_str("x")->Equals(name));
   9046   return call_ic_function;
   9047 }
   9048 
   9049 
   9050 // This test should hit the call IC for the interceptor case.
   9051 THREADED_TEST(InterceptorCallIC) {
   9052   v8::HandleScope scope;
   9053   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9054   templ->SetNamedPropertyHandler(InterceptorCallICGetter);
   9055   LocalContext context;
   9056   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9057   call_ic_function =
   9058       v8_compile("function f(x) { return x + 1; }; f")->Run();
   9059   v8::Handle<Value> value = CompileRun(
   9060     "var result = 0;"
   9061     "for (var i = 0; i < 1000; i++) {"
   9062     "  result = o.x(41);"
   9063     "}");
   9064   CHECK_EQ(42, value->Int32Value());
   9065 }
   9066 
   9067 
   9068 // This test checks that if interceptor doesn't provide
   9069 // a value, we can fetch regular value.
   9070 THREADED_TEST(InterceptorCallICSeesOthers) {
   9071   v8::HandleScope scope;
   9072   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9073   templ->SetNamedPropertyHandler(NoBlockGetterX);
   9074   LocalContext context;
   9075   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9076   v8::Handle<Value> value = CompileRun(
   9077     "o.x = function f(x) { return x + 1; };"
   9078     "var result = 0;"
   9079     "for (var i = 0; i < 7; i++) {"
   9080     "  result = o.x(41);"
   9081     "}");
   9082   CHECK_EQ(42, value->Int32Value());
   9083 }
   9084 
   9085 
   9086 static v8::Handle<Value> call_ic_function4;
   9087 static v8::Handle<Value> InterceptorCallICGetter4(Local<String> name,
   9088                                                   const AccessorInfo& info) {
   9089   ApiTestFuzzer::Fuzz();
   9090   CHECK(v8_str("x")->Equals(name));
   9091   return call_ic_function4;
   9092 }
   9093 
   9094 
   9095 // This test checks that if interceptor provides a function,
   9096 // even if we cached shadowed variant, interceptor's function
   9097 // is invoked
   9098 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
   9099   v8::HandleScope scope;
   9100   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9101   templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
   9102   LocalContext context;
   9103   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9104   call_ic_function4 =
   9105       v8_compile("function f(x) { return x - 1; }; f")->Run();
   9106   v8::Handle<Value> value = CompileRun(
   9107     "o.__proto__.x = function(x) { return x + 1; };"
   9108     "var result = 0;"
   9109     "for (var i = 0; i < 1000; i++) {"
   9110     "  result = o.x(42);"
   9111     "}");
   9112   CHECK_EQ(41, value->Int32Value());
   9113 }
   9114 
   9115 
   9116 // Test the case when we stored cacheable lookup into
   9117 // a stub, but it got invalidated later on
   9118 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
   9119   v8::HandleScope scope;
   9120   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9121   templ->SetNamedPropertyHandler(NoBlockGetterX);
   9122   LocalContext context;
   9123   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9124   v8::Handle<Value> value = CompileRun(
   9125     "proto1 = new Object();"
   9126     "proto2 = new Object();"
   9127     "o.__proto__ = proto1;"
   9128     "proto1.__proto__ = proto2;"
   9129     "proto2.y = function(x) { return x + 1; };"
   9130     // Invoke it many times to compile a stub
   9131     "for (var i = 0; i < 7; i++) {"
   9132     "  o.y(42);"
   9133     "}"
   9134     "proto1.y = function(x) { return x - 1; };"
   9135     "var result = 0;"
   9136     "for (var i = 0; i < 7; i++) {"
   9137     "  result += o.y(42);"
   9138     "}");
   9139   CHECK_EQ(41 * 7, value->Int32Value());
   9140 }
   9141 
   9142 
   9143 // This test checks that if interceptor doesn't provide a function,
   9144 // cached constant function is used
   9145 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
   9146   v8::HandleScope scope;
   9147   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9148   templ->SetNamedPropertyHandler(NoBlockGetterX);
   9149   LocalContext context;
   9150   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9151   v8::Handle<Value> value = CompileRun(
   9152     "function inc(x) { return x + 1; };"
   9153     "inc(1);"
   9154     "o.x = inc;"
   9155     "var result = 0;"
   9156     "for (var i = 0; i < 1000; i++) {"
   9157     "  result = o.x(42);"
   9158     "}");
   9159   CHECK_EQ(43, value->Int32Value());
   9160 }
   9161 
   9162 
   9163 static v8::Handle<Value> call_ic_function5;
   9164 static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name,
   9165                                                   const AccessorInfo& info) {
   9166   ApiTestFuzzer::Fuzz();
   9167   if (v8_str("x")->Equals(name))
   9168     return call_ic_function5;
   9169   else
   9170     return Local<Value>();
   9171 }
   9172 
   9173 
   9174 // This test checks that if interceptor provides a function,
   9175 // even if we cached constant function, interceptor's function
   9176 // is invoked
   9177 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
   9178   v8::HandleScope scope;
   9179   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9180   templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
   9181   LocalContext context;
   9182   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9183   call_ic_function5 =
   9184       v8_compile("function f(x) { return x - 1; }; f")->Run();
   9185   v8::Handle<Value> value = CompileRun(
   9186     "function inc(x) { return x + 1; };"
   9187     "inc(1);"
   9188     "o.x = inc;"
   9189     "var result = 0;"
   9190     "for (var i = 0; i < 1000; i++) {"
   9191     "  result = o.x(42);"
   9192     "}");
   9193   CHECK_EQ(41, value->Int32Value());
   9194 }
   9195 
   9196 
   9197 static v8::Handle<Value> call_ic_function6;
   9198 static v8::Handle<Value> InterceptorCallICGetter6(Local<String> name,
   9199                                                   const AccessorInfo& info) {
   9200   ApiTestFuzzer::Fuzz();
   9201   if (v8_str("x")->Equals(name))
   9202     return call_ic_function6;
   9203   else
   9204     return Local<Value>();
   9205 }
   9206 
   9207 
   9208 // Same test as above, except the code is wrapped in a function
   9209 // to test the optimized compiler.
   9210 THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
   9211   i::FLAG_allow_natives_syntax = true;
   9212   v8::HandleScope scope;
   9213   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9214   templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
   9215   LocalContext context;
   9216   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9217   call_ic_function6 =
   9218       v8_compile("function f(x) { return x - 1; }; f")->Run();
   9219   v8::Handle<Value> value = CompileRun(
   9220     "function inc(x) { return x + 1; };"
   9221     "inc(1);"
   9222     "o.x = inc;"
   9223     "function test() {"
   9224     "  var result = 0;"
   9225     "  for (var i = 0; i < 1000; i++) {"
   9226     "    result = o.x(42);"
   9227     "  }"
   9228     "  return result;"
   9229     "};"
   9230     "test();"
   9231     "test();"
   9232     "test();"
   9233     "%OptimizeFunctionOnNextCall(test);"
   9234     "test()");
   9235   CHECK_EQ(41, value->Int32Value());
   9236 }
   9237 
   9238 
   9239 // Test the case when we stored constant function into
   9240 // a stub, but it got invalidated later on
   9241 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
   9242   v8::HandleScope scope;
   9243   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9244   templ->SetNamedPropertyHandler(NoBlockGetterX);
   9245   LocalContext context;
   9246   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9247   v8::Handle<Value> value = CompileRun(
   9248     "function inc(x) { return x + 1; };"
   9249     "inc(1);"
   9250     "proto1 = new Object();"
   9251     "proto2 = new Object();"
   9252     "o.__proto__ = proto1;"
   9253     "proto1.__proto__ = proto2;"
   9254     "proto2.y = inc;"
   9255     // Invoke it many times to compile a stub
   9256     "for (var i = 0; i < 7; i++) {"
   9257     "  o.y(42);"
   9258     "}"
   9259     "proto1.y = function(x) { return x - 1; };"
   9260     "var result = 0;"
   9261     "for (var i = 0; i < 7; i++) {"
   9262     "  result += o.y(42);"
   9263     "}");
   9264   CHECK_EQ(41 * 7, value->Int32Value());
   9265 }
   9266 
   9267 
   9268 // Test the case when we stored constant function into
   9269 // a stub, but it got invalidated later on due to override on
   9270 // global object which is between interceptor and constant function' holders.
   9271 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
   9272   v8::HandleScope scope;
   9273   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9274   templ->SetNamedPropertyHandler(NoBlockGetterX);
   9275   LocalContext context;
   9276   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9277   v8::Handle<Value> value = CompileRun(
   9278     "function inc(x) { return x + 1; };"
   9279     "inc(1);"
   9280     "o.__proto__ = this;"
   9281     "this.__proto__.y = inc;"
   9282     // Invoke it many times to compile a stub
   9283     "for (var i = 0; i < 7; i++) {"
   9284     "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
   9285     "}"
   9286     "this.y = function(x) { return x - 1; };"
   9287     "var result = 0;"
   9288     "for (var i = 0; i < 7; i++) {"
   9289     "  result += o.y(42);"
   9290     "}");
   9291   CHECK_EQ(41 * 7, value->Int32Value());
   9292 }
   9293 
   9294 
   9295 // Test the case when actual function to call sits on global object.
   9296 THREADED_TEST(InterceptorCallICCachedFromGlobal) {
   9297   v8::HandleScope scope;
   9298   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   9299   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   9300 
   9301   LocalContext context;
   9302   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   9303 
   9304   v8::Handle<Value> value = CompileRun(
   9305     "try {"
   9306     "  o.__proto__ = this;"
   9307     "  for (var i = 0; i < 10; i++) {"
   9308     "    var v = o.parseFloat('239');"
   9309     "    if (v != 239) throw v;"
   9310       // Now it should be ICed and keep a reference to parseFloat.
   9311     "  }"
   9312     "  var result = 0;"
   9313     "  for (var i = 0; i < 10; i++) {"
   9314     "    result += o.parseFloat('239');"
   9315     "  }"
   9316     "  result"
   9317     "} catch(e) {"
   9318     "  e"
   9319     "};");
   9320   CHECK_EQ(239 * 10, value->Int32Value());
   9321 }
   9322 
   9323 static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
   9324                                                   const AccessorInfo& info) {
   9325   ApiTestFuzzer::Fuzz();
   9326   int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data()));
   9327   ++(*call_count);
   9328   if ((*call_count) % 20 == 0) {
   9329     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   9330   }
   9331   return v8::Handle<Value>();
   9332 }
   9333 
   9334 static v8::Handle<Value> FastApiCallback_TrivialSignature(
   9335     const v8::Arguments& args) {
   9336   ApiTestFuzzer::Fuzz();
   9337   CHECK_EQ(args.This(), args.Holder());
   9338   CHECK(args.Data()->Equals(v8_str("method_data")));
   9339   return v8::Integer::New(args[0]->Int32Value() + 1);
   9340 }
   9341 
   9342 static v8::Handle<Value> FastApiCallback_SimpleSignature(
   9343     const v8::Arguments& args) {
   9344   ApiTestFuzzer::Fuzz();
   9345   CHECK_EQ(args.This()->GetPrototype(), args.Holder());
   9346   CHECK(args.Data()->Equals(v8_str("method_data")));
   9347   // Note, we're using HasRealNamedProperty instead of Has to avoid
   9348   // invoking the interceptor again.
   9349   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
   9350   return v8::Integer::New(args[0]->Int32Value() + 1);
   9351 }
   9352 
   9353 // Helper to maximize the odds of object moving.
   9354 static void GenerateSomeGarbage() {
   9355   CompileRun(
   9356       "var garbage;"
   9357       "for (var i = 0; i < 1000; i++) {"
   9358       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   9359       "}"
   9360       "garbage = undefined;");
   9361 }
   9362 
   9363 
   9364 v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) {
   9365   static int count = 0;
   9366   if (count++ % 3 == 0) {
   9367     HEAP->  CollectAllGarbage(true);  // This should move the stub
   9368     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   9369   }
   9370   return v8::Handle<v8::Value>();
   9371 }
   9372 
   9373 
   9374 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   9375   v8::HandleScope scope;
   9376   LocalContext context;
   9377   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
   9378   nativeobject_templ->Set("callback",
   9379                           v8::FunctionTemplate::New(DirectApiCallback));
   9380   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   9381   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   9382   // call the api function multiple times to ensure direct call stub creation.
   9383   CompileRun(
   9384         "function f() {"
   9385         "  for (var i = 1; i <= 30; i++) {"
   9386         "    nativeobject.callback();"
   9387         "  }"
   9388         "}"
   9389         "f();");
   9390 }
   9391 
   9392 
   9393 v8::Handle<v8::Value> ThrowingDirectApiCallback(const v8::Arguments& args) {
   9394   return v8::ThrowException(v8_str("g"));
   9395 }
   9396 
   9397 
   9398 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   9399   v8::HandleScope scope;
   9400   LocalContext context;
   9401   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
   9402   nativeobject_templ->Set("callback",
   9403                           v8::FunctionTemplate::New(ThrowingDirectApiCallback));
   9404   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   9405   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   9406   // call the api function multiple times to ensure direct call stub creation.
   9407   v8::Handle<Value> result = CompileRun(
   9408       "var result = '';"
   9409       "function f() {"
   9410       "  for (var i = 1; i <= 5; i++) {"
   9411       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   9412       "  }"
   9413       "}"
   9414       "f(); result;");
   9415   CHECK_EQ(v8_str("ggggg"), result);
   9416 }
   9417 
   9418 
   9419 v8::Handle<v8::Value> DirectGetterCallback(Local<String> name,
   9420                                            const v8::AccessorInfo& info) {
   9421   if (++p_getter_count % 3 == 0) {
   9422     HEAP->CollectAllGarbage(true);
   9423     GenerateSomeGarbage();
   9424   }
   9425   return v8::Handle<v8::Value>();
   9426 }
   9427 
   9428 
   9429 THREADED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   9430   v8::HandleScope scope;
   9431   LocalContext context;
   9432   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
   9433   obj->SetAccessor(v8_str("p1"), DirectGetterCallback);
   9434   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   9435   p_getter_count = 0;
   9436   CompileRun(
   9437       "function f() {"
   9438       "  for (var i = 0; i < 30; i++) o1.p1;"
   9439       "}"
   9440       "f();");
   9441   CHECK_EQ(30, p_getter_count);
   9442 }
   9443 
   9444 
   9445 v8::Handle<v8::Value> ThrowingDirectGetterCallback(
   9446     Local<String> name, const v8::AccessorInfo& info) {
   9447   return v8::ThrowException(v8_str("g"));
   9448 }
   9449 
   9450 
   9451 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   9452   v8::HandleScope scope;
   9453   LocalContext context;
   9454   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
   9455   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   9456   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   9457   v8::Handle<Value> result = CompileRun(
   9458       "var result = '';"
   9459       "for (var i = 0; i < 5; i++) {"
   9460       "    try { o1.p1; } catch (e) { result += e; }"
   9461       "}"
   9462       "result;");
   9463   CHECK_EQ(v8_str("ggggg"), result);
   9464 }
   9465 
   9466 
   9467 THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   9468   int interceptor_call_count = 0;
   9469   v8::HandleScope scope;
   9470   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9471   v8::Handle<v8::FunctionTemplate> method_templ =
   9472       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
   9473                                 v8_str("method_data"),
   9474                                 v8::Handle<v8::Signature>());
   9475   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9476   proto_templ->Set(v8_str("method"), method_templ);
   9477   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   9478   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   9479                                  NULL, NULL, NULL, NULL,
   9480                                  v8::External::Wrap(&interceptor_call_count));
   9481   LocalContext context;
   9482   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9483   GenerateSomeGarbage();
   9484   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9485   CompileRun(
   9486       "var result = 0;"
   9487       "for (var i = 0; i < 100; i++) {"
   9488       "  result = o.method(41);"
   9489       "}");
   9490   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   9491   CHECK_EQ(100, interceptor_call_count);
   9492 }
   9493 
   9494 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   9495   int interceptor_call_count = 0;
   9496   v8::HandleScope scope;
   9497   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9498   v8::Handle<v8::FunctionTemplate> method_templ =
   9499       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   9500                                 v8_str("method_data"),
   9501                                 v8::Signature::New(fun_templ));
   9502   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9503   proto_templ->Set(v8_str("method"), method_templ);
   9504   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   9505   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   9506                                  NULL, NULL, NULL, NULL,
   9507                                  v8::External::Wrap(&interceptor_call_count));
   9508   LocalContext context;
   9509   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9510   GenerateSomeGarbage();
   9511   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9512   CompileRun(
   9513       "o.foo = 17;"
   9514       "var receiver = {};"
   9515       "receiver.__proto__ = o;"
   9516       "var result = 0;"
   9517       "for (var i = 0; i < 100; i++) {"
   9518       "  result = receiver.method(41);"
   9519       "}");
   9520   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   9521   CHECK_EQ(100, interceptor_call_count);
   9522 }
   9523 
   9524 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   9525   int interceptor_call_count = 0;
   9526   v8::HandleScope scope;
   9527   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9528   v8::Handle<v8::FunctionTemplate> method_templ =
   9529       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   9530                                 v8_str("method_data"),
   9531                                 v8::Signature::New(fun_templ));
   9532   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9533   proto_templ->Set(v8_str("method"), method_templ);
   9534   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   9535   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   9536                                  NULL, NULL, NULL, NULL,
   9537                                  v8::External::Wrap(&interceptor_call_count));
   9538   LocalContext context;
   9539   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9540   GenerateSomeGarbage();
   9541   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9542   CompileRun(
   9543       "o.foo = 17;"
   9544       "var receiver = {};"
   9545       "receiver.__proto__ = o;"
   9546       "var result = 0;"
   9547       "var saved_result = 0;"
   9548       "for (var i = 0; i < 100; i++) {"
   9549       "  result = receiver.method(41);"
   9550       "  if (i == 50) {"
   9551       "    saved_result = result;"
   9552       "    receiver = {method: function(x) { return x - 1 }};"
   9553       "  }"
   9554       "}");
   9555   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   9556   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   9557   CHECK_GE(interceptor_call_count, 50);
   9558 }
   9559 
   9560 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   9561   int interceptor_call_count = 0;
   9562   v8::HandleScope scope;
   9563   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9564   v8::Handle<v8::FunctionTemplate> method_templ =
   9565       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   9566                                 v8_str("method_data"),
   9567                                 v8::Signature::New(fun_templ));
   9568   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9569   proto_templ->Set(v8_str("method"), method_templ);
   9570   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   9571   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   9572                                  NULL, NULL, NULL, NULL,
   9573                                  v8::External::Wrap(&interceptor_call_count));
   9574   LocalContext context;
   9575   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9576   GenerateSomeGarbage();
   9577   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9578   CompileRun(
   9579       "o.foo = 17;"
   9580       "var receiver = {};"
   9581       "receiver.__proto__ = o;"
   9582       "var result = 0;"
   9583       "var saved_result = 0;"
   9584       "for (var i = 0; i < 100; i++) {"
   9585       "  result = receiver.method(41);"
   9586       "  if (i == 50) {"
   9587       "    saved_result = result;"
   9588       "    o.method = function(x) { return x - 1 };"
   9589       "  }"
   9590       "}");
   9591   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   9592   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   9593   CHECK_GE(interceptor_call_count, 50);
   9594 }
   9595 
   9596 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   9597   int interceptor_call_count = 0;
   9598   v8::HandleScope scope;
   9599   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9600   v8::Handle<v8::FunctionTemplate> method_templ =
   9601       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   9602                                 v8_str("method_data"),
   9603                                 v8::Signature::New(fun_templ));
   9604   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9605   proto_templ->Set(v8_str("method"), method_templ);
   9606   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   9607   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   9608                                  NULL, NULL, NULL, NULL,
   9609                                  v8::External::Wrap(&interceptor_call_count));
   9610   LocalContext context;
   9611   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9612   GenerateSomeGarbage();
   9613   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9614   v8::TryCatch try_catch;
   9615   CompileRun(
   9616       "o.foo = 17;"
   9617       "var receiver = {};"
   9618       "receiver.__proto__ = o;"
   9619       "var result = 0;"
   9620       "var saved_result = 0;"
   9621       "for (var i = 0; i < 100; i++) {"
   9622       "  result = receiver.method(41);"
   9623       "  if (i == 50) {"
   9624       "    saved_result = result;"
   9625       "    receiver = 333;"
   9626       "  }"
   9627       "}");
   9628   CHECK(try_catch.HasCaught());
   9629   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
   9630            try_catch.Exception()->ToString());
   9631   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   9632   CHECK_GE(interceptor_call_count, 50);
   9633 }
   9634 
   9635 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   9636   int interceptor_call_count = 0;
   9637   v8::HandleScope scope;
   9638   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9639   v8::Handle<v8::FunctionTemplate> method_templ =
   9640       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   9641                                 v8_str("method_data"),
   9642                                 v8::Signature::New(fun_templ));
   9643   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9644   proto_templ->Set(v8_str("method"), method_templ);
   9645   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   9646   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   9647                                  NULL, NULL, NULL, NULL,
   9648                                  v8::External::Wrap(&interceptor_call_count));
   9649   LocalContext context;
   9650   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9651   GenerateSomeGarbage();
   9652   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9653   v8::TryCatch try_catch;
   9654   CompileRun(
   9655       "o.foo = 17;"
   9656       "var receiver = {};"
   9657       "receiver.__proto__ = o;"
   9658       "var result = 0;"
   9659       "var saved_result = 0;"
   9660       "for (var i = 0; i < 100; i++) {"
   9661       "  result = receiver.method(41);"
   9662       "  if (i == 50) {"
   9663       "    saved_result = result;"
   9664       "    receiver = {method: receiver.method};"
   9665       "  }"
   9666       "}");
   9667   CHECK(try_catch.HasCaught());
   9668   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
   9669            try_catch.Exception()->ToString());
   9670   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   9671   CHECK_GE(interceptor_call_count, 50);
   9672 }
   9673 
   9674 THREADED_TEST(CallICFastApi_TrivialSignature) {
   9675   v8::HandleScope scope;
   9676   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9677   v8::Handle<v8::FunctionTemplate> method_templ =
   9678       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
   9679                                 v8_str("method_data"),
   9680                                 v8::Handle<v8::Signature>());
   9681   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9682   proto_templ->Set(v8_str("method"), method_templ);
   9683   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   9684   USE(templ);
   9685   LocalContext context;
   9686   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9687   GenerateSomeGarbage();
   9688   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9689   CompileRun(
   9690       "var result = 0;"
   9691       "for (var i = 0; i < 100; i++) {"
   9692       "  result = o.method(41);"
   9693       "}");
   9694 
   9695   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   9696 }
   9697 
   9698 THREADED_TEST(CallICFastApi_SimpleSignature) {
   9699   v8::HandleScope scope;
   9700   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9701   v8::Handle<v8::FunctionTemplate> method_templ =
   9702       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   9703                                 v8_str("method_data"),
   9704                                 v8::Signature::New(fun_templ));
   9705   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9706   proto_templ->Set(v8_str("method"), method_templ);
   9707   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   9708   CHECK(!templ.IsEmpty());
   9709   LocalContext context;
   9710   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9711   GenerateSomeGarbage();
   9712   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9713   CompileRun(
   9714       "o.foo = 17;"
   9715       "var receiver = {};"
   9716       "receiver.__proto__ = o;"
   9717       "var result = 0;"
   9718       "for (var i = 0; i < 100; i++) {"
   9719       "  result = receiver.method(41);"
   9720       "}");
   9721 
   9722   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   9723 }
   9724 
   9725 THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   9726   v8::HandleScope scope;
   9727   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9728   v8::Handle<v8::FunctionTemplate> method_templ =
   9729       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   9730                                 v8_str("method_data"),
   9731                                 v8::Signature::New(fun_templ));
   9732   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9733   proto_templ->Set(v8_str("method"), method_templ);
   9734   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   9735   CHECK(!templ.IsEmpty());
   9736   LocalContext context;
   9737   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9738   GenerateSomeGarbage();
   9739   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9740   CompileRun(
   9741       "o.foo = 17;"
   9742       "var receiver = {};"
   9743       "receiver.__proto__ = o;"
   9744       "var result = 0;"
   9745       "var saved_result = 0;"
   9746       "for (var i = 0; i < 100; i++) {"
   9747       "  result = receiver.method(41);"
   9748       "  if (i == 50) {"
   9749       "    saved_result = result;"
   9750       "    receiver = {method: function(x) { return x - 1 }};"
   9751       "  }"
   9752       "}");
   9753   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   9754   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   9755 }
   9756 
   9757 THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   9758   v8::HandleScope scope;
   9759   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   9760   v8::Handle<v8::FunctionTemplate> method_templ =
   9761       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   9762                                 v8_str("method_data"),
   9763                                 v8::Signature::New(fun_templ));
   9764   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   9765   proto_templ->Set(v8_str("method"), method_templ);
   9766   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   9767   CHECK(!templ.IsEmpty());
   9768   LocalContext context;
   9769   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   9770   GenerateSomeGarbage();
   9771   context->Global()->Set(v8_str("o"), fun->NewInstance());
   9772   v8::TryCatch try_catch;
   9773   CompileRun(
   9774       "o.foo = 17;"
   9775       "var receiver = {};"
   9776       "receiver.__proto__ = o;"
   9777       "var result = 0;"
   9778       "var saved_result = 0;"
   9779       "for (var i = 0; i < 100; i++) {"
   9780       "  result = receiver.method(41);"
   9781       "  if (i == 50) {"
   9782       "    saved_result = result;"
   9783       "    receiver = 333;"
   9784       "  }"
   9785       "}");
   9786   CHECK(try_catch.HasCaught());
   9787   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
   9788            try_catch.Exception()->ToString());
   9789   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   9790 }
   9791 
   9792 
   9793 v8::Handle<Value> keyed_call_ic_function;
   9794 
   9795 static v8::Handle<Value> InterceptorKeyedCallICGetter(
   9796     Local<String> name, const AccessorInfo& info) {
   9797   ApiTestFuzzer::Fuzz();
   9798   if (v8_str("x")->Equals(name)) {
   9799     return keyed_call_ic_function;
   9800   }
   9801   return v8::Handle<Value>();
   9802 }
   9803 
   9804 
   9805 // Test the case when we stored cacheable lookup into
   9806 // a stub, but the function name changed (to another cacheable function).
   9807 THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
   9808   v8::HandleScope scope;
   9809   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9810   templ->SetNamedPropertyHandler(NoBlockGetterX);
   9811   LocalContext context;
   9812   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9813   CompileRun(
   9814     "proto = new Object();"
   9815     "proto.y = function(x) { return x + 1; };"
   9816     "proto.z = function(x) { return x - 1; };"
   9817     "o.__proto__ = proto;"
   9818     "var result = 0;"
   9819     "var method = 'y';"
   9820     "for (var i = 0; i < 10; i++) {"
   9821     "  if (i == 5) { method = 'z'; };"
   9822     "  result += o[method](41);"
   9823     "}");
   9824   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   9825 }
   9826 
   9827 
   9828 // Test the case when we stored cacheable lookup into
   9829 // a stub, but the function name changed (and the new function is present
   9830 // both before and after the interceptor in the prototype chain).
   9831 THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
   9832   v8::HandleScope scope;
   9833   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9834   templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
   9835   LocalContext context;
   9836   context->Global()->Set(v8_str("proto1"), templ->NewInstance());
   9837   keyed_call_ic_function =
   9838       v8_compile("function f(x) { return x - 1; }; f")->Run();
   9839   CompileRun(
   9840     "o = new Object();"
   9841     "proto2 = new Object();"
   9842     "o.y = function(x) { return x + 1; };"
   9843     "proto2.y = function(x) { return x + 2; };"
   9844     "o.__proto__ = proto1;"
   9845     "proto1.__proto__ = proto2;"
   9846     "var result = 0;"
   9847     "var method = 'x';"
   9848     "for (var i = 0; i < 10; i++) {"
   9849     "  if (i == 5) { method = 'y'; };"
   9850     "  result += o[method](41);"
   9851     "}");
   9852   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   9853 }
   9854 
   9855 
   9856 // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
   9857 // on the global object.
   9858 THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
   9859   v8::HandleScope scope;
   9860   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9861   templ->SetNamedPropertyHandler(NoBlockGetterX);
   9862   LocalContext context;
   9863   context->Global()->Set(v8_str("o"), templ->NewInstance());
   9864   CompileRun(
   9865     "function inc(x) { return x + 1; };"
   9866     "inc(1);"
   9867     "function dec(x) { return x - 1; };"
   9868     "dec(1);"
   9869     "o.__proto__ = this;"
   9870     "this.__proto__.x = inc;"
   9871     "this.__proto__.y = dec;"
   9872     "var result = 0;"
   9873     "var method = 'x';"
   9874     "for (var i = 0; i < 10; i++) {"
   9875     "  if (i == 5) { method = 'y'; };"
   9876     "  result += o[method](41);"
   9877     "}");
   9878   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   9879 }
   9880 
   9881 
   9882 // Test the case when actual function to call sits on global object.
   9883 THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
   9884   v8::HandleScope scope;
   9885   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   9886   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   9887   LocalContext context;
   9888   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   9889 
   9890   CompileRun(
   9891     "function len(x) { return x.length; };"
   9892     "o.__proto__ = this;"
   9893     "var m = 'parseFloat';"
   9894     "var result = 0;"
   9895     "for (var i = 0; i < 10; i++) {"
   9896     "  if (i == 5) {"
   9897     "    m = 'len';"
   9898     "    saved_result = result;"
   9899     "  };"
   9900     "  result = o[m]('239');"
   9901     "}");
   9902   CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
   9903   CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   9904 }
   9905 
   9906 // Test the map transition before the interceptor.
   9907 THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
   9908   v8::HandleScope scope;
   9909   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   9910   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   9911   LocalContext context;
   9912   context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
   9913 
   9914   CompileRun(
   9915     "var o = new Object();"
   9916     "o.__proto__ = proto;"
   9917     "o.method = function(x) { return x + 1; };"
   9918     "var m = 'method';"
   9919     "var result = 0;"
   9920     "for (var i = 0; i < 10; i++) {"
   9921     "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
   9922     "  result += o[m](41);"
   9923     "}");
   9924   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   9925 }
   9926 
   9927 
   9928 // Test the map transition after the interceptor.
   9929 THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
   9930   v8::HandleScope scope;
   9931   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   9932   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   9933   LocalContext context;
   9934   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   9935 
   9936   CompileRun(
   9937     "var proto = new Object();"
   9938     "o.__proto__ = proto;"
   9939     "proto.method = function(x) { return x + 1; };"
   9940     "var m = 'method';"
   9941     "var result = 0;"
   9942     "for (var i = 0; i < 10; i++) {"
   9943     "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
   9944     "  result += o[m](41);"
   9945     "}");
   9946   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   9947 }
   9948 
   9949 
   9950 static int interceptor_call_count = 0;
   9951 
   9952 static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name,
   9953                                                      const AccessorInfo& info) {
   9954   ApiTestFuzzer::Fuzz();
   9955   if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
   9956     return call_ic_function2;
   9957   }
   9958   return v8::Handle<Value>();
   9959 }
   9960 
   9961 
   9962 // This test should hit load and call ICs for the interceptor case.
   9963 // Once in a while, the interceptor will reply that a property was not
   9964 // found in which case we should get a reference error.
   9965 THREADED_TEST(InterceptorICReferenceErrors) {
   9966   v8::HandleScope scope;
   9967   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   9968   templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
   9969   LocalContext context(0, templ, v8::Handle<Value>());
   9970   call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
   9971   v8::Handle<Value> value = CompileRun(
   9972     "function f() {"
   9973     "  for (var i = 0; i < 1000; i++) {"
   9974     "    try { x; } catch(e) { return true; }"
   9975     "  }"
   9976     "  return false;"
   9977     "};"
   9978     "f();");
   9979   CHECK_EQ(true, value->BooleanValue());
   9980   interceptor_call_count = 0;
   9981   value = CompileRun(
   9982     "function g() {"
   9983     "  for (var i = 0; i < 1000; i++) {"
   9984     "    try { x(42); } catch(e) { return true; }"
   9985     "  }"
   9986     "  return false;"
   9987     "};"
   9988     "g();");
   9989   CHECK_EQ(true, value->BooleanValue());
   9990 }
   9991 
   9992 
   9993 static int interceptor_ic_exception_get_count = 0;
   9994 
   9995 static v8::Handle<Value> InterceptorICExceptionGetter(
   9996     Local<String> name,
   9997     const AccessorInfo& info) {
   9998   ApiTestFuzzer::Fuzz();
   9999   if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
   10000     return call_ic_function3;
   10001   }
   10002   if (interceptor_ic_exception_get_count == 20) {
   10003     return v8::ThrowException(v8_num(42));
   10004   }
   10005   // Do not handle get for properties other than x.
   10006   return v8::Handle<Value>();
   10007 }
   10008 
   10009 // Test interceptor load/call IC where the interceptor throws an
   10010 // exception once in a while.
   10011 THREADED_TEST(InterceptorICGetterExceptions) {
   10012   interceptor_ic_exception_get_count = 0;
   10013   v8::HandleScope scope;
   10014   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10015   templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
   10016   LocalContext context(0, templ, v8::Handle<Value>());
   10017   call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
   10018   v8::Handle<Value> value = CompileRun(
   10019     "function f() {"
   10020     "  for (var i = 0; i < 100; i++) {"
   10021     "    try { x; } catch(e) { return true; }"
   10022     "  }"
   10023     "  return false;"
   10024     "};"
   10025     "f();");
   10026   CHECK_EQ(true, value->BooleanValue());
   10027   interceptor_ic_exception_get_count = 0;
   10028   value = CompileRun(
   10029     "function f() {"
   10030     "  for (var i = 0; i < 100; i++) {"
   10031     "    try { x(42); } catch(e) { return true; }"
   10032     "  }"
   10033     "  return false;"
   10034     "};"
   10035     "f();");
   10036   CHECK_EQ(true, value->BooleanValue());
   10037 }
   10038 
   10039 
   10040 static int interceptor_ic_exception_set_count = 0;
   10041 
   10042 static v8::Handle<Value> InterceptorICExceptionSetter(
   10043       Local<String> key, Local<Value> value, const AccessorInfo&) {
   10044   ApiTestFuzzer::Fuzz();
   10045   if (++interceptor_ic_exception_set_count > 20) {
   10046     return v8::ThrowException(v8_num(42));
   10047   }
   10048   // Do not actually handle setting.
   10049   return v8::Handle<Value>();
   10050 }
   10051 
   10052 // Test interceptor store IC where the interceptor throws an exception
   10053 // once in a while.
   10054 THREADED_TEST(InterceptorICSetterExceptions) {
   10055   interceptor_ic_exception_set_count = 0;
   10056   v8::HandleScope scope;
   10057   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10058   templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
   10059   LocalContext context(0, templ, v8::Handle<Value>());
   10060   v8::Handle<Value> value = CompileRun(
   10061     "function f() {"
   10062     "  for (var i = 0; i < 100; i++) {"
   10063     "    try { x = 42; } catch(e) { return true; }"
   10064     "  }"
   10065     "  return false;"
   10066     "};"
   10067     "f();");
   10068   CHECK_EQ(true, value->BooleanValue());
   10069 }
   10070 
   10071 
   10072 // Test that we ignore null interceptors.
   10073 THREADED_TEST(NullNamedInterceptor) {
   10074   v8::HandleScope scope;
   10075   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10076   templ->SetNamedPropertyHandler(0);
   10077   LocalContext context;
   10078   templ->Set("x", v8_num(42));
   10079   v8::Handle<v8::Object> obj = templ->NewInstance();
   10080   context->Global()->Set(v8_str("obj"), obj);
   10081   v8::Handle<Value> value = CompileRun("obj.x");
   10082   CHECK(value->IsInt32());
   10083   CHECK_EQ(42, value->Int32Value());
   10084 }
   10085 
   10086 
   10087 // Test that we ignore null interceptors.
   10088 THREADED_TEST(NullIndexedInterceptor) {
   10089   v8::HandleScope scope;
   10090   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10091   templ->SetIndexedPropertyHandler(0);
   10092   LocalContext context;
   10093   templ->Set("42", v8_num(42));
   10094   v8::Handle<v8::Object> obj = templ->NewInstance();
   10095   context->Global()->Set(v8_str("obj"), obj);
   10096   v8::Handle<Value> value = CompileRun("obj[42]");
   10097   CHECK(value->IsInt32());
   10098   CHECK_EQ(42, value->Int32Value());
   10099 }
   10100 
   10101 
   10102 THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
   10103   v8::HandleScope scope;
   10104   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   10105   templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   10106   LocalContext env;
   10107   env->Global()->Set(v8_str("obj"),
   10108                      templ->GetFunction()->NewInstance());
   10109   ExpectTrue("obj.x === 42");
   10110   ExpectTrue("!obj.propertyIsEnumerable('x')");
   10111 }
   10112 
   10113 
   10114 static Handle<Value> ThrowingGetter(Local<String> name,
   10115                                     const AccessorInfo& info) {
   10116   ApiTestFuzzer::Fuzz();
   10117   ThrowException(Handle<Value>());
   10118   return Undefined();
   10119 }
   10120 
   10121 
   10122 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   10123   HandleScope scope;
   10124   LocalContext context;
   10125 
   10126   Local<FunctionTemplate> templ = FunctionTemplate::New();
   10127   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   10128   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   10129 
   10130   Local<Object> instance = templ->GetFunction()->NewInstance();
   10131 
   10132   Local<Object> another = Object::New();
   10133   another->SetPrototype(instance);
   10134 
   10135   Local<Object> with_js_getter = CompileRun(
   10136       "o = {};\n"
   10137       "o.__defineGetter__('f', function() { throw undefined; });\n"
   10138       "o\n").As<Object>();
   10139   CHECK(!with_js_getter.IsEmpty());
   10140 
   10141   TryCatch try_catch;
   10142 
   10143   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
   10144   CHECK(try_catch.HasCaught());
   10145   try_catch.Reset();
   10146   CHECK(result.IsEmpty());
   10147 
   10148   result = another->GetRealNamedProperty(v8_str("f"));
   10149   CHECK(try_catch.HasCaught());
   10150   try_catch.Reset();
   10151   CHECK(result.IsEmpty());
   10152 
   10153   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
   10154   CHECK(try_catch.HasCaught());
   10155   try_catch.Reset();
   10156   CHECK(result.IsEmpty());
   10157 
   10158   result = another->Get(v8_str("f"));
   10159   CHECK(try_catch.HasCaught());
   10160   try_catch.Reset();
   10161   CHECK(result.IsEmpty());
   10162 
   10163   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
   10164   CHECK(try_catch.HasCaught());
   10165   try_catch.Reset();
   10166   CHECK(result.IsEmpty());
   10167 
   10168   result = with_js_getter->Get(v8_str("f"));
   10169   CHECK(try_catch.HasCaught());
   10170   try_catch.Reset();
   10171   CHECK(result.IsEmpty());
   10172 }
   10173 
   10174 
   10175 static Handle<Value> ThrowingCallbackWithTryCatch(const Arguments& args) {
   10176   TryCatch try_catch;
   10177   // Verboseness is important: it triggers message delivery which can call into
   10178   // external code.
   10179   try_catch.SetVerbose(true);
   10180   CompileRun("throw 'from JS';");
   10181   CHECK(try_catch.HasCaught());
   10182   CHECK(!i::Isolate::Current()->has_pending_exception());
   10183   CHECK(!i::Isolate::Current()->has_scheduled_exception());
   10184   return Undefined();
   10185 }
   10186 
   10187 
   10188 static int call_depth;
   10189 
   10190 
   10191 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
   10192   TryCatch try_catch;
   10193 }
   10194 
   10195 
   10196 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
   10197   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   10198 }
   10199 
   10200 
   10201 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
   10202   if (--call_depth) ThrowException(v8_str("ThrowViaApi"));
   10203 }
   10204 
   10205 
   10206 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
   10207   Handle<String> errorMessageString = message->Get();
   10208   CHECK(!errorMessageString.IsEmpty());
   10209   message->GetStackTrace();
   10210   message->GetScriptResourceName();
   10211 }
   10212 
   10213 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   10214   HandleScope scope;
   10215   LocalContext context;
   10216 
   10217   Local<Function> func =
   10218       FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction();
   10219   context->Global()->Set(v8_str("func"), func);
   10220 
   10221   MessageCallback callbacks[] =
   10222       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
   10223   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   10224     MessageCallback callback = callbacks[i];
   10225     if (callback != NULL) {
   10226       V8::AddMessageListener(callback);
   10227     }
   10228     // Some small number to control number of times message handler should
   10229     // throw an exception.
   10230     call_depth = 5;
   10231     ExpectFalse(
   10232         "var thrown = false;\n"
   10233         "try { func(); } catch(e) { thrown = true; }\n"
   10234         "thrown\n");
   10235     if (callback != NULL) {
   10236       V8::RemoveMessageListeners(callback);
   10237     }
   10238   }
   10239 }
   10240 
   10241 
   10242 static v8::Handle<Value> ParentGetter(Local<String> name,
   10243                                       const AccessorInfo& info) {
   10244   ApiTestFuzzer::Fuzz();
   10245   return v8_num(1);
   10246 }
   10247 
   10248 
   10249 static v8::Handle<Value> ChildGetter(Local<String> name,
   10250                                      const AccessorInfo& info) {
   10251   ApiTestFuzzer::Fuzz();
   10252   return v8_num(42);
   10253 }
   10254 
   10255 
   10256 THREADED_TEST(Overriding) {
   10257   v8::HandleScope scope;
   10258   LocalContext context;
   10259 
   10260   // Parent template.
   10261   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
   10262   Local<ObjectTemplate> parent_instance_templ =
   10263       parent_templ->InstanceTemplate();
   10264   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   10265 
   10266   // Template that inherits from the parent template.
   10267   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
   10268   Local<ObjectTemplate> child_instance_templ =
   10269       child_templ->InstanceTemplate();
   10270   child_templ->Inherit(parent_templ);
   10271   // Override 'f'.  The child version of 'f' should get called for child
   10272   // instances.
   10273   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   10274   // Add 'g' twice.  The 'g' added last should get called for instances.
   10275   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   10276   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   10277 
   10278   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   10279   // so 'h' can be shadowed on the instance object.
   10280   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   10281   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
   10282       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   10283 
   10284   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   10285   // but the attribute does not have effect because it is duplicated with
   10286   // NULL setter.
   10287   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
   10288       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   10289 
   10290 
   10291 
   10292   // Instantiate the child template.
   10293   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
   10294 
   10295   // Check that the child function overrides the parent one.
   10296   context->Global()->Set(v8_str("o"), instance);
   10297   Local<Value> value = v8_compile("o.f")->Run();
   10298   // Check that the 'g' that was added last is hit.
   10299   CHECK_EQ(42, value->Int32Value());
   10300   value = v8_compile("o.g")->Run();
   10301   CHECK_EQ(42, value->Int32Value());
   10302 
   10303   // Check 'h' can be shadowed.
   10304   value = v8_compile("o.h = 3; o.h")->Run();
   10305   CHECK_EQ(3, value->Int32Value());
   10306 
   10307   // Check 'i' is cannot be shadowed or changed.
   10308   value = v8_compile("o.i = 3; o.i")->Run();
   10309   CHECK_EQ(42, value->Int32Value());
   10310 }
   10311 
   10312 
   10313 static v8::Handle<Value> IsConstructHandler(const v8::Arguments& args) {
   10314   ApiTestFuzzer::Fuzz();
   10315   return v8::Boolean::New(args.IsConstructCall());
   10316 }
   10317 
   10318 
   10319 THREADED_TEST(IsConstructCall) {
   10320   v8::HandleScope scope;
   10321 
   10322   // Function template with call handler.
   10323   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   10324   templ->SetCallHandler(IsConstructHandler);
   10325 
   10326   LocalContext context;
   10327 
   10328   context->Global()->Set(v8_str("f"), templ->GetFunction());
   10329   Local<Value> value = v8_compile("f()")->Run();
   10330   CHECK(!value->BooleanValue());
   10331   value = v8_compile("new f()")->Run();
   10332   CHECK(value->BooleanValue());
   10333 }
   10334 
   10335 
   10336 THREADED_TEST(ObjectProtoToString) {
   10337   v8::HandleScope scope;
   10338   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   10339   templ->SetClassName(v8_str("MyClass"));
   10340 
   10341   LocalContext context;
   10342 
   10343   Local<String> customized_tostring = v8_str("customized toString");
   10344 
   10345   // Replace Object.prototype.toString
   10346   v8_compile("Object.prototype.toString = function() {"
   10347                   "  return 'customized toString';"
   10348                   "}")->Run();
   10349 
   10350   // Normal ToString call should call replaced Object.prototype.toString
   10351   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
   10352   Local<String> value = instance->ToString();
   10353   CHECK(value->IsString() && value->Equals(customized_tostring));
   10354 
   10355   // ObjectProtoToString should not call replace toString function.
   10356   value = instance->ObjectProtoToString();
   10357   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
   10358 
   10359   // Check global
   10360   value = context->Global()->ObjectProtoToString();
   10361   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
   10362 
   10363   // Check ordinary object
   10364   Local<Value> object = v8_compile("new Object()")->Run();
   10365   value = object.As<v8::Object>()->ObjectProtoToString();
   10366   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
   10367 }
   10368 
   10369 
   10370 THREADED_TEST(ObjectGetConstructorName) {
   10371   v8::HandleScope scope;
   10372   LocalContext context;
   10373   v8_compile("function Parent() {};"
   10374              "function Child() {};"
   10375              "Child.prototype = new Parent();"
   10376              "var outer = { inner: function() { } };"
   10377              "var p = new Parent();"
   10378              "var c = new Child();"
   10379              "var x = new outer.inner();")->Run();
   10380 
   10381   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
   10382   CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
   10383       v8_str("Parent")));
   10384 
   10385   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
   10386   CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
   10387       v8_str("Child")));
   10388 
   10389   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
   10390   CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
   10391       v8_str("outer.inner")));
   10392 }
   10393 
   10394 
   10395 bool ApiTestFuzzer::fuzzing_ = false;
   10396 i::Semaphore* ApiTestFuzzer::all_tests_done_=
   10397   i::OS::CreateSemaphore(0);
   10398 int ApiTestFuzzer::active_tests_;
   10399 int ApiTestFuzzer::tests_being_run_;
   10400 int ApiTestFuzzer::current_;
   10401 
   10402 
   10403 // We are in a callback and want to switch to another thread (if we
   10404 // are currently running the thread fuzzing test).
   10405 void ApiTestFuzzer::Fuzz() {
   10406   if (!fuzzing_) return;
   10407   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   10408   test->ContextSwitch();
   10409 }
   10410 
   10411 
   10412 // Let the next thread go.  Since it is also waiting on the V8 lock it may
   10413 // not start immediately.
   10414 bool ApiTestFuzzer::NextThread() {
   10415   int test_position = GetNextTestNumber();
   10416   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   10417   if (test_position == current_) {
   10418     if (kLogThreading)
   10419       printf("Stay with %s\n", test_name);
   10420     return false;
   10421   }
   10422   if (kLogThreading) {
   10423     printf("Switch from %s to %s\n",
   10424            test_name,
   10425            RegisterThreadedTest::nth(test_position)->name());
   10426   }
   10427   current_ = test_position;
   10428   RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
   10429   return true;
   10430 }
   10431 
   10432 
   10433 void ApiTestFuzzer::Run() {
   10434   // When it is our turn...
   10435   gate_->Wait();
   10436   {
   10437     // ... get the V8 lock and start running the test.
   10438     v8::Locker locker;
   10439     CallTest();
   10440   }
   10441   // This test finished.
   10442   active_ = false;
   10443   active_tests_--;
   10444   // If it was the last then signal that fact.
   10445   if (active_tests_ == 0) {
   10446     all_tests_done_->Signal();
   10447   } else {
   10448     // Otherwise select a new test and start that.
   10449     NextThread();
   10450   }
   10451 }
   10452 
   10453 
   10454 static unsigned linear_congruential_generator;
   10455 
   10456 
   10457 void ApiTestFuzzer::SetUp(PartOfTest part) {
   10458   linear_congruential_generator = i::FLAG_testing_prng_seed;
   10459   fuzzing_ = true;
   10460   int count = RegisterThreadedTest::count();
   10461   int start =  count * part / (LAST_PART + 1);
   10462   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   10463   active_tests_ = tests_being_run_ = end - start + 1;
   10464   for (int i = 0; i < tests_being_run_; i++) {
   10465     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   10466   }
   10467   for (int i = 0; i < active_tests_; i++) {
   10468     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   10469   }
   10470 }
   10471 
   10472 
   10473 static void CallTestNumber(int test_number) {
   10474   (RegisterThreadedTest::nth(test_number)->callback())();
   10475 }
   10476 
   10477 
   10478 void ApiTestFuzzer::RunAllTests() {
   10479   // Set off the first test.
   10480   current_ = -1;
   10481   NextThread();
   10482   // Wait till they are all done.
   10483   all_tests_done_->Wait();
   10484 }
   10485 
   10486 
   10487 int ApiTestFuzzer::GetNextTestNumber() {
   10488   int next_test;
   10489   do {
   10490     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   10491     linear_congruential_generator *= 1664525u;
   10492     linear_congruential_generator += 1013904223u;
   10493   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   10494   return next_test;
   10495 }
   10496 
   10497 
   10498 void ApiTestFuzzer::ContextSwitch() {
   10499   // If the new thread is the same as the current thread there is nothing to do.
   10500   if (NextThread()) {
   10501     // Now it can start.
   10502     v8::Unlocker unlocker;
   10503     // Wait till someone starts us again.
   10504     gate_->Wait();
   10505     // And we're off.
   10506   }
   10507 }
   10508 
   10509 
   10510 void ApiTestFuzzer::TearDown() {
   10511   fuzzing_ = false;
   10512   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   10513     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   10514     if (fuzzer != NULL) fuzzer->Join();
   10515   }
   10516 }
   10517 
   10518 
   10519 // Lets not be needlessly self-referential.
   10520 TEST(Threading) {
   10521   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
   10522   ApiTestFuzzer::RunAllTests();
   10523   ApiTestFuzzer::TearDown();
   10524 }
   10525 
   10526 TEST(Threading2) {
   10527   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
   10528   ApiTestFuzzer::RunAllTests();
   10529   ApiTestFuzzer::TearDown();
   10530 }
   10531 
   10532 TEST(Threading3) {
   10533   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
   10534   ApiTestFuzzer::RunAllTests();
   10535   ApiTestFuzzer::TearDown();
   10536 }
   10537 
   10538 TEST(Threading4) {
   10539   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
   10540   ApiTestFuzzer::RunAllTests();
   10541   ApiTestFuzzer::TearDown();
   10542 }
   10543 
   10544 void ApiTestFuzzer::CallTest() {
   10545   if (kLogThreading)
   10546     printf("Start test %d\n", test_number_);
   10547   CallTestNumber(test_number_);
   10548   if (kLogThreading)
   10549     printf("End test %d\n", test_number_);
   10550 }
   10551 
   10552 
   10553 static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) {
   10554   CHECK(v8::Locker::IsLocked());
   10555   ApiTestFuzzer::Fuzz();
   10556   v8::Unlocker unlocker;
   10557   const char* code = "throw 7;";
   10558   {
   10559     v8::Locker nested_locker;
   10560     v8::HandleScope scope;
   10561     v8::Handle<Value> exception;
   10562     { v8::TryCatch try_catch;
   10563       v8::Handle<Value> value = CompileRun(code);
   10564       CHECK(value.IsEmpty());
   10565       CHECK(try_catch.HasCaught());
   10566       // Make sure to wrap the exception in a new handle because
   10567       // the handle returned from the TryCatch is destroyed
   10568       // when the TryCatch is destroyed.
   10569       exception = Local<Value>::New(try_catch.Exception());
   10570     }
   10571     return v8::ThrowException(exception);
   10572   }
   10573 }
   10574 
   10575 
   10576 static v8::Handle<Value> ThrowInJSNoCatch(const v8::Arguments& args) {
   10577   CHECK(v8::Locker::IsLocked());
   10578   ApiTestFuzzer::Fuzz();
   10579   v8::Unlocker unlocker;
   10580   const char* code = "throw 7;";
   10581   {
   10582     v8::Locker nested_locker;
   10583     v8::HandleScope scope;
   10584     v8::Handle<Value> value = CompileRun(code);
   10585     CHECK(value.IsEmpty());
   10586     return v8_str("foo");
   10587   }
   10588 }
   10589 
   10590 
   10591 // These are locking tests that don't need to be run again
   10592 // as part of the locking aggregation tests.
   10593 TEST(NestedLockers) {
   10594   v8::Locker locker;
   10595   CHECK(v8::Locker::IsLocked());
   10596   v8::HandleScope scope;
   10597   LocalContext env;
   10598   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
   10599   Local<Function> fun = fun_templ->GetFunction();
   10600   env->Global()->Set(v8_str("throw_in_js"), fun);
   10601   Local<Script> script = v8_compile("(function () {"
   10602                                     "  try {"
   10603                                     "    throw_in_js();"
   10604                                     "    return 42;"
   10605                                     "  } catch (e) {"
   10606                                     "    return e * 13;"
   10607                                     "  }"
   10608                                     "})();");
   10609   CHECK_EQ(91, script->Run()->Int32Value());
   10610 }
   10611 
   10612 
   10613 // These are locking tests that don't need to be run again
   10614 // as part of the locking aggregation tests.
   10615 TEST(NestedLockersNoTryCatch) {
   10616   v8::Locker locker;
   10617   v8::HandleScope scope;
   10618   LocalContext env;
   10619   Local<v8::FunctionTemplate> fun_templ =
   10620       v8::FunctionTemplate::New(ThrowInJSNoCatch);
   10621   Local<Function> fun = fun_templ->GetFunction();
   10622   env->Global()->Set(v8_str("throw_in_js"), fun);
   10623   Local<Script> script = v8_compile("(function () {"
   10624                                     "  try {"
   10625                                     "    throw_in_js();"
   10626                                     "    return 42;"
   10627                                     "  } catch (e) {"
   10628                                     "    return e * 13;"
   10629                                     "  }"
   10630                                     "})();");
   10631   CHECK_EQ(91, script->Run()->Int32Value());
   10632 }
   10633 
   10634 
   10635 THREADED_TEST(RecursiveLocking) {
   10636   v8::Locker locker;
   10637   {
   10638     v8::Locker locker2;
   10639     CHECK(v8::Locker::IsLocked());
   10640   }
   10641 }
   10642 
   10643 
   10644 static v8::Handle<Value> UnlockForAMoment(const v8::Arguments& args) {
   10645   ApiTestFuzzer::Fuzz();
   10646   v8::Unlocker unlocker;
   10647   return v8::Undefined();
   10648 }
   10649 
   10650 
   10651 THREADED_TEST(LockUnlockLock) {
   10652   {
   10653     v8::Locker locker;
   10654     v8::HandleScope scope;
   10655     LocalContext env;
   10656     Local<v8::FunctionTemplate> fun_templ =
   10657         v8::FunctionTemplate::New(UnlockForAMoment);
   10658     Local<Function> fun = fun_templ->GetFunction();
   10659     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   10660     Local<Script> script = v8_compile("(function () {"
   10661                                       "  unlock_for_a_moment();"
   10662                                       "  return 42;"
   10663                                       "})();");
   10664     CHECK_EQ(42, script->Run()->Int32Value());
   10665   }
   10666   {
   10667     v8::Locker locker;
   10668     v8::HandleScope scope;
   10669     LocalContext env;
   10670     Local<v8::FunctionTemplate> fun_templ =
   10671         v8::FunctionTemplate::New(UnlockForAMoment);
   10672     Local<Function> fun = fun_templ->GetFunction();
   10673     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   10674     Local<Script> script = v8_compile("(function () {"
   10675                                       "  unlock_for_a_moment();"
   10676                                       "  return 42;"
   10677                                       "})();");
   10678     CHECK_EQ(42, script->Run()->Int32Value());
   10679   }
   10680 }
   10681 
   10682 
   10683 static int GetGlobalObjectsCount() {
   10684   i::Isolate::Current()->heap()->EnsureHeapIsIterable();
   10685   int count = 0;
   10686   i::HeapIterator it;
   10687   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
   10688     if (object->IsJSGlobalObject()) count++;
   10689   return count;
   10690 }
   10691 
   10692 
   10693 static void CheckSurvivingGlobalObjectsCount(int expected) {
   10694   // We need to collect all garbage twice to be sure that everything
   10695   // has been collected.  This is because inline caches are cleared in
   10696   // the first garbage collection but some of the maps have already
   10697   // been marked at that point.  Therefore some of the maps are not
   10698   // collected until the second garbage collection.
   10699   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   10700   HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
   10701   int count = GetGlobalObjectsCount();
   10702 #ifdef DEBUG
   10703   if (count != expected) HEAP->TracePathToGlobal();
   10704 #endif
   10705   CHECK_EQ(expected, count);
   10706 }
   10707 
   10708 
   10709 TEST(DontLeakGlobalObjects) {
   10710   // Regression test for issues 1139850 and 1174891.
   10711 
   10712   v8::V8::Initialize();
   10713 
   10714   for (int i = 0; i < 5; i++) {
   10715     { v8::HandleScope scope;
   10716       LocalContext context;
   10717     }
   10718     CheckSurvivingGlobalObjectsCount(0);
   10719 
   10720     { v8::HandleScope scope;
   10721       LocalContext context;
   10722       v8_compile("Date")->Run();
   10723     }
   10724     CheckSurvivingGlobalObjectsCount(0);
   10725 
   10726     { v8::HandleScope scope;
   10727       LocalContext context;
   10728       v8_compile("/aaa/")->Run();
   10729     }
   10730     CheckSurvivingGlobalObjectsCount(0);
   10731 
   10732     { v8::HandleScope scope;
   10733       const char* extension_list[] = { "v8/gc" };
   10734       v8::ExtensionConfiguration extensions(1, extension_list);
   10735       LocalContext context(&extensions);
   10736       v8_compile("gc();")->Run();
   10737     }
   10738     CheckSurvivingGlobalObjectsCount(0);
   10739   }
   10740 }
   10741 
   10742 
   10743 v8::Persistent<v8::Object> some_object;
   10744 v8::Persistent<v8::Object> bad_handle;
   10745 
   10746 void NewPersistentHandleCallback(v8::Persistent<v8::Value> handle, void*) {
   10747   v8::HandleScope scope;
   10748   bad_handle = v8::Persistent<v8::Object>::New(some_object);
   10749   handle.Dispose();
   10750 }
   10751 
   10752 
   10753 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   10754   LocalContext context;
   10755 
   10756   v8::Persistent<v8::Object> handle1, handle2;
   10757   {
   10758     v8::HandleScope scope;
   10759     some_object = v8::Persistent<v8::Object>::New(v8::Object::New());
   10760     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
   10761     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
   10762   }
   10763   // Note: order is implementation dependent alas: currently
   10764   // global handle nodes are processed by PostGarbageCollectionProcessing
   10765   // in reverse allocation order, so if second allocated handle is deleted,
   10766   // weak callback of the first handle would be able to 'reallocate' it.
   10767   handle1.MakeWeak(NULL, NewPersistentHandleCallback);
   10768   handle2.Dispose();
   10769   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   10770 }
   10771 
   10772 
   10773 v8::Persistent<v8::Object> to_be_disposed;
   10774 
   10775 void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) {
   10776   to_be_disposed.Dispose();
   10777   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   10778   handle.Dispose();
   10779 }
   10780 
   10781 
   10782 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   10783   LocalContext context;
   10784 
   10785   v8::Persistent<v8::Object> handle1, handle2;
   10786   {
   10787     v8::HandleScope scope;
   10788     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
   10789     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
   10790   }
   10791   handle1.MakeWeak(NULL, DisposeAndForceGcCallback);
   10792   to_be_disposed = handle2;
   10793   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   10794 }
   10795 
   10796 void DisposingCallback(v8::Persistent<v8::Value> handle, void*) {
   10797   handle.Dispose();
   10798 }
   10799 
   10800 void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) {
   10801   v8::HandleScope scope;
   10802   v8::Persistent<v8::Object>::New(v8::Object::New());
   10803   handle.Dispose();
   10804 }
   10805 
   10806 
   10807 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   10808   LocalContext context;
   10809 
   10810   v8::Persistent<v8::Object> handle1, handle2, handle3;
   10811   {
   10812     v8::HandleScope scope;
   10813     handle3 = v8::Persistent<v8::Object>::New(v8::Object::New());
   10814     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
   10815     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
   10816   }
   10817   handle2.MakeWeak(NULL, DisposingCallback);
   10818   handle3.MakeWeak(NULL, HandleCreatingCallback);
   10819   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   10820 }
   10821 
   10822 
   10823 THREADED_TEST(CheckForCrossContextObjectLiterals) {
   10824   v8::V8::Initialize();
   10825 
   10826   const int nof = 2;
   10827   const char* sources[nof] = {
   10828     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   10829     "Object()"
   10830   };
   10831 
   10832   for (int i = 0; i < nof; i++) {
   10833     const char* source = sources[i];
   10834     { v8::HandleScope scope;
   10835       LocalContext context;
   10836       CompileRun(source);
   10837     }
   10838     { v8::HandleScope scope;
   10839       LocalContext context;
   10840       CompileRun(source);
   10841     }
   10842   }
   10843 }
   10844 
   10845 
   10846 static v8::Handle<Value> NestedScope(v8::Persistent<Context> env) {
   10847   v8::HandleScope inner;
   10848   env->Enter();
   10849   v8::Handle<Value> three = v8_num(3);
   10850   v8::Handle<Value> value = inner.Close(three);
   10851   env->Exit();
   10852   return value;
   10853 }
   10854 
   10855 
   10856 THREADED_TEST(NestedHandleScopeAndContexts) {
   10857   v8::HandleScope outer;
   10858   v8::Persistent<Context> env = Context::New();
   10859   env->Enter();
   10860   v8::Handle<Value> value = NestedScope(env);
   10861   v8::Handle<String> str(value->ToString());
   10862   CHECK(!str.IsEmpty());
   10863   env->Exit();
   10864   env.Dispose();
   10865 }
   10866 
   10867 
   10868 THREADED_TEST(ExternalAllocatedMemory) {
   10869   v8::HandleScope outer;
   10870   v8::Persistent<Context> env(Context::New());
   10871   CHECK(!env.IsEmpty());
   10872   const int kSize = 1024*1024;
   10873   CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize);
   10874   CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0);
   10875 }
   10876 
   10877 
   10878 THREADED_TEST(DisposeEnteredContext) {
   10879   v8::HandleScope scope;
   10880   LocalContext outer;
   10881   { v8::Persistent<v8::Context> inner = v8::Context::New();
   10882     inner->Enter();
   10883     inner.Dispose();
   10884     inner.Clear();
   10885     inner->Exit();
   10886   }
   10887 }
   10888 
   10889 
   10890 // Regression test for issue 54, object templates with internal fields
   10891 // but no accessors or interceptors did not get their internal field
   10892 // count set on instances.
   10893 THREADED_TEST(Regress54) {
   10894   v8::HandleScope outer;
   10895   LocalContext context;
   10896   static v8::Persistent<v8::ObjectTemplate> templ;
   10897   if (templ.IsEmpty()) {
   10898     v8::HandleScope inner;
   10899     v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
   10900     local->SetInternalFieldCount(1);
   10901     templ = v8::Persistent<v8::ObjectTemplate>::New(inner.Close(local));
   10902   }
   10903   v8::Handle<v8::Object> result = templ->NewInstance();
   10904   CHECK_EQ(1, result->InternalFieldCount());
   10905 }
   10906 
   10907 
   10908 // If part of the threaded tests, this test makes ThreadingTest fail
   10909 // on mac.
   10910 TEST(CatchStackOverflow) {
   10911   v8::HandleScope scope;
   10912   LocalContext context;
   10913   v8::TryCatch try_catch;
   10914   v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
   10915     "function f() {"
   10916     "  return f();"
   10917     "}"
   10918     ""
   10919     "f();"));
   10920   v8::Handle<v8::Value> result = script->Run();
   10921   CHECK(result.IsEmpty());
   10922 }
   10923 
   10924 
   10925 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
   10926                                     const char* resource_name,
   10927                                     int line_offset) {
   10928   v8::HandleScope scope;
   10929   v8::TryCatch try_catch;
   10930   v8::Handle<v8::Value> result = script->Run();
   10931   CHECK(result.IsEmpty());
   10932   CHECK(try_catch.HasCaught());
   10933   v8::Handle<v8::Message> message = try_catch.Message();
   10934   CHECK(!message.IsEmpty());
   10935   CHECK_EQ(10 + line_offset, message->GetLineNumber());
   10936   CHECK_EQ(91, message->GetStartPosition());
   10937   CHECK_EQ(92, message->GetEndPosition());
   10938   CHECK_EQ(2, message->GetStartColumn());
   10939   CHECK_EQ(3, message->GetEndColumn());
   10940   v8::String::AsciiValue line(message->GetSourceLine());
   10941   CHECK_EQ("  throw 'nirk';", *line);
   10942   v8::String::AsciiValue name(message->GetScriptResourceName());
   10943   CHECK_EQ(resource_name, *name);
   10944 }
   10945 
   10946 
   10947 THREADED_TEST(TryCatchSourceInfo) {
   10948   v8::HandleScope scope;
   10949   LocalContext context;
   10950   v8::Handle<v8::String> source = v8::String::New(
   10951       "function Foo() {\n"
   10952       "  return Bar();\n"
   10953       "}\n"
   10954       "\n"
   10955       "function Bar() {\n"
   10956       "  return Baz();\n"
   10957       "}\n"
   10958       "\n"
   10959       "function Baz() {\n"
   10960       "  throw 'nirk';\n"
   10961       "}\n"
   10962       "\n"
   10963       "Foo();\n");
   10964 
   10965   const char* resource_name;
   10966   v8::Handle<v8::Script> script;
   10967   resource_name = "test.js";
   10968   script = v8::Script::Compile(source, v8::String::New(resource_name));
   10969   CheckTryCatchSourceInfo(script, resource_name, 0);
   10970 
   10971   resource_name = "test1.js";
   10972   v8::ScriptOrigin origin1(v8::String::New(resource_name));
   10973   script = v8::Script::Compile(source, &origin1);
   10974   CheckTryCatchSourceInfo(script, resource_name, 0);
   10975 
   10976   resource_name = "test2.js";
   10977   v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
   10978   script = v8::Script::Compile(source, &origin2);
   10979   CheckTryCatchSourceInfo(script, resource_name, 7);
   10980 }
   10981 
   10982 
   10983 THREADED_TEST(CompilationCache) {
   10984   v8::HandleScope scope;
   10985   LocalContext context;
   10986   v8::Handle<v8::String> source0 = v8::String::New("1234");
   10987   v8::Handle<v8::String> source1 = v8::String::New("1234");
   10988   v8::Handle<v8::Script> script0 =
   10989       v8::Script::Compile(source0, v8::String::New("test.js"));
   10990   v8::Handle<v8::Script> script1 =
   10991       v8::Script::Compile(source1, v8::String::New("test.js"));
   10992   v8::Handle<v8::Script> script2 =
   10993       v8::Script::Compile(source0);  // different origin
   10994   CHECK_EQ(1234, script0->Run()->Int32Value());
   10995   CHECK_EQ(1234, script1->Run()->Int32Value());
   10996   CHECK_EQ(1234, script2->Run()->Int32Value());
   10997 }
   10998 
   10999 
   11000 static v8::Handle<Value> FunctionNameCallback(const v8::Arguments& args) {
   11001   ApiTestFuzzer::Fuzz();
   11002   return v8_num(42);
   11003 }
   11004 
   11005 
   11006 THREADED_TEST(CallbackFunctionName) {
   11007   v8::HandleScope scope;
   11008   LocalContext context;
   11009   Local<ObjectTemplate> t = ObjectTemplate::New();
   11010   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
   11011   context->Global()->Set(v8_str("obj"), t->NewInstance());
   11012   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
   11013   CHECK(value->IsString());
   11014   v8::String::AsciiValue name(value);
   11015   CHECK_EQ("asdf", *name);
   11016 }
   11017 
   11018 
   11019 THREADED_TEST(DateAccess) {
   11020   v8::HandleScope scope;
   11021   LocalContext context;
   11022   v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
   11023   CHECK(date->IsDate());
   11024   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->NumberValue());
   11025 }
   11026 
   11027 
   11028 void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
   11029   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   11030   v8::Handle<v8::Array> props = obj->GetPropertyNames();
   11031   CHECK_EQ(elmc, props->Length());
   11032   for (int i = 0; i < elmc; i++) {
   11033     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
   11034     CHECK_EQ(elmv[i], *elm);
   11035   }
   11036 }
   11037 
   11038 
   11039 void CheckOwnProperties(v8::Handle<v8::Value> val,
   11040                         int elmc,
   11041                         const char* elmv[]) {
   11042   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   11043   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
   11044   CHECK_EQ(elmc, props->Length());
   11045   for (int i = 0; i < elmc; i++) {
   11046     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
   11047     CHECK_EQ(elmv[i], *elm);
   11048   }
   11049 }
   11050 
   11051 
   11052 THREADED_TEST(PropertyEnumeration) {
   11053   v8::HandleScope scope;
   11054   LocalContext context;
   11055   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
   11056       "var result = [];"
   11057       "result[0] = {};"
   11058       "result[1] = {a: 1, b: 2};"
   11059       "result[2] = [1, 2, 3];"
   11060       "var proto = {x: 1, y: 2, z: 3};"
   11061       "var x = { __proto__: proto, w: 0, z: 1 };"
   11062       "result[3] = x;"
   11063       "result;"))->Run();
   11064   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   11065   CHECK_EQ(4, elms->Length());
   11066   int elmc0 = 0;
   11067   const char** elmv0 = NULL;
   11068   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   11069   CheckOwnProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   11070   int elmc1 = 2;
   11071   const char* elmv1[] = {"a", "b"};
   11072   CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
   11073   CheckOwnProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
   11074   int elmc2 = 3;
   11075   const char* elmv2[] = {"0", "1", "2"};
   11076   CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
   11077   CheckOwnProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
   11078   int elmc3 = 4;
   11079   const char* elmv3[] = {"w", "z", "x", "y"};
   11080   CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
   11081   int elmc4 = 2;
   11082   const char* elmv4[] = {"w", "z"};
   11083   CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4);
   11084 }
   11085 
   11086 THREADED_TEST(PropertyEnumeration2) {
   11087   v8::HandleScope scope;
   11088   LocalContext context;
   11089   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
   11090       "var result = [];"
   11091       "result[0] = {};"
   11092       "result[1] = {a: 1, b: 2};"
   11093       "result[2] = [1, 2, 3];"
   11094       "var proto = {x: 1, y: 2, z: 3};"
   11095       "var x = { __proto__: proto, w: 0, z: 1 };"
   11096       "result[3] = x;"
   11097       "result;"))->Run();
   11098   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   11099   CHECK_EQ(4, elms->Length());
   11100   int elmc0 = 0;
   11101   const char** elmv0 = NULL;
   11102   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   11103 
   11104   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
   11105   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
   11106   CHECK_EQ(0, props->Length());
   11107   for (uint32_t i = 0; i < props->Length(); i++) {
   11108     printf("p[%d]\n", i);
   11109   }
   11110 }
   11111 
   11112 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
   11113                                   Local<Value> name,
   11114                                   v8::AccessType type,
   11115                                   Local<Value> data) {
   11116   return type != v8::ACCESS_SET;
   11117 }
   11118 
   11119 
   11120 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
   11121                                     uint32_t key,
   11122                                     v8::AccessType type,
   11123                                     Local<Value> data) {
   11124   return type != v8::ACCESS_SET;
   11125 }
   11126 
   11127 
   11128 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
   11129   v8::HandleScope scope;
   11130   LocalContext context;
   11131   Local<ObjectTemplate> templ = ObjectTemplate::New();
   11132   templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   11133                                  IndexedSetAccessBlocker);
   11134   templ->Set(v8_str("x"), v8::True());
   11135   Local<v8::Object> instance = templ->NewInstance();
   11136   context->Global()->Set(v8_str("obj"), instance);
   11137   Local<Value> value = CompileRun("obj.x");
   11138   CHECK(value->BooleanValue());
   11139 }
   11140 
   11141 
   11142 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
   11143                                   Local<Value> name,
   11144                                   v8::AccessType type,
   11145                                   Local<Value> data) {
   11146   return false;
   11147 }
   11148 
   11149 
   11150 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
   11151                                     uint32_t key,
   11152                                     v8::AccessType type,
   11153                                     Local<Value> data) {
   11154   return false;
   11155 }
   11156 
   11157 
   11158 
   11159 THREADED_TEST(AccessChecksReenabledCorrectly) {
   11160   v8::HandleScope scope;
   11161   LocalContext context;
   11162   Local<ObjectTemplate> templ = ObjectTemplate::New();
   11163   templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   11164                                  IndexedGetAccessBlocker);
   11165   templ->Set(v8_str("a"), v8_str("a"));
   11166   // Add more than 8 (see kMaxFastProperties) properties
   11167   // so that the constructor will force copying map.
   11168   // Cannot sprintf, gcc complains unsafety.
   11169   char buf[4];
   11170   for (char i = '0'; i <= '9' ; i++) {
   11171     buf[0] = i;
   11172     for (char j = '0'; j <= '9'; j++) {
   11173       buf[1] = j;
   11174       for (char k = '0'; k <= '9'; k++) {
   11175         buf[2] = k;
   11176         buf[3] = 0;
   11177         templ->Set(v8_str(buf), v8::Number::New(k));
   11178       }
   11179     }
   11180   }
   11181 
   11182   Local<v8::Object> instance_1 = templ->NewInstance();
   11183   context->Global()->Set(v8_str("obj_1"), instance_1);
   11184 
   11185   Local<Value> value_1 = CompileRun("obj_1.a");
   11186   CHECK(value_1->IsUndefined());
   11187 
   11188   Local<v8::Object> instance_2 = templ->NewInstance();
   11189   context->Global()->Set(v8_str("obj_2"), instance_2);
   11190 
   11191   Local<Value> value_2 = CompileRun("obj_2.a");
   11192   CHECK(value_2->IsUndefined());
   11193 }
   11194 
   11195 
   11196 // This tests that access check information remains on the global
   11197 // object template when creating contexts.
   11198 THREADED_TEST(AccessControlRepeatedContextCreation) {
   11199   v8::HandleScope handle_scope;
   11200   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   11201   global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   11202                                            IndexedSetAccessBlocker);
   11203   i::Handle<i::ObjectTemplateInfo> internal_template =
   11204       v8::Utils::OpenHandle(*global_template);
   11205   CHECK(!internal_template->constructor()->IsUndefined());
   11206   i::Handle<i::FunctionTemplateInfo> constructor(
   11207       i::FunctionTemplateInfo::cast(internal_template->constructor()));
   11208   CHECK(!constructor->access_check_info()->IsUndefined());
   11209   v8::Persistent<Context> context0(Context::New(NULL, global_template));
   11210   CHECK(!context0.IsEmpty());
   11211   CHECK(!constructor->access_check_info()->IsUndefined());
   11212 }
   11213 
   11214 
   11215 THREADED_TEST(TurnOnAccessCheck) {
   11216   v8::HandleScope handle_scope;
   11217 
   11218   // Create an environment with access check to the global object disabled by
   11219   // default.
   11220   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   11221   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   11222                                            IndexedGetAccessBlocker,
   11223                                            v8::Handle<v8::Value>(),
   11224                                            false);
   11225   v8::Persistent<Context> context = Context::New(NULL, global_template);
   11226   Context::Scope context_scope(context);
   11227 
   11228   // Set up a property and a number of functions.
   11229   context->Global()->Set(v8_str("a"), v8_num(1));
   11230   CompileRun("function f1() {return a;}"
   11231              "function f2() {return a;}"
   11232              "function g1() {return h();}"
   11233              "function g2() {return h();}"
   11234              "function h() {return 1;}");
   11235   Local<Function> f1 =
   11236       Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   11237   Local<Function> f2 =
   11238       Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   11239   Local<Function> g1 =
   11240       Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   11241   Local<Function> g2 =
   11242       Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   11243   Local<Function> h =
   11244       Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   11245 
   11246   // Get the global object.
   11247   v8::Handle<v8::Object> global = context->Global();
   11248 
   11249   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   11250   // uses the runtime system to retreive property a whereas f2 uses global load
   11251   // inline cache.
   11252   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   11253   for (int i = 0; i < 4; i++) {
   11254     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   11255   }
   11256 
   11257   // Same for g1 and g2.
   11258   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   11259   for (int i = 0; i < 4; i++) {
   11260     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   11261   }
   11262 
   11263   // Detach the global and turn on access check.
   11264   context->DetachGlobal();
   11265   context->Global()->TurnOnAccessCheck();
   11266 
   11267   // Failing access check to property get results in undefined.
   11268   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   11269   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   11270 
   11271   // Failing access check to function call results in exception.
   11272   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   11273   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   11274 
   11275   // No failing access check when just returning a constant.
   11276   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   11277 }
   11278 
   11279 
   11280 static const char* kPropertyA = "a";
   11281 static const char* kPropertyH = "h";
   11282 
   11283 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
   11284                                        Local<Value> name,
   11285                                        v8::AccessType type,
   11286                                        Local<Value> data) {
   11287   if (!name->IsString()) return false;
   11288   i::Handle<i::String> name_handle =
   11289       v8::Utils::OpenHandle(String::Cast(*name));
   11290   return !name_handle->IsEqualTo(i::CStrVector(kPropertyA))
   11291       && !name_handle->IsEqualTo(i::CStrVector(kPropertyH));
   11292 }
   11293 
   11294 
   11295 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
   11296   v8::HandleScope handle_scope;
   11297 
   11298   // Create an environment with access check to the global object disabled by
   11299   // default. When the registered access checker will block access to properties
   11300   // a and h.
   11301   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   11302   global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
   11303                                            IndexedGetAccessBlocker,
   11304                                            v8::Handle<v8::Value>(),
   11305                                            false);
   11306   v8::Persistent<Context> context = Context::New(NULL, global_template);
   11307   Context::Scope context_scope(context);
   11308 
   11309   // Set up a property and a number of functions.
   11310   context->Global()->Set(v8_str("a"), v8_num(1));
   11311   static const char* source = "function f1() {return a;}"
   11312                               "function f2() {return a;}"
   11313                               "function g1() {return h();}"
   11314                               "function g2() {return h();}"
   11315                               "function h() {return 1;}";
   11316 
   11317   CompileRun(source);
   11318   Local<Function> f1;
   11319   Local<Function> f2;
   11320   Local<Function> g1;
   11321   Local<Function> g2;
   11322   Local<Function> h;
   11323   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   11324   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   11325   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   11326   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   11327   h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   11328 
   11329   // Get the global object.
   11330   v8::Handle<v8::Object> global = context->Global();
   11331 
   11332   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   11333   // uses the runtime system to retreive property a whereas f2 uses global load
   11334   // inline cache.
   11335   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   11336   for (int i = 0; i < 4; i++) {
   11337     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   11338   }
   11339 
   11340   // Same for g1 and g2.
   11341   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   11342   for (int i = 0; i < 4; i++) {
   11343     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   11344   }
   11345 
   11346   // Detach the global and turn on access check now blocking access to property
   11347   // a and function h.
   11348   context->DetachGlobal();
   11349   context->Global()->TurnOnAccessCheck();
   11350 
   11351   // Failing access check to property get results in undefined.
   11352   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   11353   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   11354 
   11355   // Failing access check to function call results in exception.
   11356   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   11357   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   11358 
   11359   // No failing access check when just returning a constant.
   11360   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   11361 
   11362   // Now compile the source again. And get the newly compiled functions, except
   11363   // for h for which access is blocked.
   11364   CompileRun(source);
   11365   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   11366   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   11367   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   11368   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   11369   CHECK(context->Global()->Get(v8_str("h"))->IsUndefined());
   11370 
   11371   // Failing access check to property get results in undefined.
   11372   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   11373   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   11374 
   11375   // Failing access check to function call results in exception.
   11376   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   11377   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   11378 }
   11379 
   11380 
   11381 // This test verifies that pre-compilation (aka preparsing) can be called
   11382 // without initializing the whole VM. Thus we cannot run this test in a
   11383 // multi-threaded setup.
   11384 TEST(PreCompile) {
   11385   // TODO(155): This test would break without the initialization of V8. This is
   11386   // a workaround for now to make this test not fail.
   11387   v8::V8::Initialize();
   11388   const char* script = "function foo(a) { return a+1; }";
   11389   v8::ScriptData* sd =
   11390       v8::ScriptData::PreCompile(script, i::StrLength(script));
   11391   CHECK_NE(sd->Length(), 0);
   11392   CHECK_NE(sd->Data(), NULL);
   11393   CHECK(!sd->HasError());
   11394   delete sd;
   11395 }
   11396 
   11397 
   11398 TEST(PreCompileWithError) {
   11399   v8::V8::Initialize();
   11400   const char* script = "function foo(a) { return 1 * * 2; }";
   11401   v8::ScriptData* sd =
   11402       v8::ScriptData::PreCompile(script, i::StrLength(script));
   11403   CHECK(sd->HasError());
   11404   delete sd;
   11405 }
   11406 
   11407 
   11408 TEST(Regress31661) {
   11409   v8::V8::Initialize();
   11410   const char* script = " The Definintive Guide";
   11411   v8::ScriptData* sd =
   11412       v8::ScriptData::PreCompile(script, i::StrLength(script));
   11413   CHECK(sd->HasError());
   11414   delete sd;
   11415 }
   11416 
   11417 
   11418 // Tests that ScriptData can be serialized and deserialized.
   11419 TEST(PreCompileSerialization) {
   11420   v8::V8::Initialize();
   11421   const char* script = "function foo(a) { return a+1; }";
   11422   v8::ScriptData* sd =
   11423       v8::ScriptData::PreCompile(script, i::StrLength(script));
   11424 
   11425   // Serialize.
   11426   int serialized_data_length = sd->Length();
   11427   char* serialized_data = i::NewArray<char>(serialized_data_length);
   11428   memcpy(serialized_data, sd->Data(), serialized_data_length);
   11429 
   11430   // Deserialize.
   11431   v8::ScriptData* deserialized_sd =
   11432       v8::ScriptData::New(serialized_data, serialized_data_length);
   11433 
   11434   // Verify that the original is the same as the deserialized.
   11435   CHECK_EQ(sd->Length(), deserialized_sd->Length());
   11436   CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
   11437   CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
   11438 
   11439   delete sd;
   11440   delete deserialized_sd;
   11441 }
   11442 
   11443 
   11444 // Attempts to deserialize bad data.
   11445 TEST(PreCompileDeserializationError) {
   11446   v8::V8::Initialize();
   11447   const char* data = "DONT CARE";
   11448   int invalid_size = 3;
   11449   v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
   11450 
   11451   CHECK_EQ(0, sd->Length());
   11452 
   11453   delete sd;
   11454 }
   11455 
   11456 
   11457 // Attempts to deserialize bad data.
   11458 TEST(PreCompileInvalidPreparseDataError) {
   11459   v8::V8::Initialize();
   11460   v8::HandleScope scope;
   11461   LocalContext context;
   11462 
   11463   const char* script = "function foo(){ return 5;}\n"
   11464       "function bar(){ return 6 + 7;}  foo();";
   11465   v8::ScriptData* sd =
   11466       v8::ScriptData::PreCompile(script, i::StrLength(script));
   11467   CHECK(!sd->HasError());
   11468   // ScriptDataImpl private implementation details
   11469   const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
   11470   const int kFunctionEntrySize = i::FunctionEntry::kSize;
   11471   const int kFunctionEntryStartOffset = 0;
   11472   const int kFunctionEntryEndOffset = 1;
   11473   unsigned* sd_data =
   11474       reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   11475 
   11476   // Overwrite function bar's end position with 0.
   11477   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
   11478   v8::TryCatch try_catch;
   11479 
   11480   Local<String> source = String::New(script);
   11481   Local<Script> compiled_script = Script::New(source, NULL, sd);
   11482   CHECK(try_catch.HasCaught());
   11483   String::AsciiValue exception_value(try_catch.Message()->Get());
   11484   CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
   11485            *exception_value);
   11486 
   11487   try_catch.Reset();
   11488 
   11489   // Overwrite function bar's start position with 200.  The function entry
   11490   // will not be found when searching for it by position and we should fall
   11491   // back on eager compilation.
   11492   sd = v8::ScriptData::PreCompile(script, i::StrLength(script));
   11493   sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   11494   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
   11495       200;
   11496   compiled_script = Script::New(source, NULL, sd);
   11497   CHECK(!try_catch.HasCaught());
   11498 
   11499   delete sd;
   11500 }
   11501 
   11502 
   11503 // Verifies that the Handle<String> and const char* versions of the API produce
   11504 // the same results (at least for one trivial case).
   11505 TEST(PreCompileAPIVariationsAreSame) {
   11506   v8::V8::Initialize();
   11507   v8::HandleScope scope;
   11508 
   11509   const char* cstring = "function foo(a) { return a+1; }";
   11510 
   11511   v8::ScriptData* sd_from_cstring =
   11512       v8::ScriptData::PreCompile(cstring, i::StrLength(cstring));
   11513 
   11514   TestAsciiResource* resource = new TestAsciiResource(cstring);
   11515   v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
   11516       v8::String::NewExternal(resource));
   11517 
   11518   v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
   11519       v8::String::New(cstring));
   11520 
   11521   CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
   11522   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
   11523                      sd_from_external_string->Data(),
   11524                      sd_from_cstring->Length()));
   11525 
   11526   CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
   11527   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
   11528                      sd_from_string->Data(),
   11529                      sd_from_cstring->Length()));
   11530 
   11531 
   11532   delete sd_from_cstring;
   11533   delete sd_from_external_string;
   11534   delete sd_from_string;
   11535 }
   11536 
   11537 
   11538 // This tests that we do not allow dictionary load/call inline caches
   11539 // to use functions that have not yet been compiled.  The potential
   11540 // problem of loading a function that has not yet been compiled can
   11541 // arise because we share code between contexts via the compilation
   11542 // cache.
   11543 THREADED_TEST(DictionaryICLoadedFunction) {
   11544   v8::HandleScope scope;
   11545   // Test LoadIC.
   11546   for (int i = 0; i < 2; i++) {
   11547     LocalContext context;
   11548     context->Global()->Set(v8_str("tmp"), v8::True());
   11549     context->Global()->Delete(v8_str("tmp"));
   11550     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   11551   }
   11552   // Test CallIC.
   11553   for (int i = 0; i < 2; i++) {
   11554     LocalContext context;
   11555     context->Global()->Set(v8_str("tmp"), v8::True());
   11556     context->Global()->Delete(v8_str("tmp"));
   11557     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   11558   }
   11559 }
   11560 
   11561 
   11562 // Test that cross-context new calls use the context of the callee to
   11563 // create the new JavaScript object.
   11564 THREADED_TEST(CrossContextNew) {
   11565   v8::HandleScope scope;
   11566   v8::Persistent<Context> context0 = Context::New();
   11567   v8::Persistent<Context> context1 = Context::New();
   11568 
   11569   // Allow cross-domain access.
   11570   Local<String> token = v8_str("<security token>");
   11571   context0->SetSecurityToken(token);
   11572   context1->SetSecurityToken(token);
   11573 
   11574   // Set an 'x' property on the Object prototype and define a
   11575   // constructor function in context0.
   11576   context0->Enter();
   11577   CompileRun("Object.prototype.x = 42; function C() {};");
   11578   context0->Exit();
   11579 
   11580   // Call the constructor function from context0 and check that the
   11581   // result has the 'x' property.
   11582   context1->Enter();
   11583   context1->Global()->Set(v8_str("other"), context0->Global());
   11584   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   11585   CHECK(value->IsInt32());
   11586   CHECK_EQ(42, value->Int32Value());
   11587   context1->Exit();
   11588 
   11589   // Dispose the contexts to allow them to be garbage collected.
   11590   context0.Dispose();
   11591   context1.Dispose();
   11592 }
   11593 
   11594 
   11595 class RegExpInterruptTest {
   11596  public:
   11597   RegExpInterruptTest() : block_(NULL) {}
   11598   ~RegExpInterruptTest() { delete block_; }
   11599   void RunTest() {
   11600     block_ = i::OS::CreateSemaphore(0);
   11601     gc_count_ = 0;
   11602     gc_during_regexp_ = 0;
   11603     regexp_success_ = false;
   11604     gc_success_ = false;
   11605     GCThread gc_thread(this);
   11606     gc_thread.Start();
   11607     v8::Locker::StartPreemption(1);
   11608 
   11609     LongRunningRegExp();
   11610     {
   11611       v8::Unlocker unlock;
   11612       gc_thread.Join();
   11613     }
   11614     v8::Locker::StopPreemption();
   11615     CHECK(regexp_success_);
   11616     CHECK(gc_success_);
   11617   }
   11618 
   11619  private:
   11620   // Number of garbage collections required.
   11621   static const int kRequiredGCs = 5;
   11622 
   11623   class GCThread : public i::Thread {
   11624    public:
   11625     explicit GCThread(RegExpInterruptTest* test)
   11626         : Thread("GCThread"), test_(test) {}
   11627     virtual void Run() {
   11628       test_->CollectGarbage();
   11629     }
   11630    private:
   11631      RegExpInterruptTest* test_;
   11632   };
   11633 
   11634   void CollectGarbage() {
   11635     block_->Wait();
   11636     while (gc_during_regexp_ < kRequiredGCs) {
   11637       {
   11638         v8::Locker lock;
   11639         // TODO(lrn): Perhaps create some garbage before collecting.
   11640         HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   11641         gc_count_++;
   11642       }
   11643       i::OS::Sleep(1);
   11644     }
   11645     gc_success_ = true;
   11646   }
   11647 
   11648   void LongRunningRegExp() {
   11649     block_->Signal();  // Enable garbage collection thread on next preemption.
   11650     int rounds = 0;
   11651     while (gc_during_regexp_ < kRequiredGCs) {
   11652       int gc_before = gc_count_;
   11653       {
   11654         // Match 15-30 "a"'s against 14 and a "b".
   11655         const char* c_source =
   11656             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   11657             ".exec('aaaaaaaaaaaaaaab') === null";
   11658         Local<String> source = String::New(c_source);
   11659         Local<Script> script = Script::Compile(source);
   11660         Local<Value> result = script->Run();
   11661         if (!result->BooleanValue()) {
   11662           gc_during_regexp_ = kRequiredGCs;  // Allow gc thread to exit.
   11663           return;
   11664         }
   11665       }
   11666       {
   11667         // Match 15-30 "a"'s against 15 and a "b".
   11668         const char* c_source =
   11669             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   11670             ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
   11671         Local<String> source = String::New(c_source);
   11672         Local<Script> script = Script::Compile(source);
   11673         Local<Value> result = script->Run();
   11674         if (!result->BooleanValue()) {
   11675           gc_during_regexp_ = kRequiredGCs;
   11676           return;
   11677         }
   11678       }
   11679       int gc_after = gc_count_;
   11680       gc_during_regexp_ += gc_after - gc_before;
   11681       rounds++;
   11682       i::OS::Sleep(1);
   11683     }
   11684     regexp_success_ = true;
   11685   }
   11686 
   11687   i::Semaphore* block_;
   11688   int gc_count_;
   11689   int gc_during_regexp_;
   11690   bool regexp_success_;
   11691   bool gc_success_;
   11692 };
   11693 
   11694 
   11695 // Test that a regular expression execution can be interrupted and
   11696 // survive a garbage collection.
   11697 TEST(RegExpInterruption) {
   11698   v8::Locker lock;
   11699   v8::V8::Initialize();
   11700   v8::HandleScope scope;
   11701   Local<Context> local_env;
   11702   {
   11703     LocalContext env;
   11704     local_env = env.local();
   11705   }
   11706 
   11707   // Local context should still be live.
   11708   CHECK(!local_env.IsEmpty());
   11709   local_env->Enter();
   11710 
   11711   // Should complete without problems.
   11712   RegExpInterruptTest().RunTest();
   11713 
   11714   local_env->Exit();
   11715 }
   11716 
   11717 
   11718 class ApplyInterruptTest {
   11719  public:
   11720   ApplyInterruptTest() : block_(NULL) {}
   11721   ~ApplyInterruptTest() { delete block_; }
   11722   void RunTest() {
   11723     block_ = i::OS::CreateSemaphore(0);
   11724     gc_count_ = 0;
   11725     gc_during_apply_ = 0;
   11726     apply_success_ = false;
   11727     gc_success_ = false;
   11728     GCThread gc_thread(this);
   11729     gc_thread.Start();
   11730     v8::Locker::StartPreemption(1);
   11731 
   11732     LongRunningApply();
   11733     {
   11734       v8::Unlocker unlock;
   11735       gc_thread.Join();
   11736     }
   11737     v8::Locker::StopPreemption();
   11738     CHECK(apply_success_);
   11739     CHECK(gc_success_);
   11740   }
   11741 
   11742  private:
   11743   // Number of garbage collections required.
   11744   static const int kRequiredGCs = 2;
   11745 
   11746   class GCThread : public i::Thread {
   11747    public:
   11748     explicit GCThread(ApplyInterruptTest* test)
   11749         : Thread("GCThread"), test_(test) {}
   11750     virtual void Run() {
   11751       test_->CollectGarbage();
   11752     }
   11753    private:
   11754      ApplyInterruptTest* test_;
   11755   };
   11756 
   11757   void CollectGarbage() {
   11758     block_->Wait();
   11759     while (gc_during_apply_ < kRequiredGCs) {
   11760       {
   11761         v8::Locker lock;
   11762         HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   11763         gc_count_++;
   11764       }
   11765       i::OS::Sleep(1);
   11766     }
   11767     gc_success_ = true;
   11768   }
   11769 
   11770   void LongRunningApply() {
   11771     block_->Signal();
   11772     int rounds = 0;
   11773     while (gc_during_apply_ < kRequiredGCs) {
   11774       int gc_before = gc_count_;
   11775       {
   11776         const char* c_source =
   11777             "function do_very_little(bar) {"
   11778             "  this.foo = bar;"
   11779             "}"
   11780             "for (var i = 0; i < 100000; i++) {"
   11781             "  do_very_little.apply(this, ['bar']);"
   11782             "}";
   11783         Local<String> source = String::New(c_source);
   11784         Local<Script> script = Script::Compile(source);
   11785         Local<Value> result = script->Run();
   11786         // Check that no exception was thrown.
   11787         CHECK(!result.IsEmpty());
   11788       }
   11789       int gc_after = gc_count_;
   11790       gc_during_apply_ += gc_after - gc_before;
   11791       rounds++;
   11792     }
   11793     apply_success_ = true;
   11794   }
   11795 
   11796   i::Semaphore* block_;
   11797   int gc_count_;
   11798   int gc_during_apply_;
   11799   bool apply_success_;
   11800   bool gc_success_;
   11801 };
   11802 
   11803 
   11804 // Test that nothing bad happens if we get a preemption just when we were
   11805 // about to do an apply().
   11806 TEST(ApplyInterruption) {
   11807   v8::Locker lock;
   11808   v8::V8::Initialize();
   11809   v8::HandleScope scope;
   11810   Local<Context> local_env;
   11811   {
   11812     LocalContext env;
   11813     local_env = env.local();
   11814   }
   11815 
   11816   // Local context should still be live.
   11817   CHECK(!local_env.IsEmpty());
   11818   local_env->Enter();
   11819 
   11820   // Should complete without problems.
   11821   ApplyInterruptTest().RunTest();
   11822 
   11823   local_env->Exit();
   11824 }
   11825 
   11826 
   11827 // Verify that we can clone an object
   11828 TEST(ObjectClone) {
   11829   v8::HandleScope scope;
   11830   LocalContext env;
   11831 
   11832   const char* sample =
   11833     "var rv = {};"      \
   11834     "rv.alpha = 'hello';" \
   11835     "rv.beta = 123;"     \
   11836     "rv;";
   11837 
   11838   // Create an object, verify basics.
   11839   Local<Value> val = CompileRun(sample);
   11840   CHECK(val->IsObject());
   11841   Local<v8::Object> obj = val.As<v8::Object>();
   11842   obj->Set(v8_str("gamma"), v8_str("cloneme"));
   11843 
   11844   CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
   11845   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
   11846   CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
   11847 
   11848   // Clone it.
   11849   Local<v8::Object> clone = obj->Clone();
   11850   CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
   11851   CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
   11852   CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
   11853 
   11854   // Set a property on the clone, verify each object.
   11855   clone->Set(v8_str("beta"), v8::Integer::New(456));
   11856   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
   11857   CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
   11858 }
   11859 
   11860 
   11861 class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
   11862  public:
   11863   explicit AsciiVectorResource(i::Vector<const char> vector)
   11864       : data_(vector) {}
   11865   virtual ~AsciiVectorResource() {}
   11866   virtual size_t length() const { return data_.length(); }
   11867   virtual const char* data() const { return data_.start(); }
   11868  private:
   11869   i::Vector<const char> data_;
   11870 };
   11871 
   11872 
   11873 class UC16VectorResource : public v8::String::ExternalStringResource {
   11874  public:
   11875   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   11876       : data_(vector) {}
   11877   virtual ~UC16VectorResource() {}
   11878   virtual size_t length() const { return data_.length(); }
   11879   virtual const i::uc16* data() const { return data_.start(); }
   11880  private:
   11881   i::Vector<const i::uc16> data_;
   11882 };
   11883 
   11884 
   11885 static void MorphAString(i::String* string,
   11886                          AsciiVectorResource* ascii_resource,
   11887                          UC16VectorResource* uc16_resource) {
   11888   CHECK(i::StringShape(string).IsExternal());
   11889   if (string->IsAsciiRepresentation()) {
   11890     // Check old map is not symbol or long.
   11891     CHECK(string->map() == HEAP->external_ascii_string_map());
   11892     // Morph external string to be TwoByte string.
   11893     string->set_map(HEAP->external_string_map());
   11894     i::ExternalTwoByteString* morphed =
   11895          i::ExternalTwoByteString::cast(string);
   11896     morphed->set_resource(uc16_resource);
   11897   } else {
   11898     // Check old map is not symbol or long.
   11899     CHECK(string->map() == HEAP->external_string_map());
   11900     // Morph external string to be ASCII string.
   11901     string->set_map(HEAP->external_ascii_string_map());
   11902     i::ExternalAsciiString* morphed =
   11903          i::ExternalAsciiString::cast(string);
   11904     morphed->set_resource(ascii_resource);
   11905   }
   11906 }
   11907 
   11908 
   11909 // Test that we can still flatten a string if the components it is built up
   11910 // from have been turned into 16 bit strings in the mean time.
   11911 THREADED_TEST(MorphCompositeStringTest) {
   11912   char utf_buffer[129];
   11913   const char* c_string = "Now is the time for all good men"
   11914                          " to come to the aid of the party";
   11915   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   11916   {
   11917     v8::HandleScope scope;
   11918     LocalContext env;
   11919     AsciiVectorResource ascii_resource(
   11920         i::Vector<const char>(c_string, i::StrLength(c_string)));
   11921     UC16VectorResource uc16_resource(
   11922         i::Vector<const uint16_t>(two_byte_string,
   11923                                   i::StrLength(c_string)));
   11924 
   11925     Local<String> lhs(v8::Utils::ToLocal(
   11926         FACTORY->NewExternalStringFromAscii(&ascii_resource)));
   11927     Local<String> rhs(v8::Utils::ToLocal(
   11928         FACTORY->NewExternalStringFromAscii(&ascii_resource)));
   11929 
   11930     env->Global()->Set(v8_str("lhs"), lhs);
   11931     env->Global()->Set(v8_str("rhs"), rhs);
   11932 
   11933     CompileRun(
   11934         "var cons = lhs + rhs;"
   11935         "var slice = lhs.substring(1, lhs.length - 1);"
   11936         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   11937 
   11938     CHECK(!lhs->MayContainNonAscii());
   11939     CHECK(!rhs->MayContainNonAscii());
   11940 
   11941     MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
   11942     MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
   11943 
   11944     // This should UTF-8 without flattening, since everything is ASCII.
   11945     Handle<String> cons = v8_compile("cons")->Run().As<String>();
   11946     CHECK_EQ(128, cons->Utf8Length());
   11947     int nchars = -1;
   11948     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
   11949     CHECK_EQ(128, nchars);
   11950     CHECK_EQ(0, strcmp(
   11951         utf_buffer,
   11952         "Now is the time for all good men to come to the aid of the party"
   11953         "Now is the time for all good men to come to the aid of the party"));
   11954 
   11955     // Now do some stuff to make sure the strings are flattened, etc.
   11956     CompileRun(
   11957         "/[^a-z]/.test(cons);"
   11958         "/[^a-z]/.test(slice);"
   11959         "/[^a-z]/.test(slice_on_cons);");
   11960     const char* expected_cons =
   11961         "Now is the time for all good men to come to the aid of the party"
   11962         "Now is the time for all good men to come to the aid of the party";
   11963     const char* expected_slice =
   11964         "ow is the time for all good men to come to the aid of the part";
   11965     const char* expected_slice_on_cons =
   11966         "ow is the time for all good men to come to the aid of the party"
   11967         "Now is the time for all good men to come to the aid of the part";
   11968     CHECK_EQ(String::New(expected_cons),
   11969              env->Global()->Get(v8_str("cons")));
   11970     CHECK_EQ(String::New(expected_slice),
   11971              env->Global()->Get(v8_str("slice")));
   11972     CHECK_EQ(String::New(expected_slice_on_cons),
   11973              env->Global()->Get(v8_str("slice_on_cons")));
   11974   }
   11975   i::DeleteArray(two_byte_string);
   11976 }
   11977 
   11978 
   11979 TEST(CompileExternalTwoByteSource) {
   11980   v8::HandleScope scope;
   11981   LocalContext context;
   11982 
   11983   // This is a very short list of sources, which currently is to check for a
   11984   // regression caused by r2703.
   11985   const char* ascii_sources[] = {
   11986     "0.5",
   11987     "-0.5",   // This mainly testes PushBack in the Scanner.
   11988     "--0.5",  // This mainly testes PushBack in the Scanner.
   11989     NULL
   11990   };
   11991 
   11992   // Compile the sources as external two byte strings.
   11993   for (int i = 0; ascii_sources[i] != NULL; i++) {
   11994     uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
   11995     UC16VectorResource uc16_resource(
   11996         i::Vector<const uint16_t>(two_byte_string,
   11997                                   i::StrLength(ascii_sources[i])));
   11998     v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
   11999     v8::Script::Compile(source);
   12000     i::DeleteArray(two_byte_string);
   12001   }
   12002 }
   12003 
   12004 
   12005 class RegExpStringModificationTest {
   12006  public:
   12007   RegExpStringModificationTest()
   12008       : block_(i::OS::CreateSemaphore(0)),
   12009         morphs_(0),
   12010         morphs_during_regexp_(0),
   12011         ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
   12012         uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
   12013   ~RegExpStringModificationTest() { delete block_; }
   12014   void RunTest() {
   12015     regexp_success_ = false;
   12016     morph_success_ = false;
   12017 
   12018     // Initialize the contents of two_byte_content_ to be a uc16 representation
   12019     // of "aaaaaaaaaaaaaab".
   12020     for (int i = 0; i < 14; i++) {
   12021       two_byte_content_[i] = 'a';
   12022     }
   12023     two_byte_content_[14] = 'b';
   12024 
   12025     // Create the input string for the regexp - the one we are going to change
   12026     // properties of.
   12027     input_ = FACTORY->NewExternalStringFromAscii(&ascii_resource_);
   12028 
   12029     // Inject the input as a global variable.
   12030     i::Handle<i::String> input_name =
   12031         FACTORY->NewStringFromAscii(i::Vector<const char>("input", 5));
   12032     i::Isolate::Current()->global_context()->global()->SetProperty(
   12033         *input_name,
   12034         *input_,
   12035         NONE,
   12036         i::kNonStrictMode)->ToObjectChecked();
   12037 
   12038     MorphThread morph_thread(this);
   12039     morph_thread.Start();
   12040     v8::Locker::StartPreemption(1);
   12041     LongRunningRegExp();
   12042     {
   12043       v8::Unlocker unlock;
   12044       morph_thread.Join();
   12045     }
   12046     v8::Locker::StopPreemption();
   12047     CHECK(regexp_success_);
   12048     CHECK(morph_success_);
   12049   }
   12050 
   12051  private:
   12052   // Number of string modifications required.
   12053   static const int kRequiredModifications = 5;
   12054   static const int kMaxModifications = 100;
   12055 
   12056   class MorphThread : public i::Thread {
   12057    public:
   12058     explicit MorphThread(RegExpStringModificationTest* test)
   12059         : Thread("MorphThread"), test_(test) {}
   12060     virtual void Run() {
   12061       test_->MorphString();
   12062     }
   12063    private:
   12064      RegExpStringModificationTest* test_;
   12065   };
   12066 
   12067   void MorphString() {
   12068     block_->Wait();
   12069     while (morphs_during_regexp_ < kRequiredModifications &&
   12070            morphs_ < kMaxModifications) {
   12071       {
   12072         v8::Locker lock;
   12073         // Swap string between ascii and two-byte representation.
   12074         i::String* string = *input_;
   12075         MorphAString(string, &ascii_resource_, &uc16_resource_);
   12076         morphs_++;
   12077       }
   12078       i::OS::Sleep(1);
   12079     }
   12080     morph_success_ = true;
   12081   }
   12082 
   12083   void LongRunningRegExp() {
   12084     block_->Signal();  // Enable morphing thread on next preemption.
   12085     while (morphs_during_regexp_ < kRequiredModifications &&
   12086            morphs_ < kMaxModifications) {
   12087       int morphs_before = morphs_;
   12088       {
   12089         v8::HandleScope scope;
   12090         // Match 15-30 "a"'s against 14 and a "b".
   12091         const char* c_source =
   12092             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   12093             ".exec(input) === null";
   12094         Local<String> source = String::New(c_source);
   12095         Local<Script> script = Script::Compile(source);
   12096         Local<Value> result = script->Run();
   12097         CHECK(result->IsTrue());
   12098       }
   12099       int morphs_after = morphs_;
   12100       morphs_during_regexp_ += morphs_after - morphs_before;
   12101     }
   12102     regexp_success_ = true;
   12103   }
   12104 
   12105   i::uc16 two_byte_content_[15];
   12106   i::Semaphore* block_;
   12107   int morphs_;
   12108   int morphs_during_regexp_;
   12109   bool regexp_success_;
   12110   bool morph_success_;
   12111   i::Handle<i::String> input_;
   12112   AsciiVectorResource ascii_resource_;
   12113   UC16VectorResource uc16_resource_;
   12114 };
   12115 
   12116 
   12117 // Test that a regular expression execution can be interrupted and
   12118 // the string changed without failing.
   12119 TEST(RegExpStringModification) {
   12120   v8::Locker lock;
   12121   v8::V8::Initialize();
   12122   v8::HandleScope scope;
   12123   Local<Context> local_env;
   12124   {
   12125     LocalContext env;
   12126     local_env = env.local();
   12127   }
   12128 
   12129   // Local context should still be live.
   12130   CHECK(!local_env.IsEmpty());
   12131   local_env->Enter();
   12132 
   12133   // Should complete without problems.
   12134   RegExpStringModificationTest().RunTest();
   12135 
   12136   local_env->Exit();
   12137 }
   12138 
   12139 
   12140 // Test that we can set a property on the global object even if there
   12141 // is a read-only property in the prototype chain.
   12142 TEST(ReadOnlyPropertyInGlobalProto) {
   12143   v8::HandleScope scope;
   12144   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   12145   LocalContext context(0, templ);
   12146   v8::Handle<v8::Object> global = context->Global();
   12147   v8::Handle<v8::Object> global_proto =
   12148       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
   12149   global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
   12150   global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
   12151   // Check without 'eval' or 'with'.
   12152   v8::Handle<v8::Value> res =
   12153       CompileRun("function f() { x = 42; return x; }; f()");
   12154   // Check with 'eval'.
   12155   res = CompileRun("function f() { eval('1'); y = 42; return y; }; f()");
   12156   CHECK_EQ(v8::Integer::New(42), res);
   12157   // Check with 'with'.
   12158   res = CompileRun("function f() { with (this) { y = 42 }; return y; }; f()");
   12159   CHECK_EQ(v8::Integer::New(42), res);
   12160 }
   12161 
   12162 static int force_set_set_count = 0;
   12163 static int force_set_get_count = 0;
   12164 bool pass_on_get = false;
   12165 
   12166 static v8::Handle<v8::Value> ForceSetGetter(v8::Local<v8::String> name,
   12167                                             const v8::AccessorInfo& info) {
   12168   force_set_get_count++;
   12169   if (pass_on_get) {
   12170     return v8::Handle<v8::Value>();
   12171   } else {
   12172     return v8::Int32::New(3);
   12173   }
   12174 }
   12175 
   12176 static void ForceSetSetter(v8::Local<v8::String> name,
   12177                            v8::Local<v8::Value> value,
   12178                            const v8::AccessorInfo& info) {
   12179   force_set_set_count++;
   12180 }
   12181 
   12182 static v8::Handle<v8::Value> ForceSetInterceptSetter(
   12183     v8::Local<v8::String> name,
   12184     v8::Local<v8::Value> value,
   12185     const v8::AccessorInfo& info) {
   12186   force_set_set_count++;
   12187   return v8::Undefined();
   12188 }
   12189 
   12190 TEST(ForceSet) {
   12191   force_set_get_count = 0;
   12192   force_set_set_count = 0;
   12193   pass_on_get = false;
   12194 
   12195   v8::HandleScope scope;
   12196   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   12197   v8::Handle<v8::String> access_property = v8::String::New("a");
   12198   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
   12199   LocalContext context(NULL, templ);
   12200   v8::Handle<v8::Object> global = context->Global();
   12201 
   12202   // Ordinary properties
   12203   v8::Handle<v8::String> simple_property = v8::String::New("p");
   12204   global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
   12205   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   12206   // This should fail because the property is read-only
   12207   global->Set(simple_property, v8::Int32::New(5));
   12208   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   12209   // This should succeed even though the property is read-only
   12210   global->ForceSet(simple_property, v8::Int32::New(6));
   12211   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
   12212 
   12213   // Accessors
   12214   CHECK_EQ(0, force_set_set_count);
   12215   CHECK_EQ(0, force_set_get_count);
   12216   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   12217   // CHECK_EQ the property shouldn't override it, just call the setter
   12218   // which in this case does nothing.
   12219   global->Set(access_property, v8::Int32::New(7));
   12220   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   12221   CHECK_EQ(1, force_set_set_count);
   12222   CHECK_EQ(2, force_set_get_count);
   12223   // Forcing the property to be set should override the accessor without
   12224   // calling it
   12225   global->ForceSet(access_property, v8::Int32::New(8));
   12226   CHECK_EQ(8, global->Get(access_property)->Int32Value());
   12227   CHECK_EQ(1, force_set_set_count);
   12228   CHECK_EQ(2, force_set_get_count);
   12229 }
   12230 
   12231 TEST(ForceSetWithInterceptor) {
   12232   force_set_get_count = 0;
   12233   force_set_set_count = 0;
   12234   pass_on_get = false;
   12235 
   12236   v8::HandleScope scope;
   12237   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   12238   templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
   12239   LocalContext context(NULL, templ);
   12240   v8::Handle<v8::Object> global = context->Global();
   12241 
   12242   v8::Handle<v8::String> some_property = v8::String::New("a");
   12243   CHECK_EQ(0, force_set_set_count);
   12244   CHECK_EQ(0, force_set_get_count);
   12245   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   12246   // Setting the property shouldn't override it, just call the setter
   12247   // which in this case does nothing.
   12248   global->Set(some_property, v8::Int32::New(7));
   12249   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   12250   CHECK_EQ(1, force_set_set_count);
   12251   CHECK_EQ(2, force_set_get_count);
   12252   // Getting the property when the interceptor returns an empty handle
   12253   // should yield undefined, since the property isn't present on the
   12254   // object itself yet.
   12255   pass_on_get = true;
   12256   CHECK(global->Get(some_property)->IsUndefined());
   12257   CHECK_EQ(1, force_set_set_count);
   12258   CHECK_EQ(3, force_set_get_count);
   12259   // Forcing the property to be set should cause the value to be
   12260   // set locally without calling the interceptor.
   12261   global->ForceSet(some_property, v8::Int32::New(8));
   12262   CHECK_EQ(8, global->Get(some_property)->Int32Value());
   12263   CHECK_EQ(1, force_set_set_count);
   12264   CHECK_EQ(4, force_set_get_count);
   12265   // Reenabling the interceptor should cause it to take precedence over
   12266   // the property
   12267   pass_on_get = false;
   12268   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   12269   CHECK_EQ(1, force_set_set_count);
   12270   CHECK_EQ(5, force_set_get_count);
   12271   // The interceptor should also work for other properties
   12272   CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
   12273   CHECK_EQ(1, force_set_set_count);
   12274   CHECK_EQ(6, force_set_get_count);
   12275 }
   12276 
   12277 
   12278 THREADED_TEST(ForceDelete) {
   12279   v8::HandleScope scope;
   12280   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   12281   LocalContext context(NULL, templ);
   12282   v8::Handle<v8::Object> global = context->Global();
   12283 
   12284   // Ordinary properties
   12285   v8::Handle<v8::String> simple_property = v8::String::New("p");
   12286   global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
   12287   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   12288   // This should fail because the property is dont-delete.
   12289   CHECK(!global->Delete(simple_property));
   12290   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   12291   // This should succeed even though the property is dont-delete.
   12292   CHECK(global->ForceDelete(simple_property));
   12293   CHECK(global->Get(simple_property)->IsUndefined());
   12294 }
   12295 
   12296 
   12297 static int force_delete_interceptor_count = 0;
   12298 static bool pass_on_delete = false;
   12299 
   12300 
   12301 static v8::Handle<v8::Boolean> ForceDeleteDeleter(
   12302     v8::Local<v8::String> name,
   12303     const v8::AccessorInfo& info) {
   12304   force_delete_interceptor_count++;
   12305   if (pass_on_delete) {
   12306     return v8::Handle<v8::Boolean>();
   12307   } else {
   12308     return v8::True();
   12309   }
   12310 }
   12311 
   12312 
   12313 THREADED_TEST(ForceDeleteWithInterceptor) {
   12314   force_delete_interceptor_count = 0;
   12315   pass_on_delete = false;
   12316 
   12317   v8::HandleScope scope;
   12318   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   12319   templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
   12320   LocalContext context(NULL, templ);
   12321   v8::Handle<v8::Object> global = context->Global();
   12322 
   12323   v8::Handle<v8::String> some_property = v8::String::New("a");
   12324   global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
   12325 
   12326   // Deleting a property should get intercepted and nothing should
   12327   // happen.
   12328   CHECK_EQ(0, force_delete_interceptor_count);
   12329   CHECK(global->Delete(some_property));
   12330   CHECK_EQ(1, force_delete_interceptor_count);
   12331   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   12332   // Deleting the property when the interceptor returns an empty
   12333   // handle should not delete the property since it is DontDelete.
   12334   pass_on_delete = true;
   12335   CHECK(!global->Delete(some_property));
   12336   CHECK_EQ(2, force_delete_interceptor_count);
   12337   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   12338   // Forcing the property to be deleted should delete the value
   12339   // without calling the interceptor.
   12340   CHECK(global->ForceDelete(some_property));
   12341   CHECK(global->Get(some_property)->IsUndefined());
   12342   CHECK_EQ(2, force_delete_interceptor_count);
   12343 }
   12344 
   12345 
   12346 // Make sure that forcing a delete invalidates any IC stubs, so we
   12347 // don't read the hole value.
   12348 THREADED_TEST(ForceDeleteIC) {
   12349   v8::HandleScope scope;
   12350   LocalContext context;
   12351   // Create a DontDelete variable on the global object.
   12352   CompileRun("this.__proto__ = { foo: 'horse' };"
   12353              "var foo = 'fish';"
   12354              "function f() { return foo.length; }");
   12355   // Initialize the IC for foo in f.
   12356   CompileRun("for (var i = 0; i < 4; i++) f();");
   12357   // Make sure the value of foo is correct before the deletion.
   12358   CHECK_EQ(4, CompileRun("f()")->Int32Value());
   12359   // Force the deletion of foo.
   12360   CHECK(context->Global()->ForceDelete(v8_str("foo")));
   12361   // Make sure the value for foo is read from the prototype, and that
   12362   // we don't get in trouble with reading the deleted cell value
   12363   // sentinel.
   12364   CHECK_EQ(5, CompileRun("f()")->Int32Value());
   12365 }
   12366 
   12367 
   12368 v8::Persistent<Context> calling_context0;
   12369 v8::Persistent<Context> calling_context1;
   12370 v8::Persistent<Context> calling_context2;
   12371 
   12372 
   12373 // Check that the call to the callback is initiated in
   12374 // calling_context2, the directly calling context is calling_context1
   12375 // and the callback itself is in calling_context0.
   12376 static v8::Handle<Value> GetCallingContextCallback(const v8::Arguments& args) {
   12377   ApiTestFuzzer::Fuzz();
   12378   CHECK(Context::GetCurrent() == calling_context0);
   12379   CHECK(Context::GetCalling() == calling_context1);
   12380   CHECK(Context::GetEntered() == calling_context2);
   12381   return v8::Integer::New(42);
   12382 }
   12383 
   12384 
   12385 THREADED_TEST(GetCallingContext) {
   12386   v8::HandleScope scope;
   12387 
   12388   calling_context0 = Context::New();
   12389   calling_context1 = Context::New();
   12390   calling_context2 = Context::New();
   12391 
   12392   // Allow cross-domain access.
   12393   Local<String> token = v8_str("<security token>");
   12394   calling_context0->SetSecurityToken(token);
   12395   calling_context1->SetSecurityToken(token);
   12396   calling_context2->SetSecurityToken(token);
   12397 
   12398   // Create an object with a C++ callback in context0.
   12399   calling_context0->Enter();
   12400   Local<v8::FunctionTemplate> callback_templ =
   12401       v8::FunctionTemplate::New(GetCallingContextCallback);
   12402   calling_context0->Global()->Set(v8_str("callback"),
   12403                                   callback_templ->GetFunction());
   12404   calling_context0->Exit();
   12405 
   12406   // Expose context0 in context1 and set up a function that calls the
   12407   // callback function.
   12408   calling_context1->Enter();
   12409   calling_context1->Global()->Set(v8_str("context0"),
   12410                                   calling_context0->Global());
   12411   CompileRun("function f() { context0.callback() }");
   12412   calling_context1->Exit();
   12413 
   12414   // Expose context1 in context2 and call the callback function in
   12415   // context0 indirectly through f in context1.
   12416   calling_context2->Enter();
   12417   calling_context2->Global()->Set(v8_str("context1"),
   12418                                   calling_context1->Global());
   12419   CompileRun("context1.f()");
   12420   calling_context2->Exit();
   12421 
   12422   // Dispose the contexts to allow them to be garbage collected.
   12423   calling_context0.Dispose();
   12424   calling_context1.Dispose();
   12425   calling_context2.Dispose();
   12426   calling_context0.Clear();
   12427   calling_context1.Clear();
   12428   calling_context2.Clear();
   12429 }
   12430 
   12431 
   12432 // Check that a variable declaration with no explicit initialization
   12433 // value does not shadow an existing property in the prototype chain.
   12434 //
   12435 // This is consistent with Firefox and Safari.
   12436 //
   12437 // See http://crbug.com/12548.
   12438 THREADED_TEST(InitGlobalVarInProtoChain) {
   12439   v8::HandleScope scope;
   12440   LocalContext context;
   12441   // Introduce a variable in the prototype chain.
   12442   CompileRun("__proto__.x = 42");
   12443   v8::Handle<v8::Value> result = CompileRun("var x; x");
   12444   CHECK(!result->IsUndefined());
   12445   CHECK_EQ(42, result->Int32Value());
   12446 }
   12447 
   12448 
   12449 // Regression test for issue 398.
   12450 // If a function is added to an object, creating a constant function
   12451 // field, and the result is cloned, replacing the constant function on the
   12452 // original should not affect the clone.
   12453 // See http://code.google.com/p/v8/issues/detail?id=398
   12454 THREADED_TEST(ReplaceConstantFunction) {
   12455   v8::HandleScope scope;
   12456   LocalContext context;
   12457   v8::Handle<v8::Object> obj = v8::Object::New();
   12458   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
   12459   v8::Handle<v8::String> foo_string = v8::String::New("foo");
   12460   obj->Set(foo_string, func_templ->GetFunction());
   12461   v8::Handle<v8::Object> obj_clone = obj->Clone();
   12462   obj_clone->Set(foo_string, v8::String::New("Hello"));
   12463   CHECK(!obj->Get(foo_string)->IsUndefined());
   12464 }
   12465 
   12466 
   12467 // Regression test for http://crbug.com/16276.
   12468 THREADED_TEST(Regress16276) {
   12469   v8::HandleScope scope;
   12470   LocalContext context;
   12471   // Force the IC in f to be a dictionary load IC.
   12472   CompileRun("function f(obj) { return obj.x; }\n"
   12473              "var obj = { x: { foo: 42 }, y: 87 };\n"
   12474              "var x = obj.x;\n"
   12475              "delete obj.y;\n"
   12476              "for (var i = 0; i < 5; i++) f(obj);");
   12477   // Detach the global object to make 'this' refer directly to the
   12478   // global object (not the proxy), and make sure that the dictionary
   12479   // load IC doesn't mess up loading directly from the global object.
   12480   context->DetachGlobal();
   12481   CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
   12482 }
   12483 
   12484 
   12485 THREADED_TEST(PixelArray) {
   12486   v8::HandleScope scope;
   12487   LocalContext context;
   12488   const int kElementCount = 260;
   12489   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   12490   i::Handle<i::ExternalPixelArray> pixels =
   12491       i::Handle<i::ExternalPixelArray>::cast(
   12492           FACTORY->NewExternalArray(kElementCount,
   12493                                     v8::kExternalPixelArray,
   12494                                     pixel_data));
   12495   // Force GC to trigger verification.
   12496   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12497   for (int i = 0; i < kElementCount; i++) {
   12498     pixels->set(i, i % 256);
   12499   }
   12500   // Force GC to trigger verification.
   12501   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12502   for (int i = 0; i < kElementCount; i++) {
   12503     CHECK_EQ(i % 256, pixels->get_scalar(i));
   12504     CHECK_EQ(i % 256, pixel_data[i]);
   12505   }
   12506 
   12507   v8::Handle<v8::Object> obj = v8::Object::New();
   12508   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   12509   // Set the elements to be the pixels.
   12510   // jsobj->set_elements(*pixels);
   12511   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   12512   CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   12513   obj->Set(v8_str("field"), v8::Int32::New(1503));
   12514   context->Global()->Set(v8_str("pixels"), obj);
   12515   v8::Handle<v8::Value> result = CompileRun("pixels.field");
   12516   CHECK_EQ(1503, result->Int32Value());
   12517   result = CompileRun("pixels[1]");
   12518   CHECK_EQ(1, result->Int32Value());
   12519 
   12520   result = CompileRun("var sum = 0;"
   12521                       "for (var i = 0; i < 8; i++) {"
   12522                       "  sum += pixels[i] = pixels[i] = -i;"
   12523                       "}"
   12524                       "sum;");
   12525   CHECK_EQ(-28, result->Int32Value());
   12526 
   12527   result = CompileRun("var sum = 0;"
   12528                       "for (var i = 0; i < 8; i++) {"
   12529                       "  sum += pixels[i] = pixels[i] = 0;"
   12530                       "}"
   12531                       "sum;");
   12532   CHECK_EQ(0, result->Int32Value());
   12533 
   12534   result = CompileRun("var sum = 0;"
   12535                       "for (var i = 0; i < 8; i++) {"
   12536                       "  sum += pixels[i] = pixels[i] = 255;"
   12537                       "}"
   12538                       "sum;");
   12539   CHECK_EQ(8 * 255, result->Int32Value());
   12540 
   12541   result = CompileRun("var sum = 0;"
   12542                       "for (var i = 0; i < 8; i++) {"
   12543                       "  sum += pixels[i] = pixels[i] = 256 + i;"
   12544                       "}"
   12545                       "sum;");
   12546   CHECK_EQ(2076, result->Int32Value());
   12547 
   12548   result = CompileRun("var sum = 0;"
   12549                       "for (var i = 0; i < 8; i++) {"
   12550                       "  sum += pixels[i] = pixels[i] = i;"
   12551                       "}"
   12552                       "sum;");
   12553   CHECK_EQ(28, result->Int32Value());
   12554 
   12555   result = CompileRun("var sum = 0;"
   12556                       "for (var i = 0; i < 8; i++) {"
   12557                       "  sum += pixels[i];"
   12558                       "}"
   12559                       "sum;");
   12560   CHECK_EQ(28, result->Int32Value());
   12561 
   12562   i::Handle<i::Smi> value(i::Smi::FromInt(2));
   12563   i::Handle<i::Object> no_failure;
   12564   no_failure =
   12565       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   12566   ASSERT(!no_failure.is_null());
   12567   i::USE(no_failure);
   12568   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   12569   *value.location() = i::Smi::FromInt(256);
   12570   no_failure =
   12571       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   12572   ASSERT(!no_failure.is_null());
   12573   i::USE(no_failure);
   12574   CHECK_EQ(255,
   12575            i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   12576   *value.location() = i::Smi::FromInt(-1);
   12577   no_failure =
   12578       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   12579   ASSERT(!no_failure.is_null());
   12580   i::USE(no_failure);
   12581   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   12582 
   12583   result = CompileRun("for (var i = 0; i < 8; i++) {"
   12584                       "  pixels[i] = (i * 65) - 109;"
   12585                       "}"
   12586                       "pixels[1] + pixels[6];");
   12587   CHECK_EQ(255, result->Int32Value());
   12588   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
   12589   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   12590   CHECK_EQ(21,
   12591            i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
   12592   CHECK_EQ(86,
   12593            i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
   12594   CHECK_EQ(151,
   12595            i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
   12596   CHECK_EQ(216,
   12597            i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   12598   CHECK_EQ(255,
   12599            i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   12600   CHECK_EQ(255,
   12601            i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   12602   result = CompileRun("var sum = 0;"
   12603                       "for (var i = 0; i < 8; i++) {"
   12604                       "  sum += pixels[i];"
   12605                       "}"
   12606                       "sum;");
   12607   CHECK_EQ(984, result->Int32Value());
   12608 
   12609   result = CompileRun("for (var i = 0; i < 8; i++) {"
   12610                       "  pixels[i] = (i * 1.1);"
   12611                       "}"
   12612                       "pixels[1] + pixels[6];");
   12613   CHECK_EQ(8, result->Int32Value());
   12614   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
   12615   CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   12616   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
   12617   CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
   12618   CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
   12619   CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   12620   CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   12621   CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   12622 
   12623   result = CompileRun("for (var i = 0; i < 8; i++) {"
   12624                       "  pixels[7] = undefined;"
   12625                       "}"
   12626                       "pixels[7];");
   12627   CHECK_EQ(0, result->Int32Value());
   12628   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   12629 
   12630   result = CompileRun("for (var i = 0; i < 8; i++) {"
   12631                       "  pixels[6] = '2.3';"
   12632                       "}"
   12633                       "pixels[6];");
   12634   CHECK_EQ(2, result->Int32Value());
   12635   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   12636 
   12637   result = CompileRun("for (var i = 0; i < 8; i++) {"
   12638                       "  pixels[5] = NaN;"
   12639                       "}"
   12640                       "pixels[5];");
   12641   CHECK_EQ(0, result->Int32Value());
   12642   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   12643 
   12644   result = CompileRun("for (var i = 0; i < 8; i++) {"
   12645                       "  pixels[8] = Infinity;"
   12646                       "}"
   12647                       "pixels[8];");
   12648   CHECK_EQ(255, result->Int32Value());
   12649   CHECK_EQ(255,
   12650            i::Smi::cast(jsobj->GetElement(8)->ToObjectChecked())->value());
   12651 
   12652   result = CompileRun("for (var i = 0; i < 8; i++) {"
   12653                       "  pixels[9] = -Infinity;"
   12654                       "}"
   12655                       "pixels[9];");
   12656   CHECK_EQ(0, result->Int32Value());
   12657   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9)->ToObjectChecked())->value());
   12658 
   12659   result = CompileRun("pixels[3] = 33;"
   12660                       "delete pixels[3];"
   12661                       "pixels[3];");
   12662   CHECK_EQ(33, result->Int32Value());
   12663 
   12664   result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
   12665                       "pixels[2] = 12; pixels[3] = 13;"
   12666                       "pixels.__defineGetter__('2',"
   12667                       "function() { return 120; });"
   12668                       "pixels[2];");
   12669   CHECK_EQ(12, result->Int32Value());
   12670 
   12671   result = CompileRun("var js_array = new Array(40);"
   12672                       "js_array[0] = 77;"
   12673                       "js_array;");
   12674   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   12675 
   12676   result = CompileRun("pixels[1] = 23;"
   12677                       "pixels.__proto__ = [];"
   12678                       "js_array.__proto__ = pixels;"
   12679                       "js_array.concat(pixels);");
   12680   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   12681   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   12682 
   12683   result = CompileRun("pixels[1] = 23;");
   12684   CHECK_EQ(23, result->Int32Value());
   12685 
   12686   // Test for index greater than 255.  Regression test for:
   12687   // http://code.google.com/p/chromium/issues/detail?id=26337.
   12688   result = CompileRun("pixels[256] = 255;");
   12689   CHECK_EQ(255, result->Int32Value());
   12690   result = CompileRun("var i = 0;"
   12691                       "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
   12692                       "i");
   12693   CHECK_EQ(255, result->Int32Value());
   12694 
   12695   // Make sure that pixel array ICs recognize when a non-pixel array
   12696   // is passed to it.
   12697   result = CompileRun("function pa_load(p) {"
   12698                       "  var sum = 0;"
   12699                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   12700                       "  return sum;"
   12701                       "}"
   12702                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   12703                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   12704                       "just_ints = new Object();"
   12705                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   12706                       "for (var i = 0; i < 10; ++i) {"
   12707                       "  result = pa_load(just_ints);"
   12708                       "}"
   12709                       "result");
   12710   CHECK_EQ(32640, result->Int32Value());
   12711 
   12712   // Make sure that pixel array ICs recognize out-of-bound accesses.
   12713   result = CompileRun("function pa_load(p, start) {"
   12714                       "  var sum = 0;"
   12715                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   12716                       "  return sum;"
   12717                       "}"
   12718                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   12719                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   12720                       "for (var i = 0; i < 10; ++i) {"
   12721                       "  result = pa_load(pixels,-10);"
   12722                       "}"
   12723                       "result");
   12724   CHECK_EQ(0, result->Int32Value());
   12725 
   12726   // Make sure that generic ICs properly handles a pixel array.
   12727   result = CompileRun("function pa_load(p) {"
   12728                       "  var sum = 0;"
   12729                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   12730                       "  return sum;"
   12731                       "}"
   12732                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   12733                       "just_ints = new Object();"
   12734                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   12735                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   12736                       "for (var i = 0; i < 10; ++i) {"
   12737                       "  result = pa_load(pixels);"
   12738                       "}"
   12739                       "result");
   12740   CHECK_EQ(32640, result->Int32Value());
   12741 
   12742   // Make sure that generic load ICs recognize out-of-bound accesses in
   12743   // pixel arrays.
   12744   result = CompileRun("function pa_load(p, start) {"
   12745                       "  var sum = 0;"
   12746                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   12747                       "  return sum;"
   12748                       "}"
   12749                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   12750                       "just_ints = new Object();"
   12751                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   12752                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
   12753                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   12754                       "for (var i = 0; i < 10; ++i) {"
   12755                       "  result = pa_load(pixels,-10);"
   12756                       "}"
   12757                       "result");
   12758   CHECK_EQ(0, result->Int32Value());
   12759 
   12760   // Make sure that generic ICs properly handles other types than pixel
   12761   // arrays (that the inlined fast pixel array test leaves the right information
   12762   // in the right registers).
   12763   result = CompileRun("function pa_load(p) {"
   12764                       "  var sum = 0;"
   12765                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   12766                       "  return sum;"
   12767                       "}"
   12768                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   12769                       "just_ints = new Object();"
   12770                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   12771                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   12772                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   12773                       "sparse_array = new Object();"
   12774                       "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
   12775                       "sparse_array[1000000] = 3;"
   12776                       "for (var i = 0; i < 10; ++i) {"
   12777                       "  result = pa_load(sparse_array);"
   12778                       "}"
   12779                       "result");
   12780   CHECK_EQ(32640, result->Int32Value());
   12781 
   12782   // Make sure that pixel array store ICs clamp values correctly.
   12783   result = CompileRun("function pa_store(p) {"
   12784                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   12785                       "}"
   12786                       "pa_store(pixels);"
   12787                       "var sum = 0;"
   12788                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   12789                       "sum");
   12790   CHECK_EQ(48896, result->Int32Value());
   12791 
   12792   // Make sure that pixel array stores correctly handle accesses outside
   12793   // of the pixel array..
   12794   result = CompileRun("function pa_store(p,start) {"
   12795                       "  for (var j = 0; j < 256; j++) {"
   12796                       "    p[j+start] = j * 2;"
   12797                       "  }"
   12798                       "}"
   12799                       "pa_store(pixels,0);"
   12800                       "pa_store(pixels,-128);"
   12801                       "var sum = 0;"
   12802                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   12803                       "sum");
   12804   CHECK_EQ(65280, result->Int32Value());
   12805 
   12806   // Make sure that the generic store stub correctly handle accesses outside
   12807   // of the pixel array..
   12808   result = CompileRun("function pa_store(p,start) {"
   12809                       "  for (var j = 0; j < 256; j++) {"
   12810                       "    p[j+start] = j * 2;"
   12811                       "  }"
   12812                       "}"
   12813                       "pa_store(pixels,0);"
   12814                       "just_ints = new Object();"
   12815                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   12816                       "pa_store(just_ints, 0);"
   12817                       "pa_store(pixels,-128);"
   12818                       "var sum = 0;"
   12819                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   12820                       "sum");
   12821   CHECK_EQ(65280, result->Int32Value());
   12822 
   12823   // Make sure that the generic keyed store stub clamps pixel array values
   12824   // correctly.
   12825   result = CompileRun("function pa_store(p) {"
   12826                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   12827                       "}"
   12828                       "pa_store(pixels);"
   12829                       "just_ints = new Object();"
   12830                       "pa_store(just_ints);"
   12831                       "pa_store(pixels);"
   12832                       "var sum = 0;"
   12833                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   12834                       "sum");
   12835   CHECK_EQ(48896, result->Int32Value());
   12836 
   12837   // Make sure that pixel array loads are optimized by crankshaft.
   12838   result = CompileRun("function pa_load(p) {"
   12839                       "  var sum = 0;"
   12840                       "  for (var i=0; i<256; ++i) {"
   12841                       "    sum += p[i];"
   12842                       "  }"
   12843                       "  return sum; "
   12844                       "}"
   12845                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   12846                       "for (var i = 0; i < 5000; ++i) {"
   12847                       "  result = pa_load(pixels);"
   12848                       "}"
   12849                       "result");
   12850   CHECK_EQ(32640, result->Int32Value());
   12851 
   12852   // Make sure that pixel array stores are optimized by crankshaft.
   12853   result = CompileRun("function pa_init(p) {"
   12854                       "for (var i = 0; i < 256; ++i) { p[i] = i; }"
   12855                       "}"
   12856                       "function pa_load(p) {"
   12857                       "  var sum = 0;"
   12858                       "  for (var i=0; i<256; ++i) {"
   12859                       "    sum += p[i];"
   12860                       "  }"
   12861                       "  return sum; "
   12862                       "}"
   12863                       "for (var i = 0; i < 5000; ++i) {"
   12864                       "  pa_init(pixels);"
   12865                       "}"
   12866                       "result = pa_load(pixels);"
   12867                       "result");
   12868   CHECK_EQ(32640, result->Int32Value());
   12869 
   12870   free(pixel_data);
   12871 }
   12872 
   12873 
   12874 THREADED_TEST(PixelArrayInfo) {
   12875   v8::HandleScope scope;
   12876   LocalContext context;
   12877   for (int size = 0; size < 100; size += 10) {
   12878     uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
   12879     v8::Handle<v8::Object> obj = v8::Object::New();
   12880     obj->SetIndexedPropertiesToPixelData(pixel_data, size);
   12881     CHECK(obj->HasIndexedPropertiesInPixelData());
   12882     CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
   12883     CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
   12884     free(pixel_data);
   12885   }
   12886 }
   12887 
   12888 
   12889 static v8::Handle<Value> NotHandledIndexedPropertyGetter(
   12890     uint32_t index,
   12891     const AccessorInfo& info) {
   12892   ApiTestFuzzer::Fuzz();
   12893   return v8::Handle<Value>();
   12894 }
   12895 
   12896 
   12897 static v8::Handle<Value> NotHandledIndexedPropertySetter(
   12898     uint32_t index,
   12899     Local<Value> value,
   12900     const AccessorInfo& info) {
   12901   ApiTestFuzzer::Fuzz();
   12902   return v8::Handle<Value>();
   12903 }
   12904 
   12905 
   12906 THREADED_TEST(PixelArrayWithInterceptor) {
   12907   v8::HandleScope scope;
   12908   LocalContext context;
   12909   const int kElementCount = 260;
   12910   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   12911   i::Handle<i::ExternalPixelArray> pixels =
   12912       i::Handle<i::ExternalPixelArray>::cast(
   12913           FACTORY->NewExternalArray(kElementCount,
   12914                                     v8::kExternalPixelArray,
   12915                                     pixel_data));
   12916   for (int i = 0; i < kElementCount; i++) {
   12917     pixels->set(i, i % 256);
   12918   }
   12919   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   12920   templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
   12921                                    NotHandledIndexedPropertySetter);
   12922   v8::Handle<v8::Object> obj = templ->NewInstance();
   12923   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   12924   context->Global()->Set(v8_str("pixels"), obj);
   12925   v8::Handle<v8::Value> result = CompileRun("pixels[1]");
   12926   CHECK_EQ(1, result->Int32Value());
   12927   result = CompileRun("var sum = 0;"
   12928                       "for (var i = 0; i < 8; i++) {"
   12929                       "  sum += pixels[i] = pixels[i] = -i;"
   12930                       "}"
   12931                       "sum;");
   12932   CHECK_EQ(-28, result->Int32Value());
   12933   result = CompileRun("pixels.hasOwnProperty('1')");
   12934   CHECK(result->BooleanValue());
   12935   free(pixel_data);
   12936 }
   12937 
   12938 
   12939 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
   12940   switch (array_type) {
   12941     case v8::kExternalByteArray:
   12942     case v8::kExternalUnsignedByteArray:
   12943     case v8::kExternalPixelArray:
   12944       return 1;
   12945       break;
   12946     case v8::kExternalShortArray:
   12947     case v8::kExternalUnsignedShortArray:
   12948       return 2;
   12949       break;
   12950     case v8::kExternalIntArray:
   12951     case v8::kExternalUnsignedIntArray:
   12952     case v8::kExternalFloatArray:
   12953       return 4;
   12954       break;
   12955     case v8::kExternalDoubleArray:
   12956       return 8;
   12957       break;
   12958     default:
   12959       UNREACHABLE();
   12960       return -1;
   12961   }
   12962   UNREACHABLE();
   12963   return -1;
   12964 }
   12965 
   12966 
   12967 template <class ExternalArrayClass, class ElementType>
   12968 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
   12969                                     int64_t low,
   12970                                     int64_t high) {
   12971   v8::HandleScope scope;
   12972   LocalContext context;
   12973   const int kElementCount = 40;
   12974   int element_size = ExternalArrayElementSize(array_type);
   12975   ElementType* array_data =
   12976       static_cast<ElementType*>(malloc(kElementCount * element_size));
   12977   i::Handle<ExternalArrayClass> array =
   12978       i::Handle<ExternalArrayClass>::cast(
   12979           FACTORY->NewExternalArray(kElementCount, array_type, array_data));
   12980   // Force GC to trigger verification.
   12981   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12982   for (int i = 0; i < kElementCount; i++) {
   12983     array->set(i, static_cast<ElementType>(i));
   12984   }
   12985   // Force GC to trigger verification.
   12986   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12987   for (int i = 0; i < kElementCount; i++) {
   12988     CHECK_EQ(static_cast<int64_t>(i),
   12989              static_cast<int64_t>(array->get_scalar(i)));
   12990     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
   12991   }
   12992 
   12993   v8::Handle<v8::Object> obj = v8::Object::New();
   12994   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   12995   // Set the elements to be the external array.
   12996   obj->SetIndexedPropertiesToExternalArrayData(array_data,
   12997                                                array_type,
   12998                                                kElementCount);
   12999   CHECK_EQ(
   13000       1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
   13001   obj->Set(v8_str("field"), v8::Int32::New(1503));
   13002   context->Global()->Set(v8_str("ext_array"), obj);
   13003   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
   13004   CHECK_EQ(1503, result->Int32Value());
   13005   result = CompileRun("ext_array[1]");
   13006   CHECK_EQ(1, result->Int32Value());
   13007 
   13008   // Check pass through of assigned smis
   13009   result = CompileRun("var sum = 0;"
   13010                       "for (var i = 0; i < 8; i++) {"
   13011                       "  sum += ext_array[i] = ext_array[i] = -i;"
   13012                       "}"
   13013                       "sum;");
   13014   CHECK_EQ(-28, result->Int32Value());
   13015 
   13016   // Check assigned smis
   13017   result = CompileRun("for (var i = 0; i < 8; i++) {"
   13018                       "  ext_array[i] = i;"
   13019                       "}"
   13020                       "var sum = 0;"
   13021                       "for (var i = 0; i < 8; i++) {"
   13022                       "  sum += ext_array[i];"
   13023                       "}"
   13024                       "sum;");
   13025   CHECK_EQ(28, result->Int32Value());
   13026 
   13027   // Check assigned smis in reverse order
   13028   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   13029                       "  ext_array[i] = i;"
   13030                       "}"
   13031                       "var sum = 0;"
   13032                       "for (var i = 0; i < 8; i++) {"
   13033                       "  sum += ext_array[i];"
   13034                       "}"
   13035                       "sum;");
   13036   CHECK_EQ(28, result->Int32Value());
   13037 
   13038   // Check pass through of assigned HeapNumbers
   13039   result = CompileRun("var sum = 0;"
   13040                       "for (var i = 0; i < 16; i+=2) {"
   13041                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   13042                       "}"
   13043                       "sum;");
   13044   CHECK_EQ(-28, result->Int32Value());
   13045 
   13046   // Check assigned HeapNumbers
   13047   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   13048                       "  ext_array[i] = (i * 0.5);"
   13049                       "}"
   13050                       "var sum = 0;"
   13051                       "for (var i = 0; i < 16; i+=2) {"
   13052                       "  sum += ext_array[i];"
   13053                       "}"
   13054                       "sum;");
   13055   CHECK_EQ(28, result->Int32Value());
   13056 
   13057   // Check assigned HeapNumbers in reverse order
   13058   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   13059                       "  ext_array[i] = (i * 0.5);"
   13060                       "}"
   13061                       "var sum = 0;"
   13062                       "for (var i = 0; i < 16; i+=2) {"
   13063                       "  sum += ext_array[i];"
   13064                       "}"
   13065                       "sum;");
   13066   CHECK_EQ(28, result->Int32Value());
   13067 
   13068   i::ScopedVector<char> test_buf(1024);
   13069 
   13070   // Check legal boundary conditions.
   13071   // The repeated loads and stores ensure the ICs are exercised.
   13072   const char* boundary_program =
   13073       "var res = 0;"
   13074       "for (var i = 0; i < 16; i++) {"
   13075       "  ext_array[i] = %lld;"
   13076       "  if (i > 8) {"
   13077       "    res = ext_array[i];"
   13078       "  }"
   13079       "}"
   13080       "res;";
   13081   i::OS::SNPrintF(test_buf,
   13082                   boundary_program,
   13083                   low);
   13084   result = CompileRun(test_buf.start());
   13085   CHECK_EQ(low, result->IntegerValue());
   13086 
   13087   i::OS::SNPrintF(test_buf,
   13088                   boundary_program,
   13089                   high);
   13090   result = CompileRun(test_buf.start());
   13091   CHECK_EQ(high, result->IntegerValue());
   13092 
   13093   // Check misprediction of type in IC.
   13094   result = CompileRun("var tmp_array = ext_array;"
   13095                       "var sum = 0;"
   13096                       "for (var i = 0; i < 8; i++) {"
   13097                       "  tmp_array[i] = i;"
   13098                       "  sum += tmp_array[i];"
   13099                       "  if (i == 4) {"
   13100                       "    tmp_array = {};"
   13101                       "  }"
   13102                       "}"
   13103                       "sum;");
   13104   // Force GC to trigger verification.
   13105   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   13106   CHECK_EQ(28, result->Int32Value());
   13107 
   13108   // Make sure out-of-range loads do not throw.
   13109   i::OS::SNPrintF(test_buf,
   13110                   "var caught_exception = false;"
   13111                   "try {"
   13112                   "  ext_array[%d];"
   13113                   "} catch (e) {"
   13114                   "  caught_exception = true;"
   13115                   "}"
   13116                   "caught_exception;",
   13117                   kElementCount);
   13118   result = CompileRun(test_buf.start());
   13119   CHECK_EQ(false, result->BooleanValue());
   13120 
   13121   // Make sure out-of-range stores do not throw.
   13122   i::OS::SNPrintF(test_buf,
   13123                   "var caught_exception = false;"
   13124                   "try {"
   13125                   "  ext_array[%d] = 1;"
   13126                   "} catch (e) {"
   13127                   "  caught_exception = true;"
   13128                   "}"
   13129                   "caught_exception;",
   13130                   kElementCount);
   13131   result = CompileRun(test_buf.start());
   13132   CHECK_EQ(false, result->BooleanValue());
   13133 
   13134   // Check other boundary conditions, values and operations.
   13135   result = CompileRun("for (var i = 0; i < 8; i++) {"
   13136                       "  ext_array[7] = undefined;"
   13137                       "}"
   13138                       "ext_array[7];");
   13139   CHECK_EQ(0, result->Int32Value());
   13140   if (array_type == v8::kExternalDoubleArray ||
   13141       array_type == v8::kExternalFloatArray) {
   13142     CHECK_EQ(
   13143         static_cast<int>(i::OS::nan_value()),
   13144         static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number()));
   13145   } else {
   13146     CHECK_EQ(0, static_cast<int>(
   13147         jsobj->GetElement(7)->ToObjectChecked()->Number()));
   13148   }
   13149 
   13150   result = CompileRun("for (var i = 0; i < 8; i++) {"
   13151                       "  ext_array[6] = '2.3';"
   13152                       "}"
   13153                       "ext_array[6];");
   13154   CHECK_EQ(2, result->Int32Value());
   13155   CHECK_EQ(
   13156       2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number()));
   13157 
   13158   if (array_type != v8::kExternalFloatArray &&
   13159       array_type != v8::kExternalDoubleArray) {
   13160     // Though the specification doesn't state it, be explicit about
   13161     // converting NaNs and +/-Infinity to zero.
   13162     result = CompileRun("for (var i = 0; i < 8; i++) {"
   13163                         "  ext_array[i] = 5;"
   13164                         "}"
   13165                         "for (var i = 0; i < 8; i++) {"
   13166                         "  ext_array[i] = NaN;"
   13167                         "}"
   13168                         "ext_array[5];");
   13169     CHECK_EQ(0, result->Int32Value());
   13170     CHECK_EQ(0,
   13171              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   13172 
   13173     result = CompileRun("for (var i = 0; i < 8; i++) {"
   13174                         "  ext_array[i] = 5;"
   13175                         "}"
   13176                         "for (var i = 0; i < 8; i++) {"
   13177                         "  ext_array[i] = Infinity;"
   13178                         "}"
   13179                         "ext_array[5];");
   13180     int expected_value =
   13181         (array_type == v8::kExternalPixelArray) ? 255 : 0;
   13182     CHECK_EQ(expected_value, result->Int32Value());
   13183     CHECK_EQ(expected_value,
   13184              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   13185 
   13186     result = CompileRun("for (var i = 0; i < 8; i++) {"
   13187                         "  ext_array[i] = 5;"
   13188                         "}"
   13189                         "for (var i = 0; i < 8; i++) {"
   13190                         "  ext_array[i] = -Infinity;"
   13191                         "}"
   13192                         "ext_array[5];");
   13193     CHECK_EQ(0, result->Int32Value());
   13194     CHECK_EQ(0,
   13195              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   13196 
   13197     // Check truncation behavior of integral arrays.
   13198     const char* unsigned_data =
   13199         "var source_data = [0.6, 10.6];"
   13200         "var expected_results = [0, 10];";
   13201     const char* signed_data =
   13202         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   13203         "var expected_results = [0, 10, 0, -10];";
   13204     const char* pixel_data =
   13205         "var source_data = [0.6, 10.6];"
   13206         "var expected_results = [1, 11];";
   13207     bool is_unsigned =
   13208         (array_type == v8::kExternalUnsignedByteArray ||
   13209          array_type == v8::kExternalUnsignedShortArray ||
   13210          array_type == v8::kExternalUnsignedIntArray);
   13211     bool is_pixel_data = array_type == v8::kExternalPixelArray;
   13212 
   13213     i::OS::SNPrintF(test_buf,
   13214                     "%s"
   13215                     "var all_passed = true;"
   13216                     "for (var i = 0; i < source_data.length; i++) {"
   13217                     "  for (var j = 0; j < 8; j++) {"
   13218                     "    ext_array[j] = source_data[i];"
   13219                     "  }"
   13220                     "  all_passed = all_passed &&"
   13221                     "               (ext_array[5] == expected_results[i]);"
   13222                     "}"
   13223                     "all_passed;",
   13224                     (is_unsigned ?
   13225                          unsigned_data :
   13226                          (is_pixel_data ? pixel_data : signed_data)));
   13227     result = CompileRun(test_buf.start());
   13228     CHECK_EQ(true, result->BooleanValue());
   13229   }
   13230 
   13231   for (int i = 0; i < kElementCount; i++) {
   13232     array->set(i, static_cast<ElementType>(i));
   13233   }
   13234   // Test complex assignments
   13235   result = CompileRun("function ee_op_test_complex_func(sum) {"
   13236                       " for (var i = 0; i < 40; ++i) {"
   13237                       "   sum += (ext_array[i] += 1);"
   13238                       "   sum += (ext_array[i] -= 1);"
   13239                       " } "
   13240                       " return sum;"
   13241                       "}"
   13242                       "sum=0;"
   13243                       "for (var i=0;i<10000;++i) {"
   13244                       "  sum=ee_op_test_complex_func(sum);"
   13245                       "}"
   13246                       "sum;");
   13247   CHECK_EQ(16000000, result->Int32Value());
   13248 
   13249   // Test count operations
   13250   result = CompileRun("function ee_op_test_count_func(sum) {"
   13251                       " for (var i = 0; i < 40; ++i) {"
   13252                       "   sum += (++ext_array[i]);"
   13253                       "   sum += (--ext_array[i]);"
   13254                       " } "
   13255                       " return sum;"
   13256                       "}"
   13257                       "sum=0;"
   13258                       "for (var i=0;i<10000;++i) {"
   13259                       "  sum=ee_op_test_count_func(sum);"
   13260                       "}"
   13261                       "sum;");
   13262   CHECK_EQ(16000000, result->Int32Value());
   13263 
   13264   result = CompileRun("ext_array[3] = 33;"
   13265                       "delete ext_array[3];"
   13266                       "ext_array[3];");
   13267   CHECK_EQ(33, result->Int32Value());
   13268 
   13269   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
   13270                       "ext_array[2] = 12; ext_array[3] = 13;"
   13271                       "ext_array.__defineGetter__('2',"
   13272                       "function() { return 120; });"
   13273                       "ext_array[2];");
   13274   CHECK_EQ(12, result->Int32Value());
   13275 
   13276   result = CompileRun("var js_array = new Array(40);"
   13277                       "js_array[0] = 77;"
   13278                       "js_array;");
   13279   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   13280 
   13281   result = CompileRun("ext_array[1] = 23;"
   13282                       "ext_array.__proto__ = [];"
   13283                       "js_array.__proto__ = ext_array;"
   13284                       "js_array.concat(ext_array);");
   13285   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   13286   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   13287 
   13288   result = CompileRun("ext_array[1] = 23;");
   13289   CHECK_EQ(23, result->Int32Value());
   13290 
   13291   // Test more complex manipulations which cause eax to contain values
   13292   // that won't be completely overwritten by loads from the arrays.
   13293   // This catches bugs in the instructions used for the KeyedLoadIC
   13294   // for byte and word types.
   13295   {
   13296     const int kXSize = 300;
   13297     const int kYSize = 300;
   13298     const int kLargeElementCount = kXSize * kYSize * 4;
   13299     ElementType* large_array_data =
   13300         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
   13301     v8::Handle<v8::Object> large_obj = v8::Object::New();
   13302     // Set the elements to be the external array.
   13303     large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
   13304                                                        array_type,
   13305                                                        kLargeElementCount);
   13306     context->Global()->Set(v8_str("large_array"), large_obj);
   13307     // Initialize contents of a few rows.
   13308     for (int x = 0; x < 300; x++) {
   13309       int row = 0;
   13310       int offset = row * 300 * 4;
   13311       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   13312       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   13313       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   13314       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   13315       row = 150;
   13316       offset = row * 300 * 4;
   13317       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   13318       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   13319       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   13320       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   13321       row = 298;
   13322       offset = row * 300 * 4;
   13323       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   13324       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   13325       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   13326       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   13327     }
   13328     // The goal of the code below is to make "offset" large enough
   13329     // that the computation of the index (which goes into eax) has
   13330     // high bits set which will not be overwritten by a byte or short
   13331     // load.
   13332     result = CompileRun("var failed = false;"
   13333                         "var offset = 0;"
   13334                         "for (var i = 0; i < 300; i++) {"
   13335                         "  if (large_array[4 * i] != 127 ||"
   13336                         "      large_array[4 * i + 1] != 0 ||"
   13337                         "      large_array[4 * i + 2] != 0 ||"
   13338                         "      large_array[4 * i + 3] != 127) {"
   13339                         "    failed = true;"
   13340                         "  }"
   13341                         "}"
   13342                         "offset = 150 * 300 * 4;"
   13343                         "for (var i = 0; i < 300; i++) {"
   13344                         "  if (large_array[offset + 4 * i] != 127 ||"
   13345                         "      large_array[offset + 4 * i + 1] != 0 ||"
   13346                         "      large_array[offset + 4 * i + 2] != 0 ||"
   13347                         "      large_array[offset + 4 * i + 3] != 127) {"
   13348                         "    failed = true;"
   13349                         "  }"
   13350                         "}"
   13351                         "offset = 298 * 300 * 4;"
   13352                         "for (var i = 0; i < 300; i++) {"
   13353                         "  if (large_array[offset + 4 * i] != 127 ||"
   13354                         "      large_array[offset + 4 * i + 1] != 0 ||"
   13355                         "      large_array[offset + 4 * i + 2] != 0 ||"
   13356                         "      large_array[offset + 4 * i + 3] != 127) {"
   13357                         "    failed = true;"
   13358                         "  }"
   13359                         "}"
   13360                         "!failed;");
   13361     CHECK_EQ(true, result->BooleanValue());
   13362     free(large_array_data);
   13363   }
   13364 
   13365   // The "" property descriptor is overloaded to store information about
   13366   // the external array. Ensure that setting and accessing the "" property
   13367   // works (it should overwrite the information cached about the external
   13368   // array in the DescriptorArray) in various situations.
   13369   result = CompileRun("ext_array[''] = 23; ext_array['']");
   13370   CHECK_EQ(23, result->Int32Value());
   13371 
   13372   // Property "" set after the external array is associated with the object.
   13373   {
   13374     v8::Handle<v8::Object> obj2 = v8::Object::New();
   13375     obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
   13376     obj2->Set(v8_str(""), v8::Int32::New(1503));
   13377     // Set the elements to be the external array.
   13378     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   13379                                                   array_type,
   13380                                                   kElementCount);
   13381     context->Global()->Set(v8_str("ext_array"), obj2);
   13382     result = CompileRun("ext_array['']");
   13383     CHECK_EQ(1503, result->Int32Value());
   13384   }
   13385 
   13386   // Property "" set after the external array is associated with the object.
   13387   {
   13388     v8::Handle<v8::Object> obj2 = v8::Object::New();
   13389     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
   13390     // Set the elements to be the external array.
   13391     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   13392                                                   array_type,
   13393                                                   kElementCount);
   13394     obj2->Set(v8_str(""), v8::Int32::New(1503));
   13395     context->Global()->Set(v8_str("ext_array"), obj2);
   13396     result = CompileRun("ext_array['']");
   13397     CHECK_EQ(1503, result->Int32Value());
   13398   }
   13399 
   13400   // Should reuse the map from previous test.
   13401   {
   13402     v8::Handle<v8::Object> obj2 = v8::Object::New();
   13403     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
   13404     // Set the elements to be the external array. Should re-use the map
   13405     // from previous test.
   13406     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   13407                                                   array_type,
   13408                                                   kElementCount);
   13409     context->Global()->Set(v8_str("ext_array"), obj2);
   13410     result = CompileRun("ext_array['']");
   13411   }
   13412 
   13413   // Property "" is a constant function that shouldn't not be interfered with
   13414   // when an external array is set.
   13415   {
   13416     v8::Handle<v8::Object> obj2 = v8::Object::New();
   13417     // Start
   13418     obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
   13419 
   13420     // Add a constant function to an object.
   13421     context->Global()->Set(v8_str("ext_array"), obj2);
   13422     result = CompileRun("ext_array[''] = function() {return 1503;};"
   13423                         "ext_array['']();");
   13424 
   13425     // Add an external array transition to the same map that
   13426     // has the constant transition.
   13427     v8::Handle<v8::Object> obj3 = v8::Object::New();
   13428     obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
   13429     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   13430                                                   array_type,
   13431                                                   kElementCount);
   13432     context->Global()->Set(v8_str("ext_array"), obj3);
   13433   }
   13434 
   13435   // If a external array transition is in the map, it should get clobbered
   13436   // by a constant function.
   13437   {
   13438     // Add an external array transition.
   13439     v8::Handle<v8::Object> obj3 = v8::Object::New();
   13440     obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
   13441     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   13442                                                   array_type,
   13443                                                   kElementCount);
   13444 
   13445     // Add a constant function to the same map that just got an external array
   13446     // transition.
   13447     v8::Handle<v8::Object> obj2 = v8::Object::New();
   13448     obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
   13449     context->Global()->Set(v8_str("ext_array"), obj2);
   13450     result = CompileRun("ext_array[''] = function() {return 1503;};"
   13451                         "ext_array['']();");
   13452   }
   13453 
   13454   free(array_data);
   13455 }
   13456 
   13457 
   13458 THREADED_TEST(ExternalByteArray) {
   13459   ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
   13460       v8::kExternalByteArray,
   13461       -128,
   13462       127);
   13463 }
   13464 
   13465 
   13466 THREADED_TEST(ExternalUnsignedByteArray) {
   13467   ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
   13468       v8::kExternalUnsignedByteArray,
   13469       0,
   13470       255);
   13471 }
   13472 
   13473 
   13474 THREADED_TEST(ExternalPixelArray) {
   13475   ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
   13476       v8::kExternalPixelArray,
   13477       0,
   13478       255);
   13479 }
   13480 
   13481 
   13482 THREADED_TEST(ExternalShortArray) {
   13483   ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
   13484       v8::kExternalShortArray,
   13485       -32768,
   13486       32767);
   13487 }
   13488 
   13489 
   13490 THREADED_TEST(ExternalUnsignedShortArray) {
   13491   ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
   13492       v8::kExternalUnsignedShortArray,
   13493       0,
   13494       65535);
   13495 }
   13496 
   13497 
   13498 THREADED_TEST(ExternalIntArray) {
   13499   ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
   13500       v8::kExternalIntArray,
   13501       INT_MIN,   // -2147483648
   13502       INT_MAX);  //  2147483647
   13503 }
   13504 
   13505 
   13506 THREADED_TEST(ExternalUnsignedIntArray) {
   13507   ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
   13508       v8::kExternalUnsignedIntArray,
   13509       0,
   13510       UINT_MAX);  // 4294967295
   13511 }
   13512 
   13513 
   13514 THREADED_TEST(ExternalFloatArray) {
   13515   ExternalArrayTestHelper<i::ExternalFloatArray, float>(
   13516       v8::kExternalFloatArray,
   13517       -500,
   13518       500);
   13519 }
   13520 
   13521 
   13522 THREADED_TEST(ExternalDoubleArray) {
   13523   ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
   13524       v8::kExternalDoubleArray,
   13525       -500,
   13526       500);
   13527 }
   13528 
   13529 
   13530 THREADED_TEST(ExternalArrays) {
   13531   TestExternalByteArray();
   13532   TestExternalUnsignedByteArray();
   13533   TestExternalShortArray();
   13534   TestExternalUnsignedShortArray();
   13535   TestExternalIntArray();
   13536   TestExternalUnsignedIntArray();
   13537   TestExternalFloatArray();
   13538 }
   13539 
   13540 
   13541 void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
   13542   v8::HandleScope scope;
   13543   LocalContext context;
   13544   for (int size = 0; size < 100; size += 10) {
   13545     int element_size = ExternalArrayElementSize(array_type);
   13546     void* external_data = malloc(size * element_size);
   13547     v8::Handle<v8::Object> obj = v8::Object::New();
   13548     obj->SetIndexedPropertiesToExternalArrayData(
   13549         external_data, array_type, size);
   13550     CHECK(obj->HasIndexedPropertiesInExternalArrayData());
   13551     CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
   13552     CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
   13553     CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
   13554     free(external_data);
   13555   }
   13556 }
   13557 
   13558 
   13559 THREADED_TEST(ExternalArrayInfo) {
   13560   ExternalArrayInfoTestHelper(v8::kExternalByteArray);
   13561   ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
   13562   ExternalArrayInfoTestHelper(v8::kExternalShortArray);
   13563   ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
   13564   ExternalArrayInfoTestHelper(v8::kExternalIntArray);
   13565   ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
   13566   ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
   13567   ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
   13568   ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
   13569 }
   13570 
   13571 
   13572 THREADED_TEST(ScriptContextDependence) {
   13573   v8::HandleScope scope;
   13574   LocalContext c1;
   13575   const char *source = "foo";
   13576   v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
   13577   v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
   13578   c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
   13579   CHECK_EQ(dep->Run()->Int32Value(), 100);
   13580   CHECK_EQ(indep->Run()->Int32Value(), 100);
   13581   LocalContext c2;
   13582   c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
   13583   CHECK_EQ(dep->Run()->Int32Value(), 100);
   13584   CHECK_EQ(indep->Run()->Int32Value(), 101);
   13585 }
   13586 
   13587 
   13588 THREADED_TEST(StackTrace) {
   13589   v8::HandleScope scope;
   13590   LocalContext context;
   13591   v8::TryCatch try_catch;
   13592   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   13593   v8::Handle<v8::String> src = v8::String::New(source);
   13594   v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
   13595   v8::Script::New(src, origin)->Run();
   13596   CHECK(try_catch.HasCaught());
   13597   v8::String::Utf8Value stack(try_catch.StackTrace());
   13598   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
   13599 }
   13600 
   13601 
   13602 // Checks that a StackFrame has certain expected values.
   13603 void checkStackFrame(const char* expected_script_name,
   13604     const char* expected_func_name, int expected_line_number,
   13605     int expected_column, bool is_eval, bool is_constructor,
   13606     v8::Handle<v8::StackFrame> frame) {
   13607   v8::HandleScope scope;
   13608   v8::String::Utf8Value func_name(frame->GetFunctionName());
   13609   v8::String::Utf8Value script_name(frame->GetScriptName());
   13610   if (*script_name == NULL) {
   13611     // The situation where there is no associated script, like for evals.
   13612     CHECK(expected_script_name == NULL);
   13613   } else {
   13614     CHECK(strstr(*script_name, expected_script_name) != NULL);
   13615   }
   13616   CHECK(strstr(*func_name, expected_func_name) != NULL);
   13617   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   13618   CHECK_EQ(expected_column, frame->GetColumn());
   13619   CHECK_EQ(is_eval, frame->IsEval());
   13620   CHECK_EQ(is_constructor, frame->IsConstructor());
   13621 }
   13622 
   13623 
   13624 v8::Handle<Value> AnalyzeStackInNativeCode(const v8::Arguments& args) {
   13625   v8::HandleScope scope;
   13626   const char* origin = "capture-stack-trace-test";
   13627   const int kOverviewTest = 1;
   13628   const int kDetailedTest = 2;
   13629 
   13630   ASSERT(args.Length() == 1);
   13631 
   13632   int testGroup = args[0]->Int32Value();
   13633   if (testGroup == kOverviewTest) {
   13634     v8::Handle<v8::StackTrace> stackTrace =
   13635         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
   13636     CHECK_EQ(4, stackTrace->GetFrameCount());
   13637     checkStackFrame(origin, "bar", 2, 10, false, false,
   13638                     stackTrace->GetFrame(0));
   13639     checkStackFrame(origin, "foo", 6, 3, false, false,
   13640                     stackTrace->GetFrame(1));
   13641     // This is the source string inside the eval which has the call to foo.
   13642     checkStackFrame(NULL, "", 1, 5, false, false,
   13643                     stackTrace->GetFrame(2));
   13644     // The last frame is an anonymous function which has the initial eval call.
   13645     checkStackFrame(origin, "", 8, 7, false, false,
   13646                     stackTrace->GetFrame(3));
   13647 
   13648     CHECK(stackTrace->AsArray()->IsArray());
   13649   } else if (testGroup == kDetailedTest) {
   13650     v8::Handle<v8::StackTrace> stackTrace =
   13651         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
   13652     CHECK_EQ(4, stackTrace->GetFrameCount());
   13653     checkStackFrame(origin, "bat", 4, 22, false, false,
   13654                     stackTrace->GetFrame(0));
   13655     checkStackFrame(origin, "baz", 8, 3, false, true,
   13656                     stackTrace->GetFrame(1));
   13657 #ifdef ENABLE_DEBUGGER_SUPPORT
   13658     bool is_eval = true;
   13659 #else  // ENABLE_DEBUGGER_SUPPORT
   13660     bool is_eval = false;
   13661 #endif  // ENABLE_DEBUGGER_SUPPORT
   13662 
   13663     // This is the source string inside the eval which has the call to baz.
   13664     checkStackFrame(NULL, "", 1, 5, is_eval, false,
   13665                     stackTrace->GetFrame(2));
   13666     // The last frame is an anonymous function which has the initial eval call.
   13667     checkStackFrame(origin, "", 10, 1, false, false,
   13668                     stackTrace->GetFrame(3));
   13669 
   13670     CHECK(stackTrace->AsArray()->IsArray());
   13671   }
   13672   return v8::Undefined();
   13673 }
   13674 
   13675 
   13676 // Tests the C++ StackTrace API.
   13677 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   13678 // THREADED_TEST(CaptureStackTrace) {
   13679 TEST(CaptureStackTrace) {
   13680   v8::HandleScope scope;
   13681   v8::Handle<v8::String> origin = v8::String::New("capture-stack-trace-test");
   13682   Local<ObjectTemplate> templ = ObjectTemplate::New();
   13683   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   13684              v8::FunctionTemplate::New(AnalyzeStackInNativeCode));
   13685   LocalContext context(0, templ);
   13686 
   13687   // Test getting OVERVIEW information. Should ignore information that is not
   13688   // script name, function name, line number, and column offset.
   13689   const char *overview_source =
   13690     "function bar() {\n"
   13691     "  var y; AnalyzeStackInNativeCode(1);\n"
   13692     "}\n"
   13693     "function foo() {\n"
   13694     "\n"
   13695     "  bar();\n"
   13696     "}\n"
   13697     "var x;eval('new foo();');";
   13698   v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
   13699   v8::Handle<Value> overview_result(
   13700       v8::Script::New(overview_src, origin)->Run());
   13701   CHECK(!overview_result.IsEmpty());
   13702   CHECK(overview_result->IsObject());
   13703 
   13704   // Test getting DETAILED information.
   13705   const char *detailed_source =
   13706     "function bat() {AnalyzeStackInNativeCode(2);\n"
   13707     "}\n"
   13708     "\n"
   13709     "function baz() {\n"
   13710     "  bat();\n"
   13711     "}\n"
   13712     "eval('new baz();');";
   13713   v8::Handle<v8::String> detailed_src = v8::String::New(detailed_source);
   13714   // Make the script using a non-zero line and column offset.
   13715   v8::Handle<v8::Integer> line_offset = v8::Integer::New(3);
   13716   v8::Handle<v8::Integer> column_offset = v8::Integer::New(5);
   13717   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   13718   v8::Handle<v8::Script> detailed_script(
   13719       v8::Script::New(detailed_src, &detailed_origin));
   13720   v8::Handle<Value> detailed_result(detailed_script->Run());
   13721   CHECK(!detailed_result.IsEmpty());
   13722   CHECK(detailed_result->IsObject());
   13723 }
   13724 
   13725 
   13726 static void StackTraceForUncaughtExceptionListener(
   13727     v8::Handle<v8::Message> message,
   13728     v8::Handle<Value>) {
   13729   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   13730   CHECK_EQ(2, stack_trace->GetFrameCount());
   13731   checkStackFrame("origin", "foo", 2, 3, false, false,
   13732                   stack_trace->GetFrame(0));
   13733   checkStackFrame("origin", "bar", 5, 3, false, false,
   13734                   stack_trace->GetFrame(1));
   13735 }
   13736 
   13737 TEST(CaptureStackTraceForUncaughtException) {
   13738   report_count = 0;
   13739   v8::HandleScope scope;
   13740   LocalContext env;
   13741   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
   13742   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   13743 
   13744   Script::Compile(v8_str("function foo() {\n"
   13745                          "  throw 1;\n"
   13746                          "};\n"
   13747                          "function bar() {\n"
   13748                          "  foo();\n"
   13749                          "};"),
   13750                   v8_str("origin"))->Run();
   13751   v8::Local<v8::Object> global = env->Global();
   13752   Local<Value> trouble = global->Get(v8_str("bar"));
   13753   CHECK(trouble->IsFunction());
   13754   Function::Cast(*trouble)->Call(global, 0, NULL);
   13755   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   13756   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   13757 }
   13758 
   13759 
   13760 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   13761   v8::HandleScope scope;
   13762   LocalContext env;
   13763   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
   13764                                                     1024,
   13765                                                     v8::StackTrace::kDetailed);
   13766 
   13767   CompileRun(
   13768       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   13769       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   13770       "    'isConstructor'];\n"
   13771       "for (var i = 0; i < setters.length; i++) {\n"
   13772       "  var prop = setters[i];\n"
   13773       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   13774       "}\n");
   13775   CompileRun("throw 'exception';");
   13776   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   13777 }
   13778 
   13779 
   13780 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
   13781                                      v8::Handle<v8::Value> data) {
   13782   // Use the frame where JavaScript is called from.
   13783   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   13784   CHECK(!stack_trace.IsEmpty());
   13785   int frame_count = stack_trace->GetFrameCount();
   13786   CHECK_EQ(3, frame_count);
   13787   int line_number[] = {1, 2, 5};
   13788   for (int i = 0; i < frame_count; i++) {
   13789     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   13790   }
   13791 }
   13792 
   13793 
   13794 // Test that we only return the stack trace at the site where the exception
   13795 // is first thrown (not where it is rethrown).
   13796 TEST(RethrowStackTrace) {
   13797   v8::HandleScope scope;
   13798   LocalContext env;
   13799   // We make sure that
   13800   // - the stack trace of the ReferenceError in g() is reported.
   13801   // - the stack trace is not overwritten when e1 is rethrown by t().
   13802   // - the stack trace of e2 does not overwrite that of e1.
   13803   const char* source =
   13804       "function g() { error; }          \n"
   13805       "function f() { g(); }            \n"
   13806       "function t(e) { throw e; }       \n"
   13807       "try {                            \n"
   13808       "  f();                           \n"
   13809       "} catch (e1) {                   \n"
   13810       "  try {                          \n"
   13811       "    error;                       \n"
   13812       "  } catch (e2) {                 \n"
   13813       "    t(e1);                       \n"
   13814       "  }                              \n"
   13815       "}                                \n";
   13816   v8::V8::AddMessageListener(RethrowStackTraceHandler);
   13817   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   13818   CompileRun(source);
   13819   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   13820   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
   13821 }
   13822 
   13823 
   13824 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
   13825                                               v8::Handle<v8::Value> data) {
   13826   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   13827   CHECK(!stack_trace.IsEmpty());
   13828   int frame_count = stack_trace->GetFrameCount();
   13829   CHECK_EQ(2, frame_count);
   13830   int line_number[] = {3, 7};
   13831   for (int i = 0; i < frame_count; i++) {
   13832     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   13833   }
   13834 }
   13835 
   13836 
   13837 // Test that we do not recognize identity for primitive exceptions.
   13838 TEST(RethrowPrimitiveStackTrace) {
   13839   v8::HandleScope scope;
   13840   LocalContext env;
   13841   // We do not capture stack trace for non Error objects on creation time.
   13842   // Instead, we capture the stack trace on last throw.
   13843   const char* source =
   13844       "function g() { throw 404; }      \n"
   13845       "function f() { g(); }            \n"
   13846       "function t(e) { throw e; }       \n"
   13847       "try {                            \n"
   13848       "  f();                           \n"
   13849       "} catch (e1) {                   \n"
   13850       "  t(e1)                          \n"
   13851       "}                                \n";
   13852   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
   13853   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   13854   CompileRun(source);
   13855   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   13856   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   13857 }
   13858 
   13859 
   13860 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
   13861                                               v8::Handle<v8::Value> data) {
   13862   // Use the frame where JavaScript is called from.
   13863   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   13864   CHECK(!stack_trace.IsEmpty());
   13865   CHECK_EQ(1, stack_trace->GetFrameCount());
   13866   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
   13867 }
   13868 
   13869 
   13870 // Test that the stack trace is captured when the error object is created and
   13871 // not where it is thrown.
   13872 TEST(RethrowExistingStackTrace) {
   13873   v8::HandleScope scope;
   13874   LocalContext env;
   13875   const char* source =
   13876       "var e = new Error();           \n"
   13877       "throw e;                       \n";
   13878   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
   13879   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   13880   CompileRun(source);
   13881   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   13882   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
   13883 }
   13884 
   13885 
   13886 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
   13887                                                v8::Handle<v8::Value> data) {
   13888   // Use the frame where JavaScript is called from.
   13889   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   13890   CHECK(!stack_trace.IsEmpty());
   13891   CHECK_EQ(1, stack_trace->GetFrameCount());
   13892   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
   13893 }
   13894 
   13895 
   13896 // Test that the stack trace is captured where the bogus Error object is thrown.
   13897 TEST(RethrowBogusErrorStackTrace) {
   13898   v8::HandleScope scope;
   13899   LocalContext env;
   13900   const char* source =
   13901       "var e = {__proto__: new Error()} \n"
   13902       "throw e;                         \n";
   13903   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
   13904   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   13905   CompileRun(source);
   13906   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   13907   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   13908 }
   13909 
   13910 
   13911 v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) {
   13912   v8::HandleScope scope;
   13913   v8::Handle<v8::StackTrace> stackTrace =
   13914       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
   13915   CHECK_EQ(5, stackTrace->GetFrameCount());
   13916   v8::Handle<v8::String> url = v8_str("eval_url");
   13917   for (int i = 0; i < 3; i++) {
   13918     v8::Handle<v8::String> name =
   13919         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   13920     CHECK(!name.IsEmpty());
   13921     CHECK_EQ(url, name);
   13922   }
   13923   return v8::Undefined();
   13924 }
   13925 
   13926 
   13927 TEST(SourceURLInStackTrace) {
   13928   v8::HandleScope scope;
   13929   Local<ObjectTemplate> templ = ObjectTemplate::New();
   13930   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   13931              v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
   13932   LocalContext context(0, templ);
   13933 
   13934   const char *source =
   13935     "function outer() {\n"
   13936     "function bar() {\n"
   13937     "  AnalyzeStackOfEvalWithSourceURL();\n"
   13938     "}\n"
   13939     "function foo() {\n"
   13940     "\n"
   13941     "  bar();\n"
   13942     "}\n"
   13943     "foo();\n"
   13944     "}\n"
   13945     "eval('(' + outer +')()//@ sourceURL=eval_url');";
   13946   CHECK(CompileRun(source)->IsUndefined());
   13947 }
   13948 
   13949 
   13950 // Test that idle notification can be handled and eventually returns true.
   13951 // This just checks the contract of the IdleNotification() function,
   13952 // and does not verify that it does reasonable work.
   13953 THREADED_TEST(IdleNotification) {
   13954   v8::HandleScope scope;
   13955   LocalContext env;
   13956   {
   13957     // Create garbage in old-space to generate work for idle notification.
   13958     i::AlwaysAllocateScope always_allocate;
   13959     for (int i = 0; i < 100; i++) {
   13960       FACTORY->NewFixedArray(1000, i::TENURED);
   13961     }
   13962   }
   13963   bool finshed_idle_work = false;
   13964   for (int i = 0; i < 100 && !finshed_idle_work; i++) {
   13965     finshed_idle_work = v8::V8::IdleNotification();
   13966   }
   13967   CHECK(finshed_idle_work);
   13968 }
   13969 
   13970 // Test that idle notification can be handled and eventually returns true.
   13971 // This just checks the contract of the IdleNotification() function,
   13972 // and does not verify that it does reasonable work.
   13973 TEST(IdleNotificationWithSmallHint) {
   13974   v8::HandleScope scope;
   13975   LocalContext env;
   13976   {
   13977     // Create garbage in old-space to generate work for idle notification.
   13978     i::AlwaysAllocateScope always_allocate;
   13979     for (int i = 0; i < 100; i++) {
   13980       FACTORY->NewFixedArray(1000, i::TENURED);
   13981     }
   13982   }
   13983   intptr_t old_size = HEAP->SizeOfObjects();
   13984   bool finshed_idle_work = false;
   13985   bool no_idle_work = v8::V8::IdleNotification(10);
   13986   for (int i = 0; i < 200 && !finshed_idle_work; i++) {
   13987     finshed_idle_work = v8::V8::IdleNotification(10);
   13988   }
   13989   intptr_t new_size = HEAP->SizeOfObjects();
   13990   CHECK(finshed_idle_work);
   13991   CHECK(no_idle_work || new_size < old_size);
   13992 }
   13993 
   13994 
   13995 // This just checks the contract of the IdleNotification() function,
   13996 // and does not verify that it does reasonable work.
   13997 TEST(IdleNotificationWithLargeHint) {
   13998   v8::HandleScope scope;
   13999   LocalContext env;
   14000   {
   14001     // Create garbage in old-space to generate work for idle notification.
   14002     i::AlwaysAllocateScope always_allocate;
   14003     for (int i = 0; i < 100; i++) {
   14004       FACTORY->NewFixedArray(1000, i::TENURED);
   14005     }
   14006   }
   14007   intptr_t old_size = HEAP->SizeOfObjects();
   14008   bool finshed_idle_work = false;
   14009   bool no_idle_work = v8::V8::IdleNotification(900);
   14010   for (int i = 0; i < 200 && !finshed_idle_work; i++) {
   14011     finshed_idle_work = v8::V8::IdleNotification(900);
   14012   }
   14013   intptr_t new_size = HEAP->SizeOfObjects();
   14014   CHECK(finshed_idle_work);
   14015   CHECK(no_idle_work || new_size < old_size);
   14016 }
   14017 
   14018 
   14019 static uint32_t* stack_limit;
   14020 
   14021 static v8::Handle<Value> GetStackLimitCallback(const v8::Arguments& args) {
   14022   stack_limit = reinterpret_cast<uint32_t*>(
   14023       i::Isolate::Current()->stack_guard()->real_climit());
   14024   return v8::Undefined();
   14025 }
   14026 
   14027 
   14028 // Uses the address of a local variable to determine the stack top now.
   14029 // Given a size, returns an address that is that far from the current
   14030 // top of stack.
   14031 static uint32_t* ComputeStackLimit(uint32_t size) {
   14032   uint32_t* answer = &size - (size / sizeof(size));
   14033   // If the size is very large and the stack is very near the bottom of
   14034   // memory then the calculation above may wrap around and give an address
   14035   // that is above the (downwards-growing) stack.  In that case we return
   14036   // a very low address.
   14037   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   14038   return answer;
   14039 }
   14040 
   14041 
   14042 TEST(SetResourceConstraints) {
   14043   static const int K = 1024;
   14044   uint32_t* set_limit = ComputeStackLimit(128 * K);
   14045 
   14046   // Set stack limit.
   14047   v8::ResourceConstraints constraints;
   14048   constraints.set_stack_limit(set_limit);
   14049   CHECK(v8::SetResourceConstraints(&constraints));
   14050 
   14051   // Execute a script.
   14052   v8::HandleScope scope;
   14053   LocalContext env;
   14054   Local<v8::FunctionTemplate> fun_templ =
   14055       v8::FunctionTemplate::New(GetStackLimitCallback);
   14056   Local<Function> fun = fun_templ->GetFunction();
   14057   env->Global()->Set(v8_str("get_stack_limit"), fun);
   14058   CompileRun("get_stack_limit();");
   14059 
   14060   CHECK(stack_limit == set_limit);
   14061 }
   14062 
   14063 
   14064 TEST(SetResourceConstraintsInThread) {
   14065   uint32_t* set_limit;
   14066   {
   14067     v8::Locker locker;
   14068     static const int K = 1024;
   14069     set_limit = ComputeStackLimit(128 * K);
   14070 
   14071     // Set stack limit.
   14072     v8::ResourceConstraints constraints;
   14073     constraints.set_stack_limit(set_limit);
   14074     CHECK(v8::SetResourceConstraints(&constraints));
   14075 
   14076     // Execute a script.
   14077     v8::HandleScope scope;
   14078     LocalContext env;
   14079     Local<v8::FunctionTemplate> fun_templ =
   14080         v8::FunctionTemplate::New(GetStackLimitCallback);
   14081     Local<Function> fun = fun_templ->GetFunction();
   14082     env->Global()->Set(v8_str("get_stack_limit"), fun);
   14083     CompileRun("get_stack_limit();");
   14084 
   14085     CHECK(stack_limit == set_limit);
   14086   }
   14087   {
   14088     v8::Locker locker;
   14089     CHECK(stack_limit == set_limit);
   14090   }
   14091 }
   14092 
   14093 
   14094 THREADED_TEST(GetHeapStatistics) {
   14095   v8::HandleScope scope;
   14096   LocalContext c1;
   14097   v8::HeapStatistics heap_statistics;
   14098   CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
   14099   CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
   14100   v8::V8::GetHeapStatistics(&heap_statistics);
   14101   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   14102   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   14103 }
   14104 
   14105 
   14106 class VisitorImpl : public v8::ExternalResourceVisitor {
   14107  public:
   14108   VisitorImpl(TestResource* r1, TestResource* r2)
   14109       : resource1_(r1),
   14110         resource2_(r2),
   14111         found_resource1_(false),
   14112         found_resource2_(false) {}
   14113   virtual ~VisitorImpl() {}
   14114   virtual void VisitExternalString(v8::Handle<v8::String> string) {
   14115     if (!string->IsExternal()) {
   14116       CHECK(string->IsExternalAscii());
   14117       return;
   14118     }
   14119     v8::String::ExternalStringResource* resource =
   14120         string->GetExternalStringResource();
   14121     CHECK(resource);
   14122     if (resource1_ == resource) {
   14123       CHECK(!found_resource1_);
   14124       found_resource1_ = true;
   14125     }
   14126     if (resource2_ == resource) {
   14127       CHECK(!found_resource2_);
   14128       found_resource2_ = true;
   14129     }
   14130   }
   14131   void CheckVisitedResources() {
   14132     CHECK(found_resource1_);
   14133     CHECK(found_resource2_);
   14134   }
   14135 
   14136  private:
   14137   v8::String::ExternalStringResource* resource1_;
   14138   v8::String::ExternalStringResource* resource2_;
   14139   bool found_resource1_;
   14140   bool found_resource2_;
   14141 };
   14142 
   14143 TEST(VisitExternalStrings) {
   14144   v8::HandleScope scope;
   14145   LocalContext env;
   14146   const char* string = "Some string";
   14147   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   14148   TestResource* resource1 = new TestResource(two_byte_string);
   14149   v8::Local<v8::String> string1 = v8::String::NewExternal(resource1);
   14150   TestResource* resource2 = new TestResource(two_byte_string);
   14151   v8::Local<v8::String> string2 = v8::String::NewExternal(resource2);
   14152 
   14153   // We need to add usages for string1 and string2 to avoid warnings in GCC 4.7
   14154   CHECK(string1->IsExternal());
   14155   CHECK(string2->IsExternal());
   14156 
   14157   VisitorImpl visitor(resource1, resource2);
   14158   v8::V8::VisitExternalResources(&visitor);
   14159   visitor.CheckVisitedResources();
   14160 }
   14161 
   14162 
   14163 static double DoubleFromBits(uint64_t value) {
   14164   double target;
   14165   memcpy(&target, &value, sizeof(target));
   14166   return target;
   14167 }
   14168 
   14169 
   14170 static uint64_t DoubleToBits(double value) {
   14171   uint64_t target;
   14172   memcpy(&target, &value, sizeof(target));
   14173   return target;
   14174 }
   14175 
   14176 
   14177 static double DoubleToDateTime(double input) {
   14178   double date_limit = 864e13;
   14179   if (IsNaN(input) || input < -date_limit || input > date_limit) {
   14180     return i::OS::nan_value();
   14181   }
   14182   return (input < 0) ? -(floor(-input)) : floor(input);
   14183 }
   14184 
   14185 // We don't have a consistent way to write 64-bit constants syntactically, so we
   14186 // split them into two 32-bit constants and combine them programmatically.
   14187 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   14188   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   14189 }
   14190 
   14191 
   14192 THREADED_TEST(QuietSignalingNaNs) {
   14193   v8::HandleScope scope;
   14194   LocalContext context;
   14195   v8::TryCatch try_catch;
   14196 
   14197   // Special double values.
   14198   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
   14199   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
   14200   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
   14201   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
   14202   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   14203   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
   14204   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   14205 
   14206   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   14207   // on either side of the epoch.
   14208   double date_limit = 864e13;
   14209 
   14210   double test_values[] = {
   14211       snan,
   14212       qnan,
   14213       infinity,
   14214       max_normal,
   14215       date_limit + 1,
   14216       date_limit,
   14217       min_normal,
   14218       max_denormal,
   14219       min_denormal,
   14220       0,
   14221       -0,
   14222       -min_denormal,
   14223       -max_denormal,
   14224       -min_normal,
   14225       -date_limit,
   14226       -date_limit - 1,
   14227       -max_normal,
   14228       -infinity,
   14229       -qnan,
   14230       -snan
   14231   };
   14232   int num_test_values = 20;
   14233 
   14234   for (int i = 0; i < num_test_values; i++) {
   14235     double test_value = test_values[i];
   14236 
   14237     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   14238     v8::Handle<v8::Value> number = v8::Number::New(test_value);
   14239     double stored_number = number->NumberValue();
   14240     if (!IsNaN(test_value)) {
   14241       CHECK_EQ(test_value, stored_number);
   14242     } else {
   14243       uint64_t stored_bits = DoubleToBits(stored_number);
   14244       // Check if quiet nan (bits 51..62 all set).
   14245 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
   14246       // Most significant fraction bit for quiet nan is set to 0
   14247       // on MIPS architecture. Allowed by IEEE-754.
   14248       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   14249 #else
   14250       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   14251 #endif
   14252     }
   14253 
   14254     // Check that Date::New preserves non-NaNs in the date range and
   14255     // quiets SNaNs.
   14256     v8::Handle<v8::Value> date = v8::Date::New(test_value);
   14257     double expected_stored_date = DoubleToDateTime(test_value);
   14258     double stored_date = date->NumberValue();
   14259     if (!IsNaN(expected_stored_date)) {
   14260       CHECK_EQ(expected_stored_date, stored_date);
   14261     } else {
   14262       uint64_t stored_bits = DoubleToBits(stored_date);
   14263       // Check if quiet nan (bits 51..62 all set).
   14264 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
   14265       // Most significant fraction bit for quiet nan is set to 0
   14266       // on MIPS architecture. Allowed by IEEE-754.
   14267       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   14268 #else
   14269       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   14270 #endif
   14271     }
   14272   }
   14273 }
   14274 
   14275 
   14276 static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) {
   14277   v8::HandleScope scope;
   14278   v8::TryCatch tc;
   14279   v8::Handle<v8::String> str(args[0]->ToString());
   14280   USE(str);
   14281   if (tc.HasCaught())
   14282     return tc.ReThrow();
   14283   return v8::Undefined();
   14284 }
   14285 
   14286 
   14287 // Test that an exception can be propagated down through a spaghetti
   14288 // stack using ReThrow.
   14289 THREADED_TEST(SpaghettiStackReThrow) {
   14290   v8::HandleScope scope;
   14291   LocalContext context;
   14292   context->Global()->Set(
   14293       v8::String::New("s"),
   14294       v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
   14295   v8::TryCatch try_catch;
   14296   CompileRun(
   14297       "var i = 0;"
   14298       "var o = {"
   14299       "  toString: function () {"
   14300       "    if (i == 10) {"
   14301       "      throw 'Hey!';"
   14302       "    } else {"
   14303       "      i++;"
   14304       "      return s(o);"
   14305       "    }"
   14306       "  }"
   14307       "};"
   14308       "s(o);");
   14309   CHECK(try_catch.HasCaught());
   14310   v8::String::Utf8Value value(try_catch.Exception());
   14311   CHECK_EQ(0, strcmp(*value, "Hey!"));
   14312 }
   14313 
   14314 
   14315 TEST(Regress528) {
   14316   v8::V8::Initialize();
   14317 
   14318   v8::HandleScope scope;
   14319   v8::Persistent<Context> context;
   14320   v8::Persistent<Context> other_context;
   14321   int gc_count;
   14322 
   14323   // Create a context used to keep the code from aging in the compilation
   14324   // cache.
   14325   other_context = Context::New();
   14326 
   14327   // Context-dependent context data creates reference from the compilation
   14328   // cache to the global object.
   14329   const char* source_simple = "1";
   14330   context = Context::New();
   14331   {
   14332     v8::HandleScope scope;
   14333 
   14334     context->Enter();
   14335     Local<v8::String> obj = v8::String::New("");
   14336     context->SetData(obj);
   14337     CompileRun(source_simple);
   14338     context->Exit();
   14339   }
   14340   context.Dispose();
   14341   for (gc_count = 1; gc_count < 10; gc_count++) {
   14342     other_context->Enter();
   14343     CompileRun(source_simple);
   14344     other_context->Exit();
   14345     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14346     if (GetGlobalObjectsCount() == 1) break;
   14347   }
   14348   CHECK_GE(2, gc_count);
   14349   CHECK_EQ(1, GetGlobalObjectsCount());
   14350 
   14351   // Eval in a function creates reference from the compilation cache to the
   14352   // global object.
   14353   const char* source_eval = "function f(){eval('1')}; f()";
   14354   context = Context::New();
   14355   {
   14356     v8::HandleScope scope;
   14357 
   14358     context->Enter();
   14359     CompileRun(source_eval);
   14360     context->Exit();
   14361   }
   14362   context.Dispose();
   14363   for (gc_count = 1; gc_count < 10; gc_count++) {
   14364     other_context->Enter();
   14365     CompileRun(source_eval);
   14366     other_context->Exit();
   14367     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14368     if (GetGlobalObjectsCount() == 1) break;
   14369   }
   14370   CHECK_GE(2, gc_count);
   14371   CHECK_EQ(1, GetGlobalObjectsCount());
   14372 
   14373   // Looking up the line number for an exception creates reference from the
   14374   // compilation cache to the global object.
   14375   const char* source_exception = "function f(){throw 1;} f()";
   14376   context = Context::New();
   14377   {
   14378     v8::HandleScope scope;
   14379 
   14380     context->Enter();
   14381     v8::TryCatch try_catch;
   14382     CompileRun(source_exception);
   14383     CHECK(try_catch.HasCaught());
   14384     v8::Handle<v8::Message> message = try_catch.Message();
   14385     CHECK(!message.IsEmpty());
   14386     CHECK_EQ(1, message->GetLineNumber());
   14387     context->Exit();
   14388   }
   14389   context.Dispose();
   14390   for (gc_count = 1; gc_count < 10; gc_count++) {
   14391     other_context->Enter();
   14392     CompileRun(source_exception);
   14393     other_context->Exit();
   14394     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14395     if (GetGlobalObjectsCount() == 1) break;
   14396   }
   14397   CHECK_GE(2, gc_count);
   14398   CHECK_EQ(1, GetGlobalObjectsCount());
   14399 
   14400   other_context.Dispose();
   14401 }
   14402 
   14403 
   14404 THREADED_TEST(ScriptOrigin) {
   14405   v8::HandleScope scope;
   14406   LocalContext env;
   14407   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
   14408   v8::Handle<v8::String> script = v8::String::New(
   14409       "function f() {}\n\nfunction g() {}");
   14410   v8::Script::Compile(script, &origin)->Run();
   14411   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   14412       env->Global()->Get(v8::String::New("f")));
   14413   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   14414       env->Global()->Get(v8::String::New("g")));
   14415 
   14416   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   14417   CHECK_EQ("test", *v8::String::AsciiValue(script_origin_f.ResourceName()));
   14418   CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
   14419 
   14420   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   14421   CHECK_EQ("test", *v8::String::AsciiValue(script_origin_g.ResourceName()));
   14422   CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
   14423 }
   14424 
   14425 THREADED_TEST(FunctionGetInferredName) {
   14426   v8::HandleScope scope;
   14427   LocalContext env;
   14428   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
   14429   v8::Handle<v8::String> script = v8::String::New(
   14430       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   14431   v8::Script::Compile(script, &origin)->Run();
   14432   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   14433       env->Global()->Get(v8::String::New("f")));
   14434   CHECK_EQ("foo.bar.baz", *v8::String::AsciiValue(f->GetInferredName()));
   14435 }
   14436 
   14437 THREADED_TEST(ScriptLineNumber) {
   14438   v8::HandleScope scope;
   14439   LocalContext env;
   14440   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
   14441   v8::Handle<v8::String> script = v8::String::New(
   14442       "function f() {}\n\nfunction g() {}");
   14443   v8::Script::Compile(script, &origin)->Run();
   14444   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   14445       env->Global()->Get(v8::String::New("f")));
   14446   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   14447       env->Global()->Get(v8::String::New("g")));
   14448   CHECK_EQ(0, f->GetScriptLineNumber());
   14449   CHECK_EQ(2, g->GetScriptLineNumber());
   14450 }
   14451 
   14452 
   14453 THREADED_TEST(ScriptColumnNumber) {
   14454   v8::HandleScope scope;
   14455   LocalContext env;
   14456   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
   14457       v8::Integer::New(3), v8::Integer::New(2));
   14458   v8::Handle<v8::String> script = v8::String::New(
   14459       "function foo() {}\n\n     function bar() {}");
   14460   v8::Script::Compile(script, &origin)->Run();
   14461   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   14462       env->Global()->Get(v8::String::New("foo")));
   14463   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   14464       env->Global()->Get(v8::String::New("bar")));
   14465   CHECK_EQ(14, foo->GetScriptColumnNumber());
   14466   CHECK_EQ(17, bar->GetScriptColumnNumber());
   14467 }
   14468 
   14469 
   14470 THREADED_TEST(FunctionGetScriptId) {
   14471   v8::HandleScope scope;
   14472   LocalContext env;
   14473   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
   14474       v8::Integer::New(3), v8::Integer::New(2));
   14475   v8::Handle<v8::String> scriptSource = v8::String::New(
   14476       "function foo() {}\n\n     function bar() {}");
   14477   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
   14478   script->Run();
   14479   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   14480       env->Global()->Get(v8::String::New("foo")));
   14481   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   14482       env->Global()->Get(v8::String::New("bar")));
   14483   CHECK_EQ(script->Id(), foo->GetScriptId());
   14484   CHECK_EQ(script->Id(), bar->GetScriptId());
   14485 }
   14486 
   14487 
   14488 static v8::Handle<Value> GetterWhichReturns42(Local<String> name,
   14489                                               const AccessorInfo& info) {
   14490   return v8_num(42);
   14491 }
   14492 
   14493 
   14494 static void SetterWhichSetsYOnThisTo23(Local<String> name,
   14495                                        Local<Value> value,
   14496                                        const AccessorInfo& info) {
   14497   info.This()->Set(v8_str("y"), v8_num(23));
   14498 }
   14499 
   14500 
   14501 TEST(SetterOnConstructorPrototype) {
   14502   v8::HandleScope scope;
   14503   Local<ObjectTemplate> templ = ObjectTemplate::New();
   14504   templ->SetAccessor(v8_str("x"),
   14505                      GetterWhichReturns42,
   14506                      SetterWhichSetsYOnThisTo23);
   14507   LocalContext context;
   14508   context->Global()->Set(v8_str("P"), templ->NewInstance());
   14509   CompileRun("function C1() {"
   14510              "  this.x = 23;"
   14511              "};"
   14512              "C1.prototype = P;"
   14513              "function C2() {"
   14514              "  this.x = 23"
   14515              "};"
   14516              "C2.prototype = { };"
   14517              "C2.prototype.__proto__ = P;");
   14518 
   14519   v8::Local<v8::Script> script;
   14520   script = v8::Script::Compile(v8_str("new C1();"));
   14521   for (int i = 0; i < 10; i++) {
   14522     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   14523     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   14524     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   14525   }
   14526 
   14527   script = v8::Script::Compile(v8_str("new C2();"));
   14528   for (int i = 0; i < 10; i++) {
   14529     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   14530     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
   14531     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
   14532   }
   14533 }
   14534 
   14535 
   14536 static v8::Handle<Value> NamedPropertyGetterWhichReturns42(
   14537     Local<String> name, const AccessorInfo& info) {
   14538   return v8_num(42);
   14539 }
   14540 
   14541 
   14542 static v8::Handle<Value> NamedPropertySetterWhichSetsYOnThisTo23(
   14543     Local<String> name, Local<Value> value, const AccessorInfo& info) {
   14544   if (name->Equals(v8_str("x"))) {
   14545     info.This()->Set(v8_str("y"), v8_num(23));
   14546   }
   14547   return v8::Handle<Value>();
   14548 }
   14549 
   14550 
   14551 THREADED_TEST(InterceptorOnConstructorPrototype) {
   14552   v8::HandleScope scope;
   14553   Local<ObjectTemplate> templ = ObjectTemplate::New();
   14554   templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
   14555                                  NamedPropertySetterWhichSetsYOnThisTo23);
   14556   LocalContext context;
   14557   context->Global()->Set(v8_str("P"), templ->NewInstance());
   14558   CompileRun("function C1() {"
   14559              "  this.x = 23;"
   14560              "};"
   14561              "C1.prototype = P;"
   14562              "function C2() {"
   14563              "  this.x = 23"
   14564              "};"
   14565              "C2.prototype = { };"
   14566              "C2.prototype.__proto__ = P;");
   14567 
   14568   v8::Local<v8::Script> script;
   14569   script = v8::Script::Compile(v8_str("new C1();"));
   14570   for (int i = 0; i < 10; i++) {
   14571     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   14572     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   14573     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   14574   }
   14575 
   14576   script = v8::Script::Compile(v8_str("new C2();"));
   14577   for (int i = 0; i < 10; i++) {
   14578     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   14579     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
   14580     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
   14581   }
   14582 }
   14583 
   14584 
   14585 TEST(Bug618) {
   14586   const char* source = "function C1() {"
   14587                        "  this.x = 23;"
   14588                        "};"
   14589                        "C1.prototype = P;";
   14590 
   14591   v8::HandleScope scope;
   14592   LocalContext context;
   14593   v8::Local<v8::Script> script;
   14594 
   14595   // Use a simple object as prototype.
   14596   v8::Local<v8::Object> prototype = v8::Object::New();
   14597   prototype->Set(v8_str("y"), v8_num(42));
   14598   context->Global()->Set(v8_str("P"), prototype);
   14599 
   14600   // This compile will add the code to the compilation cache.
   14601   CompileRun(source);
   14602 
   14603   script = v8::Script::Compile(v8_str("new C1();"));
   14604   // Allow enough iterations for the inobject slack tracking logic
   14605   // to finalize instance size and install the fast construct stub.
   14606   for (int i = 0; i < 256; i++) {
   14607     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   14608     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   14609     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   14610   }
   14611 
   14612   // Use an API object with accessors as prototype.
   14613   Local<ObjectTemplate> templ = ObjectTemplate::New();
   14614   templ->SetAccessor(v8_str("x"),
   14615                      GetterWhichReturns42,
   14616                      SetterWhichSetsYOnThisTo23);
   14617   context->Global()->Set(v8_str("P"), templ->NewInstance());
   14618 
   14619   // This compile will get the code from the compilation cache.
   14620   CompileRun(source);
   14621 
   14622   script = v8::Script::Compile(v8_str("new C1();"));
   14623   for (int i = 0; i < 10; i++) {
   14624     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   14625     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   14626     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   14627   }
   14628 }
   14629 
   14630 int prologue_call_count = 0;
   14631 int epilogue_call_count = 0;
   14632 int prologue_call_count_second = 0;
   14633 int epilogue_call_count_second = 0;
   14634 
   14635 void PrologueCallback(v8::GCType, v8::GCCallbackFlags) {
   14636   ++prologue_call_count;
   14637 }
   14638 
   14639 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags) {
   14640   ++epilogue_call_count;
   14641 }
   14642 
   14643 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
   14644   ++prologue_call_count_second;
   14645 }
   14646 
   14647 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
   14648   ++epilogue_call_count_second;
   14649 }
   14650 
   14651 TEST(GCCallbacks) {
   14652   LocalContext context;
   14653 
   14654   v8::V8::AddGCPrologueCallback(PrologueCallback);
   14655   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
   14656   CHECK_EQ(0, prologue_call_count);
   14657   CHECK_EQ(0, epilogue_call_count);
   14658   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14659   CHECK_EQ(1, prologue_call_count);
   14660   CHECK_EQ(1, epilogue_call_count);
   14661   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
   14662   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
   14663   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14664   CHECK_EQ(2, prologue_call_count);
   14665   CHECK_EQ(2, epilogue_call_count);
   14666   CHECK_EQ(1, prologue_call_count_second);
   14667   CHECK_EQ(1, epilogue_call_count_second);
   14668   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
   14669   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
   14670   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14671   CHECK_EQ(2, prologue_call_count);
   14672   CHECK_EQ(2, epilogue_call_count);
   14673   CHECK_EQ(2, prologue_call_count_second);
   14674   CHECK_EQ(2, epilogue_call_count_second);
   14675   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
   14676   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   14677   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14678   CHECK_EQ(2, prologue_call_count);
   14679   CHECK_EQ(2, epilogue_call_count);
   14680   CHECK_EQ(2, prologue_call_count_second);
   14681   CHECK_EQ(2, epilogue_call_count_second);
   14682 }
   14683 
   14684 
   14685 THREADED_TEST(AddToJSFunctionResultCache) {
   14686   i::FLAG_allow_natives_syntax = true;
   14687   v8::HandleScope scope;
   14688 
   14689   LocalContext context;
   14690 
   14691   const char* code =
   14692       "(function() {"
   14693       "  var key0 = 'a';"
   14694       "  var key1 = 'b';"
   14695       "  var r0 = %_GetFromCache(0, key0);"
   14696       "  var r1 = %_GetFromCache(0, key1);"
   14697       "  var r0_ = %_GetFromCache(0, key0);"
   14698       "  if (r0 !== r0_)"
   14699       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
   14700       "  var r1_ = %_GetFromCache(0, key1);"
   14701       "  if (r1 !== r1_)"
   14702       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
   14703       "  return 'PASSED';"
   14704       "})()";
   14705   HEAP->ClearJSFunctionResultCaches();
   14706   ExpectString(code, "PASSED");
   14707 }
   14708 
   14709 
   14710 static const int k0CacheSize = 16;
   14711 
   14712 THREADED_TEST(FillJSFunctionResultCache) {
   14713   i::FLAG_allow_natives_syntax = true;
   14714   v8::HandleScope scope;
   14715 
   14716   LocalContext context;
   14717 
   14718   const char* code =
   14719       "(function() {"
   14720       "  var k = 'a';"
   14721       "  var r = %_GetFromCache(0, k);"
   14722       "  for (var i = 0; i < 16; i++) {"
   14723       "    %_GetFromCache(0, 'a' + i);"
   14724       "  };"
   14725       "  if (r === %_GetFromCache(0, k))"
   14726       "    return 'FAILED: k0CacheSize is too small';"
   14727       "  return 'PASSED';"
   14728       "})()";
   14729   HEAP->ClearJSFunctionResultCaches();
   14730   ExpectString(code, "PASSED");
   14731 }
   14732 
   14733 
   14734 THREADED_TEST(RoundRobinGetFromCache) {
   14735   i::FLAG_allow_natives_syntax = true;
   14736   v8::HandleScope scope;
   14737 
   14738   LocalContext context;
   14739 
   14740   const char* code =
   14741       "(function() {"
   14742       "  var keys = [];"
   14743       "  for (var i = 0; i < 16; i++) keys.push(i);"
   14744       "  var values = [];"
   14745       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   14746       "  for (var i = 0; i < 16; i++) {"
   14747       "    var v = %_GetFromCache(0, keys[i]);"
   14748       "    if (v.toString() !== values[i].toString())"
   14749       "      return 'Wrong value for ' + "
   14750       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   14751       "  };"
   14752       "  return 'PASSED';"
   14753       "})()";
   14754   HEAP->ClearJSFunctionResultCaches();
   14755   ExpectString(code, "PASSED");
   14756 }
   14757 
   14758 
   14759 THREADED_TEST(ReverseGetFromCache) {
   14760   i::FLAG_allow_natives_syntax = true;
   14761   v8::HandleScope scope;
   14762 
   14763   LocalContext context;
   14764 
   14765   const char* code =
   14766       "(function() {"
   14767       "  var keys = [];"
   14768       "  for (var i = 0; i < 16; i++) keys.push(i);"
   14769       "  var values = [];"
   14770       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   14771       "  for (var i = 15; i >= 16; i--) {"
   14772       "    var v = %_GetFromCache(0, keys[i]);"
   14773       "    if (v !== values[i])"
   14774       "      return 'Wrong value for ' + "
   14775       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   14776       "  };"
   14777       "  return 'PASSED';"
   14778       "})()";
   14779   HEAP->ClearJSFunctionResultCaches();
   14780   ExpectString(code, "PASSED");
   14781 }
   14782 
   14783 
   14784 THREADED_TEST(TestEviction) {
   14785   i::FLAG_allow_natives_syntax = true;
   14786   v8::HandleScope scope;
   14787 
   14788   LocalContext context;
   14789 
   14790   const char* code =
   14791       "(function() {"
   14792       "  for (var i = 0; i < 2*16; i++) {"
   14793       "    %_GetFromCache(0, 'a' + i);"
   14794       "  };"
   14795       "  return 'PASSED';"
   14796       "})()";
   14797   HEAP->ClearJSFunctionResultCaches();
   14798   ExpectString(code, "PASSED");
   14799 }
   14800 
   14801 
   14802 THREADED_TEST(TwoByteStringInAsciiCons) {
   14803   // See Chromium issue 47824.
   14804   v8::HandleScope scope;
   14805 
   14806   LocalContext context;
   14807   const char* init_code =
   14808       "var str1 = 'abelspendabel';"
   14809       "var str2 = str1 + str1 + str1;"
   14810       "str2;";
   14811   Local<Value> result = CompileRun(init_code);
   14812 
   14813   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   14814   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   14815 
   14816   CHECK(result->IsString());
   14817   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   14818   int length = string->length();
   14819   CHECK(string->IsAsciiRepresentation());
   14820 
   14821   FlattenString(string);
   14822   i::Handle<i::String> flat_string = FlattenGetString(string);
   14823 
   14824   CHECK(string->IsAsciiRepresentation());
   14825   CHECK(flat_string->IsAsciiRepresentation());
   14826 
   14827   // Create external resource.
   14828   uint16_t* uc16_buffer = new uint16_t[length + 1];
   14829 
   14830   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   14831   uc16_buffer[length] = 0;
   14832 
   14833   TestResource resource(uc16_buffer);
   14834 
   14835   flat_string->MakeExternal(&resource);
   14836 
   14837   CHECK(flat_string->IsTwoByteRepresentation());
   14838 
   14839   // At this point, we should have a Cons string which is flat and ASCII,
   14840   // with a first half that is a two-byte string (although it only contains
   14841   // ASCII characters). This is a valid sequence of steps, and it can happen
   14842   // in real pages.
   14843 
   14844   CHECK(string->IsAsciiRepresentation());
   14845   i::ConsString* cons = i::ConsString::cast(*string);
   14846   CHECK_EQ(0, cons->second()->length());
   14847   CHECK(cons->first()->IsTwoByteRepresentation());
   14848 
   14849   // Check that some string operations work.
   14850 
   14851   // Atom RegExp.
   14852   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   14853   CHECK_EQ(6, reresult->Int32Value());
   14854 
   14855   // Nonatom RegExp.
   14856   reresult = CompileRun("str2.match(/abe./g).length;");
   14857   CHECK_EQ(6, reresult->Int32Value());
   14858 
   14859   reresult = CompileRun("str2.search(/bel/g);");
   14860   CHECK_EQ(1, reresult->Int32Value());
   14861 
   14862   reresult = CompileRun("str2.search(/be./g);");
   14863   CHECK_EQ(1, reresult->Int32Value());
   14864 
   14865   ExpectTrue("/bel/g.test(str2);");
   14866 
   14867   ExpectTrue("/be./g.test(str2);");
   14868 
   14869   reresult = CompileRun("/bel/g.exec(str2);");
   14870   CHECK(!reresult->IsNull());
   14871 
   14872   reresult = CompileRun("/be./g.exec(str2);");
   14873   CHECK(!reresult->IsNull());
   14874 
   14875   ExpectString("str2.substring(2, 10);", "elspenda");
   14876 
   14877   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   14878 
   14879   ExpectString("str2.charAt(2);", "e");
   14880 
   14881   ExpectObject("str2.indexOf('els');", indexof);
   14882 
   14883   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   14884 
   14885   reresult = CompileRun("str2.charCodeAt(2);");
   14886   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
   14887 }
   14888 
   14889 
   14890 // Failed access check callback that performs a GC on each invocation.
   14891 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   14892                                  v8::AccessType type,
   14893                                  Local<v8::Value> data) {
   14894   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14895 }
   14896 
   14897 
   14898 TEST(GCInFailedAccessCheckCallback) {
   14899   // Install a failed access check callback that performs a GC on each
   14900   // invocation. Then force the callback to be called from va
   14901 
   14902   v8::V8::Initialize();
   14903   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   14904 
   14905   v8::HandleScope scope;
   14906 
   14907   // Create an ObjectTemplate for global objects and install access
   14908   // check callbacks that will block access.
   14909   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   14910   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   14911                                            IndexedGetAccessBlocker,
   14912                                            v8::Handle<v8::Value>(),
   14913                                            false);
   14914 
   14915   // Create a context and set an x property on it's global object.
   14916   LocalContext context0(NULL, global_template);
   14917   context0->Global()->Set(v8_str("x"), v8_num(42));
   14918   v8::Handle<v8::Object> global0 = context0->Global();
   14919 
   14920   // Create a context with a different security token so that the
   14921   // failed access check callback will be called on each access.
   14922   LocalContext context1(NULL, global_template);
   14923   context1->Global()->Set(v8_str("other"), global0);
   14924 
   14925   // Get property with failed access check.
   14926   ExpectUndefined("other.x");
   14927 
   14928   // Get element with failed access check.
   14929   ExpectUndefined("other[0]");
   14930 
   14931   // Set property with failed access check.
   14932   v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
   14933   CHECK(result->IsObject());
   14934 
   14935   // Set element with failed access check.
   14936   result = CompileRun("other[0] = new Object()");
   14937   CHECK(result->IsObject());
   14938 
   14939   // Get property attribute with failed access check.
   14940   ExpectFalse("\'x\' in other");
   14941 
   14942   // Get property attribute for element with failed access check.
   14943   ExpectFalse("0 in other");
   14944 
   14945   // Delete property.
   14946   ExpectFalse("delete other.x");
   14947 
   14948   // Delete element.
   14949   CHECK_EQ(false, global0->Delete(0));
   14950 
   14951   // DefineAccessor.
   14952   CHECK_EQ(false,
   14953            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
   14954 
   14955   // Define JavaScript accessor.
   14956   ExpectUndefined("Object.prototype.__defineGetter__.call("
   14957                   "    other, \'x\', function() { return 42; })");
   14958 
   14959   // LookupAccessor.
   14960   ExpectUndefined("Object.prototype.__lookupGetter__.call("
   14961                   "    other, \'x\')");
   14962 
   14963   // HasLocalElement.
   14964   ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
   14965 
   14966   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
   14967   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
   14968   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
   14969 
   14970   // Reset the failed access check callback so it does not influence
   14971   // the other tests.
   14972   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
   14973 }
   14974 
   14975 TEST(DefaultIsolateGetCurrent) {
   14976   CHECK(v8::Isolate::GetCurrent() != NULL);
   14977   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   14978   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   14979   printf("*** %s\n", "DefaultIsolateGetCurrent success");
   14980 }
   14981 
   14982 TEST(IsolateNewDispose) {
   14983   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
   14984   v8::Isolate* isolate = v8::Isolate::New();
   14985   CHECK(isolate != NULL);
   14986   CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   14987   CHECK(current_isolate != isolate);
   14988   CHECK(current_isolate == v8::Isolate::GetCurrent());
   14989 
   14990   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   14991   last_location = last_message = NULL;
   14992   isolate->Dispose();
   14993   CHECK_EQ(last_location, NULL);
   14994   CHECK_EQ(last_message, NULL);
   14995 }
   14996 
   14997 TEST(IsolateEnterExitDefault) {
   14998   v8::HandleScope scope;
   14999   LocalContext context;
   15000   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
   15001   CHECK(current_isolate != NULL);  // Default isolate.
   15002   ExpectString("'hello'", "hello");
   15003   current_isolate->Enter();
   15004   ExpectString("'still working'", "still working");
   15005   current_isolate->Exit();
   15006   ExpectString("'still working 2'", "still working 2");
   15007   current_isolate->Exit();
   15008   // Default isolate is always, well, 'default current'.
   15009   CHECK_EQ(v8::Isolate::GetCurrent(), current_isolate);
   15010   // Still working since default isolate is auto-entering any thread
   15011   // that has no isolate and attempts to execute V8 APIs.
   15012   ExpectString("'still working 3'", "still working 3");
   15013 }
   15014 
   15015 TEST(DisposeDefaultIsolate) {
   15016   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   15017 
   15018   // Run some V8 code to trigger default isolate to become 'current'.
   15019   v8::HandleScope scope;
   15020   LocalContext context;
   15021   ExpectString("'run some V8'", "run some V8");
   15022 
   15023   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   15024   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   15025   last_location = last_message = NULL;
   15026   isolate->Dispose();
   15027   // It is not possible to dispose default isolate via Isolate API.
   15028   CHECK_NE(last_location, NULL);
   15029   CHECK_NE(last_message, NULL);
   15030 }
   15031 
   15032 TEST(RunDefaultAndAnotherIsolate) {
   15033   v8::HandleScope scope;
   15034   LocalContext context;
   15035 
   15036   // Enter new isolate.
   15037   v8::Isolate* isolate = v8::Isolate::New();
   15038   CHECK(isolate);
   15039   isolate->Enter();
   15040   { // Need this block because subsequent Exit() will deallocate Heap,
   15041     // so we need all scope objects to be deconstructed when it happens.
   15042     v8::HandleScope scope_new;
   15043     LocalContext context_new;
   15044 
   15045     // Run something in new isolate.
   15046     CompileRun("var foo = 153;");
   15047     ExpectTrue("function f() { return foo == 153; }; f()");
   15048   }
   15049   isolate->Exit();
   15050 
   15051   // This runs automatically in default isolate.
   15052   // Variables in another isolate should be not available.
   15053   ExpectTrue("function f() {"
   15054              "  try {"
   15055              "    foo;"
   15056              "    return false;"
   15057              "  } catch(e) {"
   15058              "    return true;"
   15059              "  }"
   15060              "};"
   15061              "var bar = 371;"
   15062              "f()");
   15063 
   15064   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   15065   last_location = last_message = NULL;
   15066   isolate->Dispose();
   15067   CHECK_EQ(last_location, NULL);
   15068   CHECK_EQ(last_message, NULL);
   15069 
   15070   // Check that default isolate still runs.
   15071   ExpectTrue("function f() { return bar == 371; }; f()");
   15072 }
   15073 
   15074 TEST(DisposeIsolateWhenInUse) {
   15075   v8::Isolate* isolate = v8::Isolate::New();
   15076   CHECK(isolate);
   15077   isolate->Enter();
   15078   v8::HandleScope scope;
   15079   LocalContext context;
   15080   // Run something in this isolate.
   15081   ExpectTrue("true");
   15082   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   15083   last_location = last_message = NULL;
   15084   // Still entered, should fail.
   15085   isolate->Dispose();
   15086   CHECK_NE(last_location, NULL);
   15087   CHECK_NE(last_message, NULL);
   15088 }
   15089 
   15090 TEST(RunTwoIsolatesOnSingleThread) {
   15091   // Run isolate 1.
   15092   v8::Isolate* isolate1 = v8::Isolate::New();
   15093   isolate1->Enter();
   15094   v8::Persistent<v8::Context> context1 = v8::Context::New();
   15095 
   15096   {
   15097     v8::Context::Scope cscope(context1);
   15098     v8::HandleScope scope;
   15099     // Run something in new isolate.
   15100     CompileRun("var foo = 'isolate 1';");
   15101     ExpectString("function f() { return foo; }; f()", "isolate 1");
   15102   }
   15103 
   15104   // Run isolate 2.
   15105   v8::Isolate* isolate2 = v8::Isolate::New();
   15106   v8::Persistent<v8::Context> context2;
   15107 
   15108   {
   15109     v8::Isolate::Scope iscope(isolate2);
   15110     context2 = v8::Context::New();
   15111     v8::Context::Scope cscope(context2);
   15112     v8::HandleScope scope;
   15113 
   15114     // Run something in new isolate.
   15115     CompileRun("var foo = 'isolate 2';");
   15116     ExpectString("function f() { return foo; }; f()", "isolate 2");
   15117   }
   15118 
   15119   {
   15120     v8::Context::Scope cscope(context1);
   15121     v8::HandleScope scope;
   15122     // Now again in isolate 1
   15123     ExpectString("function f() { return foo; }; f()", "isolate 1");
   15124   }
   15125 
   15126   isolate1->Exit();
   15127 
   15128   // Run some stuff in default isolate.
   15129   v8::Persistent<v8::Context> context_default = v8::Context::New();
   15130 
   15131   {
   15132     v8::Context::Scope cscope(context_default);
   15133     v8::HandleScope scope;
   15134     // Variables in other isolates should be not available, verify there
   15135     // is an exception.
   15136     ExpectTrue("function f() {"
   15137                "  try {"
   15138                "    foo;"
   15139                "    return false;"
   15140                "  } catch(e) {"
   15141                "    return true;"
   15142                "  }"
   15143                "};"
   15144                "var isDefaultIsolate = true;"
   15145                "f()");
   15146   }
   15147 
   15148   isolate1->Enter();
   15149 
   15150   {
   15151     v8::Isolate::Scope iscope(isolate2);
   15152     v8::Context::Scope cscope(context2);
   15153     v8::HandleScope scope;
   15154     ExpectString("function f() { return foo; }; f()", "isolate 2");
   15155   }
   15156 
   15157   {
   15158     v8::Context::Scope cscope(context1);
   15159     v8::HandleScope scope;
   15160     ExpectString("function f() { return foo; }; f()", "isolate 1");
   15161   }
   15162 
   15163   {
   15164     v8::Isolate::Scope iscope(isolate2);
   15165     context2.Dispose();
   15166   }
   15167 
   15168   context1.Dispose();
   15169   isolate1->Exit();
   15170 
   15171   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   15172   last_location = last_message = NULL;
   15173 
   15174   isolate1->Dispose();
   15175   CHECK_EQ(last_location, NULL);
   15176   CHECK_EQ(last_message, NULL);
   15177 
   15178   isolate2->Dispose();
   15179   CHECK_EQ(last_location, NULL);
   15180   CHECK_EQ(last_message, NULL);
   15181 
   15182   // Check that default isolate still runs.
   15183   {
   15184     v8::Context::Scope cscope(context_default);
   15185     v8::HandleScope scope;
   15186     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   15187   }
   15188 }
   15189 
   15190 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   15191   v8::Isolate::Scope isolate_scope(isolate);
   15192   v8::HandleScope scope;
   15193   LocalContext context;
   15194   i::ScopedVector<char> code(1024);
   15195   i::OS::SNPrintF(code, "function fib(n) {"
   15196                         "  if (n <= 2) return 1;"
   15197                         "  return fib(n-1) + fib(n-2);"
   15198                         "}"
   15199                         "fib(%d)", limit);
   15200   Local<Value> value = CompileRun(code.start());
   15201   CHECK(value->IsNumber());
   15202   return static_cast<int>(value->NumberValue());
   15203 }
   15204 
   15205 class IsolateThread : public v8::internal::Thread {
   15206  public:
   15207   IsolateThread(v8::Isolate* isolate, int fib_limit)
   15208       : Thread("IsolateThread"),
   15209         isolate_(isolate),
   15210         fib_limit_(fib_limit),
   15211         result_(0) { }
   15212 
   15213   void Run() {
   15214     result_ = CalcFibonacci(isolate_, fib_limit_);
   15215   }
   15216 
   15217   int result() { return result_; }
   15218 
   15219  private:
   15220   v8::Isolate* isolate_;
   15221   int fib_limit_;
   15222   int result_;
   15223 };
   15224 
   15225 TEST(MultipleIsolatesOnIndividualThreads) {
   15226   v8::Isolate* isolate1 = v8::Isolate::New();
   15227   v8::Isolate* isolate2 = v8::Isolate::New();
   15228 
   15229   IsolateThread thread1(isolate1, 21);
   15230   IsolateThread thread2(isolate2, 12);
   15231 
   15232   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   15233   thread1.Start();
   15234   thread2.Start();
   15235 
   15236   int result1 = CalcFibonacci(v8::Isolate::GetCurrent(), 21);
   15237   int result2 = CalcFibonacci(v8::Isolate::GetCurrent(), 12);
   15238 
   15239   thread1.Join();
   15240   thread2.Join();
   15241 
   15242   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   15243   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   15244   CHECK_EQ(result1, 10946);
   15245   CHECK_EQ(result2, 144);
   15246   CHECK_EQ(result1, thread1.result());
   15247   CHECK_EQ(result2, thread2.result());
   15248 
   15249   isolate1->Dispose();
   15250   isolate2->Dispose();
   15251 }
   15252 
   15253 TEST(IsolateDifferentContexts) {
   15254   v8::Isolate* isolate = v8::Isolate::New();
   15255   Persistent<v8::Context> context;
   15256   {
   15257     v8::Isolate::Scope isolate_scope(isolate);
   15258     v8::HandleScope handle_scope;
   15259     context = v8::Context::New();
   15260     v8::Context::Scope context_scope(context);
   15261     Local<Value> v = CompileRun("2");
   15262     CHECK(v->IsNumber());
   15263     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
   15264   }
   15265   {
   15266     v8::Isolate::Scope isolate_scope(isolate);
   15267     v8::HandleScope handle_scope;
   15268     context = v8::Context::New();
   15269     v8::Context::Scope context_scope(context);
   15270     Local<Value> v = CompileRun("22");
   15271     CHECK(v->IsNumber());
   15272     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
   15273   }
   15274 }
   15275 
   15276 class InitDefaultIsolateThread : public v8::internal::Thread {
   15277  public:
   15278   enum TestCase {
   15279     IgnoreOOM,
   15280     SetResourceConstraints,
   15281     SetFatalHandler,
   15282     SetCounterFunction,
   15283     SetCreateHistogramFunction,
   15284     SetAddHistogramSampleFunction
   15285   };
   15286 
   15287   explicit InitDefaultIsolateThread(TestCase testCase)
   15288       : Thread("InitDefaultIsolateThread"),
   15289         testCase_(testCase),
   15290         result_(false) { }
   15291 
   15292   void Run() {
   15293     switch (testCase_) {
   15294     case IgnoreOOM:
   15295       v8::V8::IgnoreOutOfMemoryException();
   15296       break;
   15297 
   15298     case SetResourceConstraints: {
   15299       static const int K = 1024;
   15300       v8::ResourceConstraints constraints;
   15301       constraints.set_max_young_space_size(256 * K);
   15302       constraints.set_max_old_space_size(4 * K * K);
   15303       v8::SetResourceConstraints(&constraints);
   15304       break;
   15305     }
   15306 
   15307     case SetFatalHandler:
   15308       v8::V8::SetFatalErrorHandler(NULL);
   15309       break;
   15310 
   15311     case SetCounterFunction:
   15312       v8::V8::SetCounterFunction(NULL);
   15313       break;
   15314 
   15315     case SetCreateHistogramFunction:
   15316       v8::V8::SetCreateHistogramFunction(NULL);
   15317       break;
   15318 
   15319     case SetAddHistogramSampleFunction:
   15320       v8::V8::SetAddHistogramSampleFunction(NULL);
   15321       break;
   15322     }
   15323     result_ = true;
   15324   }
   15325 
   15326   bool result() { return result_; }
   15327 
   15328  private:
   15329   TestCase testCase_;
   15330   bool result_;
   15331 };
   15332 
   15333 
   15334 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   15335   InitDefaultIsolateThread thread(testCase);
   15336   thread.Start();
   15337   thread.Join();
   15338   CHECK_EQ(thread.result(), true);
   15339 }
   15340 
   15341 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
   15342   InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
   15343 }
   15344 
   15345 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
   15346   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
   15347 }
   15348 
   15349 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
   15350   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   15351 }
   15352 
   15353 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
   15354   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   15355 }
   15356 
   15357 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
   15358   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   15359 }
   15360 
   15361 TEST(InitializeDefaultIsolateOnSecondaryThread6) {
   15362   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   15363 }
   15364 
   15365 
   15366 TEST(StringCheckMultipleContexts) {
   15367   const char* code =
   15368       "(function() { return \"a\".charAt(0); })()";
   15369 
   15370   {
   15371     // Run the code twice in the first context to initialize the call IC.
   15372     v8::HandleScope scope;
   15373     LocalContext context1;
   15374     ExpectString(code, "a");
   15375     ExpectString(code, "a");
   15376   }
   15377 
   15378   {
   15379     // Change the String.prototype in the second context and check
   15380     // that the right function gets called.
   15381     v8::HandleScope scope;
   15382     LocalContext context2;
   15383     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   15384     ExpectString(code, "not a");
   15385   }
   15386 }
   15387 
   15388 
   15389 TEST(NumberCheckMultipleContexts) {
   15390   const char* code =
   15391       "(function() { return (42).toString(); })()";
   15392 
   15393   {
   15394     // Run the code twice in the first context to initialize the call IC.
   15395     v8::HandleScope scope;
   15396     LocalContext context1;
   15397     ExpectString(code, "42");
   15398     ExpectString(code, "42");
   15399   }
   15400 
   15401   {
   15402     // Change the Number.prototype in the second context and check
   15403     // that the right function gets called.
   15404     v8::HandleScope scope;
   15405     LocalContext context2;
   15406     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   15407     ExpectString(code, "not 42");
   15408   }
   15409 }
   15410 
   15411 
   15412 TEST(BooleanCheckMultipleContexts) {
   15413   const char* code =
   15414       "(function() { return true.toString(); })()";
   15415 
   15416   {
   15417     // Run the code twice in the first context to initialize the call IC.
   15418     v8::HandleScope scope;
   15419     LocalContext context1;
   15420     ExpectString(code, "true");
   15421     ExpectString(code, "true");
   15422   }
   15423 
   15424   {
   15425     // Change the Boolean.prototype in the second context and check
   15426     // that the right function gets called.
   15427     v8::HandleScope scope;
   15428     LocalContext context2;
   15429     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   15430     ExpectString(code, "");
   15431   }
   15432 }
   15433 
   15434 
   15435 TEST(DontDeleteCellLoadIC) {
   15436   const char* function_code =
   15437       "function readCell() { while (true) { return cell; } }";
   15438 
   15439   {
   15440     // Run the code twice in the first context to initialize the load
   15441     // IC for a don't delete cell.
   15442     v8::HandleScope scope;
   15443     LocalContext context1;
   15444     CompileRun("var cell = \"first\";");
   15445     ExpectBoolean("delete cell", false);
   15446     CompileRun(function_code);
   15447     ExpectString("readCell()", "first");
   15448     ExpectString("readCell()", "first");
   15449   }
   15450 
   15451   {
   15452     // Use a deletable cell in the second context.
   15453     v8::HandleScope scope;
   15454     LocalContext context2;
   15455     CompileRun("cell = \"second\";");
   15456     CompileRun(function_code);
   15457     ExpectString("readCell()", "second");
   15458     ExpectBoolean("delete cell", true);
   15459     ExpectString("(function() {"
   15460                  "  try {"
   15461                  "    return readCell();"
   15462                  "  } catch(e) {"
   15463                  "    return e.toString();"
   15464                  "  }"
   15465                  "})()",
   15466                  "ReferenceError: cell is not defined");
   15467     CompileRun("cell = \"new_second\";");
   15468     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   15469     ExpectString("readCell()", "new_second");
   15470     ExpectString("readCell()", "new_second");
   15471   }
   15472 }
   15473 
   15474 
   15475 TEST(DontDeleteCellLoadICForceDelete) {
   15476   const char* function_code =
   15477       "function readCell() { while (true) { return cell; } }";
   15478 
   15479   // Run the code twice to initialize the load IC for a don't delete
   15480   // cell.
   15481   v8::HandleScope scope;
   15482   LocalContext context;
   15483   CompileRun("var cell = \"value\";");
   15484   ExpectBoolean("delete cell", false);
   15485   CompileRun(function_code);
   15486   ExpectString("readCell()", "value");
   15487   ExpectString("readCell()", "value");
   15488 
   15489   // Delete the cell using the API and check the inlined code works
   15490   // correctly.
   15491   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   15492   ExpectString("(function() {"
   15493                "  try {"
   15494                "    return readCell();"
   15495                "  } catch(e) {"
   15496                "    return e.toString();"
   15497                "  }"
   15498                "})()",
   15499                "ReferenceError: cell is not defined");
   15500 }
   15501 
   15502 
   15503 TEST(DontDeleteCellLoadICAPI) {
   15504   const char* function_code =
   15505       "function readCell() { while (true) { return cell; } }";
   15506 
   15507   // Run the code twice to initialize the load IC for a don't delete
   15508   // cell created using the API.
   15509   v8::HandleScope scope;
   15510   LocalContext context;
   15511   context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
   15512   ExpectBoolean("delete cell", false);
   15513   CompileRun(function_code);
   15514   ExpectString("readCell()", "value");
   15515   ExpectString("readCell()", "value");
   15516 
   15517   // Delete the cell using the API and check the inlined code works
   15518   // correctly.
   15519   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   15520   ExpectString("(function() {"
   15521                "  try {"
   15522                "    return readCell();"
   15523                "  } catch(e) {"
   15524                "    return e.toString();"
   15525                "  }"
   15526                "})()",
   15527                "ReferenceError: cell is not defined");
   15528 }
   15529 
   15530 
   15531 TEST(RegExp) {
   15532   v8::HandleScope scope;
   15533   LocalContext context;
   15534 
   15535   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
   15536   CHECK(re->IsRegExp());
   15537   CHECK(re->GetSource()->Equals(v8_str("foo")));
   15538   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   15539 
   15540   re = v8::RegExp::New(v8_str("bar"),
   15541                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   15542                                                       v8::RegExp::kGlobal));
   15543   CHECK(re->IsRegExp());
   15544   CHECK(re->GetSource()->Equals(v8_str("bar")));
   15545   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   15546            static_cast<int>(re->GetFlags()));
   15547 
   15548   re = v8::RegExp::New(v8_str("baz"),
   15549                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   15550                                                       v8::RegExp::kMultiline));
   15551   CHECK(re->IsRegExp());
   15552   CHECK(re->GetSource()->Equals(v8_str("baz")));
   15553   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   15554            static_cast<int>(re->GetFlags()));
   15555 
   15556   re = CompileRun("/quux/").As<v8::RegExp>();
   15557   CHECK(re->IsRegExp());
   15558   CHECK(re->GetSource()->Equals(v8_str("quux")));
   15559   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   15560 
   15561   re = CompileRun("/quux/gm").As<v8::RegExp>();
   15562   CHECK(re->IsRegExp());
   15563   CHECK(re->GetSource()->Equals(v8_str("quux")));
   15564   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   15565            static_cast<int>(re->GetFlags()));
   15566 
   15567   // Override the RegExp constructor and check the API constructor
   15568   // still works.
   15569   CompileRun("RegExp = function() {}");
   15570 
   15571   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
   15572   CHECK(re->IsRegExp());
   15573   CHECK(re->GetSource()->Equals(v8_str("foobar")));
   15574   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   15575 
   15576   re = v8::RegExp::New(v8_str("foobarbaz"),
   15577                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   15578                                                       v8::RegExp::kMultiline));
   15579   CHECK(re->IsRegExp());
   15580   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
   15581   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   15582            static_cast<int>(re->GetFlags()));
   15583 
   15584   context->Global()->Set(v8_str("re"), re);
   15585   ExpectTrue("re.test('FoobarbaZ')");
   15586 
   15587   // RegExps are objects on which you can set properties.
   15588   re->Set(v8_str("property"), v8::Integer::New(32));
   15589   v8::Handle<v8::Value> value(CompileRun("re.property"));
   15590   CHECK_EQ(32, value->Int32Value());
   15591 
   15592   v8::TryCatch try_catch;
   15593   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
   15594   CHECK(re.IsEmpty());
   15595   CHECK(try_catch.HasCaught());
   15596   context->Global()->Set(v8_str("ex"), try_catch.Exception());
   15597   ExpectTrue("ex instanceof SyntaxError");
   15598 }
   15599 
   15600 
   15601 THREADED_TEST(Equals) {
   15602   v8::HandleScope handleScope;
   15603   LocalContext localContext;
   15604 
   15605   v8::Handle<v8::Object> globalProxy = localContext->Global();
   15606   v8::Handle<Value> global = globalProxy->GetPrototype();
   15607 
   15608   CHECK(global->StrictEquals(global));
   15609   CHECK(!global->StrictEquals(globalProxy));
   15610   CHECK(!globalProxy->StrictEquals(global));
   15611   CHECK(globalProxy->StrictEquals(globalProxy));
   15612 
   15613   CHECK(global->Equals(global));
   15614   CHECK(!global->Equals(globalProxy));
   15615   CHECK(!globalProxy->Equals(global));
   15616   CHECK(globalProxy->Equals(globalProxy));
   15617 }
   15618 
   15619 
   15620 static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
   15621                                     const v8::AccessorInfo& info ) {
   15622   return v8_str("42!");
   15623 }
   15624 
   15625 
   15626 static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo& info) {
   15627   v8::Handle<v8::Array> result = v8::Array::New();
   15628   result->Set(0, v8_str("universalAnswer"));
   15629   return result;
   15630 }
   15631 
   15632 
   15633 TEST(NamedEnumeratorAndForIn) {
   15634   v8::HandleScope handle_scope;
   15635   LocalContext context;
   15636   v8::Context::Scope context_scope(context.local());
   15637 
   15638   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
   15639   tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
   15640   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
   15641   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   15642         "var result = []; for (var k in o) result.push(k); result"));
   15643   CHECK_EQ(1, result->Length());
   15644   CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
   15645 }
   15646 
   15647 
   15648 TEST(DefinePropertyPostDetach) {
   15649   v8::HandleScope scope;
   15650   LocalContext context;
   15651   v8::Handle<v8::Object> proxy = context->Global();
   15652   v8::Handle<v8::Function> define_property =
   15653       CompileRun("(function() {"
   15654                  "  Object.defineProperty("
   15655                  "    this,"
   15656                  "    1,"
   15657                  "    { configurable: true, enumerable: true, value: 3 });"
   15658                  "})").As<Function>();
   15659   context->DetachGlobal();
   15660   define_property->Call(proxy, 0, NULL);
   15661 }
   15662 
   15663 
   15664 static void InstallContextId(v8::Handle<Context> context, int id) {
   15665   Context::Scope scope(context);
   15666   CompileRun("Object.prototype").As<Object>()->
   15667       Set(v8_str("context_id"), v8::Integer::New(id));
   15668 }
   15669 
   15670 
   15671 static void CheckContextId(v8::Handle<Object> object, int expected) {
   15672   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
   15673 }
   15674 
   15675 
   15676 THREADED_TEST(CreationContext) {
   15677   HandleScope handle_scope;
   15678   Persistent<Context> context1 = Context::New();
   15679   InstallContextId(context1, 1);
   15680   Persistent<Context> context2 = Context::New();
   15681   InstallContextId(context2, 2);
   15682   Persistent<Context> context3 = Context::New();
   15683   InstallContextId(context3, 3);
   15684 
   15685   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
   15686 
   15687   Local<Object> object1;
   15688   Local<Function> func1;
   15689   {
   15690     Context::Scope scope(context1);
   15691     object1 = Object::New();
   15692     func1 = tmpl->GetFunction();
   15693   }
   15694 
   15695   Local<Object> object2;
   15696   Local<Function> func2;
   15697   {
   15698     Context::Scope scope(context2);
   15699     object2 = Object::New();
   15700     func2 = tmpl->GetFunction();
   15701   }
   15702 
   15703   Local<Object> instance1;
   15704   Local<Object> instance2;
   15705 
   15706   {
   15707     Context::Scope scope(context3);
   15708     instance1 = func1->NewInstance();
   15709     instance2 = func2->NewInstance();
   15710   }
   15711 
   15712   CHECK(object1->CreationContext() == context1);
   15713   CheckContextId(object1, 1);
   15714   CHECK(func1->CreationContext() == context1);
   15715   CheckContextId(func1, 1);
   15716   CHECK(instance1->CreationContext() == context1);
   15717   CheckContextId(instance1, 1);
   15718   CHECK(object2->CreationContext() == context2);
   15719   CheckContextId(object2, 2);
   15720   CHECK(func2->CreationContext() == context2);
   15721   CheckContextId(func2, 2);
   15722   CHECK(instance2->CreationContext() == context2);
   15723   CheckContextId(instance2, 2);
   15724 
   15725   {
   15726     Context::Scope scope(context1);
   15727     CHECK(object1->CreationContext() == context1);
   15728     CheckContextId(object1, 1);
   15729     CHECK(func1->CreationContext() == context1);
   15730     CheckContextId(func1, 1);
   15731     CHECK(instance1->CreationContext() == context1);
   15732     CheckContextId(instance1, 1);
   15733     CHECK(object2->CreationContext() == context2);
   15734     CheckContextId(object2, 2);
   15735     CHECK(func2->CreationContext() == context2);
   15736     CheckContextId(func2, 2);
   15737     CHECK(instance2->CreationContext() == context2);
   15738     CheckContextId(instance2, 2);
   15739   }
   15740 
   15741   {
   15742     Context::Scope scope(context2);
   15743     CHECK(object1->CreationContext() == context1);
   15744     CheckContextId(object1, 1);
   15745     CHECK(func1->CreationContext() == context1);
   15746     CheckContextId(func1, 1);
   15747     CHECK(instance1->CreationContext() == context1);
   15748     CheckContextId(instance1, 1);
   15749     CHECK(object2->CreationContext() == context2);
   15750     CheckContextId(object2, 2);
   15751     CHECK(func2->CreationContext() == context2);
   15752     CheckContextId(func2, 2);
   15753     CHECK(instance2->CreationContext() == context2);
   15754     CheckContextId(instance2, 2);
   15755   }
   15756 
   15757   context1.Dispose();
   15758   context2.Dispose();
   15759   context3.Dispose();
   15760 }
   15761 
   15762 
   15763 THREADED_TEST(CreationContextOfJsFunction) {
   15764   HandleScope handle_scope;
   15765   Persistent<Context> context = Context::New();
   15766   InstallContextId(context, 1);
   15767 
   15768   Local<Object> function;
   15769   {
   15770     Context::Scope scope(context);
   15771     function = CompileRun("function foo() {}; foo").As<Object>();
   15772   }
   15773 
   15774   CHECK(function->CreationContext() == context);
   15775   CheckContextId(function, 1);
   15776 
   15777   context.Dispose();
   15778 }
   15779 
   15780 
   15781 Handle<Value> HasOwnPropertyIndexedPropertyGetter(uint32_t index,
   15782                                                   const AccessorInfo& info) {
   15783   if (index == 42) return v8_str("yes");
   15784   return Handle<v8::Integer>();
   15785 }
   15786 
   15787 
   15788 Handle<Value> HasOwnPropertyNamedPropertyGetter(Local<String> property,
   15789                                                 const AccessorInfo& info) {
   15790   if (property->Equals(v8_str("foo"))) return v8_str("yes");
   15791   return Handle<Value>();
   15792 }
   15793 
   15794 
   15795 Handle<v8::Integer> HasOwnPropertyIndexedPropertyQuery(
   15796     uint32_t index, const AccessorInfo& info) {
   15797   if (index == 42) return v8_num(1).As<v8::Integer>();
   15798   return Handle<v8::Integer>();
   15799 }
   15800 
   15801 
   15802 Handle<v8::Integer> HasOwnPropertyNamedPropertyQuery(
   15803     Local<String> property, const AccessorInfo& info) {
   15804   if (property->Equals(v8_str("foo"))) return v8_num(1).As<v8::Integer>();
   15805   return Handle<v8::Integer>();
   15806 }
   15807 
   15808 
   15809 Handle<v8::Integer> HasOwnPropertyNamedPropertyQuery2(
   15810     Local<String> property, const AccessorInfo& info) {
   15811   if (property->Equals(v8_str("bar"))) return v8_num(1).As<v8::Integer>();
   15812   return Handle<v8::Integer>();
   15813 }
   15814 
   15815 
   15816 Handle<Value> HasOwnPropertyAccessorGetter(Local<String> property,
   15817                                            const AccessorInfo& info) {
   15818   return v8_str("yes");
   15819 }
   15820 
   15821 
   15822 TEST(HasOwnProperty) {
   15823   v8::HandleScope scope;
   15824   LocalContext env;
   15825   { // Check normal properties and defined getters.
   15826     Handle<Value> value = CompileRun(
   15827         "function Foo() {"
   15828         "    this.foo = 11;"
   15829         "    this.__defineGetter__('baz', function() { return 1; });"
   15830         "};"
   15831         "function Bar() { "
   15832         "    this.bar = 13;"
   15833         "    this.__defineGetter__('bla', function() { return 2; });"
   15834         "};"
   15835         "Bar.prototype = new Foo();"
   15836         "new Bar();");
   15837     CHECK(value->IsObject());
   15838     Handle<Object> object = value->ToObject();
   15839     CHECK(object->Has(v8_str("foo")));
   15840     CHECK(!object->HasOwnProperty(v8_str("foo")));
   15841     CHECK(object->HasOwnProperty(v8_str("bar")));
   15842     CHECK(object->Has(v8_str("baz")));
   15843     CHECK(!object->HasOwnProperty(v8_str("baz")));
   15844     CHECK(object->HasOwnProperty(v8_str("bla")));
   15845   }
   15846   { // Check named getter interceptors.
   15847     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   15848     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
   15849     Handle<Object> instance = templ->NewInstance();
   15850     CHECK(!instance->HasOwnProperty(v8_str("42")));
   15851     CHECK(instance->HasOwnProperty(v8_str("foo")));
   15852     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   15853   }
   15854   { // Check indexed getter interceptors.
   15855     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   15856     templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
   15857     Handle<Object> instance = templ->NewInstance();
   15858     CHECK(instance->HasOwnProperty(v8_str("42")));
   15859     CHECK(!instance->HasOwnProperty(v8_str("43")));
   15860     CHECK(!instance->HasOwnProperty(v8_str("foo")));
   15861   }
   15862   { // Check named query interceptors.
   15863     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   15864     templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
   15865     Handle<Object> instance = templ->NewInstance();
   15866     CHECK(instance->HasOwnProperty(v8_str("foo")));
   15867     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   15868   }
   15869   { // Check indexed query interceptors.
   15870     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   15871     templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
   15872     Handle<Object> instance = templ->NewInstance();
   15873     CHECK(instance->HasOwnProperty(v8_str("42")));
   15874     CHECK(!instance->HasOwnProperty(v8_str("41")));
   15875   }
   15876   { // Check callbacks.
   15877     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   15878     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   15879     Handle<Object> instance = templ->NewInstance();
   15880     CHECK(instance->HasOwnProperty(v8_str("foo")));
   15881     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   15882   }
   15883   { // Check that query wins on disagreement.
   15884     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   15885     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
   15886                                    0,
   15887                                    HasOwnPropertyNamedPropertyQuery2);
   15888     Handle<Object> instance = templ->NewInstance();
   15889     CHECK(!instance->HasOwnProperty(v8_str("foo")));
   15890     CHECK(instance->HasOwnProperty(v8_str("bar")));
   15891   }
   15892 }
   15893 
   15894 
   15895 void CheckCodeGenerationAllowed() {
   15896   Handle<Value> result = CompileRun("eval('42')");
   15897   CHECK_EQ(42, result->Int32Value());
   15898   result = CompileRun("(function(e) { return e('42'); })(eval)");
   15899   CHECK_EQ(42, result->Int32Value());
   15900   result = CompileRun("var f = new Function('return 42'); f()");
   15901   CHECK_EQ(42, result->Int32Value());
   15902 }
   15903 
   15904 
   15905 void CheckCodeGenerationDisallowed() {
   15906   TryCatch try_catch;
   15907 
   15908   Handle<Value> result = CompileRun("eval('42')");
   15909   CHECK(result.IsEmpty());
   15910   CHECK(try_catch.HasCaught());
   15911   try_catch.Reset();
   15912 
   15913   result = CompileRun("(function(e) { return e('42'); })(eval)");
   15914   CHECK(result.IsEmpty());
   15915   CHECK(try_catch.HasCaught());
   15916   try_catch.Reset();
   15917 
   15918   result = CompileRun("var f = new Function('return 42'); f()");
   15919   CHECK(result.IsEmpty());
   15920   CHECK(try_catch.HasCaught());
   15921 }
   15922 
   15923 
   15924 bool CodeGenerationAllowed(Local<Context> context) {
   15925   ApiTestFuzzer::Fuzz();
   15926   return true;
   15927 }
   15928 
   15929 
   15930 bool CodeGenerationDisallowed(Local<Context> context) {
   15931   ApiTestFuzzer::Fuzz();
   15932   return false;
   15933 }
   15934 
   15935 
   15936 THREADED_TEST(AllowCodeGenFromStrings) {
   15937   v8::HandleScope scope;
   15938   LocalContext context;
   15939 
   15940   // eval and the Function constructor allowed by default.
   15941   CHECK(context->IsCodeGenerationFromStringsAllowed());
   15942   CheckCodeGenerationAllowed();
   15943 
   15944   // Disallow eval and the Function constructor.
   15945   context->AllowCodeGenerationFromStrings(false);
   15946   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   15947   CheckCodeGenerationDisallowed();
   15948 
   15949   // Allow again.
   15950   context->AllowCodeGenerationFromStrings(true);
   15951   CheckCodeGenerationAllowed();
   15952 
   15953   // Disallow but setting a global callback that will allow the calls.
   15954   context->AllowCodeGenerationFromStrings(false);
   15955   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
   15956   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   15957   CheckCodeGenerationAllowed();
   15958 
   15959   // Set a callback that disallows the code generation.
   15960   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
   15961   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   15962   CheckCodeGenerationDisallowed();
   15963 }
   15964 
   15965 
   15966 static v8::Handle<Value> NonObjectThis(const v8::Arguments& args) {
   15967   return v8::Undefined();
   15968 }
   15969 
   15970 
   15971 THREADED_TEST(CallAPIFunctionOnNonObject) {
   15972   v8::HandleScope scope;
   15973   LocalContext context;
   15974   Handle<FunctionTemplate> templ = v8::FunctionTemplate::New(NonObjectThis);
   15975   Handle<Function> function = templ->GetFunction();
   15976   context->Global()->Set(v8_str("f"), function);
   15977   TryCatch try_catch;
   15978   CompileRun("f.call(2)");
   15979 }
   15980 
   15981 
   15982 // Regression test for issue 1470.
   15983 THREADED_TEST(ReadOnlyIndexedProperties) {
   15984   v8::HandleScope scope;
   15985   Local<ObjectTemplate> templ = ObjectTemplate::New();
   15986 
   15987   LocalContext context;
   15988   Local<v8::Object> obj = templ->NewInstance();
   15989   context->Global()->Set(v8_str("obj"), obj);
   15990   obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
   15991   obj->Set(v8_str("1"), v8_str("foobar"));
   15992   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
   15993   obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
   15994   obj->Set(v8_num(2), v8_str("foobar"));
   15995   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
   15996 
   15997   // Test non-smi case.
   15998   obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
   15999   obj->Set(v8_str("2000000000"), v8_str("foobar"));
   16000   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
   16001 }
   16002 
   16003 
   16004 THREADED_TEST(Regress1516) {
   16005   v8::HandleScope scope;
   16006 
   16007   LocalContext context;
   16008   { v8::HandleScope temp_scope;
   16009     CompileRun("({'a': 0})");
   16010   }
   16011 
   16012   int elements;
   16013   { i::MapCache* map_cache =
   16014         i::MapCache::cast(i::Isolate::Current()->context()->map_cache());
   16015     elements = map_cache->NumberOfElements();
   16016     CHECK_LE(1, elements);
   16017   }
   16018 
   16019   i::Isolate::Current()->heap()->CollectAllGarbage(true);
   16020   { i::Object* raw_map_cache = i::Isolate::Current()->context()->map_cache();
   16021     if (raw_map_cache != i::Isolate::Current()->heap()->undefined_value()) {
   16022       i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
   16023       CHECK_GT(elements, map_cache->NumberOfElements());
   16024     }
   16025   }
   16026 }
   16027 
   16028 
   16029 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
   16030                                                 Local<Value> name,
   16031                                                 v8::AccessType type,
   16032                                                 Local<Value> data) {
   16033   // Only block read access to __proto__.
   16034   if (type == v8::ACCESS_GET &&
   16035       name->IsString() &&
   16036       name->ToString()->Length() == 9 &&
   16037       name->ToString()->Utf8Length() == 9) {
   16038     char buffer[10];
   16039     CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
   16040     return strncmp(buffer, "__proto__", 9) != 0;
   16041   }
   16042 
   16043   return true;
   16044 }
   16045 
   16046 
   16047 THREADED_TEST(Regress93759) {
   16048   HandleScope scope;
   16049 
   16050   // Template for object with security check.
   16051   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New();
   16052   // We don't do indexing, so any callback can be used for that.
   16053   no_proto_template->SetAccessCheckCallbacks(
   16054       BlockProtoNamedSecurityTestCallback,
   16055       IndexedSecurityTestCallback);
   16056 
   16057   // Templates for objects with hidden prototypes and possibly security check.
   16058   Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New();
   16059   hidden_proto_template->SetHiddenPrototype(true);
   16060 
   16061   Local<FunctionTemplate> protected_hidden_proto_template =
   16062       v8::FunctionTemplate::New();
   16063   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
   16064       BlockProtoNamedSecurityTestCallback,
   16065       IndexedSecurityTestCallback);
   16066   protected_hidden_proto_template->SetHiddenPrototype(true);
   16067 
   16068   // Context for "foreign" objects used in test.
   16069   Persistent<Context> context = v8::Context::New();
   16070   context->Enter();
   16071 
   16072   // Plain object, no security check.
   16073   Local<Object> simple_object = Object::New();
   16074 
   16075   // Object with explicit security check.
   16076   Local<Object> protected_object =
   16077       no_proto_template->NewInstance();
   16078 
   16079   // JSGlobalProxy object, always have security check.
   16080   Local<Object> proxy_object =
   16081       context->Global();
   16082 
   16083   // Global object, the  prototype of proxy_object. No security checks.
   16084   Local<Object> global_object =
   16085       proxy_object->GetPrototype()->ToObject();
   16086 
   16087   // Hidden prototype without security check.
   16088   Local<Object> hidden_prototype =
   16089       hidden_proto_template->GetFunction()->NewInstance();
   16090   Local<Object> object_with_hidden =
   16091     Object::New();
   16092   object_with_hidden->SetPrototype(hidden_prototype);
   16093 
   16094   // Hidden prototype with security check on the hidden prototype.
   16095   Local<Object> protected_hidden_prototype =
   16096       protected_hidden_proto_template->GetFunction()->NewInstance();
   16097   Local<Object> object_with_protected_hidden =
   16098     Object::New();
   16099   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
   16100 
   16101   context->Exit();
   16102 
   16103   // Template for object for second context. Values to test are put on it as
   16104   // properties.
   16105   Local<ObjectTemplate> global_template = ObjectTemplate::New();
   16106   global_template->Set(v8_str("simple"), simple_object);
   16107   global_template->Set(v8_str("protected"), protected_object);
   16108   global_template->Set(v8_str("global"), global_object);
   16109   global_template->Set(v8_str("proxy"), proxy_object);
   16110   global_template->Set(v8_str("hidden"), object_with_hidden);
   16111   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
   16112 
   16113   LocalContext context2(NULL, global_template);
   16114 
   16115   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   16116   CHECK(result1->Equals(simple_object->GetPrototype()));
   16117 
   16118   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
   16119   CHECK(result2->Equals(Undefined()));
   16120 
   16121   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
   16122   CHECK(result3->Equals(global_object->GetPrototype()));
   16123 
   16124   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
   16125   CHECK(result4->Equals(Undefined()));
   16126 
   16127   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
   16128   CHECK(result5->Equals(
   16129       object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
   16130 
   16131   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
   16132   CHECK(result6->Equals(Undefined()));
   16133 
   16134   context.Dispose();
   16135 }
   16136 
   16137 
   16138 THREADED_TEST(Regress125988) {
   16139   v8::HandleScope scope;
   16140   Handle<FunctionTemplate> intercept = FunctionTemplate::New();
   16141   AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
   16142   LocalContext env;
   16143   env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
   16144   CompileRun("var a = new Object();"
   16145              "var b = new Intercept();"
   16146              "var c = new Object();"
   16147              "c.__proto__ = b;"
   16148              "b.__proto__ = a;"
   16149              "a.x = 23;"
   16150              "for (var i = 0; i < 3; i++) c.x;");
   16151   ExpectBoolean("c.hasOwnProperty('x')", false);
   16152   ExpectInt32("c.x", 23);
   16153   CompileRun("a.y = 42;"
   16154              "for (var i = 0; i < 3; i++) c.x;");
   16155   ExpectBoolean("c.hasOwnProperty('x')", false);
   16156   ExpectInt32("c.x", 23);
   16157   ExpectBoolean("c.hasOwnProperty('y')", false);
   16158   ExpectInt32("c.y", 42);
   16159 }
   16160 
   16161 
   16162 static void TestReceiver(Local<Value> expected_result,
   16163                          Local<Value> expected_receiver,
   16164                          const char* code) {
   16165   Local<Value> result = CompileRun(code);
   16166   CHECK(result->IsObject());
   16167   CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
   16168   CHECK(expected_result->Equals(result->ToObject()->Get(0)));
   16169 }
   16170 
   16171 
   16172 THREADED_TEST(ForeignFunctionReceiver) {
   16173   HandleScope scope;
   16174 
   16175   // Create two contexts with different "id" properties ('i' and 'o').
   16176   // Call a function both from its own context and from a the foreign
   16177   // context, and see what "this" is bound to (returning both "this"
   16178   // and "this.id" for comparison).
   16179 
   16180   Persistent<Context> foreign_context = v8::Context::New();
   16181   foreign_context->Enter();
   16182   Local<Value> foreign_function =
   16183     CompileRun("function func() { return { 0: this.id, "
   16184                "                           1: this, "
   16185                "                           toString: function() { "
   16186                "                               return this[0];"
   16187                "                           }"
   16188                "                         };"
   16189                "}"
   16190                "var id = 'i';"
   16191                "func;");
   16192   CHECK(foreign_function->IsFunction());
   16193   foreign_context->Exit();
   16194 
   16195   LocalContext context;
   16196 
   16197   Local<String> password = v8_str("Password");
   16198   // Don't get hit by security checks when accessing foreign_context's
   16199   // global receiver (aka. global proxy).
   16200   context->SetSecurityToken(password);
   16201   foreign_context->SetSecurityToken(password);
   16202 
   16203   Local<String> i = v8_str("i");
   16204   Local<String> o = v8_str("o");
   16205   Local<String> id = v8_str("id");
   16206 
   16207   CompileRun("function ownfunc() { return { 0: this.id, "
   16208              "                              1: this, "
   16209              "                              toString: function() { "
   16210              "                                  return this[0];"
   16211              "                              }"
   16212              "                             };"
   16213              "}"
   16214              "var id = 'o';"
   16215              "ownfunc");
   16216   context->Global()->Set(v8_str("func"), foreign_function);
   16217 
   16218   // Sanity check the contexts.
   16219   CHECK(i->Equals(foreign_context->Global()->Get(id)));
   16220   CHECK(o->Equals(context->Global()->Get(id)));
   16221 
   16222   // Checking local function's receiver.
   16223   // Calling function using its call/apply methods.
   16224   TestReceiver(o, context->Global(), "ownfunc.call()");
   16225   TestReceiver(o, context->Global(), "ownfunc.apply()");
   16226   // Making calls through built-in functions.
   16227   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   16228   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
   16229   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
   16230   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
   16231   // Calling with environment record as base.
   16232   TestReceiver(o, context->Global(), "ownfunc()");
   16233   // Calling with no base.
   16234   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   16235 
   16236   // Checking foreign function return value.
   16237   // Calling function using its call/apply methods.
   16238   TestReceiver(i, foreign_context->Global(), "func.call()");
   16239   TestReceiver(i, foreign_context->Global(), "func.apply()");
   16240   // Calling function using another context's call/apply methods.
   16241   TestReceiver(i, foreign_context->Global(),
   16242                "Function.prototype.call.call(func)");
   16243   TestReceiver(i, foreign_context->Global(),
   16244                "Function.prototype.call.apply(func)");
   16245   TestReceiver(i, foreign_context->Global(),
   16246                "Function.prototype.apply.call(func)");
   16247   TestReceiver(i, foreign_context->Global(),
   16248                "Function.prototype.apply.apply(func)");
   16249   // Making calls through built-in functions.
   16250   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   16251   // ToString(func()) is func()[0], i.e., the returned this.id.
   16252   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
   16253   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
   16254   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
   16255 
   16256   // TODO(1547): Make the following also return "i".
   16257   // Calling with environment record as base.
   16258   TestReceiver(o, context->Global(), "func()");
   16259   // Calling with no base.
   16260   TestReceiver(o, context->Global(), "(1,func)()");
   16261 
   16262   foreign_context.Dispose();
   16263 }
   16264 
   16265 
   16266 uint8_t callback_fired = 0;
   16267 
   16268 
   16269 void CallCompletedCallback1() {
   16270   i::OS::Print("Firing callback 1.\n");
   16271   callback_fired ^= 1;  // Toggle first bit.
   16272 }
   16273 
   16274 
   16275 void CallCompletedCallback2() {
   16276   i::OS::Print("Firing callback 2.\n");
   16277   callback_fired ^= 2;  // Toggle second bit.
   16278 }
   16279 
   16280 
   16281 Handle<Value> RecursiveCall(const Arguments& args) {
   16282   int32_t level = args[0]->Int32Value();
   16283   if (level < 3) {
   16284     level++;
   16285     i::OS::Print("Entering recursion level %d.\n", level);
   16286     char script[64];
   16287     i::Vector<char> script_vector(script, sizeof(script));
   16288     i::OS::SNPrintF(script_vector, "recursion(%d)", level);
   16289     CompileRun(script_vector.start());
   16290     i::OS::Print("Leaving recursion level %d.\n", level);
   16291     CHECK_EQ(0, callback_fired);
   16292   } else {
   16293     i::OS::Print("Recursion ends.\n");
   16294     CHECK_EQ(0, callback_fired);
   16295   }
   16296   return Undefined();
   16297 }
   16298 
   16299 
   16300 TEST(CallCompletedCallback) {
   16301   v8::HandleScope scope;
   16302   LocalContext env;
   16303   v8::Handle<v8::FunctionTemplate> recursive_runtime =
   16304       v8::FunctionTemplate::New(RecursiveCall);
   16305   env->Global()->Set(v8_str("recursion"),
   16306                      recursive_runtime->GetFunction());
   16307   // Adding the same callback a second time has no effect.
   16308   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
   16309   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
   16310   v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
   16311   i::OS::Print("--- Script (1) ---\n");
   16312   Local<Script> script =
   16313       v8::Script::Compile(v8::String::New("recursion(0)"));
   16314   script->Run();
   16315   CHECK_EQ(3, callback_fired);
   16316 
   16317   i::OS::Print("\n--- Script (2) ---\n");
   16318   callback_fired = 0;
   16319   v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
   16320   script->Run();
   16321   CHECK_EQ(2, callback_fired);
   16322 
   16323   i::OS::Print("\n--- Function ---\n");
   16324   callback_fired = 0;
   16325   Local<Function> recursive_function =
   16326       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
   16327   v8::Handle<Value> args[] = { v8_num(0) };
   16328   recursive_function->Call(env->Global(), 1, args);
   16329   CHECK_EQ(2, callback_fired);
   16330 }
   16331 
   16332 
   16333 void CallCompletedCallbackNoException() {
   16334   v8::HandleScope scope;
   16335   CompileRun("1+1;");
   16336 }
   16337 
   16338 
   16339 void CallCompletedCallbackException() {
   16340   v8::HandleScope scope;
   16341   CompileRun("throw 'second exception';");
   16342 }
   16343 
   16344 
   16345 TEST(CallCompletedCallbackOneException) {
   16346   v8::HandleScope scope;
   16347   LocalContext env;
   16348   v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
   16349   CompileRun("throw 'exception';");
   16350 }
   16351 
   16352 
   16353 TEST(CallCompletedCallbackTwoExceptions) {
   16354   v8::HandleScope scope;
   16355   LocalContext env;
   16356   v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
   16357   CompileRun("throw 'first exception';");
   16358 }
   16359 
   16360 
   16361 static int probes_counter = 0;
   16362 static int misses_counter = 0;
   16363 static int updates_counter = 0;
   16364 
   16365 
   16366 static int* LookupCounter(const char* name) {
   16367   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
   16368     return &probes_counter;
   16369   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
   16370     return &misses_counter;
   16371   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
   16372     return &updates_counter;
   16373   }
   16374   return NULL;
   16375 }
   16376 
   16377 
   16378 static const char* kMegamorphicTestProgram =
   16379     "function ClassA() { };"
   16380     "function ClassB() { };"
   16381     "ClassA.prototype.foo = function() { };"
   16382     "ClassB.prototype.foo = function() { };"
   16383     "function fooify(obj) { obj.foo(); };"
   16384     "var a = new ClassA();"
   16385     "var b = new ClassB();"
   16386     "for (var i = 0; i < 10000; i++) {"
   16387     "  fooify(a);"
   16388     "  fooify(b);"
   16389     "}";
   16390 
   16391 
   16392 static void StubCacheHelper(bool primary) {
   16393   V8::SetCounterFunction(LookupCounter);
   16394   USE(kMegamorphicTestProgram);
   16395 #ifdef DEBUG
   16396   i::FLAG_native_code_counters = true;
   16397   if (primary) {
   16398     i::FLAG_test_primary_stub_cache = true;
   16399   } else {
   16400     i::FLAG_test_secondary_stub_cache = true;
   16401   }
   16402   i::FLAG_crankshaft = false;
   16403   v8::HandleScope scope;
   16404   LocalContext env;
   16405   int initial_probes = probes_counter;
   16406   int initial_misses = misses_counter;
   16407   int initial_updates = updates_counter;
   16408   CompileRun(kMegamorphicTestProgram);
   16409   int probes = probes_counter - initial_probes;
   16410   int misses = misses_counter - initial_misses;
   16411   int updates = updates_counter - initial_updates;
   16412   CHECK_LT(updates, 10);
   16413   CHECK_LT(misses, 10);
   16414   CHECK_GE(probes, 10000);
   16415 #endif
   16416 }
   16417 
   16418 
   16419 TEST(SecondaryStubCache) {
   16420   StubCacheHelper(true);
   16421 }
   16422 
   16423 
   16424 TEST(PrimaryStubCache) {
   16425   StubCacheHelper(false);
   16426 }
   16427 
   16428