v8: back-port fix for CVE-2013-2882
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-api.cc
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 #ifndef WIN32
31 #include <signal.h>  // kill
32 #include <unistd.h>  // getpid
33 #endif  // WIN32
34
35 #include "v8.h"
36
37 #include "api.h"
38 #include "isolate.h"
39 #include "compilation-cache.h"
40 #include "execution.h"
41 #include "objects.h"
42 #include "snapshot.h"
43 #include "platform.h"
44 #include "utils.h"
45 #include "cctest.h"
46 #include "parser.h"
47 #include "unicode-inl.h"
48
49 static const bool kLogThreading = false;
50
51 static bool IsNaN(double x) {
52 #ifdef WIN32
53   return _isnan(x);
54 #else
55   return isnan(x);
56 #endif
57 }
58
59 using ::v8::AccessorInfo;
60 using ::v8::Arguments;
61 using ::v8::Context;
62 using ::v8::Extension;
63 using ::v8::Function;
64 using ::v8::FunctionTemplate;
65 using ::v8::Handle;
66 using ::v8::HandleScope;
67 using ::v8::Local;
68 using ::v8::Message;
69 using ::v8::MessageCallback;
70 using ::v8::Object;
71 using ::v8::ObjectTemplate;
72 using ::v8::Persistent;
73 using ::v8::Script;
74 using ::v8::StackTrace;
75 using ::v8::String;
76 using ::v8::TryCatch;
77 using ::v8::Undefined;
78 using ::v8::V8;
79 using ::v8::Value;
80
81
82 static void ExpectString(const char* code, const char* expected) {
83   Local<Value> result = CompileRun(code);
84   CHECK(result->IsString());
85   String::AsciiValue ascii(result);
86   CHECK_EQ(expected, *ascii);
87 }
88
89 static void ExpectInt32(const char* code, int expected) {
90   Local<Value> result = CompileRun(code);
91   CHECK(result->IsInt32());
92   CHECK_EQ(expected, result->Int32Value());
93 }
94
95 static void ExpectBoolean(const char* code, bool expected) {
96   Local<Value> result = CompileRun(code);
97   CHECK(result->IsBoolean());
98   CHECK_EQ(expected, result->BooleanValue());
99 }
100
101
102 static void ExpectTrue(const char* code) {
103   ExpectBoolean(code, true);
104 }
105
106
107 static void ExpectFalse(const char* code) {
108   ExpectBoolean(code, false);
109 }
110
111
112 static void ExpectObject(const char* code, Local<Value> expected) {
113   Local<Value> result = CompileRun(code);
114   CHECK(result->Equals(expected));
115 }
116
117
118 static void ExpectUndefined(const char* code) {
119   Local<Value> result = CompileRun(code);
120   CHECK(result->IsUndefined());
121 }
122
123
124 static int signature_callback_count;
125 static v8::Handle<Value> IncrementingSignatureCallback(
126     const v8::Arguments& args) {
127   ApiTestFuzzer::Fuzz();
128   signature_callback_count++;
129   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
130   for (int i = 0; i < args.Length(); i++)
131     result->Set(v8::Integer::New(i), args[i]);
132   return result;
133 }
134
135
136 static v8::Handle<Value> SignatureCallback(const v8::Arguments& args) {
137   ApiTestFuzzer::Fuzz();
138   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
139   for (int i = 0; i < args.Length(); i++) {
140     result->Set(v8::Integer::New(i), args[i]);
141   }
142   return result;
143 }
144
145
146 THREADED_TEST(Handles) {
147   v8::HandleScope scope;
148   Local<Context> local_env;
149   {
150     LocalContext env;
151     local_env = env.local();
152   }
153
154   // Local context should still be live.
155   CHECK(!local_env.IsEmpty());
156   local_env->Enter();
157
158   v8::Handle<v8::Primitive> undef = v8::Undefined();
159   CHECK(!undef.IsEmpty());
160   CHECK(undef->IsUndefined());
161
162   const char* c_source = "1 + 2 + 3";
163   Local<String> source = String::New(c_source);
164   Local<Script> script = Script::Compile(source);
165   CHECK_EQ(6, script->Run()->Int32Value());
166
167   local_env->Exit();
168 }
169
170
171 THREADED_TEST(ReceiverSignature) {
172   v8::HandleScope scope;
173   LocalContext env;
174   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
175   v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
176   fun->PrototypeTemplate()->Set(
177       v8_str("m"),
178       v8::FunctionTemplate::New(IncrementingSignatureCallback,
179                                 v8::Handle<Value>(),
180                                 sig));
181   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
182   signature_callback_count = 0;
183   CompileRun(
184       "var o = new Fun();"
185       "o.m();");
186   CHECK_EQ(1, signature_callback_count);
187   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
188   sub_fun->Inherit(fun);
189   env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction());
190   CompileRun(
191       "var o = new SubFun();"
192       "o.m();");
193   CHECK_EQ(2, signature_callback_count);
194
195   v8::TryCatch try_catch;
196   CompileRun(
197       "var o = { };"
198       "o.m = Fun.prototype.m;"
199       "o.m();");
200   CHECK_EQ(2, signature_callback_count);
201   CHECK(try_catch.HasCaught());
202   try_catch.Reset();
203   v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
204   sub_fun->Inherit(fun);
205   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
206   CompileRun(
207       "var o = new UnrelFun();"
208       "o.m = Fun.prototype.m;"
209       "o.m();");
210   CHECK_EQ(2, signature_callback_count);
211   CHECK(try_catch.HasCaught());
212 }
213
214
215 THREADED_TEST(ArgumentSignature) {
216   v8::HandleScope scope;
217   LocalContext env;
218   v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
219   cons->SetClassName(v8_str("Cons"));
220   v8::Handle<v8::Signature> sig =
221       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
222   v8::Handle<v8::FunctionTemplate> fun =
223       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
224   env->Global()->Set(v8_str("Cons"), cons->GetFunction());
225   env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
226
227   v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
228   CHECK(value1->IsTrue());
229
230   v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
231   CHECK(value2->IsTrue());
232
233   v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
234   CHECK(value3->IsTrue());
235
236   v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
237   cons1->SetClassName(v8_str("Cons1"));
238   v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
239   cons2->SetClassName(v8_str("Cons2"));
240   v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
241   cons3->SetClassName(v8_str("Cons3"));
242
243   v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
244   v8::Handle<v8::Signature> wsig =
245       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
246   v8::Handle<v8::FunctionTemplate> fun2 =
247       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
248
249   env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
250   env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
251   env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
252   env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
253   v8::Handle<Value> value4 = CompileRun(
254       "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
255       "'[object Cons1],[object Cons2],[object Cons3]'");
256   CHECK(value4->IsTrue());
257
258   v8::Handle<Value> value5 = CompileRun(
259       "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
260   CHECK(value5->IsTrue());
261
262   v8::Handle<Value> value6 = CompileRun(
263       "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
264   CHECK(value6->IsTrue());
265
266   v8::Handle<Value> value7 = CompileRun(
267       "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
268       "'[object Cons1],[object Cons2],[object Cons3],d';");
269   CHECK(value7->IsTrue());
270
271   v8::Handle<Value> value8 = CompileRun(
272       "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
273   CHECK(value8->IsTrue());
274 }
275
276
277 THREADED_TEST(HulIgennem) {
278   v8::HandleScope scope;
279   LocalContext env;
280   v8::Handle<v8::Primitive> undef = v8::Undefined();
281   Local<String> undef_str = undef->ToString();
282   char* value = i::NewArray<char>(undef_str->Length() + 1);
283   undef_str->WriteAscii(value);
284   CHECK_EQ(0, strcmp(value, "undefined"));
285   i::DeleteArray(value);
286 }
287
288
289 THREADED_TEST(Access) {
290   v8::HandleScope scope;
291   LocalContext env;
292   Local<v8::Object> obj = v8::Object::New();
293   Local<Value> foo_before = obj->Get(v8_str("foo"));
294   CHECK(foo_before->IsUndefined());
295   Local<String> bar_str = v8_str("bar");
296   obj->Set(v8_str("foo"), bar_str);
297   Local<Value> foo_after = obj->Get(v8_str("foo"));
298   CHECK(!foo_after->IsUndefined());
299   CHECK(foo_after->IsString());
300   CHECK_EQ(bar_str, foo_after);
301 }
302
303
304 THREADED_TEST(AccessElement) {
305   v8::HandleScope scope;
306   LocalContext env;
307   Local<v8::Object> obj = v8::Object::New();
308   Local<Value> before = obj->Get(1);
309   CHECK(before->IsUndefined());
310   Local<String> bar_str = v8_str("bar");
311   obj->Set(1, bar_str);
312   Local<Value> after = obj->Get(1);
313   CHECK(!after->IsUndefined());
314   CHECK(after->IsString());
315   CHECK_EQ(bar_str, after);
316
317   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
318   CHECK_EQ(v8_str("a"), value->Get(0));
319   CHECK_EQ(v8_str("b"), value->Get(1));
320 }
321
322
323 THREADED_TEST(Script) {
324   v8::HandleScope scope;
325   LocalContext env;
326   const char* c_source = "1 + 2 + 3";
327   Local<String> source = String::New(c_source);
328   Local<Script> script = Script::Compile(source);
329   CHECK_EQ(6, script->Run()->Int32Value());
330 }
331
332
333 static uint16_t* AsciiToTwoByteString(const char* source) {
334   int array_length = i::StrLength(source) + 1;
335   uint16_t* converted = i::NewArray<uint16_t>(array_length);
336   for (int i = 0; i < array_length; i++) converted[i] = source[i];
337   return converted;
338 }
339
340
341 class TestResource: public String::ExternalStringResource {
342  public:
343   explicit TestResource(uint16_t* data, int* counter = NULL)
344     : data_(data), length_(0), counter_(counter) {
345     while (data[length_]) ++length_;
346   }
347
348   ~TestResource() {
349     i::DeleteArray(data_);
350     if (counter_ != NULL) ++*counter_;
351   }
352
353   const uint16_t* data() const {
354     return data_;
355   }
356
357   size_t length() const {
358     return length_;
359   }
360  private:
361   uint16_t* data_;
362   size_t length_;
363   int* counter_;
364 };
365
366
367 class TestAsciiResource: public String::ExternalAsciiStringResource {
368  public:
369   explicit TestAsciiResource(const char* data, int* counter = NULL)
370     : data_(data), length_(strlen(data)), counter_(counter) { }
371
372   ~TestAsciiResource() {
373     i::DeleteArray(data_);
374     if (counter_ != NULL) ++*counter_;
375   }
376
377   const char* data() const {
378     return data_;
379   }
380
381   size_t length() const {
382     return length_;
383   }
384  private:
385   const char* data_;
386   size_t length_;
387   int* counter_;
388 };
389
390
391 THREADED_TEST(ScriptUsingStringResource) {
392   int dispose_count = 0;
393   const char* c_source = "1 + 2 * 3";
394   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
395   {
396     v8::HandleScope scope;
397     LocalContext env;
398     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
399     Local<String> source = String::NewExternal(resource);
400     Local<Script> script = Script::Compile(source);
401     Local<Value> value = script->Run();
402     CHECK(value->IsNumber());
403     CHECK_EQ(7, value->Int32Value());
404     CHECK(source->IsExternal());
405     CHECK_EQ(resource,
406              static_cast<TestResource*>(source->GetExternalStringResource()));
407     String::Encoding encoding = String::UNKNOWN_ENCODING;
408     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
409              source->GetExternalStringResourceBase(&encoding));
410     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
411     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
412     CHECK_EQ(0, dispose_count);
413   }
414   v8::internal::Isolate::Current()->compilation_cache()->Clear();
415   HEAP->CollectAllAvailableGarbage();
416   CHECK_EQ(1, dispose_count);
417 }
418
419
420 THREADED_TEST(ScriptUsingAsciiStringResource) {
421   int dispose_count = 0;
422   const char* c_source = "1 + 2 * 3";
423   {
424     v8::HandleScope scope;
425     LocalContext env;
426     TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
427                                                         &dispose_count);
428     Local<String> source = String::NewExternal(resource);
429     CHECK(source->IsExternalAscii());
430     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
431              source->GetExternalAsciiStringResource());
432     String::Encoding encoding = String::UNKNOWN_ENCODING;
433     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
434              source->GetExternalStringResourceBase(&encoding));
435     CHECK_EQ(String::ASCII_ENCODING, encoding);
436     Local<Script> script = Script::Compile(source);
437     Local<Value> value = script->Run();
438     CHECK(value->IsNumber());
439     CHECK_EQ(7, value->Int32Value());
440     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
441     CHECK_EQ(0, dispose_count);
442   }
443   i::Isolate::Current()->compilation_cache()->Clear();
444   HEAP->CollectAllAvailableGarbage();
445   CHECK_EQ(1, dispose_count);
446 }
447
448
449 THREADED_TEST(ScriptMakingExternalString) {
450   int dispose_count = 0;
451   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
452   {
453     v8::HandleScope scope;
454     LocalContext env;
455     Local<String> source = String::New(two_byte_source);
456     // Trigger GCs so that the newly allocated string moves to old gen.
457     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
458     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
459     CHECK_EQ(source->IsExternal(), false);
460     CHECK_EQ(source->IsExternalAscii(), false);
461     String::Encoding encoding = String::UNKNOWN_ENCODING;
462     CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
463     CHECK_EQ(String::ASCII_ENCODING, encoding);
464     bool success = source->MakeExternal(new TestResource(two_byte_source,
465                                                          &dispose_count));
466     CHECK(success);
467     Local<Script> script = Script::Compile(source);
468     Local<Value> value = script->Run();
469     CHECK(value->IsNumber());
470     CHECK_EQ(7, value->Int32Value());
471     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
472     CHECK_EQ(0, dispose_count);
473   }
474   i::Isolate::Current()->compilation_cache()->Clear();
475   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
476   CHECK_EQ(1, dispose_count);
477 }
478
479
480 THREADED_TEST(ScriptMakingExternalAsciiString) {
481   int dispose_count = 0;
482   const char* c_source = "1 + 2 * 3";
483   {
484     v8::HandleScope scope;
485     LocalContext env;
486     Local<String> source = v8_str(c_source);
487     // Trigger GCs so that the newly allocated string moves to old gen.
488     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
489     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
490     bool success = source->MakeExternal(
491         new TestAsciiResource(i::StrDup(c_source), &dispose_count));
492     CHECK(success);
493     Local<Script> script = Script::Compile(source);
494     Local<Value> value = script->Run();
495     CHECK(value->IsNumber());
496     CHECK_EQ(7, value->Int32Value());
497     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
498     CHECK_EQ(0, dispose_count);
499   }
500   i::Isolate::Current()->compilation_cache()->Clear();
501   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
502   CHECK_EQ(1, dispose_count);
503 }
504
505
506 TEST(MakingExternalStringConditions) {
507   v8::HandleScope scope;
508   LocalContext env;
509
510   // Free some space in the new space so that we can check freshness.
511   HEAP->CollectGarbage(i::NEW_SPACE);
512   HEAP->CollectGarbage(i::NEW_SPACE);
513
514   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
515   Local<String> small_string = String::New(two_byte_string);
516   i::DeleteArray(two_byte_string);
517
518   // We should refuse to externalize newly created small string.
519   CHECK(!small_string->CanMakeExternal());
520   // Trigger GCs so that the newly allocated string moves to old gen.
521   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
522   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
523   // Old space strings should be accepted.
524   CHECK(small_string->CanMakeExternal());
525
526   two_byte_string = AsciiToTwoByteString("small string 2");
527   small_string = String::New(two_byte_string);
528   i::DeleteArray(two_byte_string);
529
530   // We should refuse externalizing newly created small string.
531   CHECK(!small_string->CanMakeExternal());
532   for (int i = 0; i < 100; i++) {
533     String::Value value(small_string);
534   }
535   // Frequently used strings should be accepted.
536   CHECK(small_string->CanMakeExternal());
537
538   const int buf_size = 10 * 1024;
539   char* buf = i::NewArray<char>(buf_size);
540   memset(buf, 'a', buf_size);
541   buf[buf_size - 1] = '\0';
542
543   two_byte_string = AsciiToTwoByteString(buf);
544   Local<String> large_string = String::New(two_byte_string);
545   i::DeleteArray(buf);
546   i::DeleteArray(two_byte_string);
547   // Large strings should be immediately accepted.
548   CHECK(large_string->CanMakeExternal());
549 }
550
551
552 TEST(MakingExternalAsciiStringConditions) {
553   v8::HandleScope scope;
554   LocalContext env;
555
556   // Free some space in the new space so that we can check freshness.
557   HEAP->CollectGarbage(i::NEW_SPACE);
558   HEAP->CollectGarbage(i::NEW_SPACE);
559
560   Local<String> small_string = String::New("s1");
561   // We should refuse to externalize newly created small string.
562   CHECK(!small_string->CanMakeExternal());
563   // Trigger GCs so that the newly allocated string moves to old gen.
564   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
565   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
566   // Old space strings should be accepted.
567   CHECK(small_string->CanMakeExternal());
568
569   small_string = String::New("small string 2");
570   // We should refuse externalizing newly created small string.
571   CHECK(!small_string->CanMakeExternal());
572   for (int i = 0; i < 100; i++) {
573     String::Value value(small_string);
574   }
575   // Frequently used strings should be accepted.
576   CHECK(small_string->CanMakeExternal());
577
578   const int buf_size = 10 * 1024;
579   char* buf = i::NewArray<char>(buf_size);
580   memset(buf, 'a', buf_size);
581   buf[buf_size - 1] = '\0';
582   Local<String> large_string = String::New(buf);
583   i::DeleteArray(buf);
584   // Large strings should be immediately accepted.
585   CHECK(large_string->CanMakeExternal());
586 }
587
588
589 THREADED_TEST(UsingExternalString) {
590   {
591     v8::HandleScope scope;
592     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
593     Local<String> string =
594         String::NewExternal(new TestResource(two_byte_string));
595     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
596     // Trigger GCs so that the newly allocated string moves to old gen.
597     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
598     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
599     i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
600     CHECK(isymbol->IsSymbol());
601   }
602   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
603   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
604 }
605
606
607 THREADED_TEST(UsingExternalAsciiString) {
608   {
609     v8::HandleScope scope;
610     const char* one_byte_string = "test string";
611     Local<String> string = String::NewExternal(
612         new TestAsciiResource(i::StrDup(one_byte_string)));
613     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
614     // Trigger GCs so that the newly allocated string moves to old gen.
615     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
616     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
617     i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
618     CHECK(isymbol->IsSymbol());
619   }
620   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
621   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
622 }
623
624
625 THREADED_TEST(ScavengeExternalString) {
626   int dispose_count = 0;
627   bool in_new_space = false;
628   {
629     v8::HandleScope scope;
630     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
631     Local<String> string =
632       String::NewExternal(new TestResource(two_byte_string,
633                                            &dispose_count));
634     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
635     HEAP->CollectGarbage(i::NEW_SPACE);
636     in_new_space = HEAP->InNewSpace(*istring);
637     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
638     CHECK_EQ(0, dispose_count);
639   }
640   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
641   CHECK_EQ(1, dispose_count);
642 }
643
644
645 THREADED_TEST(ScavengeExternalAsciiString) {
646   int dispose_count = 0;
647   bool in_new_space = false;
648   {
649     v8::HandleScope scope;
650     const char* one_byte_string = "test string";
651     Local<String> string = String::NewExternal(
652         new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
653     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
654     HEAP->CollectGarbage(i::NEW_SPACE);
655     in_new_space = HEAP->InNewSpace(*istring);
656     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
657     CHECK_EQ(0, dispose_count);
658   }
659   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
660   CHECK_EQ(1, dispose_count);
661 }
662
663
664 class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
665  public:
666   // Only used by non-threaded tests, so it can use static fields.
667   static int dispose_calls;
668   static int dispose_count;
669
670   TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
671       : TestAsciiResource(data, &dispose_count),
672         dispose_(dispose) { }
673
674   void Dispose() {
675     ++dispose_calls;
676     if (dispose_) delete this;
677   }
678  private:
679   bool dispose_;
680 };
681
682
683 int TestAsciiResourceWithDisposeControl::dispose_count = 0;
684 int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
685
686
687 TEST(ExternalStringWithDisposeHandling) {
688   const char* c_source = "1 + 2 * 3";
689
690   // Use a stack allocated external string resource allocated object.
691   TestAsciiResourceWithDisposeControl::dispose_count = 0;
692   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
693   TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
694   {
695     v8::HandleScope scope;
696     LocalContext env;
697     Local<String> source =  String::NewExternal(&res_stack);
698     Local<Script> script = Script::Compile(source);
699     Local<Value> value = script->Run();
700     CHECK(value->IsNumber());
701     CHECK_EQ(7, value->Int32Value());
702     HEAP->CollectAllAvailableGarbage();
703     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
704   }
705   i::Isolate::Current()->compilation_cache()->Clear();
706   HEAP->CollectAllAvailableGarbage();
707   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
708   CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
709
710   // Use a heap allocated external string resource allocated object.
711   TestAsciiResourceWithDisposeControl::dispose_count = 0;
712   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
713   TestAsciiResource* res_heap =
714       new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
715   {
716     v8::HandleScope scope;
717     LocalContext env;
718     Local<String> source =  String::NewExternal(res_heap);
719     Local<Script> script = Script::Compile(source);
720     Local<Value> value = script->Run();
721     CHECK(value->IsNumber());
722     CHECK_EQ(7, value->Int32Value());
723     HEAP->CollectAllAvailableGarbage();
724     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
725   }
726   i::Isolate::Current()->compilation_cache()->Clear();
727   HEAP->CollectAllAvailableGarbage();
728   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
729   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
730 }
731
732
733 THREADED_TEST(StringConcat) {
734   {
735     v8::HandleScope scope;
736     LocalContext env;
737     const char* one_byte_string_1 = "function a_times_t";
738     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
739     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
740     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
741     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
742     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
743     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
744     Local<String> left = v8_str(one_byte_string_1);
745
746     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
747     Local<String> right = String::New(two_byte_source);
748     i::DeleteArray(two_byte_source);
749
750     Local<String> source = String::Concat(left, right);
751     right = String::NewExternal(
752         new TestAsciiResource(i::StrDup(one_byte_extern_1)));
753     source = String::Concat(source, right);
754     right = String::NewExternal(
755         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
756     source = String::Concat(source, right);
757     right = v8_str(one_byte_string_2);
758     source = String::Concat(source, right);
759
760     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
761     right = String::New(two_byte_source);
762     i::DeleteArray(two_byte_source);
763
764     source = String::Concat(source, right);
765     right = String::NewExternal(
766         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
767     source = String::Concat(source, right);
768     Local<Script> script = Script::Compile(source);
769     Local<Value> value = script->Run();
770     CHECK(value->IsNumber());
771     CHECK_EQ(68, value->Int32Value());
772   }
773   i::Isolate::Current()->compilation_cache()->Clear();
774   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
775   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
776 }
777
778
779 THREADED_TEST(GlobalProperties) {
780   v8::HandleScope scope;
781   LocalContext env;
782   v8::Handle<v8::Object> global = env->Global();
783   global->Set(v8_str("pi"), v8_num(3.1415926));
784   Local<Value> pi = global->Get(v8_str("pi"));
785   CHECK_EQ(3.1415926, pi->NumberValue());
786 }
787
788
789 static v8::Handle<Value> handle_call(const v8::Arguments& args) {
790   ApiTestFuzzer::Fuzz();
791   return v8_num(102);
792 }
793
794
795 static v8::Handle<Value> construct_call(const v8::Arguments& args) {
796   ApiTestFuzzer::Fuzz();
797   args.This()->Set(v8_str("x"), v8_num(1));
798   args.This()->Set(v8_str("y"), v8_num(2));
799   return args.This();
800 }
801
802 static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
803   ApiTestFuzzer::Fuzz();
804   return v8_num(239);
805 }
806
807
808 THREADED_TEST(FunctionTemplate) {
809   v8::HandleScope scope;
810   LocalContext env;
811   {
812     Local<v8::FunctionTemplate> fun_templ =
813         v8::FunctionTemplate::New(handle_call);
814     Local<Function> fun = fun_templ->GetFunction();
815     env->Global()->Set(v8_str("obj"), fun);
816     Local<Script> script = v8_compile("obj()");
817     CHECK_EQ(102, script->Run()->Int32Value());
818   }
819   // Use SetCallHandler to initialize a function template, should work like the
820   // previous one.
821   {
822     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
823     fun_templ->SetCallHandler(handle_call);
824     Local<Function> fun = fun_templ->GetFunction();
825     env->Global()->Set(v8_str("obj"), fun);
826     Local<Script> script = v8_compile("obj()");
827     CHECK_EQ(102, script->Run()->Int32Value());
828   }
829   // Test constructor calls.
830   {
831     Local<v8::FunctionTemplate> fun_templ =
832         v8::FunctionTemplate::New(construct_call);
833     fun_templ->SetClassName(v8_str("funky"));
834     fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), Return239);
835     Local<Function> fun = fun_templ->GetFunction();
836     env->Global()->Set(v8_str("obj"), fun);
837     Local<Script> script = v8_compile("var s = new obj(); s.x");
838     CHECK_EQ(1, script->Run()->Int32Value());
839
840     Local<Value> result = v8_compile("(new obj()).toString()")->Run();
841     CHECK_EQ(v8_str("[object funky]"), result);
842
843     result = v8_compile("(new obj()).m")->Run();
844     CHECK_EQ(239, result->Int32Value());
845   }
846 }
847
848
849 static void* expected_ptr;
850 static v8::Handle<v8::Value> callback(const v8::Arguments& args) {
851   void* ptr = v8::External::Unwrap(args.Data());
852   CHECK_EQ(expected_ptr, ptr);
853   return v8::True();
854 }
855
856
857 static void TestExternalPointerWrapping() {
858   v8::HandleScope scope;
859   LocalContext env;
860
861   v8::Handle<v8::Value> data = v8::External::Wrap(expected_ptr);
862
863   v8::Handle<v8::Object> obj = v8::Object::New();
864   obj->Set(v8_str("func"),
865            v8::FunctionTemplate::New(callback, data)->GetFunction());
866   env->Global()->Set(v8_str("obj"), obj);
867
868   CHECK(CompileRun(
869         "function foo() {\n"
870         "  for (var i = 0; i < 13; i++) obj.func();\n"
871         "}\n"
872         "foo(), true")->BooleanValue());
873 }
874
875
876 THREADED_TEST(ExternalWrap) {
877   // Check heap allocated object.
878   int* ptr = new int;
879   expected_ptr = ptr;
880   TestExternalPointerWrapping();
881   delete ptr;
882
883   // Check stack allocated object.
884   int foo;
885   expected_ptr = &foo;
886   TestExternalPointerWrapping();
887
888   // Check not aligned addresses.
889   const int n = 100;
890   char* s = new char[n];
891   for (int i = 0; i < n; i++) {
892     expected_ptr = s + i;
893     TestExternalPointerWrapping();
894   }
895
896   delete[] s;
897
898   // Check several invalid addresses.
899   expected_ptr = reinterpret_cast<void*>(1);
900   TestExternalPointerWrapping();
901
902   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
903   TestExternalPointerWrapping();
904
905   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
906   TestExternalPointerWrapping();
907
908 #if defined(V8_HOST_ARCH_X64)
909   // Check a value with a leading 1 bit in x64 Smi encoding.
910   expected_ptr = reinterpret_cast<void*>(0x400000000);
911   TestExternalPointerWrapping();
912
913   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
914   TestExternalPointerWrapping();
915
916   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
917   TestExternalPointerWrapping();
918 #endif
919 }
920
921
922 THREADED_TEST(FindInstanceInPrototypeChain) {
923   v8::HandleScope scope;
924   LocalContext env;
925
926   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
927   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
928   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
929   derived->Inherit(base);
930
931   Local<v8::Function> base_function = base->GetFunction();
932   Local<v8::Function> derived_function = derived->GetFunction();
933   Local<v8::Function> other_function = other->GetFunction();
934
935   Local<v8::Object> base_instance = base_function->NewInstance();
936   Local<v8::Object> derived_instance = derived_function->NewInstance();
937   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
938   Local<v8::Object> other_instance = other_function->NewInstance();
939   derived_instance2->Set(v8_str("__proto__"), derived_instance);
940   other_instance->Set(v8_str("__proto__"), derived_instance2);
941
942   // base_instance is only an instance of base.
943   CHECK_EQ(base_instance,
944            base_instance->FindInstanceInPrototypeChain(base));
945   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
946   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
947
948   // derived_instance is an instance of base and derived.
949   CHECK_EQ(derived_instance,
950            derived_instance->FindInstanceInPrototypeChain(base));
951   CHECK_EQ(derived_instance,
952            derived_instance->FindInstanceInPrototypeChain(derived));
953   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
954
955   // other_instance is an instance of other and its immediate
956   // prototype derived_instance2 is an instance of base and derived.
957   // Note, derived_instance is an instance of base and derived too,
958   // but it comes after derived_instance2 in the prototype chain of
959   // other_instance.
960   CHECK_EQ(derived_instance2,
961            other_instance->FindInstanceInPrototypeChain(base));
962   CHECK_EQ(derived_instance2,
963            other_instance->FindInstanceInPrototypeChain(derived));
964   CHECK_EQ(other_instance,
965            other_instance->FindInstanceInPrototypeChain(other));
966 }
967
968
969 THREADED_TEST(TinyInteger) {
970   v8::HandleScope scope;
971   LocalContext env;
972   v8::Isolate* isolate = v8::Isolate::GetCurrent();
973
974   int32_t value = 239;
975   Local<v8::Integer> value_obj = v8::Integer::New(value);
976   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
977
978   value_obj = v8::Integer::New(value, isolate);
979   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
980 }
981
982
983 THREADED_TEST(BigSmiInteger) {
984   v8::HandleScope scope;
985   LocalContext env;
986   v8::Isolate* isolate = v8::Isolate::GetCurrent();
987
988   int32_t value = i::Smi::kMaxValue;
989   // We cannot add one to a Smi::kMaxValue without wrapping.
990   if (i::kSmiValueSize < 32) {
991     CHECK(i::Smi::IsValid(value));
992     CHECK(!i::Smi::IsValid(value + 1));
993
994     Local<v8::Integer> value_obj = v8::Integer::New(value);
995     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
996
997     value_obj = v8::Integer::New(value, isolate);
998     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
999   }
1000 }
1001
1002
1003 THREADED_TEST(BigInteger) {
1004   v8::HandleScope scope;
1005   LocalContext env;
1006   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1007
1008   // We cannot add one to a Smi::kMaxValue without wrapping.
1009   if (i::kSmiValueSize < 32) {
1010     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1011     // The code will not be run in that case, due to the "if" guard.
1012     int32_t value =
1013         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1014     CHECK(value > i::Smi::kMaxValue);
1015     CHECK(!i::Smi::IsValid(value));
1016
1017     Local<v8::Integer> value_obj = v8::Integer::New(value);
1018     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1019
1020     value_obj = v8::Integer::New(value, isolate);
1021     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1022   }
1023 }
1024
1025
1026 THREADED_TEST(TinyUnsignedInteger) {
1027   v8::HandleScope scope;
1028   LocalContext env;
1029   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1030
1031   uint32_t value = 239;
1032
1033   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1034   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1035
1036   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1037   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1038 }
1039
1040
1041 THREADED_TEST(BigUnsignedSmiInteger) {
1042   v8::HandleScope scope;
1043   LocalContext env;
1044   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1045
1046   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1047   CHECK(i::Smi::IsValid(value));
1048   CHECK(!i::Smi::IsValid(value + 1));
1049
1050   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1051   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1052
1053   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1054   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1055 }
1056
1057
1058 THREADED_TEST(BigUnsignedInteger) {
1059   v8::HandleScope scope;
1060   LocalContext env;
1061   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1062
1063   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1064   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1065   CHECK(!i::Smi::IsValid(value));
1066
1067   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1068   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1069
1070   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1071   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1072 }
1073
1074
1075 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
1076   v8::HandleScope scope;
1077   LocalContext env;
1078   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1079
1080   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1081   uint32_t value = INT32_MAX_AS_UINT + 1;
1082   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
1083
1084   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1085   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1086
1087   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1088   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1089 }
1090
1091
1092 THREADED_TEST(IsNativeError) {
1093   v8::HandleScope scope;
1094   LocalContext env;
1095   v8::Handle<Value> syntax_error = CompileRun(
1096       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1097   CHECK(syntax_error->IsNativeError());
1098   v8::Handle<Value> not_error = CompileRun("{a:42}");
1099   CHECK(!not_error->IsNativeError());
1100   v8::Handle<Value> not_object = CompileRun("42");
1101   CHECK(!not_object->IsNativeError());
1102 }
1103
1104
1105 THREADED_TEST(StringObject) {
1106   v8::HandleScope scope;
1107   LocalContext env;
1108   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1109   CHECK(boxed_string->IsStringObject());
1110   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1111   CHECK(!unboxed_string->IsStringObject());
1112   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1113   CHECK(!boxed_not_string->IsStringObject());
1114   v8::Handle<Value> not_object = CompileRun("0");
1115   CHECK(!not_object->IsStringObject());
1116   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1117   CHECK(!as_boxed.IsEmpty());
1118   Local<v8::String> the_string = as_boxed->StringValue();
1119   CHECK(!the_string.IsEmpty());
1120   ExpectObject("\"test\"", the_string);
1121   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1122   CHECK(new_boxed_string->IsStringObject());
1123   as_boxed = new_boxed_string.As<v8::StringObject>();
1124   the_string = as_boxed->StringValue();
1125   CHECK(!the_string.IsEmpty());
1126   ExpectObject("\"test\"", the_string);
1127 }
1128
1129
1130 THREADED_TEST(NumberObject) {
1131   v8::HandleScope scope;
1132   LocalContext env;
1133   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1134   CHECK(boxed_number->IsNumberObject());
1135   v8::Handle<Value> unboxed_number = CompileRun("42");
1136   CHECK(!unboxed_number->IsNumberObject());
1137   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1138   CHECK(!boxed_not_number->IsNumberObject());
1139   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1140   CHECK(!as_boxed.IsEmpty());
1141   double the_number = as_boxed->NumberValue();
1142   CHECK_EQ(42.0, the_number);
1143   v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
1144   CHECK(new_boxed_number->IsNumberObject());
1145   as_boxed = new_boxed_number.As<v8::NumberObject>();
1146   the_number = as_boxed->NumberValue();
1147   CHECK_EQ(43.0, the_number);
1148 }
1149
1150
1151 THREADED_TEST(BooleanObject) {
1152   v8::HandleScope scope;
1153   LocalContext env;
1154   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1155   CHECK(boxed_boolean->IsBooleanObject());
1156   v8::Handle<Value> unboxed_boolean = CompileRun("true");
1157   CHECK(!unboxed_boolean->IsBooleanObject());
1158   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1159   CHECK(!boxed_not_boolean->IsBooleanObject());
1160   v8::Handle<v8::BooleanObject> as_boxed =
1161       boxed_boolean.As<v8::BooleanObject>();
1162   CHECK(!as_boxed.IsEmpty());
1163   bool the_boolean = as_boxed->BooleanValue();
1164   CHECK_EQ(true, the_boolean);
1165   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1166   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1167   CHECK(boxed_true->IsBooleanObject());
1168   CHECK(boxed_false->IsBooleanObject());
1169   as_boxed = boxed_true.As<v8::BooleanObject>();
1170   CHECK_EQ(true, as_boxed->BooleanValue());
1171   as_boxed = boxed_false.As<v8::BooleanObject>();
1172   CHECK_EQ(false, as_boxed->BooleanValue());
1173 }
1174
1175
1176 THREADED_TEST(Number) {
1177   v8::HandleScope scope;
1178   LocalContext env;
1179   double PI = 3.1415926;
1180   Local<v8::Number> pi_obj = v8::Number::New(PI);
1181   CHECK_EQ(PI, pi_obj->NumberValue());
1182 }
1183
1184
1185 THREADED_TEST(ToNumber) {
1186   v8::HandleScope scope;
1187   LocalContext env;
1188   Local<String> str = v8_str("3.1415926");
1189   CHECK_EQ(3.1415926, str->NumberValue());
1190   v8::Handle<v8::Boolean> t = v8::True();
1191   CHECK_EQ(1.0, t->NumberValue());
1192   v8::Handle<v8::Boolean> f = v8::False();
1193   CHECK_EQ(0.0, f->NumberValue());
1194 }
1195
1196
1197 THREADED_TEST(Date) {
1198   v8::HandleScope scope;
1199   LocalContext env;
1200   double PI = 3.1415926;
1201   Local<Value> date = v8::Date::New(PI);
1202   CHECK_EQ(3.0, date->NumberValue());
1203   date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42));
1204   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
1205 }
1206
1207
1208 THREADED_TEST(Boolean) {
1209   v8::HandleScope scope;
1210   LocalContext env;
1211   v8::Handle<v8::Boolean> t = v8::True();
1212   CHECK(t->Value());
1213   v8::Handle<v8::Boolean> f = v8::False();
1214   CHECK(!f->Value());
1215   v8::Handle<v8::Primitive> u = v8::Undefined();
1216   CHECK(!u->BooleanValue());
1217   v8::Handle<v8::Primitive> n = v8::Null();
1218   CHECK(!n->BooleanValue());
1219   v8::Handle<String> str1 = v8_str("");
1220   CHECK(!str1->BooleanValue());
1221   v8::Handle<String> str2 = v8_str("x");
1222   CHECK(str2->BooleanValue());
1223   CHECK(!v8::Number::New(0)->BooleanValue());
1224   CHECK(v8::Number::New(-1)->BooleanValue());
1225   CHECK(v8::Number::New(1)->BooleanValue());
1226   CHECK(v8::Number::New(42)->BooleanValue());
1227   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1228 }
1229
1230
1231 static v8::Handle<Value> DummyCallHandler(const v8::Arguments& args) {
1232   ApiTestFuzzer::Fuzz();
1233   return v8_num(13.4);
1234 }
1235
1236
1237 static v8::Handle<Value> GetM(Local<String> name, const AccessorInfo&) {
1238   ApiTestFuzzer::Fuzz();
1239   return v8_num(876);
1240 }
1241
1242
1243 THREADED_TEST(GlobalPrototype) {
1244   v8::HandleScope scope;
1245   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
1246   func_templ->PrototypeTemplate()->Set(
1247       "dummy",
1248       v8::FunctionTemplate::New(DummyCallHandler));
1249   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1250   templ->Set("x", v8_num(200));
1251   templ->SetAccessor(v8_str("m"), GetM);
1252   LocalContext env(0, templ);
1253   v8::Handle<Script> script(v8_compile("dummy()"));
1254   v8::Handle<Value> result(script->Run());
1255   CHECK_EQ(13.4, result->NumberValue());
1256   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1257   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1258 }
1259
1260
1261 THREADED_TEST(ObjectTemplate) {
1262   v8::HandleScope scope;
1263   Local<ObjectTemplate> templ1 = ObjectTemplate::New();
1264   templ1->Set("x", v8_num(10));
1265   templ1->Set("y", v8_num(13));
1266   LocalContext env;
1267   Local<v8::Object> instance1 = templ1->NewInstance();
1268   env->Global()->Set(v8_str("p"), instance1);
1269   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1270   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1271   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
1272   fun->PrototypeTemplate()->Set("nirk", v8_num(123));
1273   Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
1274   templ2->Set("a", v8_num(12));
1275   templ2->Set("b", templ1);
1276   Local<v8::Object> instance2 = templ2->NewInstance();
1277   env->Global()->Set(v8_str("q"), instance2);
1278   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1279   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1280   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1281   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1282 }
1283
1284
1285 static v8::Handle<Value> GetFlabby(const v8::Arguments& args) {
1286   ApiTestFuzzer::Fuzz();
1287   return v8_num(17.2);
1288 }
1289
1290
1291 static v8::Handle<Value> GetKnurd(Local<String> property, const AccessorInfo&) {
1292   ApiTestFuzzer::Fuzz();
1293   return v8_num(15.2);
1294 }
1295
1296
1297 THREADED_TEST(DescriptorInheritance) {
1298   v8::HandleScope scope;
1299   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
1300   super->PrototypeTemplate()->Set("flabby",
1301                                   v8::FunctionTemplate::New(GetFlabby));
1302   super->PrototypeTemplate()->Set("PI", v8_num(3.14));
1303
1304   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1305
1306   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
1307   base1->Inherit(super);
1308   base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
1309
1310   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
1311   base2->Inherit(super);
1312   base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
1313
1314   LocalContext env;
1315
1316   env->Global()->Set(v8_str("s"), super->GetFunction());
1317   env->Global()->Set(v8_str("base1"), base1->GetFunction());
1318   env->Global()->Set(v8_str("base2"), base2->GetFunction());
1319
1320   // Checks right __proto__ chain.
1321   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1322   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1323
1324   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1325
1326   // Instance accessor should not be visible on function object or its prototype
1327   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1328   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1329   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1330
1331   env->Global()->Set(v8_str("obj"),
1332                      base1->GetFunction()->NewInstance());
1333   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1334   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1335   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1336   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1337   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1338
1339   env->Global()->Set(v8_str("obj2"),
1340                      base2->GetFunction()->NewInstance());
1341   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1342   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1343   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1344   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1345   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1346
1347   // base1 and base2 cannot cross reference to each's prototype
1348   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1349   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1350 }
1351
1352
1353 int echo_named_call_count;
1354
1355
1356 static v8::Handle<Value> EchoNamedProperty(Local<String> name,
1357                                            const AccessorInfo& info) {
1358   ApiTestFuzzer::Fuzz();
1359   CHECK_EQ(v8_str("data"), info.Data());
1360   echo_named_call_count++;
1361   return name;
1362 }
1363
1364 // Helper functions for Interceptor/Accessor interaction tests
1365
1366 Handle<Value> SimpleAccessorGetter(Local<String> name,
1367                                    const AccessorInfo& info) {
1368   Handle<Object> self = info.This();
1369   return self->Get(String::Concat(v8_str("accessor_"), name));
1370 }
1371
1372 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1373                           const AccessorInfo& info) {
1374   Handle<Object> self = info.This();
1375   self->Set(String::Concat(v8_str("accessor_"), name), value);
1376 }
1377
1378 Handle<Value> EmptyInterceptorGetter(Local<String> name,
1379                                      const AccessorInfo& info) {
1380   return Handle<Value>();
1381 }
1382
1383 Handle<Value> EmptyInterceptorSetter(Local<String> name,
1384                                      Local<Value> value,
1385                                      const AccessorInfo& info) {
1386   return Handle<Value>();
1387 }
1388
1389 Handle<Value> InterceptorGetter(Local<String> name,
1390                                 const AccessorInfo& info) {
1391   // Intercept names that start with 'interceptor_'.
1392   String::AsciiValue ascii(name);
1393   char* name_str = *ascii;
1394   char prefix[] = "interceptor_";
1395   int i;
1396   for (i = 0; name_str[i] && prefix[i]; ++i) {
1397     if (name_str[i] != prefix[i]) return Handle<Value>();
1398   }
1399   Handle<Object> self = info.This();
1400   return self->GetHiddenValue(v8_str(name_str + i));
1401 }
1402
1403 Handle<Value> InterceptorSetter(Local<String> name,
1404                                 Local<Value> value,
1405                                 const AccessorInfo& info) {
1406   // Intercept accesses that set certain integer values.
1407   if (value->IsInt32() && value->Int32Value() < 10000) {
1408     Handle<Object> self = info.This();
1409     self->SetHiddenValue(name, value);
1410     return value;
1411   }
1412   return Handle<Value>();
1413 }
1414
1415 void AddAccessor(Handle<FunctionTemplate> templ,
1416                  Handle<String> name,
1417                  v8::AccessorGetter getter,
1418                  v8::AccessorSetter setter) {
1419   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1420 }
1421
1422 void AddInterceptor(Handle<FunctionTemplate> templ,
1423                     v8::NamedPropertyGetter getter,
1424                     v8::NamedPropertySetter setter) {
1425   templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1426 }
1427
1428 THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
1429   v8::HandleScope scope;
1430   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1431   Handle<FunctionTemplate> child = FunctionTemplate::New();
1432   child->Inherit(parent);
1433   AddAccessor(parent, v8_str("age"),
1434               SimpleAccessorGetter, SimpleAccessorSetter);
1435   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1436   LocalContext env;
1437   env->Global()->Set(v8_str("Child"), child->GetFunction());
1438   CompileRun("var child = new Child;"
1439              "child.age = 10;");
1440   ExpectBoolean("child.hasOwnProperty('age')", false);
1441   ExpectInt32("child.age", 10);
1442   ExpectInt32("child.accessor_age", 10);
1443 }
1444
1445 THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
1446   v8::HandleScope scope;
1447   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1448   Handle<FunctionTemplate> child = FunctionTemplate::New();
1449   child->Inherit(parent);
1450   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1451   LocalContext env;
1452   env->Global()->Set(v8_str("Child"), child->GetFunction());
1453   CompileRun("var child = new Child;"
1454              "var parent = child.__proto__;"
1455              "Object.defineProperty(parent, 'age', "
1456              "  {get: function(){ return this.accessor_age; }, "
1457              "   set: function(v){ this.accessor_age = v; }, "
1458              "   enumerable: true, configurable: true});"
1459              "child.age = 10;");
1460   ExpectBoolean("child.hasOwnProperty('age')", false);
1461   ExpectInt32("child.age", 10);
1462   ExpectInt32("child.accessor_age", 10);
1463 }
1464
1465 THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
1466   v8::HandleScope scope;
1467   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1468   Handle<FunctionTemplate> child = FunctionTemplate::New();
1469   child->Inherit(parent);
1470   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1471   LocalContext env;
1472   env->Global()->Set(v8_str("Child"), child->GetFunction());
1473   CompileRun("var child = new Child;"
1474              "var parent = child.__proto__;"
1475              "parent.name = 'Alice';");
1476   ExpectBoolean("child.hasOwnProperty('name')", false);
1477   ExpectString("child.name", "Alice");
1478   CompileRun("child.name = 'Bob';");
1479   ExpectString("child.name", "Bob");
1480   ExpectBoolean("child.hasOwnProperty('name')", true);
1481   ExpectString("parent.name", "Alice");
1482 }
1483
1484 THREADED_TEST(SwitchFromInterceptorToAccessor) {
1485   v8::HandleScope scope;
1486   Handle<FunctionTemplate> templ = FunctionTemplate::New();
1487   AddAccessor(templ, v8_str("age"),
1488               SimpleAccessorGetter, SimpleAccessorSetter);
1489   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1490   LocalContext env;
1491   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1492   CompileRun("var obj = new Obj;"
1493              "function setAge(i){ obj.age = i; };"
1494              "for(var i = 0; i <= 10000; i++) setAge(i);");
1495   // All i < 10000 go to the interceptor.
1496   ExpectInt32("obj.interceptor_age", 9999);
1497   // The last i goes to the accessor.
1498   ExpectInt32("obj.accessor_age", 10000);
1499 }
1500
1501 THREADED_TEST(SwitchFromAccessorToInterceptor) {
1502   v8::HandleScope scope;
1503   Handle<FunctionTemplate> templ = FunctionTemplate::New();
1504   AddAccessor(templ, v8_str("age"),
1505               SimpleAccessorGetter, SimpleAccessorSetter);
1506   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1507   LocalContext env;
1508   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1509   CompileRun("var obj = new Obj;"
1510              "function setAge(i){ obj.age = i; };"
1511              "for(var i = 20000; i >= 9999; i--) setAge(i);");
1512   // All i >= 10000 go to the accessor.
1513   ExpectInt32("obj.accessor_age", 10000);
1514   // The last i goes to the interceptor.
1515   ExpectInt32("obj.interceptor_age", 9999);
1516 }
1517
1518 THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
1519   v8::HandleScope scope;
1520   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1521   Handle<FunctionTemplate> child = FunctionTemplate::New();
1522   child->Inherit(parent);
1523   AddAccessor(parent, v8_str("age"),
1524               SimpleAccessorGetter, SimpleAccessorSetter);
1525   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1526   LocalContext env;
1527   env->Global()->Set(v8_str("Child"), child->GetFunction());
1528   CompileRun("var child = new Child;"
1529              "function setAge(i){ child.age = i; };"
1530              "for(var i = 0; i <= 10000; i++) setAge(i);");
1531   // All i < 10000 go to the interceptor.
1532   ExpectInt32("child.interceptor_age", 9999);
1533   // The last i goes to the accessor.
1534   ExpectInt32("child.accessor_age", 10000);
1535 }
1536
1537 THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
1538   v8::HandleScope scope;
1539   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1540   Handle<FunctionTemplate> child = FunctionTemplate::New();
1541   child->Inherit(parent);
1542   AddAccessor(parent, v8_str("age"),
1543               SimpleAccessorGetter, SimpleAccessorSetter);
1544   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1545   LocalContext env;
1546   env->Global()->Set(v8_str("Child"), child->GetFunction());
1547   CompileRun("var child = new Child;"
1548              "function setAge(i){ child.age = i; };"
1549              "for(var i = 20000; i >= 9999; i--) setAge(i);");
1550   // All i >= 10000 go to the accessor.
1551   ExpectInt32("child.accessor_age", 10000);
1552   // The last i goes to the interceptor.
1553   ExpectInt32("child.interceptor_age", 9999);
1554 }
1555
1556 THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
1557   v8::HandleScope scope;
1558   Handle<FunctionTemplate> templ = FunctionTemplate::New();
1559   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1560   LocalContext env;
1561   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1562   CompileRun("var obj = new Obj;"
1563              "function setter(i) { this.accessor_age = i; };"
1564              "function getter() { return this.accessor_age; };"
1565              "function setAge(i) { obj.age = i; };"
1566              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
1567              "for(var i = 0; i <= 10000; i++) setAge(i);");
1568   // All i < 10000 go to the interceptor.
1569   ExpectInt32("obj.interceptor_age", 9999);
1570   // The last i goes to the JavaScript accessor.
1571   ExpectInt32("obj.accessor_age", 10000);
1572   // The installed JavaScript getter is still intact.
1573   // This last part is a regression test for issue 1651 and relies on the fact
1574   // that both interceptor and accessor are being installed on the same object.
1575   ExpectInt32("obj.age", 10000);
1576   ExpectBoolean("obj.hasOwnProperty('age')", true);
1577   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
1578 }
1579
1580 THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
1581   v8::HandleScope scope;
1582   Handle<FunctionTemplate> templ = FunctionTemplate::New();
1583   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1584   LocalContext env;
1585   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1586   CompileRun("var obj = new Obj;"
1587              "function setter(i) { this.accessor_age = i; };"
1588              "function getter() { return this.accessor_age; };"
1589              "function setAge(i) { obj.age = i; };"
1590              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
1591              "for(var i = 20000; i >= 9999; i--) setAge(i);");
1592   // All i >= 10000 go to the accessor.
1593   ExpectInt32("obj.accessor_age", 10000);
1594   // The last i goes to the interceptor.
1595   ExpectInt32("obj.interceptor_age", 9999);
1596   // The installed JavaScript getter is still intact.
1597   // This last part is a regression test for issue 1651 and relies on the fact
1598   // that both interceptor and accessor are being installed on the same object.
1599   ExpectInt32("obj.age", 10000);
1600   ExpectBoolean("obj.hasOwnProperty('age')", true);
1601   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
1602 }
1603
1604 THREADED_TEST(SwitchFromInterceptorToProperty) {
1605   v8::HandleScope scope;
1606   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1607   Handle<FunctionTemplate> child = FunctionTemplate::New();
1608   child->Inherit(parent);
1609   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1610   LocalContext env;
1611   env->Global()->Set(v8_str("Child"), child->GetFunction());
1612   CompileRun("var child = new Child;"
1613              "function setAge(i){ child.age = i; };"
1614              "for(var i = 0; i <= 10000; i++) setAge(i);");
1615   // All i < 10000 go to the interceptor.
1616   ExpectInt32("child.interceptor_age", 9999);
1617   // The last i goes to child's own property.
1618   ExpectInt32("child.age", 10000);
1619 }
1620
1621 THREADED_TEST(SwitchFromPropertyToInterceptor) {
1622   v8::HandleScope scope;
1623   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1624   Handle<FunctionTemplate> child = FunctionTemplate::New();
1625   child->Inherit(parent);
1626   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1627   LocalContext env;
1628   env->Global()->Set(v8_str("Child"), child->GetFunction());
1629   CompileRun("var child = new Child;"
1630              "function setAge(i){ child.age = i; };"
1631              "for(var i = 20000; i >= 9999; i--) setAge(i);");
1632   // All i >= 10000 go to child's own property.
1633   ExpectInt32("child.age", 10000);
1634   // The last i goes to the interceptor.
1635   ExpectInt32("child.interceptor_age", 9999);
1636 }
1637
1638 THREADED_TEST(NamedPropertyHandlerGetter) {
1639   echo_named_call_count = 0;
1640   v8::HandleScope scope;
1641   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
1642   templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
1643                                                      0, 0, 0, 0,
1644                                                      v8_str("data"));
1645   LocalContext env;
1646   env->Global()->Set(v8_str("obj"),
1647                      templ->GetFunction()->NewInstance());
1648   CHECK_EQ(echo_named_call_count, 0);
1649   v8_compile("obj.x")->Run();
1650   CHECK_EQ(echo_named_call_count, 1);
1651   const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
1652   v8::Handle<Value> str = CompileRun(code);
1653   String::AsciiValue value(str);
1654   CHECK_EQ(*value, "oddlepoddle");
1655   // Check default behavior
1656   CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
1657   CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
1658   CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
1659 }
1660
1661
1662 int echo_indexed_call_count = 0;
1663
1664
1665 static v8::Handle<Value> EchoIndexedProperty(uint32_t index,
1666                                              const AccessorInfo& info) {
1667   ApiTestFuzzer::Fuzz();
1668   CHECK_EQ(v8_num(637), info.Data());
1669   echo_indexed_call_count++;
1670   return v8_num(index);
1671 }
1672
1673
1674 THREADED_TEST(IndexedPropertyHandlerGetter) {
1675   v8::HandleScope scope;
1676   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
1677   templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
1678                                                        0, 0, 0, 0,
1679                                                        v8_num(637));
1680   LocalContext env;
1681   env->Global()->Set(v8_str("obj"),
1682                      templ->GetFunction()->NewInstance());
1683   Local<Script> script = v8_compile("obj[900]");
1684   CHECK_EQ(script->Run()->Int32Value(), 900);
1685 }
1686
1687
1688 v8::Handle<v8::Object> bottom;
1689
1690 static v8::Handle<Value> CheckThisIndexedPropertyHandler(
1691     uint32_t index,
1692     const AccessorInfo& info) {
1693   ApiTestFuzzer::Fuzz();
1694   CHECK(info.This()->Equals(bottom));
1695   return v8::Handle<Value>();
1696 }
1697
1698 static v8::Handle<Value> CheckThisNamedPropertyHandler(
1699     Local<String> name,
1700     const AccessorInfo& info) {
1701   ApiTestFuzzer::Fuzz();
1702   CHECK(info.This()->Equals(bottom));
1703   return v8::Handle<Value>();
1704 }
1705
1706
1707 v8::Handle<Value> CheckThisIndexedPropertySetter(uint32_t index,
1708                                                  Local<Value> value,
1709                                                  const AccessorInfo& info) {
1710   ApiTestFuzzer::Fuzz();
1711   CHECK(info.This()->Equals(bottom));
1712   return v8::Handle<Value>();
1713 }
1714
1715
1716 v8::Handle<Value> CheckThisNamedPropertySetter(Local<String> property,
1717                                                Local<Value> value,
1718                                                const AccessorInfo& info) {
1719   ApiTestFuzzer::Fuzz();
1720   CHECK(info.This()->Equals(bottom));
1721   return v8::Handle<Value>();
1722 }
1723
1724 v8::Handle<v8::Integer> CheckThisIndexedPropertyQuery(
1725     uint32_t index,
1726     const AccessorInfo& info) {
1727   ApiTestFuzzer::Fuzz();
1728   CHECK(info.This()->Equals(bottom));
1729   return v8::Handle<v8::Integer>();
1730 }
1731
1732
1733 v8::Handle<v8::Integer> CheckThisNamedPropertyQuery(Local<String> property,
1734                                                     const AccessorInfo& info) {
1735   ApiTestFuzzer::Fuzz();
1736   CHECK(info.This()->Equals(bottom));
1737   return v8::Handle<v8::Integer>();
1738 }
1739
1740
1741 v8::Handle<v8::Boolean> CheckThisIndexedPropertyDeleter(
1742     uint32_t index,
1743     const AccessorInfo& info) {
1744   ApiTestFuzzer::Fuzz();
1745   CHECK(info.This()->Equals(bottom));
1746   return v8::Handle<v8::Boolean>();
1747 }
1748
1749
1750 v8::Handle<v8::Boolean> CheckThisNamedPropertyDeleter(
1751     Local<String> property,
1752     const AccessorInfo& info) {
1753   ApiTestFuzzer::Fuzz();
1754   CHECK(info.This()->Equals(bottom));
1755   return v8::Handle<v8::Boolean>();
1756 }
1757
1758
1759 v8::Handle<v8::Array> CheckThisIndexedPropertyEnumerator(
1760     const AccessorInfo& info) {
1761   ApiTestFuzzer::Fuzz();
1762   CHECK(info.This()->Equals(bottom));
1763   return v8::Handle<v8::Array>();
1764 }
1765
1766
1767 v8::Handle<v8::Array> CheckThisNamedPropertyEnumerator(
1768     const AccessorInfo& info) {
1769   ApiTestFuzzer::Fuzz();
1770   CHECK(info.This()->Equals(bottom));
1771   return v8::Handle<v8::Array>();
1772 }
1773
1774
1775 THREADED_TEST(PropertyHandlerInPrototype) {
1776   v8::HandleScope scope;
1777   LocalContext env;
1778
1779   // Set up a prototype chain with three interceptors.
1780   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
1781   templ->InstanceTemplate()->SetIndexedPropertyHandler(
1782       CheckThisIndexedPropertyHandler,
1783       CheckThisIndexedPropertySetter,
1784       CheckThisIndexedPropertyQuery,
1785       CheckThisIndexedPropertyDeleter,
1786       CheckThisIndexedPropertyEnumerator);
1787
1788   templ->InstanceTemplate()->SetNamedPropertyHandler(
1789       CheckThisNamedPropertyHandler,
1790       CheckThisNamedPropertySetter,
1791       CheckThisNamedPropertyQuery,
1792       CheckThisNamedPropertyDeleter,
1793       CheckThisNamedPropertyEnumerator);
1794
1795   bottom = templ->GetFunction()->NewInstance();
1796   Local<v8::Object> top = templ->GetFunction()->NewInstance();
1797   Local<v8::Object> middle = templ->GetFunction()->NewInstance();
1798
1799   bottom->Set(v8_str("__proto__"), middle);
1800   middle->Set(v8_str("__proto__"), top);
1801   env->Global()->Set(v8_str("obj"), bottom);
1802
1803   // Indexed and named get.
1804   Script::Compile(v8_str("obj[0]"))->Run();
1805   Script::Compile(v8_str("obj.x"))->Run();
1806
1807   // Indexed and named set.
1808   Script::Compile(v8_str("obj[1] = 42"))->Run();
1809   Script::Compile(v8_str("obj.y = 42"))->Run();
1810
1811   // Indexed and named query.
1812   Script::Compile(v8_str("0 in obj"))->Run();
1813   Script::Compile(v8_str("'x' in obj"))->Run();
1814
1815   // Indexed and named deleter.
1816   Script::Compile(v8_str("delete obj[0]"))->Run();
1817   Script::Compile(v8_str("delete obj.x"))->Run();
1818
1819   // Enumerators.
1820   Script::Compile(v8_str("for (var p in obj) ;"))->Run();
1821 }
1822
1823
1824 static v8::Handle<Value> PrePropertyHandlerGet(Local<String> key,
1825                                                const AccessorInfo& info) {
1826   ApiTestFuzzer::Fuzz();
1827   if (v8_str("pre")->Equals(key)) {
1828     return v8_str("PrePropertyHandler: pre");
1829   }
1830   return v8::Handle<String>();
1831 }
1832
1833
1834 static v8::Handle<v8::Integer> PrePropertyHandlerQuery(Local<String> key,
1835                                                        const AccessorInfo&) {
1836   if (v8_str("pre")->Equals(key)) {
1837     return v8::Integer::New(v8::None);
1838   }
1839
1840   return v8::Handle<v8::Integer>();  // do not intercept the call
1841 }
1842
1843
1844 THREADED_TEST(PrePropertyHandler) {
1845   v8::HandleScope scope;
1846   v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
1847   desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
1848                                                     0,
1849                                                     PrePropertyHandlerQuery);
1850   LocalContext env(NULL, desc->InstanceTemplate());
1851   Script::Compile(v8_str(
1852       "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
1853   v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
1854   CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
1855   v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
1856   CHECK_EQ(v8_str("Object: on"), result_on);
1857   v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
1858   CHECK(result_post.IsEmpty());
1859 }
1860
1861
1862 THREADED_TEST(UndefinedIsNotEnumerable) {
1863   v8::HandleScope scope;
1864   LocalContext env;
1865   v8::Handle<Value> result = Script::Compile(v8_str(
1866       "this.propertyIsEnumerable(undefined)"))->Run();
1867   CHECK(result->IsFalse());
1868 }
1869
1870
1871 v8::Handle<Script> call_recursively_script;
1872 static const int kTargetRecursionDepth = 200;  // near maximum
1873
1874
1875 static v8::Handle<Value> CallScriptRecursivelyCall(const v8::Arguments& args) {
1876   ApiTestFuzzer::Fuzz();
1877   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1878   if (depth == kTargetRecursionDepth) return v8::Undefined();
1879   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
1880   return call_recursively_script->Run();
1881 }
1882
1883
1884 static v8::Handle<Value> CallFunctionRecursivelyCall(
1885     const v8::Arguments& args) {
1886   ApiTestFuzzer::Fuzz();
1887   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1888   if (depth == kTargetRecursionDepth) {
1889     printf("[depth = %d]\n", depth);
1890     return v8::Undefined();
1891   }
1892   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
1893   v8::Handle<Value> function =
1894       args.This()->Get(v8_str("callFunctionRecursively"));
1895   return function.As<Function>()->Call(args.This(), 0, NULL);
1896 }
1897
1898
1899 THREADED_TEST(DeepCrossLanguageRecursion) {
1900   v8::HandleScope scope;
1901   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
1902   global->Set(v8_str("callScriptRecursively"),
1903               v8::FunctionTemplate::New(CallScriptRecursivelyCall));
1904   global->Set(v8_str("callFunctionRecursively"),
1905               v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
1906   LocalContext env(NULL, global);
1907
1908   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
1909   call_recursively_script = v8_compile("callScriptRecursively()");
1910   call_recursively_script->Run();
1911   call_recursively_script = v8::Handle<Script>();
1912
1913   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
1914   Script::Compile(v8_str("callFunctionRecursively()"))->Run();
1915 }
1916
1917
1918 static v8::Handle<Value>
1919     ThrowingPropertyHandlerGet(Local<String> key, const AccessorInfo&) {
1920   ApiTestFuzzer::Fuzz();
1921   return v8::ThrowException(key);
1922 }
1923
1924
1925 static v8::Handle<Value> ThrowingPropertyHandlerSet(Local<String> key,
1926                                                     Local<Value>,
1927                                                     const AccessorInfo&) {
1928   v8::ThrowException(key);
1929   return v8::Undefined();  // not the same as v8::Handle<v8::Value>()
1930 }
1931
1932
1933 THREADED_TEST(CallbackExceptionRegression) {
1934   v8::HandleScope scope;
1935   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
1936   obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
1937                                ThrowingPropertyHandlerSet);
1938   LocalContext env;
1939   env->Global()->Set(v8_str("obj"), obj->NewInstance());
1940   v8::Handle<Value> otto = Script::Compile(v8_str(
1941       "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
1942   CHECK_EQ(v8_str("otto"), otto);
1943   v8::Handle<Value> netto = Script::Compile(v8_str(
1944       "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
1945   CHECK_EQ(v8_str("netto"), netto);
1946 }
1947
1948
1949 THREADED_TEST(FunctionPrototype) {
1950   v8::HandleScope scope;
1951   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
1952   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
1953   LocalContext env;
1954   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
1955   Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
1956   CHECK_EQ(script->Run()->Int32Value(), 321);
1957 }
1958
1959
1960 THREADED_TEST(InternalFields) {
1961   v8::HandleScope scope;
1962   LocalContext env;
1963
1964   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
1965   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
1966   instance_templ->SetInternalFieldCount(1);
1967   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
1968   CHECK_EQ(1, obj->InternalFieldCount());
1969   CHECK(obj->GetInternalField(0)->IsUndefined());
1970   obj->SetInternalField(0, v8_num(17));
1971   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
1972 }
1973
1974
1975 THREADED_TEST(GlobalObjectInternalFields) {
1976   v8::HandleScope scope;
1977   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
1978   global_template->SetInternalFieldCount(1);
1979   LocalContext env(NULL, global_template);
1980   v8::Handle<v8::Object> global_proxy = env->Global();
1981   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
1982   CHECK_EQ(1, global->InternalFieldCount());
1983   CHECK(global->GetInternalField(0)->IsUndefined());
1984   global->SetInternalField(0, v8_num(17));
1985   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
1986 }
1987
1988
1989 THREADED_TEST(InternalFieldsNativePointers) {
1990   v8::HandleScope scope;
1991   LocalContext env;
1992
1993   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
1994   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
1995   instance_templ->SetInternalFieldCount(1);
1996   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
1997   CHECK_EQ(1, obj->InternalFieldCount());
1998   CHECK(obj->GetPointerFromInternalField(0) == NULL);
1999
2000   char* data = new char[100];
2001
2002   void* aligned = data;
2003   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1));
2004   void* unaligned = data + 1;
2005   CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1));
2006
2007   // Check reading and writing aligned pointers.
2008   obj->SetPointerInInternalField(0, aligned);
2009   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2010   CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
2011
2012   // Check reading and writing unaligned pointers.
2013   obj->SetPointerInInternalField(0, unaligned);
2014   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2015   CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
2016
2017   delete[] data;
2018 }
2019
2020
2021 THREADED_TEST(InternalFieldsNativePointersAndExternal) {
2022   v8::HandleScope scope;
2023   LocalContext env;
2024
2025   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2026   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2027   instance_templ->SetInternalFieldCount(1);
2028   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2029   CHECK_EQ(1, obj->InternalFieldCount());
2030   CHECK(obj->GetPointerFromInternalField(0) == NULL);
2031
2032   char* data = new char[100];
2033
2034   void* aligned = data;
2035   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1));
2036   void* unaligned = data + 1;
2037   CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1));
2038
2039   obj->SetPointerInInternalField(0, aligned);
2040   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2041   CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0)));
2042
2043   obj->SetPointerInInternalField(0, unaligned);
2044   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2045   CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0)));
2046
2047   obj->SetInternalField(0, v8::External::Wrap(aligned));
2048   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2049   CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
2050
2051   obj->SetInternalField(0, v8::External::Wrap(unaligned));
2052   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2053   CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
2054
2055   delete[] data;
2056 }
2057
2058
2059 THREADED_TEST(IdentityHash) {
2060   v8::HandleScope scope;
2061   LocalContext env;
2062
2063   // Ensure that the test starts with an fresh heap to test whether the hash
2064   // code is based on the address.
2065   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2066   Local<v8::Object> obj = v8::Object::New();
2067   int hash = obj->GetIdentityHash();
2068   int hash1 = obj->GetIdentityHash();
2069   CHECK_EQ(hash, hash1);
2070   int hash2 = v8::Object::New()->GetIdentityHash();
2071   // Since the identity hash is essentially a random number two consecutive
2072   // objects should not be assigned the same hash code. If the test below fails
2073   // the random number generator should be evaluated.
2074   CHECK_NE(hash, hash2);
2075   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2076   int hash3 = v8::Object::New()->GetIdentityHash();
2077   // Make sure that the identity hash is not based on the initial address of
2078   // the object alone. If the test below fails the random number generator
2079   // should be evaluated.
2080   CHECK_NE(hash, hash3);
2081   int hash4 = obj->GetIdentityHash();
2082   CHECK_EQ(hash, hash4);
2083
2084   // Check identity hashes behaviour in the presence of JS accessors.
2085   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2086   {
2087     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2088     Local<v8::Object> o1 = v8::Object::New();
2089     Local<v8::Object> o2 = v8::Object::New();
2090     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2091   }
2092   {
2093     CompileRun(
2094         "function cnst() { return 42; };\n"
2095         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2096     Local<v8::Object> o1 = v8::Object::New();
2097     Local<v8::Object> o2 = v8::Object::New();
2098     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2099   }
2100 }
2101
2102
2103 THREADED_TEST(HiddenProperties) {
2104   v8::HandleScope scope;
2105   LocalContext env;
2106
2107   v8::Local<v8::Object> obj = v8::Object::New();
2108   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
2109   v8::Local<v8::String> empty = v8_str("");
2110   v8::Local<v8::String> prop_name = v8_str("prop_name");
2111
2112   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2113
2114   // Make sure delete of a non-existent hidden value works
2115   CHECK(obj->DeleteHiddenValue(key));
2116
2117   CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
2118   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
2119   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
2120   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2121
2122   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2123
2124   // Make sure we do not find the hidden property.
2125   CHECK(!obj->Has(empty));
2126   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2127   CHECK(obj->Get(empty)->IsUndefined());
2128   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2129   CHECK(obj->Set(empty, v8::Integer::New(2003)));
2130   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2131   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
2132
2133   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2134
2135   // Add another property and delete it afterwards to force the object in
2136   // slow case.
2137   CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
2138   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2139   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
2140   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2141   CHECK(obj->Delete(prop_name));
2142   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2143
2144   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2145
2146   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
2147   CHECK(obj->GetHiddenValue(key).IsEmpty());
2148
2149   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
2150   CHECK(obj->DeleteHiddenValue(key));
2151   CHECK(obj->GetHiddenValue(key).IsEmpty());
2152 }
2153
2154
2155 THREADED_TEST(Regress97784) {
2156   // Regression test for crbug.com/97784
2157   // Messing with the Object.prototype should not have effect on
2158   // hidden properties.
2159   v8::HandleScope scope;
2160   LocalContext env;
2161
2162   v8::Local<v8::Object> obj = v8::Object::New();
2163   v8::Local<v8::String> key = v8_str("hidden");
2164
2165   CompileRun(
2166       "set_called = false;"
2167       "Object.defineProperty("
2168       "    Object.prototype,"
2169       "    'hidden',"
2170       "    {get: function() { return 45; },"
2171       "     set: function() { set_called = true; }})");
2172
2173   CHECK(obj->GetHiddenValue(key).IsEmpty());
2174   // Make sure that the getter and setter from Object.prototype is not invoked.
2175   // If it did we would have full access to the hidden properties in
2176   // the accessor.
2177   CHECK(obj->SetHiddenValue(key, v8::Integer::New(42)));
2178   ExpectFalse("set_called");
2179   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
2180 }
2181
2182
2183 static bool interceptor_for_hidden_properties_called;
2184 static v8::Handle<Value> InterceptorForHiddenProperties(
2185     Local<String> name, const AccessorInfo& info) {
2186   interceptor_for_hidden_properties_called = true;
2187   return v8::Handle<Value>();
2188 }
2189
2190
2191 THREADED_TEST(HiddenPropertiesWithInterceptors) {
2192   v8::HandleScope scope;
2193   LocalContext context;
2194
2195   interceptor_for_hidden_properties_called = false;
2196
2197   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
2198
2199   // Associate an interceptor with an object and start setting hidden values.
2200   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
2201   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
2202   instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
2203   Local<v8::Function> function = fun_templ->GetFunction();
2204   Local<v8::Object> obj = function->NewInstance();
2205   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
2206   CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
2207   CHECK(!interceptor_for_hidden_properties_called);
2208 }
2209
2210
2211 THREADED_TEST(External) {
2212   v8::HandleScope scope;
2213   int x = 3;
2214   Local<v8::External> ext = v8::External::New(&x);
2215   LocalContext env;
2216   env->Global()->Set(v8_str("ext"), ext);
2217   Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
2218   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
2219   int* ptr = static_cast<int*>(reext->Value());
2220   CHECK_EQ(x, 3);
2221   *ptr = 10;
2222   CHECK_EQ(x, 10);
2223
2224   // Make sure unaligned pointers are wrapped properly.
2225   char* data = i::StrDup("0123456789");
2226   Local<v8::Value> zero = v8::External::Wrap(&data[0]);
2227   Local<v8::Value> one = v8::External::Wrap(&data[1]);
2228   Local<v8::Value> two = v8::External::Wrap(&data[2]);
2229   Local<v8::Value> three = v8::External::Wrap(&data[3]);
2230
2231   char* char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(zero));
2232   CHECK_EQ('0', *char_ptr);
2233   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(one));
2234   CHECK_EQ('1', *char_ptr);
2235   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(two));
2236   CHECK_EQ('2', *char_ptr);
2237   char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(three));
2238   CHECK_EQ('3', *char_ptr);
2239   i::DeleteArray(data);
2240 }
2241
2242
2243 THREADED_TEST(GlobalHandle) {
2244   v8::Persistent<String> global;
2245   {
2246     v8::HandleScope scope;
2247     Local<String> str = v8_str("str");
2248     global = v8::Persistent<String>::New(str);
2249   }
2250   CHECK_EQ(global->Length(), 3);
2251   global.Dispose();
2252 }
2253
2254
2255 class WeakCallCounter {
2256  public:
2257   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
2258   int id() { return id_; }
2259   void increment() { number_of_weak_calls_++; }
2260   int NumberOfWeakCalls() { return number_of_weak_calls_; }
2261  private:
2262   int id_;
2263   int number_of_weak_calls_;
2264 };
2265
2266
2267 static void WeakPointerCallback(Persistent<Value> handle, void* id) {
2268   WeakCallCounter* counter = reinterpret_cast<WeakCallCounter*>(id);
2269   CHECK_EQ(1234, counter->id());
2270   counter->increment();
2271   handle.Dispose();
2272 }
2273
2274
2275 THREADED_TEST(ApiObjectGroups) {
2276   HandleScope scope;
2277   LocalContext env;
2278
2279   Persistent<Object> g1s1;
2280   Persistent<Object> g1s2;
2281   Persistent<Object> g1c1;
2282   Persistent<Object> g2s1;
2283   Persistent<Object> g2s2;
2284   Persistent<Object> g2c1;
2285
2286   WeakCallCounter counter(1234);
2287
2288   {
2289     HandleScope scope;
2290     g1s1 = Persistent<Object>::New(Object::New());
2291     g1s2 = Persistent<Object>::New(Object::New());
2292     g1c1 = Persistent<Object>::New(Object::New());
2293     g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2294     g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2295     g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2296
2297     g2s1 = Persistent<Object>::New(Object::New());
2298     g2s2 = Persistent<Object>::New(Object::New());
2299     g2c1 = Persistent<Object>::New(Object::New());
2300     g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2301     g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2302     g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2303   }
2304
2305   Persistent<Object> root = Persistent<Object>::New(g1s1);  // make a root.
2306
2307   // Connect group 1 and 2, make a cycle.
2308   CHECK(g1s2->Set(0, g2s2));
2309   CHECK(g2s1->Set(0, g1s1));
2310
2311   {
2312     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2313     Persistent<Value> g1_children[] = { g1c1 };
2314     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2315     Persistent<Value> g2_children[] = { g2c1 };
2316     V8::AddObjectGroup(g1_objects, 2);
2317     V8::AddImplicitReferences(g1s1, g1_children, 1);
2318     V8::AddObjectGroup(g2_objects, 2);
2319     V8::AddImplicitReferences(g2s2, g2_children, 1);
2320   }
2321   // Do a single full GC, ensure incremental marking is stopped.
2322   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
2323
2324   // All object should be alive.
2325   CHECK_EQ(0, counter.NumberOfWeakCalls());
2326
2327   // Weaken the root.
2328   root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2329   // But make children strong roots---all the objects (except for children)
2330   // should be collectable now.
2331   g1c1.ClearWeak();
2332   g2c1.ClearWeak();
2333
2334   // Groups are deleted, rebuild groups.
2335   {
2336     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2337     Persistent<Value> g1_children[] = { g1c1 };
2338     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2339     Persistent<Value> g2_children[] = { g2c1 };
2340     V8::AddObjectGroup(g1_objects, 2);
2341     V8::AddImplicitReferences(g1s1, g1_children, 1);
2342     V8::AddObjectGroup(g2_objects, 2);
2343     V8::AddImplicitReferences(g2s2, g2_children, 1);
2344   }
2345
2346   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
2347
2348   // All objects should be gone. 5 global handles in total.
2349   CHECK_EQ(5, counter.NumberOfWeakCalls());
2350
2351   // And now make children weak again and collect them.
2352   g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2353   g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2354
2355   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
2356   CHECK_EQ(7, counter.NumberOfWeakCalls());
2357 }
2358
2359
2360 THREADED_TEST(ApiObjectGroupsCycle) {
2361   HandleScope scope;
2362   LocalContext env;
2363
2364   WeakCallCounter counter(1234);
2365
2366   Persistent<Object> g1s1;
2367   Persistent<Object> g1s2;
2368   Persistent<Object> g2s1;
2369   Persistent<Object> g2s2;
2370   Persistent<Object> g3s1;
2371   Persistent<Object> g3s2;
2372
2373   {
2374     HandleScope scope;
2375     g1s1 = Persistent<Object>::New(Object::New());
2376     g1s2 = Persistent<Object>::New(Object::New());
2377     g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2378     g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2379
2380     g2s1 = Persistent<Object>::New(Object::New());
2381     g2s2 = Persistent<Object>::New(Object::New());
2382     g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2383     g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2384
2385     g3s1 = Persistent<Object>::New(Object::New());
2386     g3s2 = Persistent<Object>::New(Object::New());
2387     g3s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2388     g3s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2389   }
2390
2391   Persistent<Object> root = Persistent<Object>::New(g1s1);  // make a root.
2392
2393   // Connect groups.  We're building the following cycle:
2394   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
2395   // groups.
2396   {
2397     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2398     Persistent<Value> g1_children[] = { g2s1 };
2399     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2400     Persistent<Value> g2_children[] = { g3s1 };
2401     Persistent<Value> g3_objects[] = { g3s1, g3s2 };
2402     Persistent<Value> g3_children[] = { g1s1 };
2403     V8::AddObjectGroup(g1_objects, 2);
2404     V8::AddImplicitReferences(g1s1, g1_children, 1);
2405     V8::AddObjectGroup(g2_objects, 2);
2406     V8::AddImplicitReferences(g2s1, g2_children, 1);
2407     V8::AddObjectGroup(g3_objects, 2);
2408     V8::AddImplicitReferences(g3s1, g3_children, 1);
2409   }
2410   // Do a single full GC
2411   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
2412
2413   // All object should be alive.
2414   CHECK_EQ(0, counter.NumberOfWeakCalls());
2415
2416   // Weaken the root.
2417   root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2418
2419   // Groups are deleted, rebuild groups.
2420   {
2421     Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2422     Persistent<Value> g1_children[] = { g2s1 };
2423     Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2424     Persistent<Value> g2_children[] = { g3s1 };
2425     Persistent<Value> g3_objects[] = { g3s1, g3s2 };
2426     Persistent<Value> g3_children[] = { g1s1 };
2427     V8::AddObjectGroup(g1_objects, 2);
2428     V8::AddImplicitReferences(g1s1, g1_children, 1);
2429     V8::AddObjectGroup(g2_objects, 2);
2430     V8::AddImplicitReferences(g2s1, g2_children, 1);
2431     V8::AddObjectGroup(g3_objects, 2);
2432     V8::AddImplicitReferences(g3s1, g3_children, 1);
2433   }
2434
2435   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
2436
2437   // All objects should be gone. 7 global handles in total.
2438   CHECK_EQ(7, counter.NumberOfWeakCalls());
2439 }
2440
2441
2442 THREADED_TEST(ScriptException) {
2443   v8::HandleScope scope;
2444   LocalContext env;
2445   Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
2446   v8::TryCatch try_catch;
2447   Local<Value> result = script->Run();
2448   CHECK(result.IsEmpty());
2449   CHECK(try_catch.HasCaught());
2450   String::AsciiValue exception_value(try_catch.Exception());
2451   CHECK_EQ(*exception_value, "panama!");
2452 }
2453
2454
2455 bool message_received;
2456
2457
2458 static void check_message_0(v8::Handle<v8::Message> message,
2459                             v8::Handle<Value> data) {
2460   CHECK_EQ(5.76, data->NumberValue());
2461   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
2462   CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
2463   message_received = true;
2464 }
2465
2466
2467 THREADED_TEST(MessageHandler0) {
2468   message_received = false;
2469   v8::HandleScope scope;
2470   CHECK(!message_received);
2471   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
2472   LocalContext context;
2473   v8::ScriptOrigin origin =
2474       v8::ScriptOrigin(v8_str("6.75"));
2475   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
2476                                                   &origin);
2477   script->SetData(v8_str("7.56"));
2478   script->Run();
2479   CHECK(message_received);
2480   // clear out the message listener
2481   v8::V8::RemoveMessageListeners(check_message_0);
2482 }
2483
2484
2485 static void check_message_1(v8::Handle<v8::Message> message,
2486                             v8::Handle<Value> data) {
2487   CHECK(data->IsNumber());
2488   CHECK_EQ(1337, data->Int32Value());
2489   message_received = true;
2490 }
2491
2492
2493 TEST(MessageHandler1) {
2494   message_received = false;
2495   v8::HandleScope scope;
2496   CHECK(!message_received);
2497   v8::V8::AddMessageListener(check_message_1);
2498   LocalContext context;
2499   CompileRun("throw 1337;");
2500   CHECK(message_received);
2501   // clear out the message listener
2502   v8::V8::RemoveMessageListeners(check_message_1);
2503 }
2504
2505
2506 static void check_message_2(v8::Handle<v8::Message> message,
2507                             v8::Handle<Value> data) {
2508   LocalContext context;
2509   CHECK(data->IsObject());
2510   v8::Local<v8::Value> hidden_property =
2511       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
2512   CHECK(v8_str("hidden value")->Equals(hidden_property));
2513   message_received = true;
2514 }
2515
2516
2517 TEST(MessageHandler2) {
2518   message_received = false;
2519   v8::HandleScope scope;
2520   CHECK(!message_received);
2521   v8::V8::AddMessageListener(check_message_2);
2522   LocalContext context;
2523   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
2524   v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
2525                                            v8_str("hidden value"));
2526   context->Global()->Set(v8_str("error"), error);
2527   CompileRun("throw error;");
2528   CHECK(message_received);
2529   // clear out the message listener
2530   v8::V8::RemoveMessageListeners(check_message_2);
2531 }
2532
2533
2534 THREADED_TEST(GetSetProperty) {
2535   v8::HandleScope scope;
2536   LocalContext context;
2537   context->Global()->Set(v8_str("foo"), v8_num(14));
2538   context->Global()->Set(v8_str("12"), v8_num(92));
2539   context->Global()->Set(v8::Integer::New(16), v8_num(32));
2540   context->Global()->Set(v8_num(13), v8_num(56));
2541   Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
2542   CHECK_EQ(14, foo->Int32Value());
2543   Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
2544   CHECK_EQ(92, twelve->Int32Value());
2545   Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
2546   CHECK_EQ(32, sixteen->Int32Value());
2547   Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
2548   CHECK_EQ(56, thirteen->Int32Value());
2549   CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
2550   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
2551   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
2552   CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
2553   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
2554   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
2555   CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
2556   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
2557   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
2558 }
2559
2560
2561 THREADED_TEST(PropertyAttributes) {
2562   v8::HandleScope scope;
2563   LocalContext context;
2564   // none
2565   Local<String> prop = v8_str("none");
2566   context->Global()->Set(prop, v8_num(7));
2567   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
2568   // read-only
2569   prop = v8_str("read_only");
2570   context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
2571   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
2572   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
2573   Script::Compile(v8_str("read_only = 9"))->Run();
2574   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
2575   context->Global()->Set(prop, v8_num(10));
2576   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
2577   // dont-delete
2578   prop = v8_str("dont_delete");
2579   context->Global()->Set(prop, v8_num(13), v8::DontDelete);
2580   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
2581   Script::Compile(v8_str("delete dont_delete"))->Run();
2582   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
2583   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
2584   // dont-enum
2585   prop = v8_str("dont_enum");
2586   context->Global()->Set(prop, v8_num(28), v8::DontEnum);
2587   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
2588   // absent
2589   prop = v8_str("absent");
2590   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
2591   Local<Value> fake_prop = v8_num(1);
2592   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
2593   // exception
2594   TryCatch try_catch;
2595   Local<Value> exception =
2596       CompileRun("({ toString: function() { throw 'exception';} })");
2597   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
2598   CHECK(try_catch.HasCaught());
2599   String::AsciiValue exception_value(try_catch.Exception());
2600   CHECK_EQ("exception", *exception_value);
2601   try_catch.Reset();
2602 }
2603
2604
2605 THREADED_TEST(Array) {
2606   v8::HandleScope scope;
2607   LocalContext context;
2608   Local<v8::Array> array = v8::Array::New();
2609   CHECK_EQ(0, array->Length());
2610   CHECK(array->Get(0)->IsUndefined());
2611   CHECK(!array->Has(0));
2612   CHECK(array->Get(100)->IsUndefined());
2613   CHECK(!array->Has(100));
2614   array->Set(2, v8_num(7));
2615   CHECK_EQ(3, array->Length());
2616   CHECK(!array->Has(0));
2617   CHECK(!array->Has(1));
2618   CHECK(array->Has(2));
2619   CHECK_EQ(7, array->Get(2)->Int32Value());
2620   Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
2621   Local<v8::Array> arr = obj.As<v8::Array>();
2622   CHECK_EQ(3, arr->Length());
2623   CHECK_EQ(1, arr->Get(0)->Int32Value());
2624   CHECK_EQ(2, arr->Get(1)->Int32Value());
2625   CHECK_EQ(3, arr->Get(2)->Int32Value());
2626   array = v8::Array::New(27);
2627   CHECK_EQ(27, array->Length());
2628   array = v8::Array::New(-27);
2629   CHECK_EQ(0, array->Length());
2630 }
2631
2632
2633 v8::Handle<Value> HandleF(const v8::Arguments& args) {
2634   v8::HandleScope scope;
2635   ApiTestFuzzer::Fuzz();
2636   Local<v8::Array> result = v8::Array::New(args.Length());
2637   for (int i = 0; i < args.Length(); i++)
2638     result->Set(i, args[i]);
2639   return scope.Close(result);
2640 }
2641
2642
2643 THREADED_TEST(Vector) {
2644   v8::HandleScope scope;
2645   Local<ObjectTemplate> global = ObjectTemplate::New();
2646   global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
2647   LocalContext context(0, global);
2648
2649   const char* fun = "f()";
2650   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
2651   CHECK_EQ(0, a0->Length());
2652
2653   const char* fun2 = "f(11)";
2654   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
2655   CHECK_EQ(1, a1->Length());
2656   CHECK_EQ(11, a1->Get(0)->Int32Value());
2657
2658   const char* fun3 = "f(12, 13)";
2659   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
2660   CHECK_EQ(2, a2->Length());
2661   CHECK_EQ(12, a2->Get(0)->Int32Value());
2662   CHECK_EQ(13, a2->Get(1)->Int32Value());
2663
2664   const char* fun4 = "f(14, 15, 16)";
2665   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
2666   CHECK_EQ(3, a3->Length());
2667   CHECK_EQ(14, a3->Get(0)->Int32Value());
2668   CHECK_EQ(15, a3->Get(1)->Int32Value());
2669   CHECK_EQ(16, a3->Get(2)->Int32Value());
2670
2671   const char* fun5 = "f(17, 18, 19, 20)";
2672   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
2673   CHECK_EQ(4, a4->Length());
2674   CHECK_EQ(17, a4->Get(0)->Int32Value());
2675   CHECK_EQ(18, a4->Get(1)->Int32Value());
2676   CHECK_EQ(19, a4->Get(2)->Int32Value());
2677   CHECK_EQ(20, a4->Get(3)->Int32Value());
2678 }
2679
2680
2681 THREADED_TEST(FunctionCall) {
2682   v8::HandleScope scope;
2683   LocalContext context;
2684   CompileRun(
2685     "function Foo() {"
2686     "  var result = [];"
2687     "  for (var i = 0; i < arguments.length; i++) {"
2688     "    result.push(arguments[i]);"
2689     "  }"
2690     "  return result;"
2691     "}");
2692   Local<Function> Foo =
2693       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
2694
2695   v8::Handle<Value>* args0 = NULL;
2696   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
2697   CHECK_EQ(0, a0->Length());
2698
2699   v8::Handle<Value> args1[] = { v8_num(1.1) };
2700   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
2701   CHECK_EQ(1, a1->Length());
2702   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
2703
2704   v8::Handle<Value> args2[] = { v8_num(2.2),
2705                                 v8_num(3.3) };
2706   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
2707   CHECK_EQ(2, a2->Length());
2708   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
2709   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
2710
2711   v8::Handle<Value> args3[] = { v8_num(4.4),
2712                                 v8_num(5.5),
2713                                 v8_num(6.6) };
2714   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
2715   CHECK_EQ(3, a3->Length());
2716   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
2717   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
2718   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
2719
2720   v8::Handle<Value> args4[] = { v8_num(7.7),
2721                                 v8_num(8.8),
2722                                 v8_num(9.9),
2723                                 v8_num(10.11) };
2724   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
2725   CHECK_EQ(4, a4->Length());
2726   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
2727   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
2728   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
2729   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
2730 }
2731
2732
2733 static const char* js_code_causing_out_of_memory =
2734     "var a = new Array(); while(true) a.push(a);";
2735
2736
2737 // These tests run for a long time and prevent us from running tests
2738 // that come after them so they cannot run in parallel.
2739 TEST(OutOfMemory) {
2740   // It's not possible to read a snapshot into a heap with different dimensions.
2741   if (i::Snapshot::IsEnabled()) return;
2742   // Set heap limits.
2743   static const int K = 1024;
2744   v8::ResourceConstraints constraints;
2745   constraints.set_max_young_space_size(256 * K);
2746   constraints.set_max_old_space_size(4 * K * K);
2747   v8::SetResourceConstraints(&constraints);
2748
2749   // Execute a script that causes out of memory.
2750   v8::HandleScope scope;
2751   LocalContext context;
2752   v8::V8::IgnoreOutOfMemoryException();
2753   Local<Script> script =
2754       Script::Compile(String::New(js_code_causing_out_of_memory));
2755   Local<Value> result = script->Run();
2756
2757   // Check for out of memory state.
2758   CHECK(result.IsEmpty());
2759   CHECK(context->HasOutOfMemoryException());
2760 }
2761
2762
2763 v8::Handle<Value> ProvokeOutOfMemory(const v8::Arguments& args) {
2764   ApiTestFuzzer::Fuzz();
2765
2766   v8::HandleScope scope;
2767   LocalContext context;
2768   Local<Script> script =
2769       Script::Compile(String::New(js_code_causing_out_of_memory));
2770   Local<Value> result = script->Run();
2771
2772   // Check for out of memory state.
2773   CHECK(result.IsEmpty());
2774   CHECK(context->HasOutOfMemoryException());
2775
2776   return result;
2777 }
2778
2779
2780 TEST(OutOfMemoryNested) {
2781   // It's not possible to read a snapshot into a heap with different dimensions.
2782   if (i::Snapshot::IsEnabled()) return;
2783   // Set heap limits.
2784   static const int K = 1024;
2785   v8::ResourceConstraints constraints;
2786   constraints.set_max_young_space_size(256 * K);
2787   constraints.set_max_old_space_size(4 * K * K);
2788   v8::SetResourceConstraints(&constraints);
2789
2790   v8::HandleScope scope;
2791   Local<ObjectTemplate> templ = ObjectTemplate::New();
2792   templ->Set(v8_str("ProvokeOutOfMemory"),
2793              v8::FunctionTemplate::New(ProvokeOutOfMemory));
2794   LocalContext context(0, templ);
2795   v8::V8::IgnoreOutOfMemoryException();
2796   Local<Value> result = CompileRun(
2797     "var thrown = false;"
2798     "try {"
2799     "  ProvokeOutOfMemory();"
2800     "} catch (e) {"
2801     "  thrown = true;"
2802     "}");
2803   // Check for out of memory state.
2804   CHECK(result.IsEmpty());
2805   CHECK(context->HasOutOfMemoryException());
2806 }
2807
2808
2809 TEST(HugeConsStringOutOfMemory) {
2810   // It's not possible to read a snapshot into a heap with different dimensions.
2811   if (i::Snapshot::IsEnabled()) return;
2812   // Set heap limits.
2813   static const int K = 1024;
2814   v8::ResourceConstraints constraints;
2815   constraints.set_max_young_space_size(256 * K);
2816   constraints.set_max_old_space_size(3 * K * K);
2817   v8::SetResourceConstraints(&constraints);
2818
2819   // Execute a script that causes out of memory.
2820   v8::V8::IgnoreOutOfMemoryException();
2821
2822   v8::HandleScope scope;
2823   LocalContext context;
2824
2825   // Build huge string. This should fail with out of memory exception.
2826   Local<Value> result = CompileRun(
2827     "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
2828     "for (var i = 0; i < 22; i++) { str = str + str; }");
2829
2830   // Check for out of memory state.
2831   CHECK(result.IsEmpty());
2832   CHECK(context->HasOutOfMemoryException());
2833 }
2834
2835
2836 THREADED_TEST(ConstructCall) {
2837   v8::HandleScope scope;
2838   LocalContext context;
2839   CompileRun(
2840     "function Foo() {"
2841     "  var result = [];"
2842     "  for (var i = 0; i < arguments.length; i++) {"
2843     "    result.push(arguments[i]);"
2844     "  }"
2845     "  return result;"
2846     "}");
2847   Local<Function> Foo =
2848       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
2849
2850   v8::Handle<Value>* args0 = NULL;
2851   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
2852   CHECK_EQ(0, a0->Length());
2853
2854   v8::Handle<Value> args1[] = { v8_num(1.1) };
2855   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
2856   CHECK_EQ(1, a1->Length());
2857   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
2858
2859   v8::Handle<Value> args2[] = { v8_num(2.2),
2860                                 v8_num(3.3) };
2861   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
2862   CHECK_EQ(2, a2->Length());
2863   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
2864   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
2865
2866   v8::Handle<Value> args3[] = { v8_num(4.4),
2867                                 v8_num(5.5),
2868                                 v8_num(6.6) };
2869   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
2870   CHECK_EQ(3, a3->Length());
2871   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
2872   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
2873   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
2874
2875   v8::Handle<Value> args4[] = { v8_num(7.7),
2876                                 v8_num(8.8),
2877                                 v8_num(9.9),
2878                                 v8_num(10.11) };
2879   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
2880   CHECK_EQ(4, a4->Length());
2881   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
2882   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
2883   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
2884   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
2885 }
2886
2887
2888 static void CheckUncle(v8::TryCatch* try_catch) {
2889   CHECK(try_catch->HasCaught());
2890   String::AsciiValue str_value(try_catch->Exception());
2891   CHECK_EQ(*str_value, "uncle?");
2892   try_catch->Reset();
2893 }
2894
2895
2896 THREADED_TEST(ConversionNumber) {
2897   v8::HandleScope scope;
2898   LocalContext env;
2899   // Very large number.
2900   CompileRun("var obj = Math.pow(2,32) * 1237;");
2901   Local<Value> obj = env->Global()->Get(v8_str("obj"));
2902   CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
2903   CHECK_EQ(0, obj->ToInt32()->Value());
2904   CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
2905   // Large number.
2906   CompileRun("var obj = -1234567890123;");
2907   obj = env->Global()->Get(v8_str("obj"));
2908   CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
2909   CHECK_EQ(-1912276171, obj->ToInt32()->Value());
2910   CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
2911   // Small positive integer.
2912   CompileRun("var obj = 42;");
2913   obj = env->Global()->Get(v8_str("obj"));
2914   CHECK_EQ(42.0, obj->ToNumber()->Value());
2915   CHECK_EQ(42, obj->ToInt32()->Value());
2916   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
2917   // Negative integer.
2918   CompileRun("var obj = -37;");
2919   obj = env->Global()->Get(v8_str("obj"));
2920   CHECK_EQ(-37.0, obj->ToNumber()->Value());
2921   CHECK_EQ(-37, obj->ToInt32()->Value());
2922   CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
2923   // Positive non-int32 integer.
2924   CompileRun("var obj = 0x81234567;");
2925   obj = env->Global()->Get(v8_str("obj"));
2926   CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
2927   CHECK_EQ(-2128394905, obj->ToInt32()->Value());
2928   CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
2929   // Fraction.
2930   CompileRun("var obj = 42.3;");
2931   obj = env->Global()->Get(v8_str("obj"));
2932   CHECK_EQ(42.3, obj->ToNumber()->Value());
2933   CHECK_EQ(42, obj->ToInt32()->Value());
2934   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
2935   // Large negative fraction.
2936   CompileRun("var obj = -5726623061.75;");
2937   obj = env->Global()->Get(v8_str("obj"));
2938   CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
2939   CHECK_EQ(-1431655765, obj->ToInt32()->Value());
2940   CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
2941 }
2942
2943
2944 THREADED_TEST(isNumberType) {
2945   v8::HandleScope scope;
2946   LocalContext env;
2947   // Very large number.
2948   CompileRun("var obj = Math.pow(2,32) * 1237;");
2949   Local<Value> obj = env->Global()->Get(v8_str("obj"));
2950   CHECK(!obj->IsInt32());
2951   CHECK(!obj->IsUint32());
2952   // Large negative number.
2953   CompileRun("var obj = -1234567890123;");
2954   obj = env->Global()->Get(v8_str("obj"));
2955   CHECK(!obj->IsInt32());
2956   CHECK(!obj->IsUint32());
2957   // Small positive integer.
2958   CompileRun("var obj = 42;");
2959   obj = env->Global()->Get(v8_str("obj"));
2960   CHECK(obj->IsInt32());
2961   CHECK(obj->IsUint32());
2962   // Negative integer.
2963   CompileRun("var obj = -37;");
2964   obj = env->Global()->Get(v8_str("obj"));
2965   CHECK(obj->IsInt32());
2966   CHECK(!obj->IsUint32());
2967   // Positive non-int32 integer.
2968   CompileRun("var obj = 0x81234567;");
2969   obj = env->Global()->Get(v8_str("obj"));
2970   CHECK(!obj->IsInt32());
2971   CHECK(obj->IsUint32());
2972   // Fraction.
2973   CompileRun("var obj = 42.3;");
2974   obj = env->Global()->Get(v8_str("obj"));
2975   CHECK(!obj->IsInt32());
2976   CHECK(!obj->IsUint32());
2977   // Large negative fraction.
2978   CompileRun("var obj = -5726623061.75;");
2979   obj = env->Global()->Get(v8_str("obj"));
2980   CHECK(!obj->IsInt32());
2981   CHECK(!obj->IsUint32());
2982   // Positive zero
2983   CompileRun("var obj = 0.0;");
2984   obj = env->Global()->Get(v8_str("obj"));
2985   CHECK(obj->IsInt32());
2986   CHECK(obj->IsUint32());
2987   // Positive zero
2988   CompileRun("var obj = -0.0;");
2989   obj = env->Global()->Get(v8_str("obj"));
2990   CHECK(!obj->IsInt32());
2991   CHECK(!obj->IsUint32());
2992 }
2993
2994
2995 THREADED_TEST(ConversionException) {
2996   v8::HandleScope scope;
2997   LocalContext env;
2998   CompileRun(
2999     "function TestClass() { };"
3000     "TestClass.prototype.toString = function () { throw 'uncle?'; };"
3001     "var obj = new TestClass();");
3002   Local<Value> obj = env->Global()->Get(v8_str("obj"));
3003
3004   v8::TryCatch try_catch;
3005
3006   Local<Value> to_string_result = obj->ToString();
3007   CHECK(to_string_result.IsEmpty());
3008   CheckUncle(&try_catch);
3009
3010   Local<Value> to_number_result = obj->ToNumber();
3011   CHECK(to_number_result.IsEmpty());
3012   CheckUncle(&try_catch);
3013
3014   Local<Value> to_integer_result = obj->ToInteger();
3015   CHECK(to_integer_result.IsEmpty());
3016   CheckUncle(&try_catch);
3017
3018   Local<Value> to_uint32_result = obj->ToUint32();
3019   CHECK(to_uint32_result.IsEmpty());
3020   CheckUncle(&try_catch);
3021
3022   Local<Value> to_int32_result = obj->ToInt32();
3023   CHECK(to_int32_result.IsEmpty());
3024   CheckUncle(&try_catch);
3025
3026   Local<Value> to_object_result = v8::Undefined()->ToObject();
3027   CHECK(to_object_result.IsEmpty());
3028   CHECK(try_catch.HasCaught());
3029   try_catch.Reset();
3030
3031   int32_t int32_value = obj->Int32Value();
3032   CHECK_EQ(0, int32_value);
3033   CheckUncle(&try_catch);
3034
3035   uint32_t uint32_value = obj->Uint32Value();
3036   CHECK_EQ(0, uint32_value);
3037   CheckUncle(&try_catch);
3038
3039   double number_value = obj->NumberValue();
3040   CHECK_NE(0, IsNaN(number_value));
3041   CheckUncle(&try_catch);
3042
3043   int64_t integer_value = obj->IntegerValue();
3044   CHECK_EQ(0.0, static_cast<double>(integer_value));
3045   CheckUncle(&try_catch);
3046 }
3047
3048
3049 v8::Handle<Value> ThrowFromC(const v8::Arguments& args) {
3050   ApiTestFuzzer::Fuzz();
3051   return v8::ThrowException(v8_str("konto"));
3052 }
3053
3054
3055 v8::Handle<Value> CCatcher(const v8::Arguments& args) {
3056   if (args.Length() < 1) return v8::False();
3057   v8::HandleScope scope;
3058   v8::TryCatch try_catch;
3059   Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
3060   CHECK(!try_catch.HasCaught() || result.IsEmpty());
3061   return v8::Boolean::New(try_catch.HasCaught());
3062 }
3063
3064
3065 THREADED_TEST(APICatch) {
3066   v8::HandleScope scope;
3067   Local<ObjectTemplate> templ = ObjectTemplate::New();
3068   templ->Set(v8_str("ThrowFromC"),
3069              v8::FunctionTemplate::New(ThrowFromC));
3070   LocalContext context(0, templ);
3071   CompileRun(
3072     "var thrown = false;"
3073     "try {"
3074     "  ThrowFromC();"
3075     "} catch (e) {"
3076     "  thrown = true;"
3077     "}");
3078   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
3079   CHECK(thrown->BooleanValue());
3080 }
3081
3082
3083 THREADED_TEST(APIThrowTryCatch) {
3084   v8::HandleScope scope;
3085   Local<ObjectTemplate> templ = ObjectTemplate::New();
3086   templ->Set(v8_str("ThrowFromC"),
3087              v8::FunctionTemplate::New(ThrowFromC));
3088   LocalContext context(0, templ);
3089   v8::TryCatch try_catch;
3090   CompileRun("ThrowFromC();");
3091   CHECK(try_catch.HasCaught());
3092 }
3093
3094
3095 // Test that a try-finally block doesn't shadow a try-catch block
3096 // when setting up an external handler.
3097 //
3098 // BUG(271): Some of the exception propagation does not work on the
3099 // ARM simulator because the simulator separates the C++ stack and the
3100 // JS stack.  This test therefore fails on the simulator.  The test is
3101 // not threaded to allow the threading tests to run on the simulator.
3102 TEST(TryCatchInTryFinally) {
3103   v8::HandleScope scope;
3104   Local<ObjectTemplate> templ = ObjectTemplate::New();
3105   templ->Set(v8_str("CCatcher"),
3106              v8::FunctionTemplate::New(CCatcher));
3107   LocalContext context(0, templ);
3108   Local<Value> result = CompileRun("try {"
3109                                    "  try {"
3110                                    "    CCatcher('throw 7;');"
3111                                    "  } finally {"
3112                                    "  }"
3113                                    "} catch (e) {"
3114                                    "}");
3115   CHECK(result->IsTrue());
3116 }
3117
3118
3119 static void check_reference_error_message(
3120     v8::Handle<v8::Message> message,
3121     v8::Handle<v8::Value> data) {
3122   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
3123   CHECK(message->Get()->Equals(v8_str(reference_error)));
3124 }
3125
3126
3127 static v8::Handle<Value> Fail(const v8::Arguments& args) {
3128   ApiTestFuzzer::Fuzz();
3129   CHECK(false);
3130   return v8::Undefined();
3131 }
3132
3133
3134 // Test that overwritten methods are not invoked on uncaught exception
3135 // formatting. However, they are invoked when performing normal error
3136 // string conversions.
3137 TEST(APIThrowMessageOverwrittenToString) {
3138   v8::HandleScope scope;
3139   v8::V8::AddMessageListener(check_reference_error_message);
3140   Local<ObjectTemplate> templ = ObjectTemplate::New();
3141   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
3142   LocalContext context(NULL, templ);
3143   CompileRun("asdf;");
3144   CompileRun("var limit = {};"
3145              "limit.valueOf = fail;"
3146              "Error.stackTraceLimit = limit;");
3147   CompileRun("asdf");
3148   CompileRun("Array.prototype.pop = fail;");
3149   CompileRun("Object.prototype.hasOwnProperty = fail;");
3150   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
3151   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
3152   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
3153   CompileRun("ReferenceError.prototype.toString ="
3154              "  function() { return 'Whoops' }");
3155   CompileRun("asdf;");
3156   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
3157   CompileRun("asdf;");
3158   CompileRun("ReferenceError.prototype.constructor = void 0;");
3159   CompileRun("asdf;");
3160   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
3161   CompileRun("asdf;");
3162   CompileRun("ReferenceError.prototype = new Object();");
3163   CompileRun("asdf;");
3164   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
3165   CHECK(string->Equals(v8_str("Whoops")));
3166   CompileRun("ReferenceError.prototype.constructor = new Object();"
3167              "ReferenceError.prototype.constructor.name = 1;"
3168              "Number.prototype.toString = function() { return 'Whoops'; };"
3169              "ReferenceError.prototype.toString = Object.prototype.toString;");
3170   CompileRun("asdf;");
3171   v8::V8::RemoveMessageListeners(check_reference_error_message);
3172 }
3173
3174
3175 static void check_custom_error_message(
3176     v8::Handle<v8::Message> message,
3177     v8::Handle<v8::Value> data) {
3178   const char* uncaught_error = "Uncaught MyError toString";
3179   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
3180 }
3181
3182
3183 TEST(CustomErrorToString) {
3184   v8::HandleScope scope;
3185   v8::V8::AddMessageListener(check_custom_error_message);
3186   LocalContext context;
3187   CompileRun(
3188     "function MyError(name, message) {                   "
3189     "  this.name = name;                                 "
3190     "  this.message = message;                           "
3191     "}                                                   "
3192     "MyError.prototype = Object.create(Error.prototype); "
3193     "MyError.prototype.toString = function() {           "
3194     "  return 'MyError toString';                        "
3195     "};                                                  "
3196     "throw new MyError('my name', 'my message');         ");
3197   v8::V8::RemoveMessageListeners(check_custom_error_message);
3198 }
3199
3200
3201 static void receive_message(v8::Handle<v8::Message> message,
3202                             v8::Handle<v8::Value> data) {
3203   message->Get();
3204   message_received = true;
3205 }
3206
3207
3208 TEST(APIThrowMessage) {
3209   message_received = false;
3210   v8::HandleScope scope;
3211   v8::V8::AddMessageListener(receive_message);
3212   Local<ObjectTemplate> templ = ObjectTemplate::New();
3213   templ->Set(v8_str("ThrowFromC"),
3214              v8::FunctionTemplate::New(ThrowFromC));
3215   LocalContext context(0, templ);
3216   CompileRun("ThrowFromC();");
3217   CHECK(message_received);
3218   v8::V8::RemoveMessageListeners(receive_message);
3219 }
3220
3221
3222 TEST(APIThrowMessageAndVerboseTryCatch) {
3223   message_received = false;
3224   v8::HandleScope scope;
3225   v8::V8::AddMessageListener(receive_message);
3226   Local<ObjectTemplate> templ = ObjectTemplate::New();
3227   templ->Set(v8_str("ThrowFromC"),
3228              v8::FunctionTemplate::New(ThrowFromC));
3229   LocalContext context(0, templ);
3230   v8::TryCatch try_catch;
3231   try_catch.SetVerbose(true);
3232   Local<Value> result = CompileRun("ThrowFromC();");
3233   CHECK(try_catch.HasCaught());
3234   CHECK(result.IsEmpty());
3235   CHECK(message_received);
3236   v8::V8::RemoveMessageListeners(receive_message);
3237 }
3238
3239
3240 TEST(APIStackOverflowAndVerboseTryCatch) {
3241   message_received = false;
3242   v8::HandleScope scope;
3243   v8::V8::AddMessageListener(receive_message);
3244   LocalContext context;
3245   v8::TryCatch try_catch;
3246   try_catch.SetVerbose(true);
3247   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
3248   CHECK(try_catch.HasCaught());
3249   CHECK(result.IsEmpty());
3250   CHECK(message_received);
3251   v8::V8::RemoveMessageListeners(receive_message);
3252 }
3253
3254
3255 THREADED_TEST(ExternalScriptException) {
3256   v8::HandleScope scope;
3257   Local<ObjectTemplate> templ = ObjectTemplate::New();
3258   templ->Set(v8_str("ThrowFromC"),
3259              v8::FunctionTemplate::New(ThrowFromC));
3260   LocalContext context(0, templ);
3261
3262   v8::TryCatch try_catch;
3263   Local<Script> script
3264       = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
3265   Local<Value> result = script->Run();
3266   CHECK(result.IsEmpty());
3267   CHECK(try_catch.HasCaught());
3268   String::AsciiValue exception_value(try_catch.Exception());
3269   CHECK_EQ("konto", *exception_value);
3270 }
3271
3272
3273
3274 v8::Handle<Value> CThrowCountDown(const v8::Arguments& args) {
3275   ApiTestFuzzer::Fuzz();
3276   CHECK_EQ(4, args.Length());
3277   int count = args[0]->Int32Value();
3278   int cInterval = args[2]->Int32Value();
3279   if (count == 0) {
3280     return v8::ThrowException(v8_str("FromC"));
3281   } else {
3282     Local<v8::Object> global = Context::GetCurrent()->Global();
3283     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
3284     v8::Handle<Value> argv[] = { v8_num(count - 1),
3285                                  args[1],
3286                                  args[2],
3287                                  args[3] };
3288     if (count % cInterval == 0) {
3289       v8::TryCatch try_catch;
3290       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
3291       int expected = args[3]->Int32Value();
3292       if (try_catch.HasCaught()) {
3293         CHECK_EQ(expected, count);
3294         CHECK(result.IsEmpty());
3295         CHECK(!i::Isolate::Current()->has_scheduled_exception());
3296       } else {
3297         CHECK_NE(expected, count);
3298       }
3299       return result;
3300     } else {
3301       return fun.As<Function>()->Call(global, 4, argv);
3302     }
3303   }
3304 }
3305
3306
3307 v8::Handle<Value> JSCheck(const v8::Arguments& args) {
3308   ApiTestFuzzer::Fuzz();
3309   CHECK_EQ(3, args.Length());
3310   bool equality = args[0]->BooleanValue();
3311   int count = args[1]->Int32Value();
3312   int expected = args[2]->Int32Value();
3313   if (equality) {
3314     CHECK_EQ(count, expected);
3315   } else {
3316     CHECK_NE(count, expected);
3317   }
3318   return v8::Undefined();
3319 }
3320
3321
3322 THREADED_TEST(EvalInTryFinally) {
3323   v8::HandleScope scope;
3324   LocalContext context;
3325   v8::TryCatch try_catch;
3326   CompileRun("(function() {"
3327              "  try {"
3328              "    eval('asldkf (*&^&*^');"
3329              "  } finally {"
3330              "    return;"
3331              "  }"
3332              "})()");
3333   CHECK(!try_catch.HasCaught());
3334 }
3335
3336
3337 // This test works by making a stack of alternating JavaScript and C
3338 // activations.  These activations set up exception handlers with regular
3339 // intervals, one interval for C activations and another for JavaScript
3340 // activations.  When enough activations have been created an exception is
3341 // thrown and we check that the right activation catches the exception and that
3342 // no other activations do.  The right activation is always the topmost one with
3343 // a handler, regardless of whether it is in JavaScript or C.
3344 //
3345 // The notation used to describe a test case looks like this:
3346 //
3347 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
3348 //
3349 // Each entry is an activation, either JS or C.  The index is the count at that
3350 // level.  Stars identify activations with exception handlers, the @ identifies
3351 // the exception handler that should catch the exception.
3352 //
3353 // BUG(271): Some of the exception propagation does not work on the
3354 // ARM simulator because the simulator separates the C++ stack and the
3355 // JS stack.  This test therefore fails on the simulator.  The test is
3356 // not threaded to allow the threading tests to run on the simulator.
3357 TEST(ExceptionOrder) {
3358   v8::HandleScope scope;
3359   Local<ObjectTemplate> templ = ObjectTemplate::New();
3360   templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
3361   templ->Set(v8_str("CThrowCountDown"),
3362              v8::FunctionTemplate::New(CThrowCountDown));
3363   LocalContext context(0, templ);
3364   CompileRun(
3365     "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
3366     "  if (count == 0) throw 'FromJS';"
3367     "  if (count % jsInterval == 0) {"
3368     "    try {"
3369     "      var value = CThrowCountDown(count - 1,"
3370     "                                  jsInterval,"
3371     "                                  cInterval,"
3372     "                                  expected);"
3373     "      check(false, count, expected);"
3374     "      return value;"
3375     "    } catch (e) {"
3376     "      check(true, count, expected);"
3377     "    }"
3378     "  } else {"
3379     "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
3380     "  }"
3381     "}");
3382   Local<Function> fun =
3383       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
3384
3385   const int argc = 4;
3386   //                             count      jsInterval cInterval  expected
3387
3388   // *JS[4] *C[3] @JS[2] C[1] JS[0]
3389   v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
3390   fun->Call(fun, argc, a0);
3391
3392   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
3393   v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
3394   fun->Call(fun, argc, a1);
3395
3396   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
3397   v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
3398   fun->Call(fun, argc, a2);
3399
3400   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
3401   v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
3402   fun->Call(fun, argc, a3);
3403
3404   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
3405   v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
3406   fun->Call(fun, argc, a4);
3407
3408   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
3409   v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
3410   fun->Call(fun, argc, a5);
3411 }
3412
3413
3414 v8::Handle<Value> ThrowValue(const v8::Arguments& args) {
3415   ApiTestFuzzer::Fuzz();
3416   CHECK_EQ(1, args.Length());
3417   return v8::ThrowException(args[0]);
3418 }
3419
3420
3421 THREADED_TEST(ThrowValues) {
3422   v8::HandleScope scope;
3423   Local<ObjectTemplate> templ = ObjectTemplate::New();
3424   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
3425   LocalContext context(0, templ);
3426   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
3427     "function Run(obj) {"
3428     "  try {"
3429     "    Throw(obj);"
3430     "  } catch (e) {"
3431     "    return e;"
3432     "  }"
3433     "  return 'no exception';"
3434     "}"
3435     "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
3436   CHECK_EQ(5, result->Length());
3437   CHECK(result->Get(v8::Integer::New(0))->IsString());
3438   CHECK(result->Get(v8::Integer::New(1))->IsNumber());
3439   CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
3440   CHECK(result->Get(v8::Integer::New(2))->IsNumber());
3441   CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
3442   CHECK(result->Get(v8::Integer::New(3))->IsNull());
3443   CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
3444 }
3445
3446
3447 THREADED_TEST(CatchZero) {
3448   v8::HandleScope scope;
3449   LocalContext context;
3450   v8::TryCatch try_catch;
3451   CHECK(!try_catch.HasCaught());
3452   Script::Compile(v8_str("throw 10"))->Run();
3453   CHECK(try_catch.HasCaught());
3454   CHECK_EQ(10, try_catch.Exception()->Int32Value());
3455   try_catch.Reset();
3456   CHECK(!try_catch.HasCaught());
3457   Script::Compile(v8_str("throw 0"))->Run();
3458   CHECK(try_catch.HasCaught());
3459   CHECK_EQ(0, try_catch.Exception()->Int32Value());
3460 }
3461
3462
3463 THREADED_TEST(CatchExceptionFromWith) {
3464   v8::HandleScope scope;
3465   LocalContext context;
3466   v8::TryCatch try_catch;
3467   CHECK(!try_catch.HasCaught());
3468   Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
3469   CHECK(try_catch.HasCaught());
3470 }
3471
3472
3473 THREADED_TEST(TryCatchAndFinallyHidingException) {
3474   v8::HandleScope scope;
3475   LocalContext context;
3476   v8::TryCatch try_catch;
3477   CHECK(!try_catch.HasCaught());
3478   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
3479   CompileRun("f({toString: function() { throw 42; }});");
3480   CHECK(!try_catch.HasCaught());
3481 }
3482
3483
3484 v8::Handle<v8::Value> WithTryCatch(const v8::Arguments& args) {
3485   v8::TryCatch try_catch;
3486   return v8::Undefined();
3487 }
3488
3489
3490 THREADED_TEST(TryCatchAndFinally) {
3491   v8::HandleScope scope;
3492   LocalContext context;
3493   context->Global()->Set(
3494       v8_str("native_with_try_catch"),
3495       v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
3496   v8::TryCatch try_catch;
3497   CHECK(!try_catch.HasCaught());
3498   CompileRun(
3499       "try {\n"
3500       "  throw new Error('a');\n"
3501       "} finally {\n"
3502       "  native_with_try_catch();\n"
3503       "}\n");
3504   CHECK(try_catch.HasCaught());
3505 }
3506
3507
3508 THREADED_TEST(Equality) {
3509   v8::HandleScope scope;
3510   LocalContext context;
3511   // Check that equality works at all before relying on CHECK_EQ
3512   CHECK(v8_str("a")->Equals(v8_str("a")));
3513   CHECK(!v8_str("a")->Equals(v8_str("b")));
3514
3515   CHECK_EQ(v8_str("a"), v8_str("a"));
3516   CHECK_NE(v8_str("a"), v8_str("b"));
3517   CHECK_EQ(v8_num(1), v8_num(1));
3518   CHECK_EQ(v8_num(1.00), v8_num(1));
3519   CHECK_NE(v8_num(1), v8_num(2));
3520
3521   // Assume String is not symbol.
3522   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
3523   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
3524   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
3525   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
3526   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
3527   CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
3528   Local<Value> not_a_number = v8_num(i::OS::nan_value());
3529   CHECK(!not_a_number->StrictEquals(not_a_number));
3530   CHECK(v8::False()->StrictEquals(v8::False()));
3531   CHECK(!v8::False()->StrictEquals(v8::Undefined()));
3532
3533   v8::Handle<v8::Object> obj = v8::Object::New();
3534   v8::Persistent<v8::Object> alias = v8::Persistent<v8::Object>::New(obj);
3535   CHECK(alias->StrictEquals(obj));
3536   alias.Dispose();
3537 }
3538
3539
3540 THREADED_TEST(MultiRun) {
3541   v8::HandleScope scope;
3542   LocalContext context;
3543   Local<Script> script = Script::Compile(v8_str("x"));
3544   for (int i = 0; i < 10; i++)
3545     script->Run();
3546 }
3547
3548
3549 static v8::Handle<Value> GetXValue(Local<String> name,
3550                                    const AccessorInfo& info) {
3551   ApiTestFuzzer::Fuzz();
3552   CHECK_EQ(info.Data(), v8_str("donut"));
3553   CHECK_EQ(name, v8_str("x"));
3554   return name;
3555 }
3556
3557
3558 THREADED_TEST(SimplePropertyRead) {
3559   v8::HandleScope scope;
3560   Local<ObjectTemplate> templ = ObjectTemplate::New();
3561   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
3562   LocalContext context;
3563   context->Global()->Set(v8_str("obj"), templ->NewInstance());
3564   Local<Script> script = Script::Compile(v8_str("obj.x"));
3565   for (int i = 0; i < 10; i++) {
3566     Local<Value> result = script->Run();
3567     CHECK_EQ(result, v8_str("x"));
3568   }
3569 }
3570
3571 THREADED_TEST(DefinePropertyOnAPIAccessor) {
3572   v8::HandleScope scope;
3573   Local<ObjectTemplate> templ = ObjectTemplate::New();
3574   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
3575   LocalContext context;
3576   context->Global()->Set(v8_str("obj"), templ->NewInstance());
3577
3578   // Uses getOwnPropertyDescriptor to check the configurable status
3579   Local<Script> script_desc
3580     = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
3581                              "obj, 'x');"
3582                              "prop.configurable;"));
3583   Local<Value> result = script_desc->Run();
3584   CHECK_EQ(result->BooleanValue(), true);
3585
3586   // Redefine get - but still configurable
3587   Local<Script> script_define
3588     = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
3589                              "            configurable: true };"
3590                              "Object.defineProperty(obj, 'x', desc);"
3591                              "obj.x"));
3592   result = script_define->Run();
3593   CHECK_EQ(result, v8_num(42));
3594
3595   // Check that the accessor is still configurable
3596   result = script_desc->Run();
3597   CHECK_EQ(result->BooleanValue(), true);
3598
3599   // Redefine to a non-configurable
3600   script_define
3601     = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
3602                              "             configurable: false };"
3603                              "Object.defineProperty(obj, 'x', desc);"
3604                              "obj.x"));
3605   result = script_define->Run();
3606   CHECK_EQ(result, v8_num(43));
3607   result = script_desc->Run();
3608   CHECK_EQ(result->BooleanValue(), false);
3609
3610   // Make sure that it is not possible to redefine again
3611   v8::TryCatch try_catch;
3612   result = script_define->Run();
3613   CHECK(try_catch.HasCaught());
3614   String::AsciiValue exception_value(try_catch.Exception());
3615   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
3616 }
3617
3618 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
3619   v8::HandleScope scope;
3620   Local<ObjectTemplate> templ = ObjectTemplate::New();
3621   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
3622   LocalContext context;
3623   context->Global()->Set(v8_str("obj"), templ->NewInstance());
3624
3625   Local<Script> script_desc = Script::Compile(v8_str("var prop ="
3626                                     "Object.getOwnPropertyDescriptor( "
3627                                     "obj, 'x');"
3628                                     "prop.configurable;"));
3629   Local<Value> result = script_desc->Run();
3630   CHECK_EQ(result->BooleanValue(), true);
3631
3632   Local<Script> script_define =
3633     Script::Compile(v8_str("var desc = {get: function(){return 42; },"
3634                            "            configurable: true };"
3635                            "Object.defineProperty(obj, 'x', desc);"
3636                            "obj.x"));
3637   result = script_define->Run();
3638   CHECK_EQ(result, v8_num(42));
3639
3640
3641   result = script_desc->Run();
3642   CHECK_EQ(result->BooleanValue(), true);
3643
3644
3645   script_define =
3646     Script::Compile(v8_str("var desc = {get: function(){return 43; },"
3647                            "            configurable: false };"
3648                            "Object.defineProperty(obj, 'x', desc);"
3649                            "obj.x"));
3650   result = script_define->Run();
3651   CHECK_EQ(result, v8_num(43));
3652   result = script_desc->Run();
3653
3654   CHECK_EQ(result->BooleanValue(), false);
3655
3656   v8::TryCatch try_catch;
3657   result = script_define->Run();
3658   CHECK(try_catch.HasCaught());
3659   String::AsciiValue exception_value(try_catch.Exception());
3660   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
3661 }
3662
3663
3664 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
3665                                                 char const* name) {
3666   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
3667 }
3668
3669
3670 THREADED_TEST(DefineAPIAccessorOnObject) {
3671   v8::HandleScope scope;
3672   Local<ObjectTemplate> templ = ObjectTemplate::New();
3673   LocalContext context;
3674
3675   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
3676   CompileRun("var obj2 = {};");
3677
3678   CHECK(CompileRun("obj1.x")->IsUndefined());
3679   CHECK(CompileRun("obj2.x")->IsUndefined());
3680
3681   CHECK(GetGlobalProperty(&context, "obj1")->
3682       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
3683
3684   ExpectString("obj1.x", "x");
3685   CHECK(CompileRun("obj2.x")->IsUndefined());
3686
3687   CHECK(GetGlobalProperty(&context, "obj2")->
3688       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
3689
3690   ExpectString("obj1.x", "x");
3691   ExpectString("obj2.x", "x");
3692
3693   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
3694   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
3695
3696   CompileRun("Object.defineProperty(obj1, 'x',"
3697              "{ get: function() { return 'y'; }, configurable: true })");
3698
3699   ExpectString("obj1.x", "y");
3700   ExpectString("obj2.x", "x");
3701
3702   CompileRun("Object.defineProperty(obj2, 'x',"
3703              "{ get: function() { return 'y'; }, configurable: true })");
3704
3705   ExpectString("obj1.x", "y");
3706   ExpectString("obj2.x", "y");
3707
3708   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
3709   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
3710
3711   CHECK(GetGlobalProperty(&context, "obj1")->
3712       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
3713   CHECK(GetGlobalProperty(&context, "obj2")->
3714       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
3715
3716   ExpectString("obj1.x", "x");
3717   ExpectString("obj2.x", "x");
3718
3719   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
3720   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
3721
3722   // Define getters/setters, but now make them not configurable.
3723   CompileRun("Object.defineProperty(obj1, 'x',"
3724              "{ get: function() { return 'z'; }, configurable: false })");
3725   CompileRun("Object.defineProperty(obj2, 'x',"
3726              "{ get: function() { return 'z'; }, configurable: false })");
3727
3728   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
3729   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
3730
3731   ExpectString("obj1.x", "z");
3732   ExpectString("obj2.x", "z");
3733
3734   CHECK(!GetGlobalProperty(&context, "obj1")->
3735       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
3736   CHECK(!GetGlobalProperty(&context, "obj2")->
3737       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
3738
3739   ExpectString("obj1.x", "z");
3740   ExpectString("obj2.x", "z");
3741 }
3742
3743
3744 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
3745   v8::HandleScope scope;
3746   Local<ObjectTemplate> templ = ObjectTemplate::New();
3747   LocalContext context;
3748
3749   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
3750   CompileRun("var obj2 = {};");
3751
3752   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
3753         v8_str("x"),
3754         GetXValue, NULL,
3755         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
3756   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
3757         v8_str("x"),
3758         GetXValue, NULL,
3759         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
3760
3761   ExpectString("obj1.x", "x");
3762   ExpectString("obj2.x", "x");
3763
3764   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
3765   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
3766
3767   CHECK(!GetGlobalProperty(&context, "obj1")->
3768       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
3769   CHECK(!GetGlobalProperty(&context, "obj2")->
3770       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
3771
3772   {
3773     v8::TryCatch try_catch;
3774     CompileRun("Object.defineProperty(obj1, 'x',"
3775         "{get: function() { return 'func'; }})");
3776     CHECK(try_catch.HasCaught());
3777     String::AsciiValue exception_value(try_catch.Exception());
3778     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
3779   }
3780   {
3781     v8::TryCatch try_catch;
3782     CompileRun("Object.defineProperty(obj2, 'x',"
3783         "{get: function() { return 'func'; }})");
3784     CHECK(try_catch.HasCaught());
3785     String::AsciiValue exception_value(try_catch.Exception());
3786     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
3787   }
3788 }
3789
3790
3791 static v8::Handle<Value> Get239Value(Local<String> name,
3792                                      const AccessorInfo& info) {
3793   ApiTestFuzzer::Fuzz();
3794   CHECK_EQ(info.Data(), v8_str("donut"));
3795   CHECK_EQ(name, v8_str("239"));
3796   return name;
3797 }
3798
3799
3800 THREADED_TEST(ElementAPIAccessor) {
3801   v8::HandleScope scope;
3802   Local<ObjectTemplate> templ = ObjectTemplate::New();
3803   LocalContext context;
3804
3805   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
3806   CompileRun("var obj2 = {};");
3807
3808   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
3809         v8_str("239"),
3810         Get239Value, NULL,
3811         v8_str("donut")));
3812   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
3813         v8_str("239"),
3814         Get239Value, NULL,
3815         v8_str("donut")));
3816
3817   ExpectString("obj1[239]", "239");
3818   ExpectString("obj2[239]", "239");
3819   ExpectString("obj1['239']", "239");
3820   ExpectString("obj2['239']", "239");
3821 }
3822
3823
3824 v8::Persistent<Value> xValue;
3825
3826
3827 static void SetXValue(Local<String> name,
3828                       Local<Value> value,
3829                       const AccessorInfo& info) {
3830   CHECK_EQ(value, v8_num(4));
3831   CHECK_EQ(info.Data(), v8_str("donut"));
3832   CHECK_EQ(name, v8_str("x"));
3833   CHECK(xValue.IsEmpty());
3834   xValue = v8::Persistent<Value>::New(value);
3835 }
3836
3837
3838 THREADED_TEST(SimplePropertyWrite) {
3839   v8::HandleScope scope;
3840   Local<ObjectTemplate> templ = ObjectTemplate::New();
3841   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
3842   LocalContext context;
3843   context->Global()->Set(v8_str("obj"), templ->NewInstance());
3844   Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
3845   for (int i = 0; i < 10; i++) {
3846     CHECK(xValue.IsEmpty());
3847     script->Run();
3848     CHECK_EQ(v8_num(4), xValue);
3849     xValue.Dispose();
3850     xValue = v8::Persistent<Value>();
3851   }
3852 }
3853
3854
3855 THREADED_TEST(SetterOnly) {
3856   v8::HandleScope scope;
3857   Local<ObjectTemplate> templ = ObjectTemplate::New();
3858   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
3859   LocalContext context;
3860   context->Global()->Set(v8_str("obj"), templ->NewInstance());
3861   Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
3862   for (int i = 0; i < 10; i++) {
3863     CHECK(xValue.IsEmpty());
3864     script->Run();
3865     CHECK_EQ(v8_num(4), xValue);
3866     xValue.Dispose();
3867     xValue = v8::Persistent<Value>();
3868   }
3869 }
3870
3871
3872 THREADED_TEST(NoAccessors) {
3873   v8::HandleScope scope;
3874   Local<ObjectTemplate> templ = ObjectTemplate::New();
3875   templ->SetAccessor(v8_str("x"), NULL, NULL, v8_str("donut"));
3876   LocalContext context;
3877   context->Global()->Set(v8_str("obj"), templ->NewInstance());
3878   Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
3879   for (int i = 0; i < 10; i++) {
3880     script->Run();
3881   }
3882 }
3883
3884
3885 static v8::Handle<Value> XPropertyGetter(Local<String> property,
3886                                          const AccessorInfo& info) {
3887   ApiTestFuzzer::Fuzz();
3888   CHECK(info.Data()->IsUndefined());
3889   return property;
3890 }
3891
3892
3893 THREADED_TEST(NamedInterceptorPropertyRead) {
3894   v8::HandleScope scope;
3895   Local<ObjectTemplate> templ = ObjectTemplate::New();
3896   templ->SetNamedPropertyHandler(XPropertyGetter);
3897   LocalContext context;
3898   context->Global()->Set(v8_str("obj"), templ->NewInstance());
3899   Local<Script> script = Script::Compile(v8_str("obj.x"));
3900   for (int i = 0; i < 10; i++) {
3901     Local<Value> result = script->Run();
3902     CHECK_EQ(result, v8_str("x"));
3903   }
3904 }
3905
3906
3907 THREADED_TEST(NamedInterceptorDictionaryIC) {
3908   v8::HandleScope scope;
3909   Local<ObjectTemplate> templ = ObjectTemplate::New();
3910   templ->SetNamedPropertyHandler(XPropertyGetter);
3911   LocalContext context;
3912   // Create an object with a named interceptor.
3913   context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
3914   Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
3915   for (int i = 0; i < 10; i++) {
3916     Local<Value> result = script->Run();
3917     CHECK_EQ(result, v8_str("x"));
3918   }
3919   // Create a slow case object and a function accessing a property in
3920   // that slow case object (with dictionary probing in generated
3921   // code). Then force object with a named interceptor into slow-case,
3922   // pass it to the function, and check that the interceptor is called
3923   // instead of accessing the local property.
3924   Local<Value> result =
3925       CompileRun("function get_x(o) { return o.x; };"
3926                  "var obj = { x : 42, y : 0 };"
3927                  "delete obj.y;"
3928                  "for (var i = 0; i < 10; i++) get_x(obj);"
3929                  "interceptor_obj.x = 42;"
3930                  "interceptor_obj.y = 10;"
3931                  "delete interceptor_obj.y;"
3932                  "get_x(interceptor_obj)");
3933   CHECK_EQ(result, v8_str("x"));
3934 }
3935
3936
3937 THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
3938   v8::HandleScope scope;
3939
3940   v8::Persistent<Context> context1 = Context::New();
3941
3942   context1->Enter();
3943   Local<ObjectTemplate> templ = ObjectTemplate::New();
3944   templ->SetNamedPropertyHandler(XPropertyGetter);
3945   // Create an object with a named interceptor.
3946   v8::Local<v8::Object> object = templ->NewInstance();
3947   context1->Global()->Set(v8_str("interceptor_obj"), object);
3948
3949   // Force the object into the slow case.
3950   CompileRun("interceptor_obj.y = 0;"
3951              "delete interceptor_obj.y;");
3952   context1->Exit();
3953
3954   {
3955     // Introduce the object into a different context.
3956     // Repeat named loads to exercise ICs.
3957     LocalContext context2;
3958     context2->Global()->Set(v8_str("interceptor_obj"), object);
3959     Local<Value> result =
3960       CompileRun("function get_x(o) { return o.x; }"
3961                  "interceptor_obj.x = 42;"
3962                  "for (var i=0; i != 10; i++) {"
3963                  "  get_x(interceptor_obj);"
3964                  "}"
3965                  "get_x(interceptor_obj)");
3966     // Check that the interceptor was actually invoked.
3967     CHECK_EQ(result, v8_str("x"));
3968   }
3969
3970   // Return to the original context and force some object to the slow case
3971   // to cause the NormalizedMapCache to verify.
3972   context1->Enter();
3973   CompileRun("var obj = { x : 0 }; delete obj.x;");
3974   context1->Exit();
3975
3976   context1.Dispose();
3977 }
3978
3979
3980 static v8::Handle<Value> SetXOnPrototypeGetter(Local<String> property,
3981                                                const AccessorInfo& info) {
3982   // Set x on the prototype object and do not handle the get request.
3983   v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
3984   proto.As<v8::Object>()->Set(v8_str("x"), v8::Integer::New(23));
3985   return v8::Handle<Value>();
3986 }
3987
3988
3989 // This is a regression test for http://crbug.com/20104. Map
3990 // transitions should not interfere with post interceptor lookup.
3991 THREADED_TEST(NamedInterceptorMapTransitionRead) {
3992   v8::HandleScope scope;
3993   Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
3994   Local<v8::ObjectTemplate> instance_template
3995       = function_template->InstanceTemplate();
3996   instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
3997   LocalContext context;
3998   context->Global()->Set(v8_str("F"), function_template->GetFunction());
3999   // Create an instance of F and introduce a map transition for x.
4000   CompileRun("var o = new F(); o.x = 23;");
4001   // Create an instance of F and invoke the getter. The result should be 23.
4002   Local<Value> result = CompileRun("o = new F(); o.x");
4003   CHECK_EQ(result->Int32Value(), 23);
4004 }
4005
4006
4007 static v8::Handle<Value> IndexedPropertyGetter(uint32_t index,
4008                                                const AccessorInfo& info) {
4009   ApiTestFuzzer::Fuzz();
4010   if (index == 37) {
4011     return v8::Handle<Value>(v8_num(625));
4012   }
4013   return v8::Handle<Value>();
4014 }
4015
4016
4017 static v8::Handle<Value> IndexedPropertySetter(uint32_t index,
4018                                                Local<Value> value,
4019                                                const AccessorInfo& info) {
4020   ApiTestFuzzer::Fuzz();
4021   if (index == 39) {
4022     return value;
4023   }
4024   return v8::Handle<Value>();
4025 }
4026
4027
4028 THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
4029   v8::HandleScope scope;
4030   Local<ObjectTemplate> templ = ObjectTemplate::New();
4031   templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
4032                                    IndexedPropertySetter);
4033   LocalContext context;
4034   context->Global()->Set(v8_str("obj"), templ->NewInstance());
4035   Local<Script> getter_script = Script::Compile(v8_str(
4036       "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
4037   Local<Script> setter_script = Script::Compile(v8_str(
4038       "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
4039       "obj[17] = 23;"
4040       "obj.foo;"));
4041   Local<Script> interceptor_setter_script = Script::Compile(v8_str(
4042       "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
4043       "obj[39] = 47;"
4044       "obj.foo;"));  // This setter should not run, due to the interceptor.
4045   Local<Script> interceptor_getter_script = Script::Compile(v8_str(
4046       "obj[37];"));
4047   Local<Value> result = getter_script->Run();
4048   CHECK_EQ(v8_num(5), result);
4049   result = setter_script->Run();
4050   CHECK_EQ(v8_num(23), result);
4051   result = interceptor_setter_script->Run();
4052   CHECK_EQ(v8_num(23), result);
4053   result = interceptor_getter_script->Run();
4054   CHECK_EQ(v8_num(625), result);
4055 }
4056
4057
4058 static v8::Handle<Value> UnboxedDoubleIndexedPropertyGetter(
4059     uint32_t index,
4060     const AccessorInfo& info) {
4061   ApiTestFuzzer::Fuzz();
4062   if (index < 25) {
4063     return v8::Handle<Value>(v8_num(index));
4064   }
4065   return v8::Handle<Value>();
4066 }
4067
4068
4069 static v8::Handle<Value> UnboxedDoubleIndexedPropertySetter(
4070     uint32_t index,
4071     Local<Value> value,
4072     const AccessorInfo& info) {
4073   ApiTestFuzzer::Fuzz();
4074   if (index < 25) {
4075     return v8::Handle<Value>(v8_num(index));
4076   }
4077   return v8::Handle<Value>();
4078 }
4079
4080
4081 Handle<v8::Array> UnboxedDoubleIndexedPropertyEnumerator(
4082     const AccessorInfo& info) {
4083   // Force the list of returned keys to be stored in a FastDoubleArray.
4084   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
4085       "keys = new Array(); keys[125000] = 1;"
4086       "for(i = 0; i < 80000; i++) { keys[i] = i; };"
4087       "keys.length = 25; keys;"));
4088   Local<Value> result = indexed_property_names_script->Run();
4089   return Local<v8::Array>(::v8::Array::Cast(*result));
4090 }
4091
4092
4093 // Make sure that the the interceptor code in the runtime properly handles
4094 // merging property name lists for double-array-backed arrays.
4095 THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
4096   v8::HandleScope scope;
4097   Local<ObjectTemplate> templ = ObjectTemplate::New();
4098   templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
4099                                    UnboxedDoubleIndexedPropertySetter,
4100                                    0,
4101                                    0,
4102                                    UnboxedDoubleIndexedPropertyEnumerator);
4103   LocalContext context;
4104   context->Global()->Set(v8_str("obj"), templ->NewInstance());
4105   // When obj is created, force it to be Stored in a FastDoubleArray.
4106   Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
4107       "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
4108       "key_count = 0; "
4109       "for (x in obj) {key_count++;};"
4110       "obj;"));
4111   Local<Value> result = create_unboxed_double_script->Run();
4112   CHECK(result->ToObject()->HasRealIndexedProperty(2000));
4113   Local<Script> key_count_check = Script::Compile(v8_str(
4114       "key_count;"));
4115   result = key_count_check->Run();
4116   CHECK_EQ(v8_num(40013), result);
4117 }
4118
4119
4120 Handle<v8::Array> NonStrictArgsIndexedPropertyEnumerator(
4121     const AccessorInfo& info) {
4122   // Force the list of returned keys to be stored in a Arguments object.
4123   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
4124       "function f(w,x) {"
4125       " return arguments;"
4126       "}"
4127       "keys = f(0, 1, 2, 3);"
4128       "keys;"));
4129   Local<Value> result = indexed_property_names_script->Run();
4130   return Local<v8::Array>(static_cast<v8::Array*>(::v8::Object::Cast(*result)));
4131 }
4132
4133
4134 static v8::Handle<Value> NonStrictIndexedPropertyGetter(
4135     uint32_t index,
4136     const AccessorInfo& info) {
4137   ApiTestFuzzer::Fuzz();
4138   if (index < 4) {
4139     return v8::Handle<Value>(v8_num(index));
4140   }
4141   return v8::Handle<Value>();
4142 }
4143
4144
4145 // Make sure that the the interceptor code in the runtime properly handles
4146 // merging property name lists for non-string arguments arrays.
4147 THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
4148   v8::HandleScope scope;
4149   Local<ObjectTemplate> templ = ObjectTemplate::New();
4150   templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
4151                                    0,
4152                                    0,
4153                                    0,
4154                                    NonStrictArgsIndexedPropertyEnumerator);
4155   LocalContext context;
4156   context->Global()->Set(v8_str("obj"), templ->NewInstance());
4157   Local<Script> create_args_script =
4158       Script::Compile(v8_str(
4159           "var key_count = 0;"
4160           "for (x in obj) {key_count++;} key_count;"));
4161   Local<Value> result = create_args_script->Run();
4162   CHECK_EQ(v8_num(4), result);
4163 }
4164
4165
4166 static v8::Handle<Value> IdentityIndexedPropertyGetter(
4167     uint32_t index,
4168     const AccessorInfo& info) {
4169   return v8::Integer::NewFromUnsigned(index);
4170 }
4171
4172
4173 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
4174   v8::HandleScope scope;
4175   Local<ObjectTemplate> templ = ObjectTemplate::New();
4176   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4177
4178   LocalContext context;
4179   context->Global()->Set(v8_str("obj"), templ->NewInstance());
4180
4181   // Check fast object case.
4182   const char* fast_case_code =
4183       "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
4184   ExpectString(fast_case_code, "0");
4185
4186   // Check slow case.
4187   const char* slow_case_code =
4188       "obj.x = 1; delete obj.x;"
4189       "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
4190   ExpectString(slow_case_code, "1");
4191 }
4192
4193
4194 THREADED_TEST(IndexedInterceptorWithNoSetter) {
4195   v8::HandleScope scope;
4196   Local<ObjectTemplate> templ = ObjectTemplate::New();
4197   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4198
4199   LocalContext context;
4200   context->Global()->Set(v8_str("obj"), templ->NewInstance());
4201
4202   const char* code =
4203       "try {"
4204       "  obj[0] = 239;"
4205       "  for (var i = 0; i < 100; i++) {"
4206       "    var v = obj[0];"
4207       "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
4208       "  }"
4209       "  'PASSED'"
4210       "} catch(e) {"
4211       "  e"
4212       "}";
4213   ExpectString(code, "PASSED");
4214 }
4215
4216
4217 THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
4218   v8::HandleScope scope;
4219   Local<ObjectTemplate> templ = ObjectTemplate::New();
4220   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4221
4222   LocalContext context;
4223   Local<v8::Object> obj = templ->NewInstance();
4224   obj->TurnOnAccessCheck();
4225   context->Global()->Set(v8_str("obj"), obj);
4226
4227   const char* code =
4228       "try {"
4229       "  for (var i = 0; i < 100; i++) {"
4230       "    var v = obj[0];"
4231       "    if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
4232       "  }"
4233       "  'PASSED'"
4234       "} catch(e) {"
4235       "  e"
4236       "}";
4237   ExpectString(code, "PASSED");
4238 }
4239
4240
4241 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
4242   i::FLAG_allow_natives_syntax = true;
4243   v8::HandleScope scope;
4244   Local<ObjectTemplate> templ = ObjectTemplate::New();
4245   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4246
4247   LocalContext context;
4248   Local<v8::Object> obj = templ->NewInstance();
4249   context->Global()->Set(v8_str("obj"), obj);
4250
4251   const char* code =
4252       "try {"
4253       "  for (var i = 0; i < 100; i++) {"
4254       "    var expected = i;"
4255       "    if (i == 5) {"
4256       "      %EnableAccessChecks(obj);"
4257       "      expected = undefined;"
4258       "    }"
4259       "    var v = obj[i];"
4260       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4261       "    if (i == 5) %DisableAccessChecks(obj);"
4262       "  }"
4263       "  'PASSED'"
4264       "} catch(e) {"
4265       "  e"
4266       "}";
4267   ExpectString(code, "PASSED");
4268 }
4269
4270
4271 THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
4272   v8::HandleScope scope;
4273   Local<ObjectTemplate> templ = ObjectTemplate::New();
4274   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4275
4276   LocalContext context;
4277   Local<v8::Object> obj = templ->NewInstance();
4278   context->Global()->Set(v8_str("obj"), obj);
4279
4280   const char* code =
4281       "try {"
4282       "  for (var i = 0; i < 100; i++) {"
4283       "    var v = obj[i];"
4284       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
4285       "  }"
4286       "  'PASSED'"
4287       "} catch(e) {"
4288       "  e"
4289       "}";
4290   ExpectString(code, "PASSED");
4291 }
4292
4293
4294 THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
4295   v8::HandleScope scope;
4296   Local<ObjectTemplate> templ = ObjectTemplate::New();
4297   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4298
4299   LocalContext context;
4300   Local<v8::Object> obj = templ->NewInstance();
4301   context->Global()->Set(v8_str("obj"), obj);
4302
4303   const char* code =
4304       "try {"
4305       "  for (var i = 0; i < 100; i++) {"
4306       "    var expected = i;"
4307       "    var key = i;"
4308       "    if (i == 25) {"
4309       "       key = -1;"
4310       "       expected = undefined;"
4311       "    }"
4312       "    if (i == 50) {"
4313       "       /* probe minimal Smi number on 32-bit platforms */"
4314       "       key = -(1 << 30);"
4315       "       expected = undefined;"
4316       "    }"
4317       "    if (i == 75) {"
4318       "       /* probe minimal Smi number on 64-bit platforms */"
4319       "       key = 1 << 31;"
4320       "       expected = undefined;"
4321       "    }"
4322       "    var v = obj[key];"
4323       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4324       "  }"
4325       "  'PASSED'"
4326       "} catch(e) {"
4327       "  e"
4328       "}";
4329   ExpectString(code, "PASSED");
4330 }
4331
4332
4333 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
4334   v8::HandleScope scope;
4335   Local<ObjectTemplate> templ = ObjectTemplate::New();
4336   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4337
4338   LocalContext context;
4339   Local<v8::Object> obj = templ->NewInstance();
4340   context->Global()->Set(v8_str("obj"), obj);
4341
4342   const char* code =
4343       "try {"
4344       "  for (var i = 0; i < 100; i++) {"
4345       "    var expected = i;"
4346       "    var key = i;"
4347       "    if (i == 50) {"
4348       "       key = 'foobar';"
4349       "       expected = undefined;"
4350       "    }"
4351       "    var v = obj[key];"
4352       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4353       "  }"
4354       "  'PASSED'"
4355       "} catch(e) {"
4356       "  e"
4357       "}";
4358   ExpectString(code, "PASSED");
4359 }
4360
4361
4362 THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
4363   v8::HandleScope scope;
4364   Local<ObjectTemplate> templ = ObjectTemplate::New();
4365   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4366
4367   LocalContext context;
4368   Local<v8::Object> obj = templ->NewInstance();
4369   context->Global()->Set(v8_str("obj"), obj);
4370
4371   const char* code =
4372       "var original = obj;"
4373       "try {"
4374       "  for (var i = 0; i < 100; i++) {"
4375       "    var expected = i;"
4376       "    if (i == 50) {"
4377       "       obj = {50: 'foobar'};"
4378       "       expected = 'foobar';"
4379       "    }"
4380       "    var v = obj[i];"
4381       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4382       "    if (i == 50) obj = original;"
4383       "  }"
4384       "  'PASSED'"
4385       "} catch(e) {"
4386       "  e"
4387       "}";
4388   ExpectString(code, "PASSED");
4389 }
4390
4391
4392 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
4393   v8::HandleScope scope;
4394   Local<ObjectTemplate> templ = ObjectTemplate::New();
4395   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4396
4397   LocalContext context;
4398   Local<v8::Object> obj = templ->NewInstance();
4399   context->Global()->Set(v8_str("obj"), obj);
4400
4401   const char* code =
4402       "var original = obj;"
4403       "try {"
4404       "  for (var i = 0; i < 100; i++) {"
4405       "    var expected = i;"
4406       "    if (i == 5) {"
4407       "       obj = 239;"
4408       "       expected = undefined;"
4409       "    }"
4410       "    var v = obj[i];"
4411       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4412       "    if (i == 5) obj = original;"
4413       "  }"
4414       "  'PASSED'"
4415       "} catch(e) {"
4416       "  e"
4417       "}";
4418   ExpectString(code, "PASSED");
4419 }
4420
4421
4422 THREADED_TEST(IndexedInterceptorOnProto) {
4423   v8::HandleScope scope;
4424   Local<ObjectTemplate> templ = ObjectTemplate::New();
4425   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4426
4427   LocalContext context;
4428   Local<v8::Object> obj = templ->NewInstance();
4429   context->Global()->Set(v8_str("obj"), obj);
4430
4431   const char* code =
4432       "var o = {__proto__: obj};"
4433       "try {"
4434       "  for (var i = 0; i < 100; i++) {"
4435       "    var v = o[i];"
4436       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
4437       "  }"
4438       "  'PASSED'"
4439       "} catch(e) {"
4440       "  e"
4441       "}";
4442   ExpectString(code, "PASSED");
4443 }
4444
4445
4446 THREADED_TEST(MultiContexts) {
4447   v8::HandleScope scope;
4448   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
4449   templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
4450
4451   Local<String> password = v8_str("Password");
4452
4453   // Create an environment
4454   LocalContext context0(0, templ);
4455   context0->SetSecurityToken(password);
4456   v8::Handle<v8::Object> global0 = context0->Global();
4457   global0->Set(v8_str("custom"), v8_num(1234));
4458   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
4459
4460   // Create an independent environment
4461   LocalContext context1(0, templ);
4462   context1->SetSecurityToken(password);
4463   v8::Handle<v8::Object> global1 = context1->Global();
4464   global1->Set(v8_str("custom"), v8_num(1234));
4465   CHECK_NE(global0, global1);
4466   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
4467   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
4468
4469   // Now create a new context with the old global
4470   LocalContext context2(0, templ, global1);
4471   context2->SetSecurityToken(password);
4472   v8::Handle<v8::Object> global2 = context2->Global();
4473   CHECK_EQ(global1, global2);
4474   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
4475   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
4476 }
4477
4478
4479 THREADED_TEST(FunctionPrototypeAcrossContexts) {
4480   // Make sure that functions created by cloning boilerplates cannot
4481   // communicate through their __proto__ field.
4482
4483   v8::HandleScope scope;
4484
4485   LocalContext env0;
4486   v8::Handle<v8::Object> global0 =
4487       env0->Global();
4488   v8::Handle<v8::Object> object0 =
4489       global0->Get(v8_str("Object")).As<v8::Object>();
4490   v8::Handle<v8::Object> tostring0 =
4491       object0->Get(v8_str("toString")).As<v8::Object>();
4492   v8::Handle<v8::Object> proto0 =
4493       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
4494   proto0->Set(v8_str("custom"), v8_num(1234));
4495
4496   LocalContext env1;
4497   v8::Handle<v8::Object> global1 =
4498       env1->Global();
4499   v8::Handle<v8::Object> object1 =
4500       global1->Get(v8_str("Object")).As<v8::Object>();
4501   v8::Handle<v8::Object> tostring1 =
4502       object1->Get(v8_str("toString")).As<v8::Object>();
4503   v8::Handle<v8::Object> proto1 =
4504       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
4505   CHECK(!proto1->Has(v8_str("custom")));
4506 }
4507
4508
4509 THREADED_TEST(Regress892105) {
4510   // Make sure that object and array literals created by cloning
4511   // boilerplates cannot communicate through their __proto__
4512   // field. This is rather difficult to check, but we try to add stuff
4513   // to Object.prototype and Array.prototype and create a new
4514   // environment. This should succeed.
4515
4516   v8::HandleScope scope;
4517
4518   Local<String> source = v8_str("Object.prototype.obj = 1234;"
4519                                 "Array.prototype.arr = 4567;"
4520                                 "8901");
4521
4522   LocalContext env0;
4523   Local<Script> script0 = Script::Compile(source);
4524   CHECK_EQ(8901.0, script0->Run()->NumberValue());
4525
4526   LocalContext env1;
4527   Local<Script> script1 = Script::Compile(source);
4528   CHECK_EQ(8901.0, script1->Run()->NumberValue());
4529 }
4530
4531
4532 THREADED_TEST(UndetectableObject) {
4533   v8::HandleScope scope;
4534   LocalContext env;
4535
4536   Local<v8::FunctionTemplate> desc =
4537       v8::FunctionTemplate::New(0, v8::Handle<Value>());
4538   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
4539
4540   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
4541   env->Global()->Set(v8_str("undetectable"), obj);
4542
4543   ExpectString("undetectable.toString()", "[object Object]");
4544   ExpectString("typeof undetectable", "undefined");
4545   ExpectString("typeof(undetectable)", "undefined");
4546   ExpectBoolean("typeof undetectable == 'undefined'", true);
4547   ExpectBoolean("typeof undetectable == 'object'", false);
4548   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
4549   ExpectBoolean("!undetectable", true);
4550
4551   ExpectObject("true&&undetectable", obj);
4552   ExpectBoolean("false&&undetectable", false);
4553   ExpectBoolean("true||undetectable", true);
4554   ExpectObject("false||undetectable", obj);
4555
4556   ExpectObject("undetectable&&true", obj);
4557   ExpectObject("undetectable&&false", obj);
4558   ExpectBoolean("undetectable||true", true);
4559   ExpectBoolean("undetectable||false", false);
4560
4561   ExpectBoolean("undetectable==null", true);
4562   ExpectBoolean("null==undetectable", true);
4563   ExpectBoolean("undetectable==undefined", true);
4564   ExpectBoolean("undefined==undetectable", true);
4565   ExpectBoolean("undetectable==undetectable", true);
4566
4567
4568   ExpectBoolean("undetectable===null", false);
4569   ExpectBoolean("null===undetectable", false);
4570   ExpectBoolean("undetectable===undefined", false);
4571   ExpectBoolean("undefined===undetectable", false);
4572   ExpectBoolean("undetectable===undetectable", true);
4573 }
4574
4575
4576 THREADED_TEST(VoidLiteral) {
4577   v8::HandleScope scope;
4578   LocalContext env;
4579
4580   Local<v8::FunctionTemplate> desc =
4581       v8::FunctionTemplate::New(0, v8::Handle<Value>());
4582   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
4583
4584   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
4585   env->Global()->Set(v8_str("undetectable"), obj);
4586
4587   ExpectBoolean("undefined == void 0", true);
4588   ExpectBoolean("undetectable == void 0", true);
4589   ExpectBoolean("null == void 0", true);
4590   ExpectBoolean("undefined === void 0", true);
4591   ExpectBoolean("undetectable === void 0", false);
4592   ExpectBoolean("null === void 0", false);
4593
4594   ExpectBoolean("void 0 == undefined", true);
4595   ExpectBoolean("void 0 == undetectable", true);
4596   ExpectBoolean("void 0 == null", true);
4597   ExpectBoolean("void 0 === undefined", true);
4598   ExpectBoolean("void 0 === undetectable", false);
4599   ExpectBoolean("void 0 === null", false);
4600
4601   ExpectString("(function() {"
4602                "  try {"
4603                "    return x === void 0;"
4604                "  } catch(e) {"
4605                "    return e.toString();"
4606                "  }"
4607                "})()",
4608                "ReferenceError: x is not defined");
4609   ExpectString("(function() {"
4610                "  try {"
4611                "    return void 0 === x;"
4612                "  } catch(e) {"
4613                "    return e.toString();"
4614                "  }"
4615                "})()",
4616                "ReferenceError: x is not defined");
4617 }
4618
4619
4620 THREADED_TEST(ExtensibleOnUndetectable) {
4621   v8::HandleScope scope;
4622   LocalContext env;
4623
4624   Local<v8::FunctionTemplate> desc =
4625       v8::FunctionTemplate::New(0, v8::Handle<Value>());
4626   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
4627
4628   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
4629   env->Global()->Set(v8_str("undetectable"), obj);
4630
4631   Local<String> source = v8_str("undetectable.x = 42;"
4632                                 "undetectable.x");
4633
4634   Local<Script> script = Script::Compile(source);
4635
4636   CHECK_EQ(v8::Integer::New(42), script->Run());
4637
4638   ExpectBoolean("Object.isExtensible(undetectable)", true);
4639
4640   source = v8_str("Object.preventExtensions(undetectable);");
4641   script = Script::Compile(source);
4642   script->Run();
4643   ExpectBoolean("Object.isExtensible(undetectable)", false);
4644
4645   source = v8_str("undetectable.y = 2000;");
4646   script = Script::Compile(source);
4647   script->Run();
4648   ExpectBoolean("undetectable.y == undefined", true);
4649 }
4650
4651
4652
4653 THREADED_TEST(UndetectableString) {
4654   v8::HandleScope scope;
4655   LocalContext env;
4656
4657   Local<String> obj = String::NewUndetectable("foo");
4658   env->Global()->Set(v8_str("undetectable"), obj);
4659
4660   ExpectString("undetectable", "foo");
4661   ExpectString("typeof undetectable", "undefined");
4662   ExpectString("typeof(undetectable)", "undefined");
4663   ExpectBoolean("typeof undetectable == 'undefined'", true);
4664   ExpectBoolean("typeof undetectable == 'string'", false);
4665   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
4666   ExpectBoolean("!undetectable", true);
4667
4668   ExpectObject("true&&undetectable", obj);
4669   ExpectBoolean("false&&undetectable", false);
4670   ExpectBoolean("true||undetectable", true);
4671   ExpectObject("false||undetectable", obj);
4672
4673   ExpectObject("undetectable&&true", obj);
4674   ExpectObject("undetectable&&false", obj);
4675   ExpectBoolean("undetectable||true", true);
4676   ExpectBoolean("undetectable||false", false);
4677
4678   ExpectBoolean("undetectable==null", true);
4679   ExpectBoolean("null==undetectable", true);
4680   ExpectBoolean("undetectable==undefined", true);
4681   ExpectBoolean("undefined==undetectable", true);
4682   ExpectBoolean("undetectable==undetectable", true);
4683
4684
4685   ExpectBoolean("undetectable===null", false);
4686   ExpectBoolean("null===undetectable", false);
4687   ExpectBoolean("undetectable===undefined", false);
4688   ExpectBoolean("undefined===undetectable", false);
4689   ExpectBoolean("undetectable===undetectable", true);
4690 }
4691
4692
4693 TEST(UndetectableOptimized) {
4694   i::FLAG_allow_natives_syntax = true;
4695   v8::HandleScope scope;
4696   LocalContext env;
4697
4698   Local<String> obj = String::NewUndetectable("foo");
4699   env->Global()->Set(v8_str("undetectable"), obj);
4700   env->Global()->Set(v8_str("detectable"), v8_str("bar"));
4701
4702   ExpectString(
4703       "function testBranch() {"
4704       "  if (!%_IsUndetectableObject(undetectable)) throw 1;"
4705       "  if (%_IsUndetectableObject(detectable)) throw 2;"
4706       "}\n"
4707       "function testBool() {"
4708       "  var b1 = !%_IsUndetectableObject(undetectable);"
4709       "  var b2 = %_IsUndetectableObject(detectable);"
4710       "  if (b1) throw 3;"
4711       "  if (b2) throw 4;"
4712       "  return b1 == b2;"
4713       "}\n"
4714       "%OptimizeFunctionOnNextCall(testBranch);"
4715       "%OptimizeFunctionOnNextCall(testBool);"
4716       "for (var i = 0; i < 10; i++) {"
4717       "  testBranch();"
4718       "  testBool();"
4719       "}\n"
4720       "\"PASS\"",
4721       "PASS");
4722 }
4723
4724
4725 template <typename T> static void USE(T) { }
4726
4727
4728 // This test is not intended to be run, just type checked.
4729 static inline void PersistentHandles() {
4730   USE(PersistentHandles);
4731   Local<String> str = v8_str("foo");
4732   v8::Persistent<String> p_str = v8::Persistent<String>::New(str);
4733   USE(p_str);
4734   Local<Script> scr = Script::Compile(v8_str(""));
4735   v8::Persistent<Script> p_scr = v8::Persistent<Script>::New(scr);
4736   USE(p_scr);
4737   Local<ObjectTemplate> templ = ObjectTemplate::New();
4738   v8::Persistent<ObjectTemplate> p_templ =
4739     v8::Persistent<ObjectTemplate>::New(templ);
4740   USE(p_templ);
4741 }
4742
4743
4744 static v8::Handle<Value> HandleLogDelegator(const v8::Arguments& args) {
4745   ApiTestFuzzer::Fuzz();
4746   return v8::Undefined();
4747 }
4748
4749
4750 THREADED_TEST(GlobalObjectTemplate) {
4751   v8::HandleScope handle_scope;
4752   Local<ObjectTemplate> global_template = ObjectTemplate::New();
4753   global_template->Set(v8_str("JSNI_Log"),
4754                        v8::FunctionTemplate::New(HandleLogDelegator));
4755   v8::Persistent<Context> context = Context::New(0, global_template);
4756   Context::Scope context_scope(context);
4757   Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
4758   context.Dispose();
4759 }
4760
4761
4762 static const char* kSimpleExtensionSource =
4763   "function Foo() {"
4764   "  return 4;"
4765   "}";
4766
4767
4768 THREADED_TEST(SimpleExtensions) {
4769   v8::HandleScope handle_scope;
4770   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
4771   const char* extension_names[] = { "simpletest" };
4772   v8::ExtensionConfiguration extensions(1, extension_names);
4773   v8::Handle<Context> context = Context::New(&extensions);
4774   Context::Scope lock(context);
4775   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
4776   CHECK_EQ(result, v8::Integer::New(4));
4777 }
4778
4779
4780 THREADED_TEST(NullExtensions) {
4781   v8::HandleScope handle_scope;
4782   v8::RegisterExtension(new Extension("nulltest", NULL));
4783   const char* extension_names[] = { "nulltest" };
4784   v8::ExtensionConfiguration extensions(1, extension_names);
4785   v8::Handle<Context> context = Context::New(&extensions);
4786   Context::Scope lock(context);
4787   v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
4788   CHECK_EQ(result, v8::Integer::New(4));
4789 }
4790
4791
4792 static const char* kEmbeddedExtensionSource =
4793     "function Ret54321(){return 54321;}~~@@$"
4794     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
4795 static const int kEmbeddedExtensionSourceValidLen = 34;
4796
4797
4798 THREADED_TEST(ExtensionMissingSourceLength) {
4799   v8::HandleScope handle_scope;
4800   v8::RegisterExtension(new Extension("srclentest_fail",
4801                                       kEmbeddedExtensionSource));
4802   const char* extension_names[] = { "srclentest_fail" };
4803   v8::ExtensionConfiguration extensions(1, extension_names);
4804   v8::Handle<Context> context = Context::New(&extensions);
4805   CHECK_EQ(0, *context);
4806 }
4807
4808
4809 THREADED_TEST(ExtensionWithSourceLength) {
4810   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
4811        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
4812     v8::HandleScope handle_scope;
4813     i::ScopedVector<char> extension_name(32);
4814     i::OS::SNPrintF(extension_name, "ext #%d", source_len);
4815     v8::RegisterExtension(new Extension(extension_name.start(),
4816                                         kEmbeddedExtensionSource, 0, 0,
4817                                         source_len));
4818     const char* extension_names[1] = { extension_name.start() };
4819     v8::ExtensionConfiguration extensions(1, extension_names);
4820     v8::Handle<Context> context = Context::New(&extensions);
4821     if (source_len == kEmbeddedExtensionSourceValidLen) {
4822       Context::Scope lock(context);
4823       v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
4824       CHECK_EQ(v8::Integer::New(54321), result);
4825     } else {
4826       // Anything but exactly the right length should fail to compile.
4827       CHECK_EQ(0, *context);
4828     }
4829   }
4830 }
4831
4832
4833 static const char* kEvalExtensionSource1 =
4834   "function UseEval1() {"
4835   "  var x = 42;"
4836   "  return eval('x');"
4837   "}";
4838
4839
4840 static const char* kEvalExtensionSource2 =
4841   "(function() {"
4842   "  var x = 42;"
4843   "  function e() {"
4844   "    return eval('x');"
4845   "  }"
4846   "  this.UseEval2 = e;"
4847   "})()";
4848
4849
4850 THREADED_TEST(UseEvalFromExtension) {
4851   v8::HandleScope handle_scope;
4852   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
4853   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
4854   const char* extension_names[] = { "evaltest1", "evaltest2" };
4855   v8::ExtensionConfiguration extensions(2, extension_names);
4856   v8::Handle<Context> context = Context::New(&extensions);
4857   Context::Scope lock(context);
4858   v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
4859   CHECK_EQ(result, v8::Integer::New(42));
4860   result = Script::Compile(v8_str("UseEval2()"))->Run();
4861   CHECK_EQ(result, v8::Integer::New(42));
4862 }
4863
4864
4865 static const char* kWithExtensionSource1 =
4866   "function UseWith1() {"
4867   "  var x = 42;"
4868   "  with({x:87}) { return x; }"
4869   "}";
4870
4871
4872
4873 static const char* kWithExtensionSource2 =
4874   "(function() {"
4875   "  var x = 42;"
4876   "  function e() {"
4877   "    with ({x:87}) { return x; }"
4878   "  }"
4879   "  this.UseWith2 = e;"
4880   "})()";
4881
4882
4883 THREADED_TEST(UseWithFromExtension) {
4884   v8::HandleScope handle_scope;
4885   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
4886   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
4887   const char* extension_names[] = { "withtest1", "withtest2" };
4888   v8::ExtensionConfiguration extensions(2, extension_names);
4889   v8::Handle<Context> context = Context::New(&extensions);
4890   Context::Scope lock(context);
4891   v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
4892   CHECK_EQ(result, v8::Integer::New(87));
4893   result = Script::Compile(v8_str("UseWith2()"))->Run();
4894   CHECK_EQ(result, v8::Integer::New(87));
4895 }
4896
4897
4898 THREADED_TEST(AutoExtensions) {
4899   v8::HandleScope handle_scope;
4900   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
4901   extension->set_auto_enable(true);
4902   v8::RegisterExtension(extension);
4903   v8::Handle<Context> context = Context::New();
4904   Context::Scope lock(context);
4905   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
4906   CHECK_EQ(result, v8::Integer::New(4));
4907 }
4908
4909
4910 static const char* kSyntaxErrorInExtensionSource =
4911     "[";
4912
4913
4914 // Test that a syntax error in an extension does not cause a fatal
4915 // error but results in an empty context.
4916 THREADED_TEST(SyntaxErrorExtensions) {
4917   v8::HandleScope handle_scope;
4918   v8::RegisterExtension(new Extension("syntaxerror",
4919                                       kSyntaxErrorInExtensionSource));
4920   const char* extension_names[] = { "syntaxerror" };
4921   v8::ExtensionConfiguration extensions(1, extension_names);
4922   v8::Handle<Context> context = Context::New(&extensions);
4923   CHECK(context.IsEmpty());
4924 }
4925
4926
4927 static const char* kExceptionInExtensionSource =
4928     "throw 42";
4929
4930
4931 // Test that an exception when installing an extension does not cause
4932 // a fatal error but results in an empty context.
4933 THREADED_TEST(ExceptionExtensions) {
4934   v8::HandleScope handle_scope;
4935   v8::RegisterExtension(new Extension("exception",
4936                                       kExceptionInExtensionSource));
4937   const char* extension_names[] = { "exception" };
4938   v8::ExtensionConfiguration extensions(1, extension_names);
4939   v8::Handle<Context> context = Context::New(&extensions);
4940   CHECK(context.IsEmpty());
4941 }
4942
4943
4944 static const char* kNativeCallInExtensionSource =
4945     "function call_runtime_last_index_of(x) {"
4946     "  return %StringLastIndexOf(x, 'bob', 10);"
4947     "}";
4948
4949
4950 static const char* kNativeCallTest =
4951     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
4952
4953 // Test that a native runtime calls are supported in extensions.
4954 THREADED_TEST(NativeCallInExtensions) {
4955   v8::HandleScope handle_scope;
4956   v8::RegisterExtension(new Extension("nativecall",
4957                                       kNativeCallInExtensionSource));
4958   const char* extension_names[] = { "nativecall" };
4959   v8::ExtensionConfiguration extensions(1, extension_names);
4960   v8::Handle<Context> context = Context::New(&extensions);
4961   Context::Scope lock(context);
4962   v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
4963   CHECK_EQ(result, v8::Integer::New(3));
4964 }
4965
4966
4967 class NativeFunctionExtension : public Extension {
4968  public:
4969   NativeFunctionExtension(const char* name,
4970                           const char* source,
4971                           v8::InvocationCallback fun = &Echo)
4972       : Extension(name, source),
4973         function_(fun) { }
4974
4975   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
4976       v8::Handle<v8::String> name) {
4977     return v8::FunctionTemplate::New(function_);
4978   }
4979
4980   static v8::Handle<v8::Value> Echo(const v8::Arguments& args) {
4981     if (args.Length() >= 1) return (args[0]);
4982     return v8::Undefined();
4983   }
4984  private:
4985   v8::InvocationCallback function_;
4986 };
4987
4988
4989 THREADED_TEST(NativeFunctionDeclaration) {
4990   v8::HandleScope handle_scope;
4991   const char* name = "nativedecl";
4992   v8::RegisterExtension(new NativeFunctionExtension(name,
4993                                                     "native function foo();"));
4994   const char* extension_names[] = { name };
4995   v8::ExtensionConfiguration extensions(1, extension_names);
4996   v8::Handle<Context> context = Context::New(&extensions);
4997   Context::Scope lock(context);
4998   v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
4999   CHECK_EQ(result, v8::Integer::New(42));
5000 }
5001
5002
5003 THREADED_TEST(NativeFunctionDeclarationError) {
5004   v8::HandleScope handle_scope;
5005   const char* name = "nativedeclerr";
5006   // Syntax error in extension code.
5007   v8::RegisterExtension(new NativeFunctionExtension(name,
5008                                                     "native\nfunction foo();"));
5009   const char* extension_names[] = { name };
5010   v8::ExtensionConfiguration extensions(1, extension_names);
5011   v8::Handle<Context> context(Context::New(&extensions));
5012   CHECK(context.IsEmpty());
5013 }
5014
5015
5016 THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
5017   v8::HandleScope handle_scope;
5018   const char* name = "nativedeclerresc";
5019   // Syntax error in extension code - escape code in "native" means that
5020   // it's not treated as a keyword.
5021   v8::RegisterExtension(new NativeFunctionExtension(
5022       name,
5023       "nativ\\u0065 function foo();"));
5024   const char* extension_names[] = { name };
5025   v8::ExtensionConfiguration extensions(1, extension_names);
5026   v8::Handle<Context> context(Context::New(&extensions));
5027   CHECK(context.IsEmpty());
5028 }
5029
5030
5031 static void CheckDependencies(const char* name, const char* expected) {
5032   v8::HandleScope handle_scope;
5033   v8::ExtensionConfiguration config(1, &name);
5034   LocalContext context(&config);
5035   CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
5036 }
5037
5038
5039 /*
5040  * Configuration:
5041  *
5042  *     /-- B <--\
5043  * A <-          -- D <-- E
5044  *     \-- C <--/
5045  */
5046 THREADED_TEST(ExtensionDependency) {
5047   static const char* kEDeps[] = { "D" };
5048   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
5049   static const char* kDDeps[] = { "B", "C" };
5050   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
5051   static const char* kBCDeps[] = { "A" };
5052   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
5053   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
5054   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
5055   CheckDependencies("A", "undefinedA");
5056   CheckDependencies("B", "undefinedAB");
5057   CheckDependencies("C", "undefinedAC");
5058   CheckDependencies("D", "undefinedABCD");
5059   CheckDependencies("E", "undefinedABCDE");
5060   v8::HandleScope handle_scope;
5061   static const char* exts[2] = { "C", "E" };
5062   v8::ExtensionConfiguration config(2, exts);
5063   LocalContext context(&config);
5064   CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
5065 }
5066
5067
5068 static const char* kExtensionTestScript =
5069   "native function A();"
5070   "native function B();"
5071   "native function C();"
5072   "function Foo(i) {"
5073   "  if (i == 0) return A();"
5074   "  if (i == 1) return B();"
5075   "  if (i == 2) return C();"
5076   "}";
5077
5078
5079 static v8::Handle<Value> CallFun(const v8::Arguments& args) {
5080   ApiTestFuzzer::Fuzz();
5081   if (args.IsConstructCall()) {
5082     args.This()->Set(v8_str("data"), args.Data());
5083     return v8::Null();
5084   }
5085   return args.Data();
5086 }
5087
5088
5089 class FunctionExtension : public Extension {
5090  public:
5091   FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
5092   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
5093       v8::Handle<String> name);
5094 };
5095
5096
5097 static int lookup_count = 0;
5098 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
5099       v8::Handle<String> name) {
5100   lookup_count++;
5101   if (name->Equals(v8_str("A"))) {
5102     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
5103   } else if (name->Equals(v8_str("B"))) {
5104     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
5105   } else if (name->Equals(v8_str("C"))) {
5106     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
5107   } else {
5108     return v8::Handle<v8::FunctionTemplate>();
5109   }
5110 }
5111
5112
5113 THREADED_TEST(FunctionLookup) {
5114   v8::RegisterExtension(new FunctionExtension());
5115   v8::HandleScope handle_scope;
5116   static const char* exts[1] = { "functiontest" };
5117   v8::ExtensionConfiguration config(1, exts);
5118   LocalContext context(&config);
5119   CHECK_EQ(3, lookup_count);
5120   CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
5121   CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
5122   CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
5123 }
5124
5125
5126 THREADED_TEST(NativeFunctionConstructCall) {
5127   v8::RegisterExtension(new FunctionExtension());
5128   v8::HandleScope handle_scope;
5129   static const char* exts[1] = { "functiontest" };
5130   v8::ExtensionConfiguration config(1, exts);
5131   LocalContext context(&config);
5132   for (int i = 0; i < 10; i++) {
5133     // Run a few times to ensure that allocation of objects doesn't
5134     // change behavior of a constructor function.
5135     CHECK_EQ(v8::Integer::New(8),
5136              Script::Compile(v8_str("(new A()).data"))->Run());
5137     CHECK_EQ(v8::Integer::New(7),
5138              Script::Compile(v8_str("(new B()).data"))->Run());
5139     CHECK_EQ(v8::Integer::New(6),
5140              Script::Compile(v8_str("(new C()).data"))->Run());
5141   }
5142 }
5143
5144
5145 static const char* last_location;
5146 static const char* last_message;
5147 void StoringErrorCallback(const char* location, const char* message) {
5148   if (last_location == NULL) {
5149     last_location = location;
5150     last_message = message;
5151   }
5152 }
5153
5154
5155 // ErrorReporting creates a circular extensions configuration and
5156 // tests that the fatal error handler gets called.  This renders V8
5157 // unusable and therefore this test cannot be run in parallel.
5158 TEST(ErrorReporting) {
5159   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
5160   static const char* aDeps[] = { "B" };
5161   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
5162   static const char* bDeps[] = { "A" };
5163   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
5164   last_location = NULL;
5165   v8::ExtensionConfiguration config(1, bDeps);
5166   v8::Handle<Context> context = Context::New(&config);
5167   CHECK(context.IsEmpty());
5168   CHECK_NE(last_location, NULL);
5169 }
5170
5171
5172 static const char* js_code_causing_huge_string_flattening =
5173     "var str = 'X';"
5174     "for (var i = 0; i < 30; i++) {"
5175     "  str = str + str;"
5176     "}"
5177     "str.match(/X/);";
5178
5179
5180 void OOMCallback(const char* location, const char* message) {
5181   exit(0);
5182 }
5183
5184
5185 TEST(RegexpOutOfMemory) {
5186   // Execute a script that causes out of memory when flattening a string.
5187   v8::HandleScope scope;
5188   v8::V8::SetFatalErrorHandler(OOMCallback);
5189   LocalContext context;
5190   Local<Script> script =
5191       Script::Compile(String::New(js_code_causing_huge_string_flattening));
5192   last_location = NULL;
5193   script->Run();
5194
5195   CHECK(false);  // Should not return.
5196 }
5197
5198
5199 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
5200                                              v8::Handle<Value> data) {
5201   CHECK(message->GetScriptResourceName()->IsUndefined());
5202   CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
5203   message->GetLineNumber();
5204   message->GetSourceLine();
5205 }
5206
5207
5208 THREADED_TEST(ErrorWithMissingScriptInfo) {
5209   v8::HandleScope scope;
5210   LocalContext context;
5211   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
5212   Script::Compile(v8_str("throw Error()"))->Run();
5213   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
5214 }
5215
5216
5217 int global_index = 0;
5218
5219 class Snorkel {
5220  public:
5221   Snorkel() { index_ = global_index++; }
5222   int index_;
5223 };
5224
5225 class Whammy {
5226  public:
5227   Whammy() {
5228     cursor_ = 0;
5229   }
5230   ~Whammy() {
5231     script_.Dispose();
5232   }
5233   v8::Handle<Script> getScript() {
5234     if (script_.IsEmpty())
5235       script_ = v8::Persistent<Script>::New(v8_compile("({}).blammo"));
5236     return Local<Script>(*script_);
5237   }
5238
5239  public:
5240   static const int kObjectCount = 256;
5241   int cursor_;
5242   v8::Persistent<v8::Object> objects_[kObjectCount];
5243   v8::Persistent<Script> script_;
5244 };
5245
5246 static void HandleWeakReference(v8::Persistent<v8::Value> obj, void* data) {
5247   Snorkel* snorkel = reinterpret_cast<Snorkel*>(data);
5248   delete snorkel;
5249   obj.ClearWeak();
5250 }
5251
5252 v8::Handle<Value> WhammyPropertyGetter(Local<String> name,
5253                                        const AccessorInfo& info) {
5254   Whammy* whammy =
5255     static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
5256
5257   v8::Persistent<v8::Object> prev = whammy->objects_[whammy->cursor_];
5258
5259   v8::Handle<v8::Object> obj = v8::Object::New();
5260   v8::Persistent<v8::Object> global = v8::Persistent<v8::Object>::New(obj);
5261   if (!prev.IsEmpty()) {
5262     prev->Set(v8_str("next"), obj);
5263     prev.MakeWeak(new Snorkel(), &HandleWeakReference);
5264     whammy->objects_[whammy->cursor_].Clear();
5265   }
5266   whammy->objects_[whammy->cursor_] = global;
5267   whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
5268   return whammy->getScript()->Run();
5269 }
5270
5271 THREADED_TEST(WeakReference) {
5272   v8::HandleScope handle_scope;
5273   v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
5274   Whammy* whammy = new Whammy();
5275   templ->SetNamedPropertyHandler(WhammyPropertyGetter,
5276                                  0, 0, 0, 0,
5277                                  v8::External::New(whammy));
5278   const char* extension_list[] = { "v8/gc" };
5279   v8::ExtensionConfiguration extensions(1, extension_list);
5280   v8::Persistent<Context> context = Context::New(&extensions);
5281   Context::Scope context_scope(context);
5282
5283   v8::Handle<v8::Object> interceptor = templ->NewInstance();
5284   context->Global()->Set(v8_str("whammy"), interceptor);
5285   const char* code =
5286       "var last;"
5287       "for (var i = 0; i < 10000; i++) {"
5288       "  var obj = whammy.length;"
5289       "  if (last) last.next = obj;"
5290       "  last = obj;"
5291       "}"
5292       "gc();"
5293       "4";
5294   v8::Handle<Value> result = CompileRun(code);
5295   CHECK_EQ(4.0, result->NumberValue());
5296   delete whammy;
5297   context.Dispose();
5298 }
5299
5300
5301 static void DisposeAndSetFlag(v8::Persistent<v8::Value> obj, void* data) {
5302   obj.Dispose();
5303   obj.Clear();
5304   *(reinterpret_cast<bool*>(data)) = true;
5305 }
5306
5307
5308 THREADED_TEST(IndependentWeakHandle) {
5309   v8::Persistent<Context> context = Context::New();
5310   Context::Scope context_scope(context);
5311
5312   v8::Persistent<v8::Object> object_a;
5313
5314   {
5315     v8::HandleScope handle_scope;
5316     object_a = v8::Persistent<v8::Object>::New(v8::Object::New());
5317   }
5318
5319   bool object_a_disposed = false;
5320   object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag);
5321   CHECK(!object_a.IsIndependent());
5322   object_a.MarkIndependent();
5323   CHECK(object_a.IsIndependent());
5324   HEAP->PerformScavenge();
5325   CHECK(object_a_disposed);
5326 }
5327
5328
5329 static void InvokeScavenge() {
5330   HEAP->PerformScavenge();
5331 }
5332
5333
5334 static void InvokeMarkSweep() {
5335   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
5336 }
5337
5338
5339 static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) {
5340   obj.Dispose();
5341   obj.Clear();
5342   *(reinterpret_cast<bool*>(data)) = true;
5343   InvokeScavenge();
5344 }
5345
5346
5347 static void ForceMarkSweep(v8::Persistent<v8::Value> obj, void* data) {
5348   obj.Dispose();
5349   obj.Clear();
5350   *(reinterpret_cast<bool*>(data)) = true;
5351   InvokeMarkSweep();
5352 }
5353
5354
5355 THREADED_TEST(GCFromWeakCallbacks) {
5356   v8::Persistent<Context> context = Context::New();
5357   Context::Scope context_scope(context);
5358
5359   static const int kNumberOfGCTypes = 2;
5360   v8::WeakReferenceCallback gc_forcing_callback[kNumberOfGCTypes] =
5361       {&ForceScavenge, &ForceMarkSweep};
5362
5363   typedef void (*GCInvoker)();
5364   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
5365
5366   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
5367     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
5368       v8::Persistent<v8::Object> object;
5369       {
5370         v8::HandleScope handle_scope;
5371         object = v8::Persistent<v8::Object>::New(v8::Object::New());
5372       }
5373       bool disposed = false;
5374       object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]);
5375       object.MarkIndependent();
5376       invoke_gc[outer_gc]();
5377       CHECK(disposed);
5378     }
5379   }
5380 }
5381
5382
5383 static void RevivingCallback(v8::Persistent<v8::Value> obj, void* data) {
5384   obj.ClearWeak();
5385   *(reinterpret_cast<bool*>(data)) = true;
5386 }
5387
5388
5389 THREADED_TEST(IndependentHandleRevival) {
5390   v8::Persistent<Context> context = Context::New();
5391   Context::Scope context_scope(context);
5392
5393   v8::Persistent<v8::Object> object;
5394   {
5395     v8::HandleScope handle_scope;
5396     object = v8::Persistent<v8::Object>::New(v8::Object::New());
5397     object->Set(v8_str("x"), v8::Integer::New(1));
5398     v8::Local<String> y_str = v8_str("y");
5399     object->Set(y_str, y_str);
5400   }
5401   bool revived = false;
5402   object.MakeWeak(&revived, &RevivingCallback);
5403   object.MarkIndependent();
5404   HEAP->PerformScavenge();
5405   CHECK(revived);
5406   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
5407   {
5408     v8::HandleScope handle_scope;
5409     v8::Local<String> y_str = v8_str("y");
5410     CHECK_EQ(v8::Integer::New(1), object->Get(v8_str("x")));
5411     CHECK(object->Get(y_str)->Equals(y_str));
5412   }
5413 }
5414
5415
5416 v8::Handle<Function> args_fun;
5417
5418
5419 static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) {
5420   ApiTestFuzzer::Fuzz();
5421   CHECK_EQ(args_fun, args.Callee());
5422   CHECK_EQ(3, args.Length());
5423   CHECK_EQ(v8::Integer::New(1), args[0]);
5424   CHECK_EQ(v8::Integer::New(2), args[1]);
5425   CHECK_EQ(v8::Integer::New(3), args[2]);
5426   CHECK_EQ(v8::Undefined(), args[3]);
5427   v8::HandleScope scope;
5428   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
5429   return v8::Undefined();
5430 }
5431
5432
5433 THREADED_TEST(Arguments) {
5434   v8::HandleScope scope;
5435   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
5436   global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
5437   LocalContext context(NULL, global);
5438   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
5439   v8_compile("f(1, 2, 3)")->Run();
5440 }
5441
5442
5443 static v8::Handle<Value> NoBlockGetterX(Local<String> name,
5444                                         const AccessorInfo&) {
5445   return v8::Handle<Value>();
5446 }
5447
5448
5449 static v8::Handle<Value> NoBlockGetterI(uint32_t index,
5450                                         const AccessorInfo&) {
5451   return v8::Handle<Value>();
5452 }
5453
5454
5455 static v8::Handle<v8::Boolean> PDeleter(Local<String> name,
5456                                         const AccessorInfo&) {
5457   if (!name->Equals(v8_str("foo"))) {
5458     return v8::Handle<v8::Boolean>();  // not intercepted
5459   }
5460
5461   return v8::False();  // intercepted, and don't delete the property
5462 }
5463
5464
5465 static v8::Handle<v8::Boolean> IDeleter(uint32_t index, const AccessorInfo&) {
5466   if (index != 2) {
5467     return v8::Handle<v8::Boolean>();  // not intercepted
5468   }
5469
5470   return v8::False();  // intercepted, and don't delete the property
5471 }
5472
5473
5474 THREADED_TEST(Deleter) {
5475   v8::HandleScope scope;
5476   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
5477   obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
5478   obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
5479   LocalContext context;
5480   context->Global()->Set(v8_str("k"), obj->NewInstance());
5481   CompileRun(
5482     "k.foo = 'foo';"
5483     "k.bar = 'bar';"
5484     "k[2] = 2;"
5485     "k[4] = 4;");
5486   CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
5487   CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
5488
5489   CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
5490   CHECK(v8_compile("k.bar")->Run()->IsUndefined());
5491
5492   CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
5493   CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
5494
5495   CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
5496   CHECK(v8_compile("k[4]")->Run()->IsUndefined());
5497 }
5498
5499
5500 static v8::Handle<Value> GetK(Local<String> name, const AccessorInfo&) {
5501   ApiTestFuzzer::Fuzz();
5502   if (name->Equals(v8_str("foo")) ||
5503       name->Equals(v8_str("bar")) ||
5504       name->Equals(v8_str("baz"))) {
5505     return v8::Undefined();
5506   }
5507   return v8::Handle<Value>();
5508 }
5509
5510
5511 static v8::Handle<Value> IndexedGetK(uint32_t index, const AccessorInfo&) {
5512   ApiTestFuzzer::Fuzz();
5513   if (index == 0 || index == 1) return v8::Undefined();
5514   return v8::Handle<Value>();
5515 }
5516
5517
5518 static v8::Handle<v8::Array> NamedEnum(const AccessorInfo&) {
5519   ApiTestFuzzer::Fuzz();
5520   v8::Handle<v8::Array> result = v8::Array::New(3);
5521   result->Set(v8::Integer::New(0), v8_str("foo"));
5522   result->Set(v8::Integer::New(1), v8_str("bar"));
5523   result->Set(v8::Integer::New(2), v8_str("baz"));
5524   return result;
5525 }
5526
5527
5528 static v8::Handle<v8::Array> IndexedEnum(const AccessorInfo&) {
5529   ApiTestFuzzer::Fuzz();
5530   v8::Handle<v8::Array> result = v8::Array::New(2);
5531   result->Set(v8::Integer::New(0), v8_str("0"));
5532   result->Set(v8::Integer::New(1), v8_str("1"));
5533   return result;
5534 }
5535
5536
5537 THREADED_TEST(Enumerators) {
5538   v8::HandleScope scope;
5539   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
5540   obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
5541   obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
5542   LocalContext context;
5543   context->Global()->Set(v8_str("k"), obj->NewInstance());
5544   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5545     "k[10] = 0;"
5546     "k.a = 0;"
5547     "k[5] = 0;"
5548     "k.b = 0;"
5549     "k[4294967295] = 0;"
5550     "k.c = 0;"
5551     "k[4294967296] = 0;"
5552     "k.d = 0;"
5553     "k[140000] = 0;"
5554     "k.e = 0;"
5555     "k[30000000000] = 0;"
5556     "k.f = 0;"
5557     "var result = [];"
5558     "for (var prop in k) {"
5559     "  result.push(prop);"
5560     "}"
5561     "result"));
5562   // Check that we get all the property names returned including the
5563   // ones from the enumerators in the right order: indexed properties
5564   // in numerical order, indexed interceptor properties, named
5565   // properties in insertion order, named interceptor properties.
5566   // This order is not mandated by the spec, so this test is just
5567   // documenting our behavior.
5568   CHECK_EQ(17, result->Length());
5569   // Indexed properties in numerical order.
5570   CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
5571   CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
5572   CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
5573   CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
5574   // Indexed interceptor properties in the order they are returned
5575   // from the enumerator interceptor.
5576   CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
5577   CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
5578   // Named properties in insertion order.
5579   CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
5580   CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
5581   CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
5582   CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
5583   CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
5584   CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
5585   CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
5586   CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
5587   // Named interceptor properties.
5588   CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
5589   CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
5590   CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
5591 }
5592
5593
5594 int p_getter_count;
5595 int p_getter_count2;
5596
5597
5598 static v8::Handle<Value> PGetter(Local<String> name, const AccessorInfo& info) {
5599   ApiTestFuzzer::Fuzz();
5600   p_getter_count++;
5601   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
5602   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
5603   if (name->Equals(v8_str("p1"))) {
5604     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
5605   } else if (name->Equals(v8_str("p2"))) {
5606     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
5607   } else if (name->Equals(v8_str("p3"))) {
5608     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
5609   } else if (name->Equals(v8_str("p4"))) {
5610     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
5611   }
5612   return v8::Undefined();
5613 }
5614
5615
5616 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
5617   ApiTestFuzzer::Fuzz();
5618   LocalContext context;
5619   context->Global()->Set(v8_str("o1"), obj->NewInstance());
5620   CompileRun(
5621     "o1.__proto__ = { };"
5622     "var o2 = { __proto__: o1 };"
5623     "var o3 = { __proto__: o2 };"
5624     "var o4 = { __proto__: o3 };"
5625     "for (var i = 0; i < 10; i++) o4.p4;"
5626     "for (var i = 0; i < 10; i++) o3.p3;"
5627     "for (var i = 0; i < 10; i++) o2.p2;"
5628     "for (var i = 0; i < 10; i++) o1.p1;");
5629 }
5630
5631
5632 static v8::Handle<Value> PGetter2(Local<String> name,
5633                                   const AccessorInfo& info) {
5634   ApiTestFuzzer::Fuzz();
5635   p_getter_count2++;
5636   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
5637   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
5638   if (name->Equals(v8_str("p1"))) {
5639     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
5640   } else if (name->Equals(v8_str("p2"))) {
5641     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
5642   } else if (name->Equals(v8_str("p3"))) {
5643     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
5644   } else if (name->Equals(v8_str("p4"))) {
5645     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
5646   }
5647   return v8::Undefined();
5648 }
5649
5650
5651 THREADED_TEST(GetterHolders) {
5652   v8::HandleScope scope;
5653   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
5654   obj->SetAccessor(v8_str("p1"), PGetter);
5655   obj->SetAccessor(v8_str("p2"), PGetter);
5656   obj->SetAccessor(v8_str("p3"), PGetter);
5657   obj->SetAccessor(v8_str("p4"), PGetter);
5658   p_getter_count = 0;
5659   RunHolderTest(obj);
5660   CHECK_EQ(40, p_getter_count);
5661 }
5662
5663
5664 THREADED_TEST(PreInterceptorHolders) {
5665   v8::HandleScope scope;
5666   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
5667   obj->SetNamedPropertyHandler(PGetter2);
5668   p_getter_count2 = 0;
5669   RunHolderTest(obj);
5670   CHECK_EQ(40, p_getter_count2);
5671 }
5672
5673
5674 THREADED_TEST(ObjectInstantiation) {
5675   v8::HandleScope scope;
5676   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5677   templ->SetAccessor(v8_str("t"), PGetter2);
5678   LocalContext context;
5679   context->Global()->Set(v8_str("o"), templ->NewInstance());
5680   for (int i = 0; i < 100; i++) {
5681     v8::HandleScope inner_scope;
5682     v8::Handle<v8::Object> obj = templ->NewInstance();
5683     CHECK_NE(obj, context->Global()->Get(v8_str("o")));
5684     context->Global()->Set(v8_str("o2"), obj);
5685     v8::Handle<Value> value =
5686         Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
5687     CHECK_EQ(v8::True(), value);
5688     context->Global()->Set(v8_str("o"), obj);
5689   }
5690 }
5691
5692
5693 static int StrCmp16(uint16_t* a, uint16_t* b) {
5694   while (true) {
5695     if (*a == 0 && *b == 0) return 0;
5696     if (*a != *b) return 0 + *a - *b;
5697     a++;
5698     b++;
5699   }
5700 }
5701
5702
5703 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
5704   while (true) {
5705     if (n-- == 0) return 0;
5706     if (*a == 0 && *b == 0) return 0;
5707     if (*a != *b) return 0 + *a - *b;
5708     a++;
5709     b++;
5710   }
5711 }
5712
5713
5714 int GetUtf8Length(Handle<String> str) {
5715   int len = str->Utf8Length();
5716   if (len < 0) {
5717     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
5718     i::FlattenString(istr);
5719     len = str->Utf8Length();
5720   }
5721   return len;
5722 }
5723
5724
5725 THREADED_TEST(StringWrite) {
5726   LocalContext context;
5727   v8::HandleScope scope;
5728   v8::Handle<String> str = v8_str("abcde");
5729   // abc<Icelandic eth><Unicode snowman>.
5730   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
5731   v8::Handle<String> str3 = v8::String::New("abc\0def", 7);
5732   const int kStride = 4;  // Must match stride in for loops in JS below.
5733   CompileRun(
5734       "var left = '';"
5735       "for (var i = 0; i < 0xd800; i += 4) {"
5736       "  left = left + String.fromCharCode(i);"
5737       "}");
5738   CompileRun(
5739       "var right = '';"
5740       "for (var i = 0; i < 0xd800; i += 4) {"
5741       "  right = String.fromCharCode(i) + right;"
5742       "}");
5743   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
5744   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
5745   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
5746
5747   CHECK_EQ(5, str2->Length());
5748   CHECK_EQ(0xd800 / kStride, left_tree->Length());
5749   CHECK_EQ(0xd800 / kStride, right_tree->Length());
5750
5751   char buf[100];
5752   char utf8buf[0xd800 * 3];
5753   uint16_t wbuf[100];
5754   int len;
5755   int charlen;
5756
5757   memset(utf8buf, 0x1, 1000);
5758   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
5759   CHECK_EQ(9, len);
5760   CHECK_EQ(5, charlen);
5761   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
5762
5763   memset(utf8buf, 0x1, 1000);
5764   len = str2->WriteUtf8(utf8buf, 8, &charlen);
5765   CHECK_EQ(8, len);
5766   CHECK_EQ(5, charlen);
5767   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
5768
5769   memset(utf8buf, 0x1, 1000);
5770   len = str2->WriteUtf8(utf8buf, 7, &charlen);
5771   CHECK_EQ(5, len);
5772   CHECK_EQ(4, charlen);
5773   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
5774
5775   memset(utf8buf, 0x1, 1000);
5776   len = str2->WriteUtf8(utf8buf, 6, &charlen);
5777   CHECK_EQ(5, len);
5778   CHECK_EQ(4, charlen);
5779   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
5780
5781   memset(utf8buf, 0x1, 1000);
5782   len = str2->WriteUtf8(utf8buf, 5, &charlen);
5783   CHECK_EQ(5, len);
5784   CHECK_EQ(4, charlen);
5785   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
5786
5787   memset(utf8buf, 0x1, 1000);
5788   len = str2->WriteUtf8(utf8buf, 4, &charlen);
5789   CHECK_EQ(3, len);
5790   CHECK_EQ(3, charlen);
5791   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
5792
5793   memset(utf8buf, 0x1, 1000);
5794   len = str2->WriteUtf8(utf8buf, 3, &charlen);
5795   CHECK_EQ(3, len);
5796   CHECK_EQ(3, charlen);
5797   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
5798
5799   memset(utf8buf, 0x1, 1000);
5800   len = str2->WriteUtf8(utf8buf, 2, &charlen);
5801   CHECK_EQ(2, len);
5802   CHECK_EQ(2, charlen);
5803   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
5804
5805   memset(utf8buf, 0x1, sizeof(utf8buf));
5806   len = GetUtf8Length(left_tree);
5807   int utf8_expected =
5808       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
5809   CHECK_EQ(utf8_expected, len);
5810   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
5811   CHECK_EQ(utf8_expected, len);
5812   CHECK_EQ(0xd800 / kStride, charlen);
5813   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
5814   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
5815   CHECK_EQ(0xc0 - kStride,
5816            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
5817   CHECK_EQ(1, utf8buf[utf8_expected]);
5818
5819   memset(utf8buf, 0x1, sizeof(utf8buf));
5820   len = GetUtf8Length(right_tree);
5821   CHECK_EQ(utf8_expected, len);
5822   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
5823   CHECK_EQ(utf8_expected, len);
5824   CHECK_EQ(0xd800 / kStride, charlen);
5825   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
5826   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
5827   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
5828   CHECK_EQ(1, utf8buf[utf8_expected]);
5829
5830   memset(buf, 0x1, sizeof(buf));
5831   memset(wbuf, 0x1, sizeof(wbuf));
5832   len = str->WriteAscii(buf);
5833   CHECK_EQ(5, len);
5834   len = str->Write(wbuf);
5835   CHECK_EQ(5, len);
5836   CHECK_EQ(0, strcmp("abcde", buf));
5837   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
5838   CHECK_EQ(0, StrCmp16(answer1, wbuf));
5839
5840   memset(buf, 0x1, sizeof(buf));
5841   memset(wbuf, 0x1, sizeof(wbuf));
5842   len = str->WriteAscii(buf, 0, 4);
5843   CHECK_EQ(4, len);
5844   len = str->Write(wbuf, 0, 4);
5845   CHECK_EQ(4, len);
5846   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
5847   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
5848   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
5849
5850   memset(buf, 0x1, sizeof(buf));
5851   memset(wbuf, 0x1, sizeof(wbuf));
5852   len = str->WriteAscii(buf, 0, 5);
5853   CHECK_EQ(5, len);
5854   len = str->Write(wbuf, 0, 5);
5855   CHECK_EQ(5, len);
5856   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
5857   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
5858   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
5859
5860   memset(buf, 0x1, sizeof(buf));
5861   memset(wbuf, 0x1, sizeof(wbuf));
5862   len = str->WriteAscii(buf, 0, 6);
5863   CHECK_EQ(5, len);
5864   len = str->Write(wbuf, 0, 6);
5865   CHECK_EQ(5, len);
5866   CHECK_EQ(0, strcmp("abcde", buf));
5867   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
5868   CHECK_EQ(0, StrCmp16(answer4, wbuf));
5869
5870   memset(buf, 0x1, sizeof(buf));
5871   memset(wbuf, 0x1, sizeof(wbuf));
5872   len = str->WriteAscii(buf, 4, -1);
5873   CHECK_EQ(1, len);
5874   len = str->Write(wbuf, 4, -1);
5875   CHECK_EQ(1, len);
5876   CHECK_EQ(0, strcmp("e", buf));
5877   uint16_t answer5[] = {'e', '\0'};
5878   CHECK_EQ(0, StrCmp16(answer5, wbuf));
5879
5880   memset(buf, 0x1, sizeof(buf));
5881   memset(wbuf, 0x1, sizeof(wbuf));
5882   len = str->WriteAscii(buf, 4, 6);
5883   CHECK_EQ(1, len);
5884   len = str->Write(wbuf, 4, 6);
5885   CHECK_EQ(1, len);
5886   CHECK_EQ(0, strcmp("e", buf));
5887   CHECK_EQ(0, StrCmp16(answer5, wbuf));
5888
5889   memset(buf, 0x1, sizeof(buf));
5890   memset(wbuf, 0x1, sizeof(wbuf));
5891   len = str->WriteAscii(buf, 4, 1);
5892   CHECK_EQ(1, len);
5893   len = str->Write(wbuf, 4, 1);
5894   CHECK_EQ(1, len);
5895   CHECK_EQ(0, strncmp("e\1", buf, 2));
5896   uint16_t answer6[] = {'e', 0x101};
5897   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
5898
5899   memset(buf, 0x1, sizeof(buf));
5900   memset(wbuf, 0x1, sizeof(wbuf));
5901   len = str->WriteAscii(buf, 3, 1);
5902   CHECK_EQ(1, len);
5903   len = str->Write(wbuf, 3, 1);
5904   CHECK_EQ(1, len);
5905   CHECK_EQ(0, strncmp("d\1", buf, 2));
5906   uint16_t answer7[] = {'d', 0x101};
5907   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
5908
5909   memset(wbuf, 0x1, sizeof(wbuf));
5910   wbuf[5] = 'X';
5911   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
5912   CHECK_EQ(5, len);
5913   CHECK_EQ('X', wbuf[5]);
5914   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
5915   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
5916   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
5917   CHECK_NE(0, StrCmp16(answer8b, wbuf));
5918   wbuf[5] = '\0';
5919   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
5920
5921   memset(buf, 0x1, sizeof(buf));
5922   buf[5] = 'X';
5923   len = str->WriteAscii(buf, 0, 6, String::NO_NULL_TERMINATION);
5924   CHECK_EQ(5, len);
5925   CHECK_EQ('X', buf[5]);
5926   CHECK_EQ(0, strncmp("abcde", buf, 5));
5927   CHECK_NE(0, strcmp("abcde", buf));
5928   buf[5] = '\0';
5929   CHECK_EQ(0, strcmp("abcde", buf));
5930
5931   memset(utf8buf, 0x1, sizeof(utf8buf));
5932   utf8buf[8] = 'X';
5933   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
5934                         String::NO_NULL_TERMINATION);
5935   CHECK_EQ(8, len);
5936   CHECK_EQ('X', utf8buf[8]);
5937   CHECK_EQ(5, charlen);
5938   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
5939   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
5940   utf8buf[8] = '\0';
5941   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
5942
5943   memset(utf8buf, 0x1, sizeof(utf8buf));
5944   utf8buf[5] = 'X';
5945   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
5946                         String::NO_NULL_TERMINATION);
5947   CHECK_EQ(5, len);
5948   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
5949   CHECK_EQ(5, charlen);
5950   utf8buf[5] = '\0';
5951   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
5952
5953   memset(buf, 0x1, sizeof(buf));
5954   len = str3->WriteAscii(buf);
5955   CHECK_EQ(7, len);
5956   CHECK_EQ(0, strcmp("abc def", buf));
5957
5958   memset(buf, 0x1, sizeof(buf));
5959   len = str3->WriteAscii(buf, 0, -1, String::PRESERVE_ASCII_NULL);
5960   CHECK_EQ(7, len);
5961   CHECK_EQ(0, strcmp("abc", buf));
5962   CHECK_EQ(0, buf[3]);
5963   CHECK_EQ(0, strcmp("def", buf + 4));
5964 }
5965
5966
5967 static void Utf16Helper(
5968     LocalContext& context,
5969     const char* name,
5970     const char* lengths_name,
5971     int len) {
5972   Local<v8::Array> a =
5973       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
5974   Local<v8::Array> alens =
5975       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
5976   for (int i = 0; i < len; i++) {
5977     Local<v8::String> string =
5978       Local<v8::String>::Cast(a->Get(i));
5979     Local<v8::Number> expected_len =
5980       Local<v8::Number>::Cast(alens->Get(i));
5981     CHECK_EQ(expected_len->Value() != string->Length(),
5982              string->MayContainNonAscii());
5983     int length = GetUtf8Length(string);
5984     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
5985   }
5986 }
5987
5988
5989 static uint16_t StringGet(Handle<String> str, int index) {
5990   i::Handle<i::String> istring =
5991       v8::Utils::OpenHandle(String::Cast(*str));
5992   return istring->Get(index);
5993 }
5994
5995
5996 static void WriteUtf8Helper(
5997     LocalContext& context,
5998     const char* name,
5999     const char* lengths_name,
6000     int len) {
6001   Local<v8::Array> b =
6002       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
6003   Local<v8::Array> alens =
6004       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
6005   char buffer[1000];
6006   char buffer2[1000];
6007   for (int i = 0; i < len; i++) {
6008     Local<v8::String> string =
6009       Local<v8::String>::Cast(b->Get(i));
6010     Local<v8::Number> expected_len =
6011       Local<v8::Number>::Cast(alens->Get(i));
6012     int utf8_length = static_cast<int>(expected_len->Value());
6013     for (int j = utf8_length + 1; j >= 0; j--) {
6014       memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
6015       memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
6016       int nchars;
6017       int utf8_written =
6018           string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
6019       int utf8_written2 =
6020           string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
6021       CHECK_GE(utf8_length + 1, utf8_written);
6022       CHECK_GE(utf8_length, utf8_written2);
6023       for (int k = 0; k < utf8_written2; k++) {
6024         CHECK_EQ(buffer[k], buffer2[k]);
6025       }
6026       CHECK(nchars * 3 >= utf8_written - 1);
6027       CHECK(nchars <= utf8_written);
6028       if (j == utf8_length + 1) {
6029         CHECK_EQ(utf8_written2, utf8_length);
6030         CHECK_EQ(utf8_written2 + 1, utf8_written);
6031       }
6032       CHECK_EQ(buffer[utf8_written], 42);
6033       if (j > utf8_length) {
6034         if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
6035         if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
6036         Handle<String> roundtrip = v8_str(buffer);
6037         CHECK(roundtrip->Equals(string));
6038       } else {
6039         if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
6040       }
6041       if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
6042       if (nchars >= 2) {
6043         uint16_t trail = StringGet(string, nchars - 1);
6044         uint16_t lead = StringGet(string, nchars - 2);
6045         if (((lead & 0xfc00) == 0xd800) &&
6046             ((trail & 0xfc00) == 0xdc00)) {
6047           unsigned char u1 = buffer2[utf8_written2 - 4];
6048           unsigned char u2 = buffer2[utf8_written2 - 3];
6049           unsigned char u3 = buffer2[utf8_written2 - 2];
6050           unsigned char u4 = buffer2[utf8_written2 - 1];
6051           CHECK_EQ((u1 & 0xf8), 0xf0);
6052           CHECK_EQ((u2 & 0xc0), 0x80);
6053           CHECK_EQ((u3 & 0xc0), 0x80);
6054           CHECK_EQ((u4 & 0xc0), 0x80);
6055           uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
6056           CHECK_EQ((u4 & 0x3f), (c & 0x3f));
6057           CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
6058           CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
6059           CHECK_EQ((u1 & 0x3), c >> 18);
6060         }
6061       }
6062     }
6063   }
6064 }
6065
6066
6067 THREADED_TEST(Utf16) {
6068   LocalContext context;
6069   v8::HandleScope scope;
6070   CompileRun(
6071       "var pad = '01234567890123456789';"
6072       "var p = [];"
6073       "var plens = [20, 3, 3];"
6074       "p.push('01234567890123456789');"
6075       "var lead = 0xd800;"
6076       "var trail = 0xdc00;"
6077       "p.push(String.fromCharCode(0xd800));"
6078       "p.push(String.fromCharCode(0xdc00));"
6079       "var a = [];"
6080       "var b = [];"
6081       "var c = [];"
6082       "var alens = [];"
6083       "for (var i = 0; i < 3; i++) {"
6084       "  p[1] = String.fromCharCode(lead++);"
6085       "  for (var j = 0; j < 3; j++) {"
6086       "    p[2] = String.fromCharCode(trail++);"
6087       "    a.push(p[i] + p[j]);"
6088       "    b.push(p[i] + p[j]);"
6089       "    c.push(p[i] + p[j]);"
6090       "    alens.push(plens[i] + plens[j]);"
6091       "  }"
6092       "}"
6093       "alens[5] -= 2;"  // Here the surrogate pairs match up.
6094       "var a2 = [];"
6095       "var b2 = [];"
6096       "var c2 = [];"
6097       "var a2lens = [];"
6098       "for (var m = 0; m < 9; m++) {"
6099       "  for (var n = 0; n < 9; n++) {"
6100       "    a2.push(a[m] + a[n]);"
6101       "    b2.push(b[m] + b[n]);"
6102       "    var newc = 'x' + c[m] + c[n] + 'y';"
6103       "    c2.push(newc.substring(1, newc.length - 1));"
6104       "    var utf = alens[m] + alens[n];"  // And here.
6105            // The 'n's that start with 0xdc.. are 6-8
6106            // The 'm's that end with 0xd8.. are 1, 4 and 7
6107       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
6108       "    a2lens.push(utf);"
6109       "  }"
6110       "}");
6111   Utf16Helper(context, "a", "alens", 9);
6112   Utf16Helper(context, "a2", "a2lens", 81);
6113   WriteUtf8Helper(context, "b", "alens", 9);
6114   WriteUtf8Helper(context, "b2", "a2lens", 81);
6115   WriteUtf8Helper(context, "c2", "a2lens", 81);
6116 }
6117
6118
6119 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
6120   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
6121   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
6122   return *is1 == *is2;
6123 }
6124
6125
6126 static void SameSymbolHelper(const char* a, const char* b) {
6127   Handle<String> symbol1 = v8::String::NewSymbol(a);
6128   Handle<String> symbol2 = v8::String::NewSymbol(b);
6129   CHECK(SameSymbol(symbol1, symbol2));
6130 }
6131
6132
6133 THREADED_TEST(Utf16Symbol) {
6134   LocalContext context;
6135   v8::HandleScope scope;
6136
6137   Handle<String> symbol1 = v8::String::NewSymbol("abc");
6138   Handle<String> symbol2 = v8::String::NewSymbol("abc");
6139   CHECK(SameSymbol(symbol1, symbol2));
6140
6141   SameSymbolHelper("\360\220\220\205",  // 4 byte encoding.
6142                    "\355\240\201\355\260\205");  // 2 3-byte surrogates.
6143   SameSymbolHelper("\355\240\201\355\260\206",  // 2 3-byte surrogates.
6144                    "\360\220\220\206");  // 4 byte encoding.
6145   SameSymbolHelper("x\360\220\220\205",  // 4 byte encoding.
6146                    "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
6147   SameSymbolHelper("x\355\240\201\355\260\206",  // 2 3-byte surrogates.
6148                    "x\360\220\220\206");  // 4 byte encoding.
6149   CompileRun(
6150       "var sym0 = 'benedictus';"
6151       "var sym0b = 'S\303\270ren';"
6152       "var sym1 = '\355\240\201\355\260\207';"
6153       "var sym2 = '\360\220\220\210';"
6154       "var sym3 = 'x\355\240\201\355\260\207';"
6155       "var sym4 = 'x\360\220\220\210';"
6156       "if (sym1.length != 2) throw sym1;"
6157       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
6158       "if (sym2.length != 2) throw sym2;"
6159       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
6160       "if (sym3.length != 3) throw sym3;"
6161       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
6162       "if (sym4.length != 3) throw sym4;"
6163       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
6164   Handle<String> sym0 = v8::String::NewSymbol("benedictus");
6165   Handle<String> sym0b = v8::String::NewSymbol("S\303\270ren");
6166   Handle<String> sym1 = v8::String::NewSymbol("\355\240\201\355\260\207");
6167   Handle<String> sym2 = v8::String::NewSymbol("\360\220\220\210");
6168   Handle<String> sym3 = v8::String::NewSymbol("x\355\240\201\355\260\207");
6169   Handle<String> sym4 = v8::String::NewSymbol("x\360\220\220\210");
6170   v8::Local<v8::Object> global = context->Global();
6171   Local<Value> s0 = global->Get(v8_str("sym0"));
6172   Local<Value> s0b = global->Get(v8_str("sym0b"));
6173   Local<Value> s1 = global->Get(v8_str("sym1"));
6174   Local<Value> s2 = global->Get(v8_str("sym2"));
6175   Local<Value> s3 = global->Get(v8_str("sym3"));
6176   Local<Value> s4 = global->Get(v8_str("sym4"));
6177   CHECK(SameSymbol(sym0, Handle<String>(String::Cast(*s0))));
6178   CHECK(SameSymbol(sym0b, Handle<String>(String::Cast(*s0b))));
6179   CHECK(SameSymbol(sym1, Handle<String>(String::Cast(*s1))));
6180   CHECK(SameSymbol(sym2, Handle<String>(String::Cast(*s2))));
6181   CHECK(SameSymbol(sym3, Handle<String>(String::Cast(*s3))));
6182   CHECK(SameSymbol(sym4, Handle<String>(String::Cast(*s4))));
6183 }
6184
6185
6186 THREADED_TEST(ToArrayIndex) {
6187   v8::HandleScope scope;
6188   LocalContext context;
6189
6190   v8::Handle<String> str = v8_str("42");
6191   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
6192   CHECK(!index.IsEmpty());
6193   CHECK_EQ(42.0, index->Uint32Value());
6194   str = v8_str("42asdf");
6195   index = str->ToArrayIndex();
6196   CHECK(index.IsEmpty());
6197   str = v8_str("-42");
6198   index = str->ToArrayIndex();
6199   CHECK(index.IsEmpty());
6200   str = v8_str("4294967295");
6201   index = str->ToArrayIndex();
6202   CHECK(!index.IsEmpty());
6203   CHECK_EQ(4294967295.0, index->Uint32Value());
6204   v8::Handle<v8::Number> num = v8::Number::New(1);
6205   index = num->ToArrayIndex();
6206   CHECK(!index.IsEmpty());
6207   CHECK_EQ(1.0, index->Uint32Value());
6208   num = v8::Number::New(-1);
6209   index = num->ToArrayIndex();
6210   CHECK(index.IsEmpty());
6211   v8::Handle<v8::Object> obj = v8::Object::New();
6212   index = obj->ToArrayIndex();
6213   CHECK(index.IsEmpty());
6214 }
6215
6216
6217 THREADED_TEST(ErrorConstruction) {
6218   v8::HandleScope scope;
6219   LocalContext context;
6220
6221   v8::Handle<String> foo = v8_str("foo");
6222   v8::Handle<String> message = v8_str("message");
6223   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
6224   CHECK(range_error->IsObject());
6225   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
6226   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
6227   CHECK(reference_error->IsObject());
6228   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
6229   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
6230   CHECK(syntax_error->IsObject());
6231   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
6232   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
6233   CHECK(type_error->IsObject());
6234   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
6235   v8::Handle<Value> error = v8::Exception::Error(foo);
6236   CHECK(error->IsObject());
6237   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
6238 }
6239
6240
6241 static v8::Handle<Value> YGetter(Local<String> name, const AccessorInfo& info) {
6242   ApiTestFuzzer::Fuzz();
6243   return v8_num(10);
6244 }
6245
6246
6247 static void YSetter(Local<String> name,
6248                     Local<Value> value,
6249                     const AccessorInfo& info) {
6250   if (info.This()->Has(name)) {
6251     info.This()->Delete(name);
6252   }
6253   info.This()->Set(name, value);
6254 }
6255
6256
6257 THREADED_TEST(DeleteAccessor) {
6258   v8::HandleScope scope;
6259   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
6260   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
6261   LocalContext context;
6262   v8::Handle<v8::Object> holder = obj->NewInstance();
6263   context->Global()->Set(v8_str("holder"), holder);
6264   v8::Handle<Value> result = CompileRun(
6265       "holder.y = 11; holder.y = 12; holder.y");
6266   CHECK_EQ(12, result->Uint32Value());
6267 }
6268
6269
6270 THREADED_TEST(TypeSwitch) {
6271   v8::HandleScope scope;
6272   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
6273   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
6274   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
6275   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
6276   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
6277   LocalContext context;
6278   v8::Handle<v8::Object> obj0 = v8::Object::New();
6279   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
6280   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
6281   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
6282   for (int i = 0; i < 10; i++) {
6283     CHECK_EQ(0, type_switch->match(obj0));
6284     CHECK_EQ(1, type_switch->match(obj1));
6285     CHECK_EQ(2, type_switch->match(obj2));
6286     CHECK_EQ(3, type_switch->match(obj3));
6287     CHECK_EQ(3, type_switch->match(obj3));
6288     CHECK_EQ(2, type_switch->match(obj2));
6289     CHECK_EQ(1, type_switch->match(obj1));
6290     CHECK_EQ(0, type_switch->match(obj0));
6291   }
6292 }
6293
6294
6295 // For use within the TestSecurityHandler() test.
6296 static bool g_security_callback_result = false;
6297 static bool NamedSecurityTestCallback(Local<v8::Object> global,
6298                                       Local<Value> name,
6299                                       v8::AccessType type,
6300                                       Local<Value> data) {
6301   // Always allow read access.
6302   if (type == v8::ACCESS_GET)
6303     return true;
6304
6305   // Sometimes allow other access.
6306   return g_security_callback_result;
6307 }
6308
6309
6310 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
6311                                         uint32_t key,
6312                                         v8::AccessType type,
6313                                         Local<Value> data) {
6314   // Always allow read access.
6315   if (type == v8::ACCESS_GET)
6316     return true;
6317
6318   // Sometimes allow other access.
6319   return g_security_callback_result;
6320 }
6321
6322
6323 static int trouble_nesting = 0;
6324 static v8::Handle<Value> TroubleCallback(const v8::Arguments& args) {
6325   ApiTestFuzzer::Fuzz();
6326   trouble_nesting++;
6327
6328   // Call a JS function that throws an uncaught exception.
6329   Local<v8::Object> arg_this = Context::GetCurrent()->Global();
6330   Local<Value> trouble_callee = (trouble_nesting == 3) ?
6331     arg_this->Get(v8_str("trouble_callee")) :
6332     arg_this->Get(v8_str("trouble_caller"));
6333   CHECK(trouble_callee->IsFunction());
6334   return Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL);
6335 }
6336
6337
6338 static int report_count = 0;
6339 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
6340                                              v8::Handle<Value>) {
6341   report_count++;
6342 }
6343
6344
6345 // Counts uncaught exceptions, but other tests running in parallel
6346 // also have uncaught exceptions.
6347 TEST(ApiUncaughtException) {
6348   report_count = 0;
6349   v8::HandleScope scope;
6350   LocalContext env;
6351   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
6352
6353   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
6354   v8::Local<v8::Object> global = env->Global();
6355   global->Set(v8_str("trouble"), fun->GetFunction());
6356
6357   Script::Compile(v8_str("function trouble_callee() {"
6358                          "  var x = null;"
6359                          "  return x.foo;"
6360                          "};"
6361                          "function trouble_caller() {"
6362                          "  trouble();"
6363                          "};"))->Run();
6364   Local<Value> trouble = global->Get(v8_str("trouble"));
6365   CHECK(trouble->IsFunction());
6366   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
6367   CHECK(trouble_callee->IsFunction());
6368   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
6369   CHECK(trouble_caller->IsFunction());
6370   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
6371   CHECK_EQ(1, report_count);
6372   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
6373 }
6374
6375 static const char* script_resource_name = "ExceptionInNativeScript.js";
6376 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
6377                                                 v8::Handle<Value>) {
6378   v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
6379   CHECK(!name_val.IsEmpty() && name_val->IsString());
6380   v8::String::AsciiValue name(message->GetScriptResourceName());
6381   CHECK_EQ(script_resource_name, *name);
6382   CHECK_EQ(3, message->GetLineNumber());
6383   v8::String::AsciiValue source_line(message->GetSourceLine());
6384   CHECK_EQ("  new o.foo();", *source_line);
6385 }
6386
6387 TEST(ExceptionInNativeScript) {
6388   v8::HandleScope scope;
6389   LocalContext env;
6390   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
6391
6392   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
6393   v8::Local<v8::Object> global = env->Global();
6394   global->Set(v8_str("trouble"), fun->GetFunction());
6395
6396   Script::Compile(v8_str("function trouble() {\n"
6397                          "  var o = {};\n"
6398                          "  new o.foo();\n"
6399                          "};"), v8::String::New(script_resource_name))->Run();
6400   Local<Value> trouble = global->Get(v8_str("trouble"));
6401   CHECK(trouble->IsFunction());
6402   Function::Cast(*trouble)->Call(global, 0, NULL);
6403   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
6404 }
6405
6406
6407 TEST(CompilationErrorUsingTryCatchHandler) {
6408   v8::HandleScope scope;
6409   LocalContext env;
6410   v8::TryCatch try_catch;
6411   Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
6412   CHECK_NE(NULL, *try_catch.Exception());
6413   CHECK(try_catch.HasCaught());
6414 }
6415
6416
6417 TEST(TryCatchFinallyUsingTryCatchHandler) {
6418   v8::HandleScope scope;
6419   LocalContext env;
6420   v8::TryCatch try_catch;
6421   Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
6422   CHECK(!try_catch.HasCaught());
6423   Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
6424   CHECK(try_catch.HasCaught());
6425   try_catch.Reset();
6426   Script::Compile(v8_str("(function() {"
6427                          "try { throw ''; } finally { return; }"
6428                          "})()"))->Run();
6429   CHECK(!try_catch.HasCaught());
6430   Script::Compile(v8_str("(function()"
6431                          "  { try { throw ''; } finally { throw 0; }"
6432                          "})()"))->Run();
6433   CHECK(try_catch.HasCaught());
6434 }
6435
6436
6437 // SecurityHandler can't be run twice
6438 TEST(SecurityHandler) {
6439   v8::HandleScope scope0;
6440   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
6441   global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
6442                                            IndexedSecurityTestCallback);
6443   // Create an environment
6444   v8::Persistent<Context> context0 =
6445     Context::New(NULL, global_template);
6446   context0->Enter();
6447
6448   v8::Handle<v8::Object> global0 = context0->Global();
6449   v8::Handle<Script> script0 = v8_compile("foo = 111");
6450   script0->Run();
6451   global0->Set(v8_str("0"), v8_num(999));
6452   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
6453   CHECK_EQ(111, foo0->Int32Value());
6454   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
6455   CHECK_EQ(999, z0->Int32Value());
6456
6457   // Create another environment, should fail security checks.
6458   v8::HandleScope scope1;
6459
6460   v8::Persistent<Context> context1 =
6461     Context::New(NULL, global_template);
6462   context1->Enter();
6463
6464   v8::Handle<v8::Object> global1 = context1->Global();
6465   global1->Set(v8_str("othercontext"), global0);
6466   // This set will fail the security check.
6467   v8::Handle<Script> script1 =
6468     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
6469   script1->Run();
6470   // This read will pass the security check.
6471   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
6472   CHECK_EQ(111, foo1->Int32Value());
6473   // This read will pass the security check.
6474   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
6475   CHECK_EQ(999, z1->Int32Value());
6476
6477   // Create another environment, should pass security checks.
6478   { g_security_callback_result = true;  // allow security handler to pass.
6479     v8::HandleScope scope2;
6480     LocalContext context2;
6481     v8::Handle<v8::Object> global2 = context2->Global();
6482     global2->Set(v8_str("othercontext"), global0);
6483     v8::Handle<Script> script2 =
6484         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
6485     script2->Run();
6486     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
6487     CHECK_EQ(333, foo2->Int32Value());
6488     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
6489     CHECK_EQ(888, z2->Int32Value());
6490   }
6491
6492   context1->Exit();
6493   context1.Dispose();
6494
6495   context0->Exit();
6496   context0.Dispose();
6497 }
6498
6499
6500 THREADED_TEST(SecurityChecks) {
6501   v8::HandleScope handle_scope;
6502   LocalContext env1;
6503   v8::Persistent<Context> env2 = Context::New();
6504
6505   Local<Value> foo = v8_str("foo");
6506   Local<Value> bar = v8_str("bar");
6507
6508   // Set to the same domain.
6509   env1->SetSecurityToken(foo);
6510
6511   // Create a function in env1.
6512   Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
6513   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
6514   CHECK(spy->IsFunction());
6515
6516   // Create another function accessing global objects.
6517   Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
6518   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
6519   CHECK(spy2->IsFunction());
6520
6521   // Switch to env2 in the same domain and invoke spy on env2.
6522   {
6523     env2->SetSecurityToken(foo);
6524     // Enter env2
6525     Context::Scope scope_env2(env2);
6526     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
6527     CHECK(result->IsFunction());
6528   }
6529
6530   {
6531     env2->SetSecurityToken(bar);
6532     Context::Scope scope_env2(env2);
6533
6534     // Call cross_domain_call, it should throw an exception
6535     v8::TryCatch try_catch;
6536     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
6537     CHECK(try_catch.HasCaught());
6538   }
6539
6540   env2.Dispose();
6541 }
6542
6543
6544 // Regression test case for issue 1183439.
6545 THREADED_TEST(SecurityChecksForPrototypeChain) {
6546   v8::HandleScope scope;
6547   LocalContext current;
6548   v8::Persistent<Context> other = Context::New();
6549
6550   // Change context to be able to get to the Object function in the
6551   // other context without hitting the security checks.
6552   v8::Local<Value> other_object;
6553   { Context::Scope scope(other);
6554     other_object = other->Global()->Get(v8_str("Object"));
6555     other->Global()->Set(v8_num(42), v8_num(87));
6556   }
6557
6558   current->Global()->Set(v8_str("other"), other->Global());
6559   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
6560
6561   // Make sure the security check fails here and we get an undefined
6562   // result instead of getting the Object function. Repeat in a loop
6563   // to make sure to exercise the IC code.
6564   v8::Local<Script> access_other0 = v8_compile("other.Object");
6565   v8::Local<Script> access_other1 = v8_compile("other[42]");
6566   for (int i = 0; i < 5; i++) {
6567     CHECK(!access_other0->Run()->Equals(other_object));
6568     CHECK(access_other0->Run()->IsUndefined());
6569     CHECK(!access_other1->Run()->Equals(v8_num(87)));
6570     CHECK(access_other1->Run()->IsUndefined());
6571   }
6572
6573   // Create an object that has 'other' in its prototype chain and make
6574   // sure we cannot access the Object function indirectly through
6575   // that. Repeat in a loop to make sure to exercise the IC code.
6576   v8_compile("function F() { };"
6577              "F.prototype = other;"
6578              "var f = new F();")->Run();
6579   v8::Local<Script> access_f0 = v8_compile("f.Object");
6580   v8::Local<Script> access_f1 = v8_compile("f[42]");
6581   for (int j = 0; j < 5; j++) {
6582     CHECK(!access_f0->Run()->Equals(other_object));
6583     CHECK(access_f0->Run()->IsUndefined());
6584     CHECK(!access_f1->Run()->Equals(v8_num(87)));
6585     CHECK(access_f1->Run()->IsUndefined());
6586   }
6587
6588   // Now it gets hairy: Set the prototype for the other global object
6589   // to be the current global object. The prototype chain for 'f' now
6590   // goes through 'other' but ends up in the current global object.
6591   { Context::Scope scope(other);
6592     other->Global()->Set(v8_str("__proto__"), current->Global());
6593   }
6594   // Set a named and an index property on the current global
6595   // object. To force the lookup to go through the other global object,
6596   // the properties must not exist in the other global object.
6597   current->Global()->Set(v8_str("foo"), v8_num(100));
6598   current->Global()->Set(v8_num(99), v8_num(101));
6599   // Try to read the properties from f and make sure that the access
6600   // gets stopped by the security checks on the other global object.
6601   Local<Script> access_f2 = v8_compile("f.foo");
6602   Local<Script> access_f3 = v8_compile("f[99]");
6603   for (int k = 0; k < 5; k++) {
6604     CHECK(!access_f2->Run()->Equals(v8_num(100)));
6605     CHECK(access_f2->Run()->IsUndefined());
6606     CHECK(!access_f3->Run()->Equals(v8_num(101)));
6607     CHECK(access_f3->Run()->IsUndefined());
6608   }
6609   other.Dispose();
6610 }
6611
6612
6613 THREADED_TEST(CrossDomainDelete) {
6614   v8::HandleScope handle_scope;
6615   LocalContext env1;
6616   v8::Persistent<Context> env2 = Context::New();
6617
6618   Local<Value> foo = v8_str("foo");
6619   Local<Value> bar = v8_str("bar");
6620
6621   // Set to the same domain.
6622   env1->SetSecurityToken(foo);
6623   env2->SetSecurityToken(foo);
6624
6625   env1->Global()->Set(v8_str("prop"), v8_num(3));
6626   env2->Global()->Set(v8_str("env1"), env1->Global());
6627
6628   // Change env2 to a different domain and delete env1.prop.
6629   env2->SetSecurityToken(bar);
6630   {
6631     Context::Scope scope_env2(env2);
6632     Local<Value> result =
6633         Script::Compile(v8_str("delete env1.prop"))->Run();
6634     CHECK(result->IsFalse());
6635   }
6636
6637   // Check that env1.prop still exists.
6638   Local<Value> v = env1->Global()->Get(v8_str("prop"));
6639   CHECK(v->IsNumber());
6640   CHECK_EQ(3, v->Int32Value());
6641
6642   env2.Dispose();
6643 }
6644
6645
6646 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
6647   v8::HandleScope handle_scope;
6648   LocalContext env1;
6649   v8::Persistent<Context> env2 = Context::New();
6650
6651   Local<Value> foo = v8_str("foo");
6652   Local<Value> bar = v8_str("bar");
6653
6654   // Set to the same domain.
6655   env1->SetSecurityToken(foo);
6656   env2->SetSecurityToken(foo);
6657
6658   env1->Global()->Set(v8_str("prop"), v8_num(3));
6659   env2->Global()->Set(v8_str("env1"), env1->Global());
6660
6661   // env1.prop is enumerable in env2.
6662   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
6663   {
6664     Context::Scope scope_env2(env2);
6665     Local<Value> result = Script::Compile(test)->Run();
6666     CHECK(result->IsTrue());
6667   }
6668
6669   // Change env2 to a different domain and test again.
6670   env2->SetSecurityToken(bar);
6671   {
6672     Context::Scope scope_env2(env2);
6673     Local<Value> result = Script::Compile(test)->Run();
6674     CHECK(result->IsFalse());
6675   }
6676
6677   env2.Dispose();
6678 }
6679
6680
6681 THREADED_TEST(CrossDomainForIn) {
6682   v8::HandleScope handle_scope;
6683   LocalContext env1;
6684   v8::Persistent<Context> env2 = Context::New();
6685
6686   Local<Value> foo = v8_str("foo");
6687   Local<Value> bar = v8_str("bar");
6688
6689   // Set to the same domain.
6690   env1->SetSecurityToken(foo);
6691   env2->SetSecurityToken(foo);
6692
6693   env1->Global()->Set(v8_str("prop"), v8_num(3));
6694   env2->Global()->Set(v8_str("env1"), env1->Global());
6695
6696   // Change env2 to a different domain and set env1's global object
6697   // as the __proto__ of an object in env2 and enumerate properties
6698   // in for-in. It shouldn't enumerate properties on env1's global
6699   // object.
6700   env2->SetSecurityToken(bar);
6701   {
6702     Context::Scope scope_env2(env2);
6703     Local<Value> result =
6704         CompileRun("(function(){var obj = {'__proto__':env1};"
6705                    "for (var p in obj)"
6706                    "   if (p == 'prop') return false;"
6707                    "return true;})()");
6708     CHECK(result->IsTrue());
6709   }
6710   env2.Dispose();
6711 }
6712
6713
6714 TEST(ContextDetachGlobal) {
6715   v8::HandleScope handle_scope;
6716   LocalContext env1;
6717   v8::Persistent<Context> env2 = Context::New();
6718
6719   Local<v8::Object> global1 = env1->Global();
6720
6721   Local<Value> foo = v8_str("foo");
6722
6723   // Set to the same domain.
6724   env1->SetSecurityToken(foo);
6725   env2->SetSecurityToken(foo);
6726
6727   // Enter env2
6728   env2->Enter();
6729
6730   // Create a function in env2 and add a reference to it in env1.
6731   Local<v8::Object> global2 = env2->Global();
6732   global2->Set(v8_str("prop"), v8::Integer::New(1));
6733   CompileRun("function getProp() {return prop;}");
6734
6735   env1->Global()->Set(v8_str("getProp"),
6736                       global2->Get(v8_str("getProp")));
6737
6738   // Detach env2's global, and reuse the global object of env2
6739   env2->Exit();
6740   env2->DetachGlobal();
6741   // env2 has a new global object.
6742   CHECK(!env2->Global()->Equals(global2));
6743
6744   v8::Persistent<Context> env3 =
6745       Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
6746   env3->SetSecurityToken(v8_str("bar"));
6747   env3->Enter();
6748
6749   Local<v8::Object> global3 = env3->Global();
6750   CHECK_EQ(global2, global3);
6751   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
6752   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
6753   global3->Set(v8_str("prop"), v8::Integer::New(-1));
6754   global3->Set(v8_str("prop2"), v8::Integer::New(2));
6755   env3->Exit();
6756
6757   // Call getProp in env1, and it should return the value 1
6758   {
6759     Local<Value> get_prop = global1->Get(v8_str("getProp"));
6760     CHECK(get_prop->IsFunction());
6761     v8::TryCatch try_catch;
6762     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
6763     CHECK(!try_catch.HasCaught());
6764     CHECK_EQ(1, r->Int32Value());
6765   }
6766
6767   // Check that env3 is not accessible from env1
6768   {
6769     Local<Value> r = global3->Get(v8_str("prop2"));
6770     CHECK(r->IsUndefined());
6771   }
6772
6773   env2.Dispose();
6774   env3.Dispose();
6775 }
6776
6777
6778 TEST(DetachAndReattachGlobal) {
6779   v8::HandleScope scope;
6780   LocalContext env1;
6781
6782   // Create second environment.
6783   v8::Persistent<Context> env2 = Context::New();
6784
6785   Local<Value> foo = v8_str("foo");
6786
6787   // Set same security token for env1 and env2.
6788   env1->SetSecurityToken(foo);
6789   env2->SetSecurityToken(foo);
6790
6791   // Create a property on the global object in env2.
6792   {
6793     v8::Context::Scope scope(env2);
6794     env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
6795   }
6796
6797   // Create a reference to env2 global from env1 global.
6798   env1->Global()->Set(v8_str("other"), env2->Global());
6799
6800   // Check that we have access to other.p in env2 from env1.
6801   Local<Value> result = CompileRun("other.p");
6802   CHECK(result->IsInt32());
6803   CHECK_EQ(42, result->Int32Value());
6804
6805   // Hold on to global from env2 and detach global from env2.
6806   Local<v8::Object> global2 = env2->Global();
6807   env2->DetachGlobal();
6808
6809   // Check that the global has been detached. No other.p property can
6810   // be found.
6811   result = CompileRun("other.p");
6812   CHECK(result->IsUndefined());
6813
6814   // Reuse global2 for env3.
6815   v8::Persistent<Context> env3 =
6816       Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
6817   CHECK_EQ(global2, env3->Global());
6818
6819   // Start by using the same security token for env3 as for env1 and env2.
6820   env3->SetSecurityToken(foo);
6821
6822   // Create a property on the global object in env3.
6823   {
6824     v8::Context::Scope scope(env3);
6825     env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
6826   }
6827
6828   // Check that other.p is now the property in env3 and that we have access.
6829   result = CompileRun("other.p");
6830   CHECK(result->IsInt32());
6831   CHECK_EQ(24, result->Int32Value());
6832
6833   // Change security token for env3 to something different from env1 and env2.
6834   env3->SetSecurityToken(v8_str("bar"));
6835
6836   // Check that we do not have access to other.p in env1. |other| is now
6837   // the global object for env3 which has a different security token,
6838   // so access should be blocked.
6839   result = CompileRun("other.p");
6840   CHECK(result->IsUndefined());
6841
6842   // Detach the global for env3 and reattach it to env2.
6843   env3->DetachGlobal();
6844   env2->ReattachGlobal(global2);
6845
6846   // Check that we have access to other.p again in env1.  |other| is now
6847   // the global object for env2 which has the same security token as env1.
6848   result = CompileRun("other.p");
6849   CHECK(result->IsInt32());
6850   CHECK_EQ(42, result->Int32Value());
6851
6852   env2.Dispose();
6853   env3.Dispose();
6854 }
6855
6856
6857 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
6858 static bool NamedAccessBlocker(Local<v8::Object> global,
6859                                Local<Value> name,
6860                                v8::AccessType type,
6861                                Local<Value> data) {
6862   return Context::GetCurrent()->Global()->Equals(global) ||
6863       allowed_access_type[type];
6864 }
6865
6866
6867 static bool IndexedAccessBlocker(Local<v8::Object> global,
6868                                  uint32_t key,
6869                                  v8::AccessType type,
6870                                  Local<Value> data) {
6871   return Context::GetCurrent()->Global()->Equals(global) ||
6872       allowed_access_type[type];
6873 }
6874
6875
6876 static int g_echo_value = -1;
6877 static v8::Handle<Value> EchoGetter(Local<String> name,
6878                                     const AccessorInfo& info) {
6879   return v8_num(g_echo_value);
6880 }
6881
6882
6883 static void EchoSetter(Local<String> name,
6884                        Local<Value> value,
6885                        const AccessorInfo&) {
6886   if (value->IsNumber())
6887     g_echo_value = value->Int32Value();
6888 }
6889
6890
6891 static v8::Handle<Value> UnreachableGetter(Local<String> name,
6892                                            const AccessorInfo& info) {
6893   CHECK(false);  // This function should not be called..
6894   return v8::Undefined();
6895 }
6896
6897
6898 static void UnreachableSetter(Local<String>, Local<Value>,
6899                               const AccessorInfo&) {
6900   CHECK(false);  // This function should nto be called.
6901 }
6902
6903
6904 TEST(AccessControl) {
6905   v8::HandleScope handle_scope;
6906   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
6907
6908   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
6909                                            IndexedAccessBlocker);
6910
6911   // Add an accessor accessible by cross-domain JS code.
6912   global_template->SetAccessor(
6913       v8_str("accessible_prop"),
6914       EchoGetter, EchoSetter,
6915       v8::Handle<Value>(),
6916       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
6917
6918   // Add an accessor that is not accessible by cross-domain JS code.
6919   global_template->SetAccessor(v8_str("blocked_prop"),
6920                                UnreachableGetter, UnreachableSetter,
6921                                v8::Handle<Value>(),
6922                                v8::DEFAULT);
6923
6924   // Create an environment
6925   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
6926   context0->Enter();
6927
6928   v8::Handle<v8::Object> global0 = context0->Global();
6929
6930   // Define a property with JS getter and setter.
6931   CompileRun(
6932       "function getter() { return 'getter'; };\n"
6933       "function setter() { return 'setter'; }\n"
6934       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
6935
6936   Local<Value> getter = global0->Get(v8_str("getter"));
6937   Local<Value> setter = global0->Get(v8_str("setter"));
6938
6939   // And define normal element.
6940   global0->Set(239, v8_str("239"));
6941
6942   // Define an element with JS getter and setter.
6943   CompileRun(
6944       "function el_getter() { return 'el_getter'; };\n"
6945       "function el_setter() { return 'el_setter'; };\n"
6946       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
6947
6948   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
6949   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
6950
6951   v8::HandleScope scope1;
6952
6953   v8::Persistent<Context> context1 = Context::New();
6954   context1->Enter();
6955
6956   v8::Handle<v8::Object> global1 = context1->Global();
6957   global1->Set(v8_str("other"), global0);
6958
6959   // Access blocked property.
6960   CompileRun("other.blocked_prop = 1");
6961
6962   ExpectUndefined("other.blocked_prop");
6963   ExpectUndefined(
6964       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
6965   ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
6966
6967   // Enable ACCESS_HAS
6968   allowed_access_type[v8::ACCESS_HAS] = true;
6969   ExpectUndefined("other.blocked_prop");
6970   // ... and now we can get the descriptor...
6971   ExpectUndefined(
6972       "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
6973   // ... and enumerate the property.
6974   ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
6975   allowed_access_type[v8::ACCESS_HAS] = false;
6976
6977   // Access blocked element.
6978   CompileRun("other[239] = 1");
6979
6980   ExpectUndefined("other[239]");
6981   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
6982   ExpectFalse("propertyIsEnumerable.call(other, '239')");
6983
6984   // Enable ACCESS_HAS
6985   allowed_access_type[v8::ACCESS_HAS] = true;
6986   ExpectUndefined("other[239]");
6987   // ... and now we can get the descriptor...
6988   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
6989   // ... and enumerate the property.
6990   ExpectTrue("propertyIsEnumerable.call(other, '239')");
6991   allowed_access_type[v8::ACCESS_HAS] = false;
6992
6993   // Access a property with JS accessor.
6994   CompileRun("other.js_accessor_p = 2");
6995
6996   ExpectUndefined("other.js_accessor_p");
6997   ExpectUndefined(
6998       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
6999
7000   // Enable ACCESS_HAS.
7001   allowed_access_type[v8::ACCESS_HAS] = true;
7002   ExpectUndefined("other.js_accessor_p");
7003   ExpectUndefined(
7004       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
7005   ExpectUndefined(
7006       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
7007   ExpectUndefined(
7008       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
7009   allowed_access_type[v8::ACCESS_HAS] = false;
7010
7011   // Enable both ACCESS_HAS and ACCESS_GET.
7012   allowed_access_type[v8::ACCESS_HAS] = true;
7013   allowed_access_type[v8::ACCESS_GET] = true;
7014
7015   ExpectString("other.js_accessor_p", "getter");
7016   ExpectObject(
7017       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
7018   ExpectUndefined(
7019       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
7020   ExpectUndefined(
7021       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
7022
7023   allowed_access_type[v8::ACCESS_GET] = false;
7024   allowed_access_type[v8::ACCESS_HAS] = false;
7025
7026   // Enable both ACCESS_HAS and ACCESS_SET.
7027   allowed_access_type[v8::ACCESS_HAS] = true;
7028   allowed_access_type[v8::ACCESS_SET] = true;
7029
7030   ExpectUndefined("other.js_accessor_p");
7031   ExpectUndefined(
7032       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
7033   ExpectObject(
7034       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
7035   ExpectUndefined(
7036       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
7037
7038   allowed_access_type[v8::ACCESS_SET] = false;
7039   allowed_access_type[v8::ACCESS_HAS] = false;
7040
7041   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
7042   allowed_access_type[v8::ACCESS_HAS] = true;
7043   allowed_access_type[v8::ACCESS_GET] = true;
7044   allowed_access_type[v8::ACCESS_SET] = true;
7045
7046   ExpectString("other.js_accessor_p", "getter");
7047   ExpectObject(
7048       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
7049   ExpectObject(
7050       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
7051   ExpectUndefined(
7052       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
7053
7054   allowed_access_type[v8::ACCESS_SET] = false;
7055   allowed_access_type[v8::ACCESS_GET] = false;
7056   allowed_access_type[v8::ACCESS_HAS] = false;
7057
7058   // Access an element with JS accessor.
7059   CompileRun("other[42] = 2");
7060
7061   ExpectUndefined("other[42]");
7062   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
7063
7064   // Enable ACCESS_HAS.
7065   allowed_access_type[v8::ACCESS_HAS] = true;
7066   ExpectUndefined("other[42]");
7067   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
7068   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
7069   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
7070   allowed_access_type[v8::ACCESS_HAS] = false;
7071
7072   // Enable both ACCESS_HAS and ACCESS_GET.
7073   allowed_access_type[v8::ACCESS_HAS] = true;
7074   allowed_access_type[v8::ACCESS_GET] = true;
7075
7076   ExpectString("other[42]", "el_getter");
7077   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
7078   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
7079   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
7080
7081   allowed_access_type[v8::ACCESS_GET] = false;
7082   allowed_access_type[v8::ACCESS_HAS] = false;
7083
7084   // Enable both ACCESS_HAS and ACCESS_SET.
7085   allowed_access_type[v8::ACCESS_HAS] = true;
7086   allowed_access_type[v8::ACCESS_SET] = true;
7087
7088   ExpectUndefined("other[42]");
7089   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
7090   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
7091   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
7092
7093   allowed_access_type[v8::ACCESS_SET] = false;
7094   allowed_access_type[v8::ACCESS_HAS] = false;
7095
7096   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
7097   allowed_access_type[v8::ACCESS_HAS] = true;
7098   allowed_access_type[v8::ACCESS_GET] = true;
7099   allowed_access_type[v8::ACCESS_SET] = true;
7100
7101   ExpectString("other[42]", "el_getter");
7102   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
7103   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
7104   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
7105
7106   allowed_access_type[v8::ACCESS_SET] = false;
7107   allowed_access_type[v8::ACCESS_GET] = false;
7108   allowed_access_type[v8::ACCESS_HAS] = false;
7109
7110   v8::Handle<Value> value;
7111
7112   // Access accessible property
7113   value = CompileRun("other.accessible_prop = 3");
7114   CHECK(value->IsNumber());
7115   CHECK_EQ(3, value->Int32Value());
7116   CHECK_EQ(3, g_echo_value);
7117
7118   value = CompileRun("other.accessible_prop");
7119   CHECK(value->IsNumber());
7120   CHECK_EQ(3, value->Int32Value());
7121
7122   value = CompileRun(
7123       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
7124   CHECK(value->IsNumber());
7125   CHECK_EQ(3, value->Int32Value());
7126
7127   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
7128   CHECK(value->IsTrue());
7129
7130   // Enumeration doesn't enumerate accessors from inaccessible objects in
7131   // the prototype chain even if the accessors are in themselves accessible.
7132   value =
7133       CompileRun("(function(){var obj = {'__proto__':other};"
7134                  "for (var p in obj)"
7135                  "   if (p == 'accessible_prop' || p == 'blocked_prop') {"
7136                  "     return false;"
7137                  "   }"
7138                  "return true;})()");
7139   CHECK(value->IsTrue());
7140
7141   context1->Exit();
7142   context0->Exit();
7143   context1.Dispose();
7144   context0.Dispose();
7145 }
7146
7147
7148 TEST(AccessControlES5) {
7149   v8::HandleScope handle_scope;
7150   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
7151
7152   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
7153                                            IndexedAccessBlocker);
7154
7155   // Add accessible accessor.
7156   global_template->SetAccessor(
7157       v8_str("accessible_prop"),
7158       EchoGetter, EchoSetter,
7159       v8::Handle<Value>(),
7160       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
7161
7162
7163   // Add an accessor that is not accessible by cross-domain JS code.
7164   global_template->SetAccessor(v8_str("blocked_prop"),
7165                                UnreachableGetter, UnreachableSetter,
7166                                v8::Handle<Value>(),
7167                                v8::DEFAULT);
7168
7169   // Create an environment
7170   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
7171   context0->Enter();
7172
7173   v8::Handle<v8::Object> global0 = context0->Global();
7174
7175   v8::Persistent<Context> context1 = Context::New();
7176   context1->Enter();
7177   v8::Handle<v8::Object> global1 = context1->Global();
7178   global1->Set(v8_str("other"), global0);
7179
7180   // Regression test for issue 1154.
7181   ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
7182
7183   ExpectUndefined("other.blocked_prop");
7184
7185   // Regression test for issue 1027.
7186   CompileRun("Object.defineProperty(\n"
7187              "  other, 'blocked_prop', {configurable: false})");
7188   ExpectUndefined("other.blocked_prop");
7189   ExpectUndefined(
7190       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
7191
7192   // Regression test for issue 1171.
7193   ExpectTrue("Object.isExtensible(other)");
7194   CompileRun("Object.preventExtensions(other)");
7195   ExpectTrue("Object.isExtensible(other)");
7196
7197   // Object.seal and Object.freeze.
7198   CompileRun("Object.freeze(other)");
7199   ExpectTrue("Object.isExtensible(other)");
7200
7201   CompileRun("Object.seal(other)");
7202   ExpectTrue("Object.isExtensible(other)");
7203
7204   // Regression test for issue 1250.
7205   // Make sure that we can set the accessible accessors value using normal
7206   // assignment.
7207   CompileRun("other.accessible_prop = 42");
7208   CHECK_EQ(42, g_echo_value);
7209
7210   v8::Handle<Value> value;
7211   // We follow Safari in ignoring assignments to host object accessors.
7212   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
7213   value = CompileRun("other.accessible_prop == 42");
7214   CHECK(value->IsTrue());
7215 }
7216
7217
7218 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
7219                                             Local<Value> name,
7220                                             v8::AccessType type,
7221                                             Local<Value> data) {
7222   return false;
7223 }
7224
7225
7226 static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
7227                                               uint32_t key,
7228                                               v8::AccessType type,
7229                                               Local<Value> data) {
7230   return false;
7231 }
7232
7233
7234 THREADED_TEST(AccessControlGetOwnPropertyNames) {
7235   v8::HandleScope handle_scope;
7236   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
7237
7238   obj_template->Set(v8_str("x"), v8::Integer::New(42));
7239   obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
7240                                         GetOwnPropertyNamesIndexedBlocker);
7241
7242   // Create an environment
7243   v8::Persistent<Context> context0 = Context::New(NULL, obj_template);
7244   context0->Enter();
7245
7246   v8::Handle<v8::Object> global0 = context0->Global();
7247
7248   v8::HandleScope scope1;
7249
7250   v8::Persistent<Context> context1 = Context::New();
7251   context1->Enter();
7252
7253   v8::Handle<v8::Object> global1 = context1->Global();
7254   global1->Set(v8_str("other"), global0);
7255   global1->Set(v8_str("object"), obj_template->NewInstance());
7256
7257   v8::Handle<Value> value;
7258
7259   // Attempt to get the property names of the other global object and
7260   // of an object that requires access checks.  Accessing the other
7261   // global object should be blocked by access checks on the global
7262   // proxy object.  Accessing the object that requires access checks
7263   // is blocked by the access checks on the object itself.
7264   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
7265   CHECK(value->IsTrue());
7266
7267   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
7268   CHECK(value->IsTrue());
7269
7270   context1->Exit();
7271   context0->Exit();
7272   context1.Dispose();
7273   context0.Dispose();
7274 }
7275
7276
7277 static v8::Handle<v8::Array> NamedPropertyEnumerator(const AccessorInfo& info) {
7278   v8::Handle<v8::Array> result = v8::Array::New(1);
7279   result->Set(0, v8_str("x"));
7280   return result;
7281 }
7282
7283
7284 THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
7285   v8::HandleScope handle_scope;
7286   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
7287
7288   obj_template->Set(v8_str("x"), v8::Integer::New(42));
7289   obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
7290                                         NamedPropertyEnumerator);
7291
7292   LocalContext context;
7293   v8::Handle<v8::Object> global = context->Global();
7294   global->Set(v8_str("object"), obj_template->NewInstance());
7295
7296   v8::Handle<Value> value =
7297       CompileRun("Object.getOwnPropertyNames(object).join(',')");
7298   CHECK_EQ(v8_str("x"), value);
7299 }
7300
7301
7302 static v8::Handle<Value> ConstTenGetter(Local<String> name,
7303                                         const AccessorInfo& info) {
7304   return v8_num(10);
7305 }
7306
7307
7308 THREADED_TEST(CrossDomainAccessors) {
7309   v8::HandleScope handle_scope;
7310
7311   v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
7312
7313   v8::Handle<v8::ObjectTemplate> global_template =
7314       func_template->InstanceTemplate();
7315
7316   v8::Handle<v8::ObjectTemplate> proto_template =
7317       func_template->PrototypeTemplate();
7318
7319   // Add an accessor to proto that's accessible by cross-domain JS code.
7320   proto_template->SetAccessor(v8_str("accessible"),
7321                               ConstTenGetter, 0,
7322                               v8::Handle<Value>(),
7323                               v8::ALL_CAN_READ);
7324
7325   // Add an accessor that is not accessible by cross-domain JS code.
7326   global_template->SetAccessor(v8_str("unreachable"),
7327                                UnreachableGetter, 0,
7328                                v8::Handle<Value>(),
7329                                v8::DEFAULT);
7330
7331   v8::Persistent<Context> context0 = Context::New(NULL, global_template);
7332   context0->Enter();
7333
7334   Local<v8::Object> global = context0->Global();
7335   // Add a normal property that shadows 'accessible'
7336   global->Set(v8_str("accessible"), v8_num(11));
7337
7338   // Enter a new context.
7339   v8::HandleScope scope1;
7340   v8::Persistent<Context> context1 = Context::New();
7341   context1->Enter();
7342
7343   v8::Handle<v8::Object> global1 = context1->Global();
7344   global1->Set(v8_str("other"), global);
7345
7346   // Should return 10, instead of 11
7347   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
7348   CHECK(value->IsNumber());
7349   CHECK_EQ(10, value->Int32Value());
7350
7351   value = v8_compile("other.unreachable")->Run();
7352   CHECK(value->IsUndefined());
7353
7354   context1->Exit();
7355   context0->Exit();
7356   context1.Dispose();
7357   context0.Dispose();
7358 }
7359
7360
7361 static int named_access_count = 0;
7362 static int indexed_access_count = 0;
7363
7364 static bool NamedAccessCounter(Local<v8::Object> global,
7365                                Local<Value> name,
7366                                v8::AccessType type,
7367                                Local<Value> data) {
7368   named_access_count++;
7369   return true;
7370 }
7371
7372
7373 static bool IndexedAccessCounter(Local<v8::Object> global,
7374                                  uint32_t key,
7375                                  v8::AccessType type,
7376                                  Local<Value> data) {
7377   indexed_access_count++;
7378   return true;
7379 }
7380
7381
7382 // This one is too easily disturbed by other tests.
7383 TEST(AccessControlIC) {
7384   named_access_count = 0;
7385   indexed_access_count = 0;
7386
7387   v8::HandleScope handle_scope;
7388
7389   // Create an environment.
7390   v8::Persistent<Context> context0 = Context::New();
7391   context0->Enter();
7392
7393   // Create an object that requires access-check functions to be
7394   // called for cross-domain access.
7395   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
7396   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
7397                                            IndexedAccessCounter);
7398   Local<v8::Object> object = object_template->NewInstance();
7399
7400   v8::HandleScope scope1;
7401
7402   // Create another environment.
7403   v8::Persistent<Context> context1 = Context::New();
7404   context1->Enter();
7405
7406   // Make easy access to the object from the other environment.
7407   v8::Handle<v8::Object> global1 = context1->Global();
7408   global1->Set(v8_str("obj"), object);
7409
7410   v8::Handle<Value> value;
7411
7412   // Check that the named access-control function is called every time.
7413   CompileRun("function testProp(obj) {"
7414              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
7415              "  for (var j = 0; j < 10; j++) obj.prop;"
7416              "  return obj.prop"
7417              "}");
7418   value = CompileRun("testProp(obj)");
7419   CHECK(value->IsNumber());
7420   CHECK_EQ(1, value->Int32Value());
7421   CHECK_EQ(21, named_access_count);
7422
7423   // Check that the named access-control function is called every time.
7424   CompileRun("var p = 'prop';"
7425              "function testKeyed(obj) {"
7426              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
7427              "  for (var j = 0; j < 10; j++) obj[p];"
7428              "  return obj[p];"
7429              "}");
7430   // Use obj which requires access checks.  No inline caching is used
7431   // in that case.
7432   value = CompileRun("testKeyed(obj)");
7433   CHECK(value->IsNumber());
7434   CHECK_EQ(1, value->Int32Value());
7435   CHECK_EQ(42, named_access_count);
7436   // Force the inline caches into generic state and try again.
7437   CompileRun("testKeyed({ a: 0 })");
7438   CompileRun("testKeyed({ b: 0 })");
7439   value = CompileRun("testKeyed(obj)");
7440   CHECK(value->IsNumber());
7441   CHECK_EQ(1, value->Int32Value());
7442   CHECK_EQ(63, named_access_count);
7443
7444   // Check that the indexed access-control function is called every time.
7445   CompileRun("function testIndexed(obj) {"
7446              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
7447              "  for (var j = 0; j < 10; j++) obj[0];"
7448              "  return obj[0]"
7449              "}");
7450   value = CompileRun("testIndexed(obj)");
7451   CHECK(value->IsNumber());
7452   CHECK_EQ(1, value->Int32Value());
7453   CHECK_EQ(21, indexed_access_count);
7454   // Force the inline caches into generic state.
7455   CompileRun("testIndexed(new Array(1))");
7456   // Test that the indexed access check is called.
7457   value = CompileRun("testIndexed(obj)");
7458   CHECK(value->IsNumber());
7459   CHECK_EQ(1, value->Int32Value());
7460   CHECK_EQ(42, indexed_access_count);
7461
7462   // Check that the named access check is called when invoking
7463   // functions on an object that requires access checks.
7464   CompileRun("obj.f = function() {}");
7465   CompileRun("function testCallNormal(obj) {"
7466              "  for (var i = 0; i < 10; i++) obj.f();"
7467              "}");
7468   CompileRun("testCallNormal(obj)");
7469   CHECK_EQ(74, named_access_count);
7470
7471   // Force obj into slow case.
7472   value = CompileRun("delete obj.prop");
7473   CHECK(value->BooleanValue());
7474   // Force inline caches into dictionary probing mode.
7475   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
7476   // Test that the named access check is called.
7477   value = CompileRun("testProp(obj);");
7478   CHECK(value->IsNumber());
7479   CHECK_EQ(1, value->Int32Value());
7480   CHECK_EQ(96, named_access_count);
7481
7482   // Force the call inline cache into dictionary probing mode.
7483   CompileRun("o.f = function() {}; testCallNormal(o)");
7484   // Test that the named access check is still called for each
7485   // invocation of the function.
7486   value = CompileRun("testCallNormal(obj)");
7487   CHECK_EQ(106, named_access_count);
7488
7489   context1->Exit();
7490   context0->Exit();
7491   context1.Dispose();
7492   context0.Dispose();
7493 }
7494
7495
7496 static bool NamedAccessFlatten(Local<v8::Object> global,
7497                                Local<Value> name,
7498                                v8::AccessType type,
7499                                Local<Value> data) {
7500   char buf[100];
7501   int len;
7502
7503   CHECK(name->IsString());
7504
7505   memset(buf, 0x1, sizeof(buf));
7506   len = name.As<String>()->WriteAscii(buf);
7507   CHECK_EQ(4, len);
7508
7509   uint16_t buf2[100];
7510
7511   memset(buf, 0x1, sizeof(buf));
7512   len = name.As<String>()->Write(buf2);
7513   CHECK_EQ(4, len);
7514
7515   return true;
7516 }
7517
7518
7519 static bool IndexedAccessFlatten(Local<v8::Object> global,
7520                                  uint32_t key,
7521                                  v8::AccessType type,
7522                                  Local<Value> data) {
7523   return true;
7524 }
7525
7526
7527 // Regression test.  In access checks, operations that may cause
7528 // garbage collection are not allowed.  It used to be the case that
7529 // using the Write operation on a string could cause a garbage
7530 // collection due to flattening of the string.  This is no longer the
7531 // case.
7532 THREADED_TEST(AccessControlFlatten) {
7533   named_access_count = 0;
7534   indexed_access_count = 0;
7535
7536   v8::HandleScope handle_scope;
7537
7538   // Create an environment.
7539   v8::Persistent<Context> context0 = Context::New();
7540   context0->Enter();
7541
7542   // Create an object that requires access-check functions to be
7543   // called for cross-domain access.
7544   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
7545   object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
7546                                            IndexedAccessFlatten);
7547   Local<v8::Object> object = object_template->NewInstance();
7548
7549   v8::HandleScope scope1;
7550
7551   // Create another environment.
7552   v8::Persistent<Context> context1 = Context::New();
7553   context1->Enter();
7554
7555   // Make easy access to the object from the other environment.
7556   v8::Handle<v8::Object> global1 = context1->Global();
7557   global1->Set(v8_str("obj"), object);
7558
7559   v8::Handle<Value> value;
7560
7561   value = v8_compile("var p = 'as' + 'df';")->Run();
7562   value = v8_compile("obj[p];")->Run();
7563
7564   context1->Exit();
7565   context0->Exit();
7566   context1.Dispose();
7567   context0.Dispose();
7568 }
7569
7570
7571 static v8::Handle<Value> AccessControlNamedGetter(
7572     Local<String>, const AccessorInfo&) {
7573   return v8::Integer::New(42);
7574 }
7575
7576
7577 static v8::Handle<Value> AccessControlNamedSetter(
7578     Local<String>, Local<Value> value, const AccessorInfo&) {
7579   return value;
7580 }
7581
7582
7583 static v8::Handle<Value> AccessControlIndexedGetter(
7584       uint32_t index,
7585       const AccessorInfo& info) {
7586   return v8_num(42);
7587 }
7588
7589
7590 static v8::Handle<Value> AccessControlIndexedSetter(
7591     uint32_t, Local<Value> value, const AccessorInfo&) {
7592   return value;
7593 }
7594
7595
7596 THREADED_TEST(AccessControlInterceptorIC) {
7597   named_access_count = 0;
7598   indexed_access_count = 0;
7599
7600   v8::HandleScope handle_scope;
7601
7602   // Create an environment.
7603   v8::Persistent<Context> context0 = Context::New();
7604   context0->Enter();
7605
7606   // Create an object that requires access-check functions to be
7607   // called for cross-domain access.  The object also has interceptors
7608   // interceptor.
7609   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
7610   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
7611                                            IndexedAccessCounter);
7612   object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
7613                                            AccessControlNamedSetter);
7614   object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
7615                                              AccessControlIndexedSetter);
7616   Local<v8::Object> object = object_template->NewInstance();
7617
7618   v8::HandleScope scope1;
7619
7620   // Create another environment.
7621   v8::Persistent<Context> context1 = Context::New();
7622   context1->Enter();
7623
7624   // Make easy access to the object from the other environment.
7625   v8::Handle<v8::Object> global1 = context1->Global();
7626   global1->Set(v8_str("obj"), object);
7627
7628   v8::Handle<Value> value;
7629
7630   // Check that the named access-control function is called every time
7631   // eventhough there is an interceptor on the object.
7632   value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
7633   value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
7634                      "obj.x")->Run();
7635   CHECK(value->IsNumber());
7636   CHECK_EQ(42, value->Int32Value());
7637   CHECK_EQ(21, named_access_count);
7638
7639   value = v8_compile("var p = 'x';")->Run();
7640   value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
7641   value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
7642                      "obj[p]")->Run();
7643   CHECK(value->IsNumber());
7644   CHECK_EQ(42, value->Int32Value());
7645   CHECK_EQ(42, named_access_count);
7646
7647   // Check that the indexed access-control function is called every
7648   // time eventhough there is an interceptor on the object.
7649   value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
7650   value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
7651                      "obj[0]")->Run();
7652   CHECK(value->IsNumber());
7653   CHECK_EQ(42, value->Int32Value());
7654   CHECK_EQ(21, indexed_access_count);
7655
7656   context1->Exit();
7657   context0->Exit();
7658   context1.Dispose();
7659   context0.Dispose();
7660 }
7661
7662
7663 THREADED_TEST(Version) {
7664   v8::V8::GetVersion();
7665 }
7666
7667
7668 static v8::Handle<Value> InstanceFunctionCallback(const v8::Arguments& args) {
7669   ApiTestFuzzer::Fuzz();
7670   return v8_num(12);
7671 }
7672
7673
7674 THREADED_TEST(InstanceProperties) {
7675   v8::HandleScope handle_scope;
7676   LocalContext context;
7677
7678   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
7679   Local<ObjectTemplate> instance = t->InstanceTemplate();
7680
7681   instance->Set(v8_str("x"), v8_num(42));
7682   instance->Set(v8_str("f"),
7683                 v8::FunctionTemplate::New(InstanceFunctionCallback));
7684
7685   Local<Value> o = t->GetFunction()->NewInstance();
7686
7687   context->Global()->Set(v8_str("i"), o);
7688   Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
7689   CHECK_EQ(42, value->Int32Value());
7690
7691   value = Script::Compile(v8_str("i.f()"))->Run();
7692   CHECK_EQ(12, value->Int32Value());
7693 }
7694
7695
7696 static v8::Handle<Value>
7697 GlobalObjectInstancePropertiesGet(Local<String> key, const AccessorInfo&) {
7698   ApiTestFuzzer::Fuzz();
7699   return v8::Handle<Value>();
7700 }
7701
7702
7703 THREADED_TEST(GlobalObjectInstanceProperties) {
7704   v8::HandleScope handle_scope;
7705
7706   Local<Value> global_object;
7707
7708   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
7709   t->InstanceTemplate()->SetNamedPropertyHandler(
7710       GlobalObjectInstancePropertiesGet);
7711   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
7712   instance_template->Set(v8_str("x"), v8_num(42));
7713   instance_template->Set(v8_str("f"),
7714                          v8::FunctionTemplate::New(InstanceFunctionCallback));
7715
7716   // The script to check how Crankshaft compiles missing global function
7717   // invocations.  function g is not defined and should throw on call.
7718   const char* script =
7719       "function wrapper(call) {"
7720       "  var x = 0, y = 1;"
7721       "  for (var i = 0; i < 1000; i++) {"
7722       "    x += i * 100;"
7723       "    y += i * 100;"
7724       "  }"
7725       "  if (call) g();"
7726       "}"
7727       "for (var i = 0; i < 17; i++) wrapper(false);"
7728       "var thrown = 0;"
7729       "try { wrapper(true); } catch (e) { thrown = 1; };"
7730       "thrown";
7731
7732   {
7733     LocalContext env(NULL, instance_template);
7734     // Hold on to the global object so it can be used again in another
7735     // environment initialization.
7736     global_object = env->Global();
7737
7738     Local<Value> value = Script::Compile(v8_str("x"))->Run();
7739     CHECK_EQ(42, value->Int32Value());
7740     value = Script::Compile(v8_str("f()"))->Run();
7741     CHECK_EQ(12, value->Int32Value());
7742     value = Script::Compile(v8_str(script))->Run();
7743     CHECK_EQ(1, value->Int32Value());
7744   }
7745
7746   {
7747     // Create new environment reusing the global object.
7748     LocalContext env(NULL, instance_template, global_object);
7749     Local<Value> value = Script::Compile(v8_str("x"))->Run();
7750     CHECK_EQ(42, value->Int32Value());
7751     value = Script::Compile(v8_str("f()"))->Run();
7752     CHECK_EQ(12, value->Int32Value());
7753     value = Script::Compile(v8_str(script))->Run();
7754     CHECK_EQ(1, value->Int32Value());
7755   }
7756 }
7757
7758
7759 THREADED_TEST(CallKnownGlobalReceiver) {
7760   v8::HandleScope handle_scope;
7761
7762   Local<Value> global_object;
7763
7764   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
7765   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
7766
7767   // The script to check that we leave global object not
7768   // global object proxy on stack when we deoptimize from inside
7769   // arguments evaluation.
7770   // To provoke error we need to both force deoptimization
7771   // from arguments evaluation and to force CallIC to take
7772   // CallIC_Miss code path that can't cope with global proxy.
7773   const char* script =
7774       "function bar(x, y) { try { } finally { } }"
7775       "function baz(x) { try { } finally { } }"
7776       "function bom(x) { try { } finally { } }"
7777       "function foo(x) { bar([x], bom(2)); }"
7778       "for (var i = 0; i < 10000; i++) foo(1);"
7779       "foo";
7780
7781   Local<Value> foo;
7782   {
7783     LocalContext env(NULL, instance_template);
7784     // Hold on to the global object so it can be used again in another
7785     // environment initialization.
7786     global_object = env->Global();
7787     foo = Script::Compile(v8_str(script))->Run();
7788   }
7789
7790   {
7791     // Create new environment reusing the global object.
7792     LocalContext env(NULL, instance_template, global_object);
7793     env->Global()->Set(v8_str("foo"), foo);
7794     Script::Compile(v8_str("foo()"))->Run();
7795   }
7796 }
7797
7798
7799 static v8::Handle<Value> ShadowFunctionCallback(const v8::Arguments& args) {
7800   ApiTestFuzzer::Fuzz();
7801   return v8_num(42);
7802 }
7803
7804
7805 static int shadow_y;
7806 static int shadow_y_setter_call_count;
7807 static int shadow_y_getter_call_count;
7808
7809
7810 static void ShadowYSetter(Local<String>, Local<Value>, const AccessorInfo&) {
7811   shadow_y_setter_call_count++;
7812   shadow_y = 42;
7813 }
7814
7815
7816 static v8::Handle<Value> ShadowYGetter(Local<String> name,
7817                                        const AccessorInfo& info) {
7818   ApiTestFuzzer::Fuzz();
7819   shadow_y_getter_call_count++;
7820   return v8_num(shadow_y);
7821 }
7822
7823
7824 static v8::Handle<Value> ShadowIndexedGet(uint32_t index,
7825                                           const AccessorInfo& info) {
7826   return v8::Handle<Value>();
7827 }
7828
7829
7830 static v8::Handle<Value> ShadowNamedGet(Local<String> key,
7831                                         const AccessorInfo&) {
7832   return v8::Handle<Value>();
7833 }
7834
7835
7836 THREADED_TEST(ShadowObject) {
7837   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
7838   v8::HandleScope handle_scope;
7839
7840   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
7841   LocalContext context(NULL, global_template);
7842
7843   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
7844   t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
7845   t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
7846   Local<ObjectTemplate> proto = t->PrototypeTemplate();
7847   Local<ObjectTemplate> instance = t->InstanceTemplate();
7848
7849   // Only allow calls of f on instances of t.
7850   Local<v8::Signature> signature = v8::Signature::New(t);
7851   proto->Set(v8_str("f"),
7852              v8::FunctionTemplate::New(ShadowFunctionCallback,
7853                                        Local<Value>(),
7854                                        signature));
7855   proto->Set(v8_str("x"), v8_num(12));
7856
7857   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
7858
7859   Local<Value> o = t->GetFunction()->NewInstance();
7860   context->Global()->Set(v8_str("__proto__"), o);
7861
7862   Local<Value> value =
7863       Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
7864   CHECK(value->IsBoolean());
7865   CHECK(!value->BooleanValue());
7866
7867   value = Script::Compile(v8_str("x"))->Run();
7868   CHECK_EQ(12, value->Int32Value());
7869
7870   value = Script::Compile(v8_str("f()"))->Run();
7871   CHECK_EQ(42, value->Int32Value());
7872
7873   Script::Compile(v8_str("y = 43"))->Run();
7874   CHECK_EQ(1, shadow_y_setter_call_count);
7875   value = Script::Compile(v8_str("y"))->Run();
7876   CHECK_EQ(1, shadow_y_getter_call_count);
7877   CHECK_EQ(42, value->Int32Value());
7878 }
7879
7880
7881 THREADED_TEST(HiddenPrototype) {
7882   v8::HandleScope handle_scope;
7883   LocalContext context;
7884
7885   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
7886   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
7887   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
7888   t1->SetHiddenPrototype(true);
7889   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
7890   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
7891   t2->SetHiddenPrototype(true);
7892   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
7893   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
7894   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
7895
7896   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
7897   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
7898   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
7899   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
7900
7901   // Setting the prototype on an object skips hidden prototypes.
7902   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
7903   o0->Set(v8_str("__proto__"), o1);
7904   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
7905   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
7906   o0->Set(v8_str("__proto__"), o2);
7907   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
7908   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
7909   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
7910   o0->Set(v8_str("__proto__"), o3);
7911   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
7912   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
7913   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
7914   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
7915
7916   // Getting the prototype of o0 should get the first visible one
7917   // which is o3.  Therefore, z should not be defined on the prototype
7918   // object.
7919   Local<Value> proto = o0->Get(v8_str("__proto__"));
7920   CHECK(proto->IsObject());
7921   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
7922 }
7923
7924
7925 THREADED_TEST(SetPrototype) {
7926   v8::HandleScope handle_scope;
7927   LocalContext context;
7928
7929   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
7930   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
7931   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
7932   t1->SetHiddenPrototype(true);
7933   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
7934   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
7935   t2->SetHiddenPrototype(true);
7936   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
7937   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
7938   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
7939
7940   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
7941   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
7942   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
7943   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
7944
7945   // Setting the prototype on an object does not skip hidden prototypes.
7946   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
7947   CHECK(o0->SetPrototype(o1));
7948   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
7949   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
7950   CHECK(o1->SetPrototype(o2));
7951   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
7952   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
7953   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
7954   CHECK(o2->SetPrototype(o3));
7955   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
7956   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
7957   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
7958   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
7959
7960   // Getting the prototype of o0 should get the first visible one
7961   // which is o3.  Therefore, z should not be defined on the prototype
7962   // object.
7963   Local<Value> proto = o0->Get(v8_str("__proto__"));
7964   CHECK(proto->IsObject());
7965   CHECK_EQ(proto.As<v8::Object>(), o3);
7966
7967   // However, Object::GetPrototype ignores hidden prototype.
7968   Local<Value> proto0 = o0->GetPrototype();
7969   CHECK(proto0->IsObject());
7970   CHECK_EQ(proto0.As<v8::Object>(), o1);
7971
7972   Local<Value> proto1 = o1->GetPrototype();
7973   CHECK(proto1->IsObject());
7974   CHECK_EQ(proto1.As<v8::Object>(), o2);
7975
7976   Local<Value> proto2 = o2->GetPrototype();
7977   CHECK(proto2->IsObject());
7978   CHECK_EQ(proto2.As<v8::Object>(), o3);
7979 }
7980
7981
7982 // Getting property names of an object with a prototype chain that
7983 // triggers dictionary elements in GetLocalPropertyNames() shouldn't
7984 // crash the runtime.
7985 THREADED_TEST(Regress91517) {
7986   i::FLAG_allow_natives_syntax = true;
7987   v8::HandleScope handle_scope;
7988   LocalContext context;
7989
7990   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
7991   t1->SetHiddenPrototype(true);
7992   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
7993   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
7994   t2->SetHiddenPrototype(true);
7995   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
7996   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New());
7997   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
7998   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
7999   t3->SetHiddenPrototype(true);
8000   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
8001   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
8002   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
8003
8004   // Force dictionary-based properties.
8005   i::ScopedVector<char> name_buf(1024);
8006   for (int i = 1; i <= 1000; i++) {
8007     i::OS::SNPrintF(name_buf, "sdf%d", i);
8008     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
8009   }
8010
8011   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
8012   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
8013   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
8014   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
8015
8016   // Create prototype chain of hidden prototypes.
8017   CHECK(o4->SetPrototype(o3));
8018   CHECK(o3->SetPrototype(o2));
8019   CHECK(o2->SetPrototype(o1));
8020
8021   // Call the runtime version of GetLocalPropertyNames() on the natively
8022   // created object through JavaScript.
8023   context->Global()->Set(v8_str("obj"), o4);
8024   CompileRun("var names = %GetLocalPropertyNames(obj);");
8025
8026   ExpectInt32("names.length", 1006);
8027   ExpectTrue("names.indexOf(\"baz\") >= 0");
8028   ExpectTrue("names.indexOf(\"boo\") >= 0");
8029   ExpectTrue("names.indexOf(\"foo\") >= 0");
8030   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
8031   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
8032   ExpectFalse("names[1005] == undefined");
8033 }
8034
8035
8036 THREADED_TEST(FunctionReadOnlyPrototype) {
8037   v8::HandleScope handle_scope;
8038   LocalContext context;
8039
8040   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
8041   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
8042   t1->ReadOnlyPrototype();
8043   context->Global()->Set(v8_str("func1"), t1->GetFunction());
8044   // Configured value of ReadOnly flag.
8045   CHECK(CompileRun(
8046       "(function() {"
8047       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
8048       "  return (descriptor['writable'] == false);"
8049       "})()")->BooleanValue());
8050   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
8051   CHECK_EQ(42,
8052            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
8053
8054   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
8055   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
8056   context->Global()->Set(v8_str("func2"), t2->GetFunction());
8057   // Default value of ReadOnly flag.
8058   CHECK(CompileRun(
8059       "(function() {"
8060       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
8061       "  return (descriptor['writable'] == true);"
8062       "})()")->BooleanValue());
8063   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
8064 }
8065
8066
8067 THREADED_TEST(SetPrototypeThrows) {
8068   v8::HandleScope handle_scope;
8069   LocalContext context;
8070
8071   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8072
8073   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
8074   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
8075
8076   CHECK(o0->SetPrototype(o1));
8077   // If setting the prototype leads to the cycle, SetPrototype should
8078   // return false and keep VM in sane state.
8079   v8::TryCatch try_catch;
8080   CHECK(!o1->SetPrototype(o0));
8081   CHECK(!try_catch.HasCaught());
8082   ASSERT(!i::Isolate::Current()->has_pending_exception());
8083
8084   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
8085 }
8086
8087
8088 THREADED_TEST(GetterSetterExceptions) {
8089   v8::HandleScope handle_scope;
8090   LocalContext context;
8091   CompileRun(
8092     "function Foo() { };"
8093     "function Throw() { throw 5; };"
8094     "var x = { };"
8095     "x.__defineSetter__('set', Throw);"
8096     "x.__defineGetter__('get', Throw);");
8097   Local<v8::Object> x =
8098       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
8099   v8::TryCatch try_catch;
8100   x->Set(v8_str("set"), v8::Integer::New(8));
8101   x->Get(v8_str("get"));
8102   x->Set(v8_str("set"), v8::Integer::New(8));
8103   x->Get(v8_str("get"));
8104   x->Set(v8_str("set"), v8::Integer::New(8));
8105   x->Get(v8_str("get"));
8106   x->Set(v8_str("set"), v8::Integer::New(8));
8107   x->Get(v8_str("get"));
8108 }
8109
8110
8111 THREADED_TEST(Constructor) {
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<v8::Object> inst = cons->NewInstance();
8119   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
8120   CHECK(obj->IsJSObject());
8121   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
8122   CHECK(value->BooleanValue());
8123 }
8124
8125
8126 static Handle<Value> ConstructorCallback(const Arguments& args) {
8127   ApiTestFuzzer::Fuzz();
8128   Local<Object> This;
8129
8130   if (args.IsConstructCall()) {
8131     Local<Object> Holder = args.Holder();
8132     This = Object::New();
8133     Local<Value> proto = Holder->GetPrototype();
8134     if (proto->IsObject()) {
8135       This->SetPrototype(proto);
8136     }
8137   } else {
8138     This = args.This();
8139   }
8140
8141   This->Set(v8_str("a"), args[0]);
8142   return This;
8143 }
8144
8145
8146 static Handle<Value> FakeConstructorCallback(const Arguments& args) {
8147   ApiTestFuzzer::Fuzz();
8148   return args[0];
8149 }
8150
8151
8152 THREADED_TEST(ConstructorForObject) {
8153   v8::HandleScope handle_scope;
8154   LocalContext context;
8155
8156   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8157     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
8158     Local<Object> instance = instance_template->NewInstance();
8159     context->Global()->Set(v8_str("obj"), instance);
8160     v8::TryCatch try_catch;
8161     Local<Value> value;
8162     CHECK(!try_catch.HasCaught());
8163
8164     // Call the Object's constructor with a 32-bit signed integer.
8165     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
8166     CHECK(!try_catch.HasCaught());
8167     CHECK(value->IsInt32());
8168     CHECK_EQ(28, value->Int32Value());
8169
8170     Local<Value> args1[] = { v8_num(28) };
8171     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
8172     CHECK(value_obj1->IsObject());
8173     Local<Object> object1 = Local<Object>::Cast(value_obj1);
8174     value = object1->Get(v8_str("a"));
8175     CHECK(value->IsInt32());
8176     CHECK(!try_catch.HasCaught());
8177     CHECK_EQ(28, value->Int32Value());
8178
8179     // Call the Object's constructor with a String.
8180     value = CompileRun(
8181         "(function() { var o = new obj('tipli'); return o.a; })()");
8182     CHECK(!try_catch.HasCaught());
8183     CHECK(value->IsString());
8184     String::AsciiValue string_value1(value->ToString());
8185     CHECK_EQ("tipli", *string_value1);
8186
8187     Local<Value> args2[] = { v8_str("tipli") };
8188     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
8189     CHECK(value_obj2->IsObject());
8190     Local<Object> object2 = Local<Object>::Cast(value_obj2);
8191     value = object2->Get(v8_str("a"));
8192     CHECK(!try_catch.HasCaught());
8193     CHECK(value->IsString());
8194     String::AsciiValue string_value2(value->ToString());
8195     CHECK_EQ("tipli", *string_value2);
8196
8197     // Call the Object's constructor with a Boolean.
8198     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
8199     CHECK(!try_catch.HasCaught());
8200     CHECK(value->IsBoolean());
8201     CHECK_EQ(true, value->BooleanValue());
8202
8203     Handle<Value> args3[] = { v8::True() };
8204     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
8205     CHECK(value_obj3->IsObject());
8206     Local<Object> object3 = Local<Object>::Cast(value_obj3);
8207     value = object3->Get(v8_str("a"));
8208     CHECK(!try_catch.HasCaught());
8209     CHECK(value->IsBoolean());
8210     CHECK_EQ(true, value->BooleanValue());
8211
8212     // Call the Object's constructor with undefined.
8213     Handle<Value> args4[] = { v8::Undefined() };
8214     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
8215     CHECK(value_obj4->IsObject());
8216     Local<Object> object4 = Local<Object>::Cast(value_obj4);
8217     value = object4->Get(v8_str("a"));
8218     CHECK(!try_catch.HasCaught());
8219     CHECK(value->IsUndefined());
8220
8221     // Call the Object's constructor with null.
8222     Handle<Value> args5[] = { v8::Null() };
8223     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
8224     CHECK(value_obj5->IsObject());
8225     Local<Object> object5 = Local<Object>::Cast(value_obj5);
8226     value = object5->Get(v8_str("a"));
8227     CHECK(!try_catch.HasCaught());
8228     CHECK(value->IsNull());
8229   }
8230
8231   // Check exception handling when there is no constructor set for the Object.
8232   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8233     Local<Object> instance = instance_template->NewInstance();
8234     context->Global()->Set(v8_str("obj2"), instance);
8235     v8::TryCatch try_catch;
8236     Local<Value> value;
8237     CHECK(!try_catch.HasCaught());
8238
8239     value = CompileRun("new obj2(28)");
8240     CHECK(try_catch.HasCaught());
8241     String::AsciiValue exception_value1(try_catch.Exception());
8242     CHECK_EQ("TypeError: object is not a function", *exception_value1);
8243     try_catch.Reset();
8244
8245     Local<Value> args[] = { v8_num(29) };
8246     value = instance->CallAsConstructor(1, args);
8247     CHECK(try_catch.HasCaught());
8248     String::AsciiValue exception_value2(try_catch.Exception());
8249     CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
8250     try_catch.Reset();
8251   }
8252
8253   // Check the case when constructor throws exception.
8254   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8255     instance_template->SetCallAsFunctionHandler(ThrowValue);
8256     Local<Object> instance = instance_template->NewInstance();
8257     context->Global()->Set(v8_str("obj3"), instance);
8258     v8::TryCatch try_catch;
8259     Local<Value> value;
8260     CHECK(!try_catch.HasCaught());
8261
8262     value = CompileRun("new obj3(22)");
8263     CHECK(try_catch.HasCaught());
8264     String::AsciiValue exception_value1(try_catch.Exception());
8265     CHECK_EQ("22", *exception_value1);
8266     try_catch.Reset();
8267
8268     Local<Value> args[] = { v8_num(23) };
8269     value = instance->CallAsConstructor(1, args);
8270     CHECK(try_catch.HasCaught());
8271     String::AsciiValue exception_value2(try_catch.Exception());
8272     CHECK_EQ("23", *exception_value2);
8273     try_catch.Reset();
8274   }
8275
8276   // Check whether constructor returns with an object or non-object.
8277   { Local<FunctionTemplate> function_template =
8278         FunctionTemplate::New(FakeConstructorCallback);
8279     Local<Function> function = function_template->GetFunction();
8280     Local<Object> instance1 = function;
8281     context->Global()->Set(v8_str("obj4"), instance1);
8282     v8::TryCatch try_catch;
8283     Local<Value> value;
8284     CHECK(!try_catch.HasCaught());
8285
8286     CHECK(instance1->IsObject());
8287     CHECK(instance1->IsFunction());
8288
8289     value = CompileRun("new obj4(28)");
8290     CHECK(!try_catch.HasCaught());
8291     CHECK(value->IsObject());
8292
8293     Local<Value> args1[] = { v8_num(28) };
8294     value = instance1->CallAsConstructor(1, args1);
8295     CHECK(!try_catch.HasCaught());
8296     CHECK(value->IsObject());
8297
8298     Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8299     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
8300     Local<Object> instance2 = instance_template->NewInstance();
8301     context->Global()->Set(v8_str("obj5"), instance2);
8302     CHECK(!try_catch.HasCaught());
8303
8304     CHECK(instance2->IsObject());
8305     CHECK(!instance2->IsFunction());
8306
8307     value = CompileRun("new obj5(28)");
8308     CHECK(!try_catch.HasCaught());
8309     CHECK(!value->IsObject());
8310
8311     Local<Value> args2[] = { v8_num(28) };
8312     value = instance2->CallAsConstructor(1, args2);
8313     CHECK(!try_catch.HasCaught());
8314     CHECK(!value->IsObject());
8315   }
8316 }
8317
8318
8319 THREADED_TEST(FunctionDescriptorException) {
8320   v8::HandleScope handle_scope;
8321   LocalContext context;
8322   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
8323   templ->SetClassName(v8_str("Fun"));
8324   Local<Function> cons = templ->GetFunction();
8325   context->Global()->Set(v8_str("Fun"), cons);
8326   Local<Value> value = CompileRun(
8327     "function test() {"
8328     "  try {"
8329     "    (new Fun()).blah()"
8330     "  } catch (e) {"
8331     "    var str = String(e);"
8332     "    if (str.indexOf('TypeError') == -1) return 1;"
8333     "    if (str.indexOf('[object Fun]') != -1) return 2;"
8334     "    if (str.indexOf('#<Fun>') == -1) return 3;"
8335     "    return 0;"
8336     "  }"
8337     "  return 4;"
8338     "}"
8339     "test();");
8340   CHECK_EQ(0, value->Int32Value());
8341 }
8342
8343
8344 THREADED_TEST(EvalAliasedDynamic) {
8345   v8::HandleScope scope;
8346   LocalContext current;
8347
8348   // Tests where aliased eval can only be resolved dynamically.
8349   Local<Script> script =
8350       Script::Compile(v8_str("function f(x) { "
8351                              "  var foo = 2;"
8352                              "  with (x) { return eval('foo'); }"
8353                              "}"
8354                              "foo = 0;"
8355                              "result1 = f(new Object());"
8356                              "result2 = f(this);"
8357                              "var x = new Object();"
8358                              "x.eval = function(x) { return 1; };"
8359                              "result3 = f(x);"));
8360   script->Run();
8361   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
8362   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
8363   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
8364
8365   v8::TryCatch try_catch;
8366   script =
8367     Script::Compile(v8_str("function f(x) { "
8368                            "  var bar = 2;"
8369                            "  with (x) { return eval('bar'); }"
8370                            "}"
8371                            "result4 = f(this)"));
8372   script->Run();
8373   CHECK(!try_catch.HasCaught());
8374   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
8375
8376   try_catch.Reset();
8377 }
8378
8379
8380 THREADED_TEST(CrossEval) {
8381   v8::HandleScope scope;
8382   LocalContext other;
8383   LocalContext current;
8384
8385   Local<String> token = v8_str("<security token>");
8386   other->SetSecurityToken(token);
8387   current->SetSecurityToken(token);
8388
8389   // Set up reference from current to other.
8390   current->Global()->Set(v8_str("other"), other->Global());
8391
8392   // Check that new variables are introduced in other context.
8393   Local<Script> script =
8394       Script::Compile(v8_str("other.eval('var foo = 1234')"));
8395   script->Run();
8396   Local<Value> foo = other->Global()->Get(v8_str("foo"));
8397   CHECK_EQ(1234, foo->Int32Value());
8398   CHECK(!current->Global()->Has(v8_str("foo")));
8399
8400   // Check that writing to non-existing properties introduces them in
8401   // the other context.
8402   script =
8403       Script::Compile(v8_str("other.eval('na = 1234')"));
8404   script->Run();
8405   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
8406   CHECK(!current->Global()->Has(v8_str("na")));
8407
8408   // Check that global variables in current context are not visible in other
8409   // context.
8410   v8::TryCatch try_catch;
8411   script =
8412       Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
8413   Local<Value> result = script->Run();
8414   CHECK(try_catch.HasCaught());
8415   try_catch.Reset();
8416
8417   // Check that local variables in current context are not visible in other
8418   // context.
8419   script =
8420       Script::Compile(v8_str("(function() { "
8421                              "  var baz = 87;"
8422                              "  return other.eval('baz');"
8423                              "})();"));
8424   result = script->Run();
8425   CHECK(try_catch.HasCaught());
8426   try_catch.Reset();
8427
8428   // Check that global variables in the other environment are visible
8429   // when evaluting code.
8430   other->Global()->Set(v8_str("bis"), v8_num(1234));
8431   script = Script::Compile(v8_str("other.eval('bis')"));
8432   CHECK_EQ(1234, script->Run()->Int32Value());
8433   CHECK(!try_catch.HasCaught());
8434
8435   // Check that the 'this' pointer points to the global object evaluating
8436   // code.
8437   other->Global()->Set(v8_str("t"), other->Global());
8438   script = Script::Compile(v8_str("other.eval('this == t')"));
8439   result = script->Run();
8440   CHECK(result->IsTrue());
8441   CHECK(!try_catch.HasCaught());
8442
8443   // Check that variables introduced in with-statement are not visible in
8444   // other context.
8445   script =
8446       Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
8447   result = script->Run();
8448   CHECK(try_catch.HasCaught());
8449   try_catch.Reset();
8450
8451   // Check that you cannot use 'eval.call' with another object than the
8452   // current global object.
8453   script =
8454       Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
8455   result = script->Run();
8456   CHECK(try_catch.HasCaught());
8457 }
8458
8459
8460 // Test that calling eval in a context which has been detached from
8461 // its global throws an exception.  This behavior is consistent with
8462 // other JavaScript implementations.
8463 THREADED_TEST(EvalInDetachedGlobal) {
8464   v8::HandleScope scope;
8465
8466   v8::Persistent<Context> context0 = Context::New();
8467   v8::Persistent<Context> context1 = Context::New();
8468
8469   // Set up function in context0 that uses eval from context0.
8470   context0->Enter();
8471   v8::Handle<v8::Value> fun =
8472       CompileRun("var x = 42;"
8473                  "(function() {"
8474                  "  var e = eval;"
8475                  "  return function(s) { return e(s); }"
8476                  "})()");
8477   context0->Exit();
8478
8479   // Put the function into context1 and call it before and after
8480   // detaching the global.  Before detaching, the call succeeds and
8481   // after detaching and exception is thrown.
8482   context1->Enter();
8483   context1->Global()->Set(v8_str("fun"), fun);
8484   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
8485   CHECK_EQ(42, x_value->Int32Value());
8486   context0->DetachGlobal();
8487   v8::TryCatch catcher;
8488   x_value = CompileRun("fun('x')");
8489   CHECK(x_value.IsEmpty());
8490   CHECK(catcher.HasCaught());
8491   context1->Exit();
8492
8493   context1.Dispose();
8494   context0.Dispose();
8495 }
8496
8497
8498 THREADED_TEST(CrossLazyLoad) {
8499   v8::HandleScope scope;
8500   LocalContext other;
8501   LocalContext current;
8502
8503   Local<String> token = v8_str("<security token>");
8504   other->SetSecurityToken(token);
8505   current->SetSecurityToken(token);
8506
8507   // Set up reference from current to other.
8508   current->Global()->Set(v8_str("other"), other->Global());
8509
8510   // Trigger lazy loading in other context.
8511   Local<Script> script =
8512       Script::Compile(v8_str("other.eval('new Date(42)')"));
8513   Local<Value> value = script->Run();
8514   CHECK_EQ(42.0, value->NumberValue());
8515 }
8516
8517
8518 static v8::Handle<Value> call_as_function(const v8::Arguments& args) {
8519   ApiTestFuzzer::Fuzz();
8520   if (args.IsConstructCall()) {
8521     if (args[0]->IsInt32()) {
8522        return v8_num(-args[0]->Int32Value());
8523     }
8524   }
8525
8526   return args[0];
8527 }
8528
8529
8530 // Test that a call handler can be set for objects which will allow
8531 // non-function objects created through the API to be called as
8532 // functions.
8533 THREADED_TEST(CallAsFunction) {
8534   v8::HandleScope scope;
8535   LocalContext context;
8536
8537   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8538     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
8539     instance_template->SetCallAsFunctionHandler(call_as_function);
8540     Local<v8::Object> instance = t->GetFunction()->NewInstance();
8541     context->Global()->Set(v8_str("obj"), instance);
8542     v8::TryCatch try_catch;
8543     Local<Value> value;
8544     CHECK(!try_catch.HasCaught());
8545
8546     value = CompileRun("obj(42)");
8547     CHECK(!try_catch.HasCaught());
8548     CHECK_EQ(42, value->Int32Value());
8549
8550     value = CompileRun("(function(o){return o(49)})(obj)");
8551     CHECK(!try_catch.HasCaught());
8552     CHECK_EQ(49, value->Int32Value());
8553
8554     // test special case of call as function
8555     value = CompileRun("[obj]['0'](45)");
8556     CHECK(!try_catch.HasCaught());
8557     CHECK_EQ(45, value->Int32Value());
8558
8559     value = CompileRun("obj.call = Function.prototype.call;"
8560                        "obj.call(null, 87)");
8561     CHECK(!try_catch.HasCaught());
8562     CHECK_EQ(87, value->Int32Value());
8563
8564     // Regression tests for bug #1116356: Calling call through call/apply
8565     // must work for non-function receivers.
8566     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
8567     value = CompileRun(apply_99);
8568     CHECK(!try_catch.HasCaught());
8569     CHECK_EQ(99, value->Int32Value());
8570
8571     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
8572     value = CompileRun(call_17);
8573     CHECK(!try_catch.HasCaught());
8574     CHECK_EQ(17, value->Int32Value());
8575
8576     // Check that the call-as-function handler can be called through
8577     // new.
8578     value = CompileRun("new obj(43)");
8579     CHECK(!try_catch.HasCaught());
8580     CHECK_EQ(-43, value->Int32Value());
8581
8582     // Check that the call-as-function handler can be called through
8583     // the API.
8584     v8::Handle<Value> args[] = { v8_num(28) };
8585     value = instance->CallAsFunction(instance, 1, args);
8586     CHECK(!try_catch.HasCaught());
8587     CHECK_EQ(28, value->Int32Value());
8588   }
8589
8590   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8591     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
8592     USE(instance_template);
8593     Local<v8::Object> instance = t->GetFunction()->NewInstance();
8594     context->Global()->Set(v8_str("obj2"), instance);
8595     v8::TryCatch try_catch;
8596     Local<Value> value;
8597     CHECK(!try_catch.HasCaught());
8598
8599     // Call an object without call-as-function handler through the JS
8600     value = CompileRun("obj2(28)");
8601     CHECK(value.IsEmpty());
8602     CHECK(try_catch.HasCaught());
8603     String::AsciiValue exception_value1(try_catch.Exception());
8604     CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
8605              *exception_value1);
8606     try_catch.Reset();
8607
8608     // Call an object without call-as-function handler through the API
8609     value = CompileRun("obj2(28)");
8610     v8::Handle<Value> args[] = { v8_num(28) };
8611     value = instance->CallAsFunction(instance, 1, args);
8612     CHECK(value.IsEmpty());
8613     CHECK(try_catch.HasCaught());
8614     String::AsciiValue exception_value2(try_catch.Exception());
8615     CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
8616     try_catch.Reset();
8617   }
8618
8619   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8620     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
8621     instance_template->SetCallAsFunctionHandler(ThrowValue);
8622     Local<v8::Object> instance = t->GetFunction()->NewInstance();
8623     context->Global()->Set(v8_str("obj3"), instance);
8624     v8::TryCatch try_catch;
8625     Local<Value> value;
8626     CHECK(!try_catch.HasCaught());
8627
8628     // Catch the exception which is thrown by call-as-function handler
8629     value = CompileRun("obj3(22)");
8630     CHECK(try_catch.HasCaught());
8631     String::AsciiValue exception_value1(try_catch.Exception());
8632     CHECK_EQ("22", *exception_value1);
8633     try_catch.Reset();
8634
8635     v8::Handle<Value> args[] = { v8_num(23) };
8636     value = instance->CallAsFunction(instance, 1, args);
8637     CHECK(try_catch.HasCaught());
8638     String::AsciiValue exception_value2(try_catch.Exception());
8639     CHECK_EQ("23", *exception_value2);
8640     try_catch.Reset();
8641   }
8642 }
8643
8644
8645 // Check whether a non-function object is callable.
8646 THREADED_TEST(CallableObject) {
8647   v8::HandleScope scope;
8648   LocalContext context;
8649
8650   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8651     instance_template->SetCallAsFunctionHandler(call_as_function);
8652     Local<Object> instance = instance_template->NewInstance();
8653     v8::TryCatch try_catch;
8654
8655     CHECK(instance->IsCallable());
8656     CHECK(!try_catch.HasCaught());
8657   }
8658
8659   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8660     Local<Object> instance = instance_template->NewInstance();
8661     v8::TryCatch try_catch;
8662
8663     CHECK(!instance->IsCallable());
8664     CHECK(!try_catch.HasCaught());
8665   }
8666
8667   { Local<FunctionTemplate> function_template =
8668         FunctionTemplate::New(call_as_function);
8669     Local<Function> function = function_template->GetFunction();
8670     Local<Object> instance = function;
8671     v8::TryCatch try_catch;
8672
8673     CHECK(instance->IsCallable());
8674     CHECK(!try_catch.HasCaught());
8675   }
8676
8677   { Local<FunctionTemplate> function_template = FunctionTemplate::New();
8678     Local<Function> function = function_template->GetFunction();
8679     Local<Object> instance = function;
8680     v8::TryCatch try_catch;
8681
8682     CHECK(instance->IsCallable());
8683     CHECK(!try_catch.HasCaught());
8684   }
8685 }
8686
8687
8688 static int CountHandles() {
8689   return v8::HandleScope::NumberOfHandles();
8690 }
8691
8692
8693 static int Recurse(int depth, int iterations) {
8694   v8::HandleScope scope;
8695   if (depth == 0) return CountHandles();
8696   for (int i = 0; i < iterations; i++) {
8697     Local<v8::Number> n(v8::Integer::New(42));
8698   }
8699   return Recurse(depth - 1, iterations);
8700 }
8701
8702
8703 THREADED_TEST(HandleIteration) {
8704   static const int kIterations = 500;
8705   static const int kNesting = 200;
8706   CHECK_EQ(0, CountHandles());
8707   {
8708     v8::HandleScope scope1;
8709     CHECK_EQ(0, CountHandles());
8710     for (int i = 0; i < kIterations; i++) {
8711       Local<v8::Number> n(v8::Integer::New(42));
8712       CHECK_EQ(i + 1, CountHandles());
8713     }
8714
8715     CHECK_EQ(kIterations, CountHandles());
8716     {
8717       v8::HandleScope scope2;
8718       for (int j = 0; j < kIterations; j++) {
8719         Local<v8::Number> n(v8::Integer::New(42));
8720         CHECK_EQ(j + 1 + kIterations, CountHandles());
8721       }
8722     }
8723     CHECK_EQ(kIterations, CountHandles());
8724   }
8725   CHECK_EQ(0, CountHandles());
8726   CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
8727 }
8728
8729
8730 static v8::Handle<Value> InterceptorHasOwnPropertyGetter(
8731     Local<String> name,
8732     const AccessorInfo& info) {
8733   ApiTestFuzzer::Fuzz();
8734   return v8::Handle<Value>();
8735 }
8736
8737
8738 THREADED_TEST(InterceptorHasOwnProperty) {
8739   v8::HandleScope scope;
8740   LocalContext context;
8741   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
8742   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
8743   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
8744   Local<Function> function = fun_templ->GetFunction();
8745   context->Global()->Set(v8_str("constructor"), function);
8746   v8::Handle<Value> value = CompileRun(
8747       "var o = new constructor();"
8748       "o.hasOwnProperty('ostehaps');");
8749   CHECK_EQ(false, value->BooleanValue());
8750   value = CompileRun(
8751       "o.ostehaps = 42;"
8752       "o.hasOwnProperty('ostehaps');");
8753   CHECK_EQ(true, value->BooleanValue());
8754   value = CompileRun(
8755       "var p = new constructor();"
8756       "p.hasOwnProperty('ostehaps');");
8757   CHECK_EQ(false, value->BooleanValue());
8758 }
8759
8760
8761 static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC(
8762     Local<String> name,
8763     const AccessorInfo& info) {
8764   ApiTestFuzzer::Fuzz();
8765   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
8766   return v8::Handle<Value>();
8767 }
8768
8769
8770 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
8771   v8::HandleScope scope;
8772   LocalContext context;
8773   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
8774   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
8775   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
8776   Local<Function> function = fun_templ->GetFunction();
8777   context->Global()->Set(v8_str("constructor"), function);
8778   // Let's first make some stuff so we can be sure to get a good GC.
8779   CompileRun(
8780       "function makestr(size) {"
8781       "  switch (size) {"
8782       "    case 1: return 'f';"
8783       "    case 2: return 'fo';"
8784       "    case 3: return 'foo';"
8785       "  }"
8786       "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
8787       "}"
8788       "var x = makestr(12345);"
8789       "x = makestr(31415);"
8790       "x = makestr(23456);");
8791   v8::Handle<Value> value = CompileRun(
8792       "var o = new constructor();"
8793       "o.__proto__ = new String(x);"
8794       "o.hasOwnProperty('ostehaps');");
8795   CHECK_EQ(false, value->BooleanValue());
8796 }
8797
8798
8799 typedef v8::Handle<Value> (*NamedPropertyGetter)(Local<String> property,
8800                                                  const AccessorInfo& info);
8801
8802
8803 static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
8804                                    const char* source,
8805                                    int expected) {
8806   v8::HandleScope scope;
8807   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
8808   templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
8809   LocalContext context;
8810   context->Global()->Set(v8_str("o"), templ->NewInstance());
8811   v8::Handle<Value> value = CompileRun(source);
8812   CHECK_EQ(expected, value->Int32Value());
8813 }
8814
8815
8816 static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
8817                                                  const AccessorInfo& info) {
8818   ApiTestFuzzer::Fuzz();
8819   v8::Isolate* isolate = v8::Isolate::GetCurrent();
8820   CHECK_EQ(isolate, info.GetIsolate());
8821   CHECK_EQ(v8_str("data"), info.Data());
8822   CHECK_EQ(v8_str("x"), name);
8823   return v8::Integer::New(42);
8824 }
8825
8826
8827 // This test should hit the load IC for the interceptor case.
8828 THREADED_TEST(InterceptorLoadIC) {
8829   CheckInterceptorLoadIC(InterceptorLoadICGetter,
8830     "var result = 0;"
8831     "for (var i = 0; i < 1000; i++) {"
8832     "  result = o.x;"
8833     "}",
8834     42);
8835 }
8836
8837
8838 // Below go several tests which verify that JITing for various
8839 // configurations of interceptor and explicit fields works fine
8840 // (those cases are special cased to get better performance).
8841
8842 static v8::Handle<Value> InterceptorLoadXICGetter(Local<String> name,
8843                                                  const AccessorInfo& info) {
8844   ApiTestFuzzer::Fuzz();
8845   return v8_str("x")->Equals(name)
8846       ? v8::Integer::New(42) : v8::Handle<v8::Value>();
8847 }
8848
8849
8850 THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
8851   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
8852     "var result = 0;"
8853     "o.y = 239;"
8854     "for (var i = 0; i < 1000; i++) {"
8855     "  result = o.y;"
8856     "}",
8857     239);
8858 }
8859
8860
8861 THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
8862   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
8863     "var result = 0;"
8864     "o.__proto__ = { 'y': 239 };"
8865     "for (var i = 0; i < 1000; i++) {"
8866     "  result = o.y + o.x;"
8867     "}",
8868     239 + 42);
8869 }
8870
8871
8872 THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
8873   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
8874     "var result = 0;"
8875     "o.__proto__.y = 239;"
8876     "for (var i = 0; i < 1000; i++) {"
8877     "  result = o.y + o.x;"
8878     "}",
8879     239 + 42);
8880 }
8881
8882
8883 THREADED_TEST(InterceptorLoadICUndefined) {
8884   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
8885     "var result = 0;"
8886     "for (var i = 0; i < 1000; i++) {"
8887     "  result = (o.y == undefined) ? 239 : 42;"
8888     "}",
8889     239);
8890 }
8891
8892
8893 THREADED_TEST(InterceptorLoadICWithOverride) {
8894   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
8895     "fst = new Object();  fst.__proto__ = o;"
8896     "snd = new Object();  snd.__proto__ = fst;"
8897     "var result1 = 0;"
8898     "for (var i = 0; i < 1000;  i++) {"
8899     "  result1 = snd.x;"
8900     "}"
8901     "fst.x = 239;"
8902     "var result = 0;"
8903     "for (var i = 0; i < 1000; i++) {"
8904     "  result = snd.x;"
8905     "}"
8906     "result + result1",
8907     239 + 42);
8908 }
8909
8910
8911 // Test the case when we stored field into
8912 // a stub, but interceptor produced value on its own.
8913 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
8914   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
8915     "proto = new Object();"
8916     "o.__proto__ = proto;"
8917     "proto.x = 239;"
8918     "for (var i = 0; i < 1000; i++) {"
8919     "  o.x;"
8920     // Now it should be ICed and keep a reference to x defined on proto
8921     "}"
8922     "var result = 0;"
8923     "for (var i = 0; i < 1000; i++) {"
8924     "  result += o.x;"
8925     "}"
8926     "result;",
8927     42 * 1000);
8928 }
8929
8930
8931 // Test the case when we stored field into
8932 // a stub, but it got invalidated later on.
8933 THREADED_TEST(InterceptorLoadICInvalidatedField) {
8934   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
8935     "proto1 = new Object();"
8936     "proto2 = new Object();"
8937     "o.__proto__ = proto1;"
8938     "proto1.__proto__ = proto2;"
8939     "proto2.y = 239;"
8940     "for (var i = 0; i < 1000; i++) {"
8941     "  o.y;"
8942     // Now it should be ICed and keep a reference to y defined on proto2
8943     "}"
8944     "proto1.y = 42;"
8945     "var result = 0;"
8946     "for (var i = 0; i < 1000; i++) {"
8947     "  result += o.y;"
8948     "}"
8949     "result;",
8950     42 * 1000);
8951 }
8952
8953
8954 static int interceptor_load_not_handled_calls = 0;
8955 static v8::Handle<Value> InterceptorLoadNotHandled(Local<String> name,
8956                                                    const AccessorInfo& info) {
8957   ++interceptor_load_not_handled_calls;
8958   return v8::Handle<v8::Value>();
8959 }
8960
8961
8962 // Test how post-interceptor lookups are done in the non-cacheable
8963 // case: the interceptor should not be invoked during this lookup.
8964 THREADED_TEST(InterceptorLoadICPostInterceptor) {
8965   interceptor_load_not_handled_calls = 0;
8966   CheckInterceptorLoadIC(InterceptorLoadNotHandled,
8967     "receiver = new Object();"
8968     "receiver.__proto__ = o;"
8969     "proto = new Object();"
8970     "/* Make proto a slow-case object. */"
8971     "for (var i = 0; i < 1000; i++) {"
8972     "  proto[\"xxxxxxxx\" + i] = [];"
8973     "}"
8974     "proto.x = 17;"
8975     "o.__proto__ = proto;"
8976     "var result = 0;"
8977     "for (var i = 0; i < 1000; i++) {"
8978     "  result += receiver.x;"
8979     "}"
8980     "result;",
8981     17 * 1000);
8982   CHECK_EQ(1000, interceptor_load_not_handled_calls);
8983 }
8984
8985
8986 // Test the case when we stored field into
8987 // a stub, but it got invalidated later on due to override on
8988 // global object which is between interceptor and fields' holders.
8989 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
8990   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
8991     "o.__proto__ = this;"  // set a global to be a proto of o.
8992     "this.__proto__.y = 239;"
8993     "for (var i = 0; i < 10; i++) {"
8994     "  if (o.y != 239) throw 'oops: ' + o.y;"
8995     // Now it should be ICed and keep a reference to y defined on field_holder.
8996     "}"
8997     "this.y = 42;"  // Assign on a global.
8998     "var result = 0;"
8999     "for (var i = 0; i < 10; i++) {"
9000     "  result += o.y;"
9001     "}"
9002     "result;",
9003     42 * 10);
9004 }
9005
9006
9007 static void SetOnThis(Local<String> name,
9008                       Local<Value> value,
9009                       const AccessorInfo& info) {
9010   info.This()->ForceSet(name, value);
9011 }
9012
9013
9014 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
9015   v8::HandleScope scope;
9016   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9017   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9018   templ->SetAccessor(v8_str("y"), Return239);
9019   LocalContext context;
9020   context->Global()->Set(v8_str("o"), templ->NewInstance());
9021
9022   // Check the case when receiver and interceptor's holder
9023   // are the same objects.
9024   v8::Handle<Value> value = CompileRun(
9025       "var result = 0;"
9026       "for (var i = 0; i < 7; i++) {"
9027       "  result = o.y;"
9028       "}");
9029   CHECK_EQ(239, value->Int32Value());
9030
9031   // Check the case when interceptor's holder is in proto chain
9032   // of receiver.
9033   value = CompileRun(
9034       "r = { __proto__: o };"
9035       "var result = 0;"
9036       "for (var i = 0; i < 7; i++) {"
9037       "  result = r.y;"
9038       "}");
9039   CHECK_EQ(239, value->Int32Value());
9040 }
9041
9042
9043 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
9044   v8::HandleScope scope;
9045   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9046   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9047   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
9048   templ_p->SetAccessor(v8_str("y"), Return239);
9049
9050   LocalContext context;
9051   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9052   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
9053
9054   // Check the case when receiver and interceptor's holder
9055   // are the same objects.
9056   v8::Handle<Value> value = CompileRun(
9057       "o.__proto__ = p;"
9058       "var result = 0;"
9059       "for (var i = 0; i < 7; i++) {"
9060       "  result = o.x + o.y;"
9061       "}");
9062   CHECK_EQ(239 + 42, value->Int32Value());
9063
9064   // Check the case when interceptor's holder is in proto chain
9065   // of receiver.
9066   value = CompileRun(
9067       "r = { __proto__: o };"
9068       "var result = 0;"
9069       "for (var i = 0; i < 7; i++) {"
9070       "  result = r.x + r.y;"
9071       "}");
9072   CHECK_EQ(239 + 42, value->Int32Value());
9073 }
9074
9075
9076 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
9077   v8::HandleScope scope;
9078   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9079   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9080   templ->SetAccessor(v8_str("y"), Return239);
9081
9082   LocalContext context;
9083   context->Global()->Set(v8_str("o"), templ->NewInstance());
9084
9085   v8::Handle<Value> value = CompileRun(
9086     "fst = new Object();  fst.__proto__ = o;"
9087     "snd = new Object();  snd.__proto__ = fst;"
9088     "var result1 = 0;"
9089     "for (var i = 0; i < 7;  i++) {"
9090     "  result1 = snd.x;"
9091     "}"
9092     "fst.x = 239;"
9093     "var result = 0;"
9094     "for (var i = 0; i < 7; i++) {"
9095     "  result = snd.x;"
9096     "}"
9097     "result + result1");
9098   CHECK_EQ(239 + 42, value->Int32Value());
9099 }
9100
9101
9102 // Test the case when we stored callback into
9103 // a stub, but interceptor produced value on its own.
9104 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
9105   v8::HandleScope scope;
9106   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9107   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9108   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
9109   templ_p->SetAccessor(v8_str("y"), Return239);
9110
9111   LocalContext context;
9112   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9113   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
9114
9115   v8::Handle<Value> value = CompileRun(
9116     "o.__proto__ = p;"
9117     "for (var i = 0; i < 7; i++) {"
9118     "  o.x;"
9119     // Now it should be ICed and keep a reference to x defined on p
9120     "}"
9121     "var result = 0;"
9122     "for (var i = 0; i < 7; i++) {"
9123     "  result += o.x;"
9124     "}"
9125     "result");
9126   CHECK_EQ(42 * 7, value->Int32Value());
9127 }
9128
9129
9130 // Test the case when we stored callback into
9131 // a stub, but it got invalidated later on.
9132 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
9133   v8::HandleScope scope;
9134   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9135   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9136   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
9137   templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
9138
9139   LocalContext context;
9140   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9141   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
9142
9143   v8::Handle<Value> value = CompileRun(
9144     "inbetween = new Object();"
9145     "o.__proto__ = inbetween;"
9146     "inbetween.__proto__ = p;"
9147     "for (var i = 0; i < 10; i++) {"
9148     "  o.y;"
9149     // Now it should be ICed and keep a reference to y defined on p
9150     "}"
9151     "inbetween.y = 42;"
9152     "var result = 0;"
9153     "for (var i = 0; i < 10; i++) {"
9154     "  result += o.y;"
9155     "}"
9156     "result");
9157   CHECK_EQ(42 * 10, value->Int32Value());
9158 }
9159
9160
9161 // Test the case when we stored callback into
9162 // a stub, but it got invalidated later on due to override on
9163 // global object which is between interceptor and callbacks' holders.
9164 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
9165   v8::HandleScope scope;
9166   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9167   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9168   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
9169   templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
9170
9171   LocalContext context;
9172   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9173   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
9174
9175   v8::Handle<Value> value = CompileRun(
9176     "o.__proto__ = this;"
9177     "this.__proto__ = p;"
9178     "for (var i = 0; i < 10; i++) {"
9179     "  if (o.y != 239) throw 'oops: ' + o.y;"
9180     // Now it should be ICed and keep a reference to y defined on p
9181     "}"
9182     "this.y = 42;"
9183     "var result = 0;"
9184     "for (var i = 0; i < 10; i++) {"
9185     "  result += o.y;"
9186     "}"
9187     "result");
9188   CHECK_EQ(42 * 10, value->Int32Value());
9189 }
9190
9191
9192 static v8::Handle<Value> InterceptorLoadICGetter0(Local<String> name,
9193                                                   const AccessorInfo& info) {
9194   ApiTestFuzzer::Fuzz();
9195   CHECK(v8_str("x")->Equals(name));
9196   return v8::Integer::New(0);
9197 }
9198
9199
9200 THREADED_TEST(InterceptorReturningZero) {
9201   CheckInterceptorLoadIC(InterceptorLoadICGetter0,
9202      "o.x == undefined ? 1 : 0",
9203      0);
9204 }
9205
9206
9207 static v8::Handle<Value> InterceptorStoreICSetter(
9208     Local<String> key, Local<Value> value, const AccessorInfo&) {
9209   CHECK(v8_str("x")->Equals(key));
9210   CHECK_EQ(42, value->Int32Value());
9211   return value;
9212 }
9213
9214
9215 // This test should hit the store IC for the interceptor case.
9216 THREADED_TEST(InterceptorStoreIC) {
9217   v8::HandleScope scope;
9218   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9219   templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
9220                                  InterceptorStoreICSetter,
9221                                  0, 0, 0, v8_str("data"));
9222   LocalContext context;
9223   context->Global()->Set(v8_str("o"), templ->NewInstance());
9224   CompileRun(
9225       "for (var i = 0; i < 1000; i++) {"
9226       "  o.x = 42;"
9227       "}");
9228 }
9229
9230
9231 THREADED_TEST(InterceptorStoreICWithNoSetter) {
9232   v8::HandleScope scope;
9233   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9234   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9235   LocalContext context;
9236   context->Global()->Set(v8_str("o"), templ->NewInstance());
9237   v8::Handle<Value> value = CompileRun(
9238     "for (var i = 0; i < 1000; i++) {"
9239     "  o.y = 239;"
9240     "}"
9241     "42 + o.y");
9242   CHECK_EQ(239 + 42, value->Int32Value());
9243 }
9244
9245
9246
9247
9248 v8::Handle<Value> call_ic_function;
9249 v8::Handle<Value> call_ic_function2;
9250 v8::Handle<Value> call_ic_function3;
9251
9252 static v8::Handle<Value> InterceptorCallICGetter(Local<String> name,
9253                                                  const AccessorInfo& info) {
9254   ApiTestFuzzer::Fuzz();
9255   CHECK(v8_str("x")->Equals(name));
9256   return call_ic_function;
9257 }
9258
9259
9260 // This test should hit the call IC for the interceptor case.
9261 THREADED_TEST(InterceptorCallIC) {
9262   v8::HandleScope scope;
9263   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9264   templ->SetNamedPropertyHandler(InterceptorCallICGetter);
9265   LocalContext context;
9266   context->Global()->Set(v8_str("o"), templ->NewInstance());
9267   call_ic_function =
9268       v8_compile("function f(x) { return x + 1; }; f")->Run();
9269   v8::Handle<Value> value = CompileRun(
9270     "var result = 0;"
9271     "for (var i = 0; i < 1000; i++) {"
9272     "  result = o.x(41);"
9273     "}");
9274   CHECK_EQ(42, value->Int32Value());
9275 }
9276
9277
9278 // This test checks that if interceptor doesn't provide
9279 // a value, we can fetch regular value.
9280 THREADED_TEST(InterceptorCallICSeesOthers) {
9281   v8::HandleScope scope;
9282   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9283   templ->SetNamedPropertyHandler(NoBlockGetterX);
9284   LocalContext context;
9285   context->Global()->Set(v8_str("o"), templ->NewInstance());
9286   v8::Handle<Value> value = CompileRun(
9287     "o.x = function f(x) { return x + 1; };"
9288     "var result = 0;"
9289     "for (var i = 0; i < 7; i++) {"
9290     "  result = o.x(41);"
9291     "}");
9292   CHECK_EQ(42, value->Int32Value());
9293 }
9294
9295
9296 static v8::Handle<Value> call_ic_function4;
9297 static v8::Handle<Value> InterceptorCallICGetter4(Local<String> name,
9298                                                   const AccessorInfo& info) {
9299   ApiTestFuzzer::Fuzz();
9300   CHECK(v8_str("x")->Equals(name));
9301   return call_ic_function4;
9302 }
9303
9304
9305 // This test checks that if interceptor provides a function,
9306 // even if we cached shadowed variant, interceptor's function
9307 // is invoked
9308 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
9309   v8::HandleScope scope;
9310   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9311   templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
9312   LocalContext context;
9313   context->Global()->Set(v8_str("o"), templ->NewInstance());
9314   call_ic_function4 =
9315       v8_compile("function f(x) { return x - 1; }; f")->Run();
9316   v8::Handle<Value> value = CompileRun(
9317     "o.__proto__.x = function(x) { return x + 1; };"
9318     "var result = 0;"
9319     "for (var i = 0; i < 1000; i++) {"
9320     "  result = o.x(42);"
9321     "}");
9322   CHECK_EQ(41, value->Int32Value());
9323 }
9324
9325
9326 // Test the case when we stored cacheable lookup into
9327 // a stub, but it got invalidated later on
9328 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
9329   v8::HandleScope scope;
9330   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9331   templ->SetNamedPropertyHandler(NoBlockGetterX);
9332   LocalContext context;
9333   context->Global()->Set(v8_str("o"), templ->NewInstance());
9334   v8::Handle<Value> value = CompileRun(
9335     "proto1 = new Object();"
9336     "proto2 = new Object();"
9337     "o.__proto__ = proto1;"
9338     "proto1.__proto__ = proto2;"
9339     "proto2.y = function(x) { return x + 1; };"
9340     // Invoke it many times to compile a stub
9341     "for (var i = 0; i < 7; i++) {"
9342     "  o.y(42);"
9343     "}"
9344     "proto1.y = function(x) { return x - 1; };"
9345     "var result = 0;"
9346     "for (var i = 0; i < 7; i++) {"
9347     "  result += o.y(42);"
9348     "}");
9349   CHECK_EQ(41 * 7, value->Int32Value());
9350 }
9351
9352
9353 // This test checks that if interceptor doesn't provide a function,
9354 // cached constant function is used
9355 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
9356   v8::HandleScope scope;
9357   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9358   templ->SetNamedPropertyHandler(NoBlockGetterX);
9359   LocalContext context;
9360   context->Global()->Set(v8_str("o"), templ->NewInstance());
9361   v8::Handle<Value> value = CompileRun(
9362     "function inc(x) { return x + 1; };"
9363     "inc(1);"
9364     "o.x = inc;"
9365     "var result = 0;"
9366     "for (var i = 0; i < 1000; i++) {"
9367     "  result = o.x(42);"
9368     "}");
9369   CHECK_EQ(43, value->Int32Value());
9370 }
9371
9372
9373 static v8::Handle<Value> call_ic_function5;
9374 static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name,
9375                                                   const AccessorInfo& info) {
9376   ApiTestFuzzer::Fuzz();
9377   if (v8_str("x")->Equals(name))
9378     return call_ic_function5;
9379   else
9380     return Local<Value>();
9381 }
9382
9383
9384 // This test checks that if interceptor provides a function,
9385 // even if we cached constant function, interceptor's function
9386 // is invoked
9387 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
9388   v8::HandleScope scope;
9389   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9390   templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
9391   LocalContext context;
9392   context->Global()->Set(v8_str("o"), templ->NewInstance());
9393   call_ic_function5 =
9394       v8_compile("function f(x) { return x - 1; }; f")->Run();
9395   v8::Handle<Value> value = CompileRun(
9396     "function inc(x) { return x + 1; };"
9397     "inc(1);"
9398     "o.x = inc;"
9399     "var result = 0;"
9400     "for (var i = 0; i < 1000; i++) {"
9401     "  result = o.x(42);"
9402     "}");
9403   CHECK_EQ(41, value->Int32Value());
9404 }
9405
9406
9407 static v8::Handle<Value> call_ic_function6;
9408 static v8::Handle<Value> InterceptorCallICGetter6(Local<String> name,
9409                                                   const AccessorInfo& info) {
9410   ApiTestFuzzer::Fuzz();
9411   if (v8_str("x")->Equals(name))
9412     return call_ic_function6;
9413   else
9414     return Local<Value>();
9415 }
9416
9417
9418 // Same test as above, except the code is wrapped in a function
9419 // to test the optimized compiler.
9420 THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
9421   i::FLAG_allow_natives_syntax = true;
9422   v8::HandleScope scope;
9423   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9424   templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
9425   LocalContext context;
9426   context->Global()->Set(v8_str("o"), templ->NewInstance());
9427   call_ic_function6 =
9428       v8_compile("function f(x) { return x - 1; }; f")->Run();
9429   v8::Handle<Value> value = CompileRun(
9430     "function inc(x) { return x + 1; };"
9431     "inc(1);"
9432     "o.x = inc;"
9433     "function test() {"
9434     "  var result = 0;"
9435     "  for (var i = 0; i < 1000; i++) {"
9436     "    result = o.x(42);"
9437     "  }"
9438     "  return result;"
9439     "};"
9440     "test();"
9441     "test();"
9442     "test();"
9443     "%OptimizeFunctionOnNextCall(test);"
9444     "test()");
9445   CHECK_EQ(41, value->Int32Value());
9446 }
9447
9448
9449 // Test the case when we stored constant function into
9450 // a stub, but it got invalidated later on
9451 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
9452   v8::HandleScope scope;
9453   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9454   templ->SetNamedPropertyHandler(NoBlockGetterX);
9455   LocalContext context;
9456   context->Global()->Set(v8_str("o"), templ->NewInstance());
9457   v8::Handle<Value> value = CompileRun(
9458     "function inc(x) { return x + 1; };"
9459     "inc(1);"
9460     "proto1 = new Object();"
9461     "proto2 = new Object();"
9462     "o.__proto__ = proto1;"
9463     "proto1.__proto__ = proto2;"
9464     "proto2.y = inc;"
9465     // Invoke it many times to compile a stub
9466     "for (var i = 0; i < 7; i++) {"
9467     "  o.y(42);"
9468     "}"
9469     "proto1.y = function(x) { return x - 1; };"
9470     "var result = 0;"
9471     "for (var i = 0; i < 7; i++) {"
9472     "  result += o.y(42);"
9473     "}");
9474   CHECK_EQ(41 * 7, value->Int32Value());
9475 }
9476
9477
9478 // Test the case when we stored constant function into
9479 // a stub, but it got invalidated later on due to override on
9480 // global object which is between interceptor and constant function' holders.
9481 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
9482   v8::HandleScope scope;
9483   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9484   templ->SetNamedPropertyHandler(NoBlockGetterX);
9485   LocalContext context;
9486   context->Global()->Set(v8_str("o"), templ->NewInstance());
9487   v8::Handle<Value> value = CompileRun(
9488     "function inc(x) { return x + 1; };"
9489     "inc(1);"
9490     "o.__proto__ = this;"
9491     "this.__proto__.y = inc;"
9492     // Invoke it many times to compile a stub
9493     "for (var i = 0; i < 7; i++) {"
9494     "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
9495     "}"
9496     "this.y = function(x) { return x - 1; };"
9497     "var result = 0;"
9498     "for (var i = 0; i < 7; i++) {"
9499     "  result += o.y(42);"
9500     "}");
9501   CHECK_EQ(41 * 7, value->Int32Value());
9502 }
9503
9504
9505 // Test the case when actual function to call sits on global object.
9506 THREADED_TEST(InterceptorCallICCachedFromGlobal) {
9507   v8::HandleScope scope;
9508   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9509   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
9510
9511   LocalContext context;
9512   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9513
9514   v8::Handle<Value> value = CompileRun(
9515     "try {"
9516     "  o.__proto__ = this;"
9517     "  for (var i = 0; i < 10; i++) {"
9518     "    var v = o.parseFloat('239');"
9519     "    if (v != 239) throw v;"
9520       // Now it should be ICed and keep a reference to parseFloat.
9521     "  }"
9522     "  var result = 0;"
9523     "  for (var i = 0; i < 10; i++) {"
9524     "    result += o.parseFloat('239');"
9525     "  }"
9526     "  result"
9527     "} catch(e) {"
9528     "  e"
9529     "};");
9530   CHECK_EQ(239 * 10, value->Int32Value());
9531 }
9532
9533 static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
9534                                                   const AccessorInfo& info) {
9535   ApiTestFuzzer::Fuzz();
9536   int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data()));
9537   ++(*call_count);
9538   if ((*call_count) % 20 == 0) {
9539     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
9540   }
9541   return v8::Handle<Value>();
9542 }
9543
9544 static v8::Handle<Value> FastApiCallback_TrivialSignature(
9545     const v8::Arguments& args) {
9546   ApiTestFuzzer::Fuzz();
9547   v8::Isolate* isolate = v8::Isolate::GetCurrent();
9548   CHECK_EQ(isolate, args.GetIsolate());
9549   CHECK_EQ(args.This(), args.Holder());
9550   CHECK(args.Data()->Equals(v8_str("method_data")));
9551   return v8::Integer::New(args[0]->Int32Value() + 1);
9552 }
9553
9554 static v8::Handle<Value> FastApiCallback_SimpleSignature(
9555     const v8::Arguments& args) {
9556   ApiTestFuzzer::Fuzz();
9557   v8::Isolate* isolate = v8::Isolate::GetCurrent();
9558   CHECK_EQ(isolate, args.GetIsolate());
9559   CHECK_EQ(args.This()->GetPrototype(), args.Holder());
9560   CHECK(args.Data()->Equals(v8_str("method_data")));
9561   // Note, we're using HasRealNamedProperty instead of Has to avoid
9562   // invoking the interceptor again.
9563   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
9564   return v8::Integer::New(args[0]->Int32Value() + 1);
9565 }
9566
9567 // Helper to maximize the odds of object moving.
9568 static void GenerateSomeGarbage() {
9569   CompileRun(
9570       "var garbage;"
9571       "for (var i = 0; i < 1000; i++) {"
9572       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
9573       "}"
9574       "garbage = undefined;");
9575 }
9576
9577
9578 v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) {
9579   static int count = 0;
9580   if (count++ % 3 == 0) {
9581     HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
9582         // This should move the stub
9583     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
9584   }
9585   return v8::Handle<v8::Value>();
9586 }
9587
9588
9589 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
9590   v8::HandleScope scope;
9591   LocalContext context;
9592   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
9593   nativeobject_templ->Set("callback",
9594                           v8::FunctionTemplate::New(DirectApiCallback));
9595   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
9596   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
9597   // call the api function multiple times to ensure direct call stub creation.
9598   CompileRun(
9599         "function f() {"
9600         "  for (var i = 1; i <= 30; i++) {"
9601         "    nativeobject.callback();"
9602         "  }"
9603         "}"
9604         "f();");
9605 }
9606
9607
9608 v8::Handle<v8::Value> ThrowingDirectApiCallback(const v8::Arguments& args) {
9609   return v8::ThrowException(v8_str("g"));
9610 }
9611
9612
9613 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
9614   v8::HandleScope scope;
9615   LocalContext context;
9616   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
9617   nativeobject_templ->Set("callback",
9618                           v8::FunctionTemplate::New(ThrowingDirectApiCallback));
9619   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
9620   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
9621   // call the api function multiple times to ensure direct call stub creation.
9622   v8::Handle<Value> result = CompileRun(
9623       "var result = '';"
9624       "function f() {"
9625       "  for (var i = 1; i <= 5; i++) {"
9626       "    try { nativeobject.callback(); } catch (e) { result += e; }"
9627       "  }"
9628       "}"
9629       "f(); result;");
9630   CHECK_EQ(v8_str("ggggg"), result);
9631 }
9632
9633
9634 v8::Handle<v8::Value> DirectGetterCallback(Local<String> name,
9635                                            const v8::AccessorInfo& info) {
9636   if (++p_getter_count % 3 == 0) {
9637     HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
9638     GenerateSomeGarbage();
9639   }
9640   return v8::Handle<v8::Value>();
9641 }
9642
9643
9644 THREADED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
9645   v8::HandleScope scope;
9646   LocalContext context;
9647   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
9648   obj->SetAccessor(v8_str("p1"), DirectGetterCallback);
9649   context->Global()->Set(v8_str("o1"), obj->NewInstance());
9650   p_getter_count = 0;
9651   CompileRun(
9652       "function f() {"
9653       "  for (var i = 0; i < 30; i++) o1.p1;"
9654       "}"
9655       "f();");
9656   CHECK_EQ(30, p_getter_count);
9657 }
9658
9659
9660 v8::Handle<v8::Value> ThrowingDirectGetterCallback(
9661     Local<String> name, const v8::AccessorInfo& info) {
9662   return v8::ThrowException(v8_str("g"));
9663 }
9664
9665
9666 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
9667   v8::HandleScope scope;
9668   LocalContext context;
9669   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
9670   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
9671   context->Global()->Set(v8_str("o1"), obj->NewInstance());
9672   v8::Handle<Value> result = CompileRun(
9673       "var result = '';"
9674       "for (var i = 0; i < 5; i++) {"
9675       "    try { o1.p1; } catch (e) { result += e; }"
9676       "}"
9677       "result;");
9678   CHECK_EQ(v8_str("ggggg"), result);
9679 }
9680
9681
9682 THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) {
9683   int interceptor_call_count = 0;
9684   v8::HandleScope scope;
9685   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9686   v8::Handle<v8::FunctionTemplate> method_templ =
9687       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
9688                                 v8_str("method_data"),
9689                                 v8::Handle<v8::Signature>());
9690   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9691   proto_templ->Set(v8_str("method"), method_templ);
9692   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
9693   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
9694                                  NULL, NULL, NULL, NULL,
9695                                  v8::External::Wrap(&interceptor_call_count));
9696   LocalContext context;
9697   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9698   GenerateSomeGarbage();
9699   context->Global()->Set(v8_str("o"), fun->NewInstance());
9700   CompileRun(
9701       "var result = 0;"
9702       "for (var i = 0; i < 100; i++) {"
9703       "  result = o.method(41);"
9704       "}");
9705   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
9706   CHECK_EQ(100, interceptor_call_count);
9707 }
9708
9709 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) {
9710   int interceptor_call_count = 0;
9711   v8::HandleScope scope;
9712   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9713   v8::Handle<v8::FunctionTemplate> method_templ =
9714       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
9715                                 v8_str("method_data"),
9716                                 v8::Signature::New(fun_templ));
9717   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9718   proto_templ->Set(v8_str("method"), method_templ);
9719   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
9720   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
9721                                  NULL, NULL, NULL, NULL,
9722                                  v8::External::Wrap(&interceptor_call_count));
9723   LocalContext context;
9724   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9725   GenerateSomeGarbage();
9726   context->Global()->Set(v8_str("o"), fun->NewInstance());
9727   CompileRun(
9728       "o.foo = 17;"
9729       "var receiver = {};"
9730       "receiver.__proto__ = o;"
9731       "var result = 0;"
9732       "for (var i = 0; i < 100; i++) {"
9733       "  result = receiver.method(41);"
9734       "}");
9735   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
9736   CHECK_EQ(100, interceptor_call_count);
9737 }
9738
9739 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
9740   int interceptor_call_count = 0;
9741   v8::HandleScope scope;
9742   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9743   v8::Handle<v8::FunctionTemplate> method_templ =
9744       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
9745                                 v8_str("method_data"),
9746                                 v8::Signature::New(fun_templ));
9747   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9748   proto_templ->Set(v8_str("method"), method_templ);
9749   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
9750   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
9751                                  NULL, NULL, NULL, NULL,
9752                                  v8::External::Wrap(&interceptor_call_count));
9753   LocalContext context;
9754   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9755   GenerateSomeGarbage();
9756   context->Global()->Set(v8_str("o"), fun->NewInstance());
9757   CompileRun(
9758       "o.foo = 17;"
9759       "var receiver = {};"
9760       "receiver.__proto__ = o;"
9761       "var result = 0;"
9762       "var saved_result = 0;"
9763       "for (var i = 0; i < 100; i++) {"
9764       "  result = receiver.method(41);"
9765       "  if (i == 50) {"
9766       "    saved_result = result;"
9767       "    receiver = {method: function(x) { return x - 1 }};"
9768       "  }"
9769       "}");
9770   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
9771   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
9772   CHECK_GE(interceptor_call_count, 50);
9773 }
9774
9775 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
9776   int interceptor_call_count = 0;
9777   v8::HandleScope scope;
9778   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9779   v8::Handle<v8::FunctionTemplate> method_templ =
9780       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
9781                                 v8_str("method_data"),
9782                                 v8::Signature::New(fun_templ));
9783   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9784   proto_templ->Set(v8_str("method"), method_templ);
9785   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
9786   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
9787                                  NULL, NULL, NULL, NULL,
9788                                  v8::External::Wrap(&interceptor_call_count));
9789   LocalContext context;
9790   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9791   GenerateSomeGarbage();
9792   context->Global()->Set(v8_str("o"), fun->NewInstance());
9793   CompileRun(
9794       "o.foo = 17;"
9795       "var receiver = {};"
9796       "receiver.__proto__ = o;"
9797       "var result = 0;"
9798       "var saved_result = 0;"
9799       "for (var i = 0; i < 100; i++) {"
9800       "  result = receiver.method(41);"
9801       "  if (i == 50) {"
9802       "    saved_result = result;"
9803       "    o.method = function(x) { return x - 1 };"
9804       "  }"
9805       "}");
9806   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
9807   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
9808   CHECK_GE(interceptor_call_count, 50);
9809 }
9810
9811 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
9812   int interceptor_call_count = 0;
9813   v8::HandleScope scope;
9814   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9815   v8::Handle<v8::FunctionTemplate> method_templ =
9816       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
9817                                 v8_str("method_data"),
9818                                 v8::Signature::New(fun_templ));
9819   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9820   proto_templ->Set(v8_str("method"), method_templ);
9821   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
9822   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
9823                                  NULL, NULL, NULL, NULL,
9824                                  v8::External::Wrap(&interceptor_call_count));
9825   LocalContext context;
9826   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9827   GenerateSomeGarbage();
9828   context->Global()->Set(v8_str("o"), fun->NewInstance());
9829   v8::TryCatch try_catch;
9830   CompileRun(
9831       "o.foo = 17;"
9832       "var receiver = {};"
9833       "receiver.__proto__ = o;"
9834       "var result = 0;"
9835       "var saved_result = 0;"
9836       "for (var i = 0; i < 100; i++) {"
9837       "  result = receiver.method(41);"
9838       "  if (i == 50) {"
9839       "    saved_result = result;"
9840       "    receiver = 333;"
9841       "  }"
9842       "}");
9843   CHECK(try_catch.HasCaught());
9844   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
9845            try_catch.Exception()->ToString());
9846   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
9847   CHECK_GE(interceptor_call_count, 50);
9848 }
9849
9850 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
9851   int interceptor_call_count = 0;
9852   v8::HandleScope scope;
9853   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9854   v8::Handle<v8::FunctionTemplate> method_templ =
9855       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
9856                                 v8_str("method_data"),
9857                                 v8::Signature::New(fun_templ));
9858   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9859   proto_templ->Set(v8_str("method"), method_templ);
9860   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
9861   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
9862                                  NULL, NULL, NULL, NULL,
9863                                  v8::External::Wrap(&interceptor_call_count));
9864   LocalContext context;
9865   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9866   GenerateSomeGarbage();
9867   context->Global()->Set(v8_str("o"), fun->NewInstance());
9868   v8::TryCatch try_catch;
9869   CompileRun(
9870       "o.foo = 17;"
9871       "var receiver = {};"
9872       "receiver.__proto__ = o;"
9873       "var result = 0;"
9874       "var saved_result = 0;"
9875       "for (var i = 0; i < 100; i++) {"
9876       "  result = receiver.method(41);"
9877       "  if (i == 50) {"
9878       "    saved_result = result;"
9879       "    receiver = {method: receiver.method};"
9880       "  }"
9881       "}");
9882   CHECK(try_catch.HasCaught());
9883   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
9884            try_catch.Exception()->ToString());
9885   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
9886   CHECK_GE(interceptor_call_count, 50);
9887 }
9888
9889 THREADED_TEST(CallICFastApi_TrivialSignature) {
9890   v8::HandleScope scope;
9891   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9892   v8::Handle<v8::FunctionTemplate> method_templ =
9893       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
9894                                 v8_str("method_data"),
9895                                 v8::Handle<v8::Signature>());
9896   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9897   proto_templ->Set(v8_str("method"), method_templ);
9898   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
9899   USE(templ);
9900   LocalContext context;
9901   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9902   GenerateSomeGarbage();
9903   context->Global()->Set(v8_str("o"), fun->NewInstance());
9904   CompileRun(
9905       "var result = 0;"
9906       "for (var i = 0; i < 100; i++) {"
9907       "  result = o.method(41);"
9908       "}");
9909
9910   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
9911 }
9912
9913 THREADED_TEST(CallICFastApi_SimpleSignature) {
9914   v8::HandleScope scope;
9915   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9916   v8::Handle<v8::FunctionTemplate> method_templ =
9917       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
9918                                 v8_str("method_data"),
9919                                 v8::Signature::New(fun_templ));
9920   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9921   proto_templ->Set(v8_str("method"), method_templ);
9922   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
9923   CHECK(!templ.IsEmpty());
9924   LocalContext context;
9925   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9926   GenerateSomeGarbage();
9927   context->Global()->Set(v8_str("o"), fun->NewInstance());
9928   CompileRun(
9929       "o.foo = 17;"
9930       "var receiver = {};"
9931       "receiver.__proto__ = o;"
9932       "var result = 0;"
9933       "for (var i = 0; i < 100; i++) {"
9934       "  result = receiver.method(41);"
9935       "}");
9936
9937   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
9938 }
9939
9940 THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
9941   v8::HandleScope scope;
9942   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9943   v8::Handle<v8::FunctionTemplate> method_templ =
9944       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
9945                                 v8_str("method_data"),
9946                                 v8::Signature::New(fun_templ));
9947   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9948   proto_templ->Set(v8_str("method"), method_templ);
9949   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
9950   CHECK(!templ.IsEmpty());
9951   LocalContext context;
9952   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9953   GenerateSomeGarbage();
9954   context->Global()->Set(v8_str("o"), fun->NewInstance());
9955   CompileRun(
9956       "o.foo = 17;"
9957       "var receiver = {};"
9958       "receiver.__proto__ = o;"
9959       "var result = 0;"
9960       "var saved_result = 0;"
9961       "for (var i = 0; i < 100; i++) {"
9962       "  result = receiver.method(41);"
9963       "  if (i == 50) {"
9964       "    saved_result = result;"
9965       "    receiver = {method: function(x) { return x - 1 }};"
9966       "  }"
9967       "}");
9968   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
9969   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
9970 }
9971
9972 THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
9973   v8::HandleScope scope;
9974   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9975   v8::Handle<v8::FunctionTemplate> method_templ =
9976       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
9977                                 v8_str("method_data"),
9978                                 v8::Signature::New(fun_templ));
9979   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
9980   proto_templ->Set(v8_str("method"), method_templ);
9981   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
9982   CHECK(!templ.IsEmpty());
9983   LocalContext context;
9984   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
9985   GenerateSomeGarbage();
9986   context->Global()->Set(v8_str("o"), fun->NewInstance());
9987   v8::TryCatch try_catch;
9988   CompileRun(
9989       "o.foo = 17;"
9990       "var receiver = {};"
9991       "receiver.__proto__ = o;"
9992       "var result = 0;"
9993       "var saved_result = 0;"
9994       "for (var i = 0; i < 100; i++) {"
9995       "  result = receiver.method(41);"
9996       "  if (i == 50) {"
9997       "    saved_result = result;"
9998       "    receiver = 333;"
9999       "  }"
10000       "}");
10001   CHECK(try_catch.HasCaught());
10002   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
10003            try_catch.Exception()->ToString());
10004   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10005 }
10006
10007
10008 v8::Handle<Value> keyed_call_ic_function;
10009
10010 static v8::Handle<Value> InterceptorKeyedCallICGetter(
10011     Local<String> name, const AccessorInfo& info) {
10012   ApiTestFuzzer::Fuzz();
10013   if (v8_str("x")->Equals(name)) {
10014     return keyed_call_ic_function;
10015   }
10016   return v8::Handle<Value>();
10017 }
10018
10019
10020 // Test the case when we stored cacheable lookup into
10021 // a stub, but the function name changed (to another cacheable function).
10022 THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
10023   v8::HandleScope scope;
10024   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10025   templ->SetNamedPropertyHandler(NoBlockGetterX);
10026   LocalContext context;
10027   context->Global()->Set(v8_str("o"), templ->NewInstance());
10028   CompileRun(
10029     "proto = new Object();"
10030     "proto.y = function(x) { return x + 1; };"
10031     "proto.z = function(x) { return x - 1; };"
10032     "o.__proto__ = proto;"
10033     "var result = 0;"
10034     "var method = 'y';"
10035     "for (var i = 0; i < 10; i++) {"
10036     "  if (i == 5) { method = 'z'; };"
10037     "  result += o[method](41);"
10038     "}");
10039   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10040 }
10041
10042
10043 // Test the case when we stored cacheable lookup into
10044 // a stub, but the function name changed (and the new function is present
10045 // both before and after the interceptor in the prototype chain).
10046 THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
10047   v8::HandleScope scope;
10048   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10049   templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
10050   LocalContext context;
10051   context->Global()->Set(v8_str("proto1"), templ->NewInstance());
10052   keyed_call_ic_function =
10053       v8_compile("function f(x) { return x - 1; }; f")->Run();
10054   CompileRun(
10055     "o = new Object();"
10056     "proto2 = new Object();"
10057     "o.y = function(x) { return x + 1; };"
10058     "proto2.y = function(x) { return x + 2; };"
10059     "o.__proto__ = proto1;"
10060     "proto1.__proto__ = proto2;"
10061     "var result = 0;"
10062     "var method = 'x';"
10063     "for (var i = 0; i < 10; i++) {"
10064     "  if (i == 5) { method = 'y'; };"
10065     "  result += o[method](41);"
10066     "}");
10067   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10068 }
10069
10070
10071 // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
10072 // on the global object.
10073 THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
10074   v8::HandleScope scope;
10075   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10076   templ->SetNamedPropertyHandler(NoBlockGetterX);
10077   LocalContext context;
10078   context->Global()->Set(v8_str("o"), templ->NewInstance());
10079   CompileRun(
10080     "function inc(x) { return x + 1; };"
10081     "inc(1);"
10082     "function dec(x) { return x - 1; };"
10083     "dec(1);"
10084     "o.__proto__ = this;"
10085     "this.__proto__.x = inc;"
10086     "this.__proto__.y = dec;"
10087     "var result = 0;"
10088     "var method = 'x';"
10089     "for (var i = 0; i < 10; i++) {"
10090     "  if (i == 5) { method = 'y'; };"
10091     "  result += o[method](41);"
10092     "}");
10093   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10094 }
10095
10096
10097 // Test the case when actual function to call sits on global object.
10098 THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
10099   v8::HandleScope scope;
10100   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10101   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
10102   LocalContext context;
10103   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10104
10105   CompileRun(
10106     "function len(x) { return x.length; };"
10107     "o.__proto__ = this;"
10108     "var m = 'parseFloat';"
10109     "var result = 0;"
10110     "for (var i = 0; i < 10; i++) {"
10111     "  if (i == 5) {"
10112     "    m = 'len';"
10113     "    saved_result = result;"
10114     "  };"
10115     "  result = o[m]('239');"
10116     "}");
10117   CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
10118   CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10119 }
10120
10121 // Test the map transition before the interceptor.
10122 THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
10123   v8::HandleScope scope;
10124   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10125   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
10126   LocalContext context;
10127   context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
10128
10129   CompileRun(
10130     "var o = new Object();"
10131     "o.__proto__ = proto;"
10132     "o.method = function(x) { return x + 1; };"
10133     "var m = 'method';"
10134     "var result = 0;"
10135     "for (var i = 0; i < 10; i++) {"
10136     "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
10137     "  result += o[m](41);"
10138     "}");
10139   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10140 }
10141
10142
10143 // Test the map transition after the interceptor.
10144 THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
10145   v8::HandleScope scope;
10146   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10147   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
10148   LocalContext context;
10149   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10150
10151   CompileRun(
10152     "var proto = new Object();"
10153     "o.__proto__ = proto;"
10154     "proto.method = function(x) { return x + 1; };"
10155     "var m = 'method';"
10156     "var result = 0;"
10157     "for (var i = 0; i < 10; i++) {"
10158     "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
10159     "  result += o[m](41);"
10160     "}");
10161   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10162 }
10163
10164
10165 static int interceptor_call_count = 0;
10166
10167 static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name,
10168                                                      const AccessorInfo& info) {
10169   ApiTestFuzzer::Fuzz();
10170   if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
10171     return call_ic_function2;
10172   }
10173   return v8::Handle<Value>();
10174 }
10175
10176
10177 // This test should hit load and call ICs for the interceptor case.
10178 // Once in a while, the interceptor will reply that a property was not
10179 // found in which case we should get a reference error.
10180 THREADED_TEST(InterceptorICReferenceErrors) {
10181   v8::HandleScope scope;
10182   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10183   templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
10184   LocalContext context(0, templ, v8::Handle<Value>());
10185   call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
10186   v8::Handle<Value> value = CompileRun(
10187     "function f() {"
10188     "  for (var i = 0; i < 1000; i++) {"
10189     "    try { x; } catch(e) { return true; }"
10190     "  }"
10191     "  return false;"
10192     "};"
10193     "f();");
10194   CHECK_EQ(true, value->BooleanValue());
10195   interceptor_call_count = 0;
10196   value = CompileRun(
10197     "function g() {"
10198     "  for (var i = 0; i < 1000; i++) {"
10199     "    try { x(42); } catch(e) { return true; }"
10200     "  }"
10201     "  return false;"
10202     "};"
10203     "g();");
10204   CHECK_EQ(true, value->BooleanValue());
10205 }
10206
10207
10208 static int interceptor_ic_exception_get_count = 0;
10209
10210 static v8::Handle<Value> InterceptorICExceptionGetter(
10211     Local<String> name,
10212     const AccessorInfo& info) {
10213   ApiTestFuzzer::Fuzz();
10214   if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
10215     return call_ic_function3;
10216   }
10217   if (interceptor_ic_exception_get_count == 20) {
10218     return v8::ThrowException(v8_num(42));
10219   }
10220   // Do not handle get for properties other than x.
10221   return v8::Handle<Value>();
10222 }
10223
10224 // Test interceptor load/call IC where the interceptor throws an
10225 // exception once in a while.
10226 THREADED_TEST(InterceptorICGetterExceptions) {
10227   interceptor_ic_exception_get_count = 0;
10228   v8::HandleScope scope;
10229   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10230   templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
10231   LocalContext context(0, templ, v8::Handle<Value>());
10232   call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
10233   v8::Handle<Value> value = CompileRun(
10234     "function f() {"
10235     "  for (var i = 0; i < 100; i++) {"
10236     "    try { x; } catch(e) { return true; }"
10237     "  }"
10238     "  return false;"
10239     "};"
10240     "f();");
10241   CHECK_EQ(true, value->BooleanValue());
10242   interceptor_ic_exception_get_count = 0;
10243   value = CompileRun(
10244     "function f() {"
10245     "  for (var i = 0; i < 100; i++) {"
10246     "    try { x(42); } catch(e) { return true; }"
10247     "  }"
10248     "  return false;"
10249     "};"
10250     "f();");
10251   CHECK_EQ(true, value->BooleanValue());
10252 }
10253
10254
10255 static int interceptor_ic_exception_set_count = 0;
10256
10257 static v8::Handle<Value> InterceptorICExceptionSetter(
10258       Local<String> key, Local<Value> value, const AccessorInfo&) {
10259   ApiTestFuzzer::Fuzz();
10260   if (++interceptor_ic_exception_set_count > 20) {
10261     return v8::ThrowException(v8_num(42));
10262   }
10263   // Do not actually handle setting.
10264   return v8::Handle<Value>();
10265 }
10266
10267 // Test interceptor store IC where the interceptor throws an exception
10268 // once in a while.
10269 THREADED_TEST(InterceptorICSetterExceptions) {
10270   interceptor_ic_exception_set_count = 0;
10271   v8::HandleScope scope;
10272   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10273   templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
10274   LocalContext context(0, templ, v8::Handle<Value>());
10275   v8::Handle<Value> value = CompileRun(
10276     "function f() {"
10277     "  for (var i = 0; i < 100; i++) {"
10278     "    try { x = 42; } catch(e) { return true; }"
10279     "  }"
10280     "  return false;"
10281     "};"
10282     "f();");
10283   CHECK_EQ(true, value->BooleanValue());
10284 }
10285
10286
10287 // Test that we ignore null interceptors.
10288 THREADED_TEST(NullNamedInterceptor) {
10289   v8::HandleScope scope;
10290   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10291   templ->SetNamedPropertyHandler(0);
10292   LocalContext context;
10293   templ->Set("x", v8_num(42));
10294   v8::Handle<v8::Object> obj = templ->NewInstance();
10295   context->Global()->Set(v8_str("obj"), obj);
10296   v8::Handle<Value> value = CompileRun("obj.x");
10297   CHECK(value->IsInt32());
10298   CHECK_EQ(42, value->Int32Value());
10299 }
10300
10301
10302 // Test that we ignore null interceptors.
10303 THREADED_TEST(NullIndexedInterceptor) {
10304   v8::HandleScope scope;
10305   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10306   templ->SetIndexedPropertyHandler(0);
10307   LocalContext context;
10308   templ->Set("42", v8_num(42));
10309   v8::Handle<v8::Object> obj = templ->NewInstance();
10310   context->Global()->Set(v8_str("obj"), obj);
10311   v8::Handle<Value> value = CompileRun("obj[42]");
10312   CHECK(value->IsInt32());
10313   CHECK_EQ(42, value->Int32Value());
10314 }
10315
10316
10317 THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
10318   v8::HandleScope scope;
10319   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
10320   templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10321   LocalContext env;
10322   env->Global()->Set(v8_str("obj"),
10323                      templ->GetFunction()->NewInstance());
10324   ExpectTrue("obj.x === 42");
10325   ExpectTrue("!obj.propertyIsEnumerable('x')");
10326 }
10327
10328
10329 static Handle<Value> ThrowingGetter(Local<String> name,
10330                                     const AccessorInfo& info) {
10331   ApiTestFuzzer::Fuzz();
10332   ThrowException(Handle<Value>());
10333   return Undefined();
10334 }
10335
10336
10337 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
10338   HandleScope scope;
10339   LocalContext context;
10340
10341   Local<FunctionTemplate> templ = FunctionTemplate::New();
10342   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
10343   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
10344
10345   Local<Object> instance = templ->GetFunction()->NewInstance();
10346
10347   Local<Object> another = Object::New();
10348   another->SetPrototype(instance);
10349
10350   Local<Object> with_js_getter = CompileRun(
10351       "o = {};\n"
10352       "o.__defineGetter__('f', function() { throw undefined; });\n"
10353       "o\n").As<Object>();
10354   CHECK(!with_js_getter.IsEmpty());
10355
10356   TryCatch try_catch;
10357
10358   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
10359   CHECK(try_catch.HasCaught());
10360   try_catch.Reset();
10361   CHECK(result.IsEmpty());
10362
10363   result = another->GetRealNamedProperty(v8_str("f"));
10364   CHECK(try_catch.HasCaught());
10365   try_catch.Reset();
10366   CHECK(result.IsEmpty());
10367
10368   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
10369   CHECK(try_catch.HasCaught());
10370   try_catch.Reset();
10371   CHECK(result.IsEmpty());
10372
10373   result = another->Get(v8_str("f"));
10374   CHECK(try_catch.HasCaught());
10375   try_catch.Reset();
10376   CHECK(result.IsEmpty());
10377
10378   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
10379   CHECK(try_catch.HasCaught());
10380   try_catch.Reset();
10381   CHECK(result.IsEmpty());
10382
10383   result = with_js_getter->Get(v8_str("f"));
10384   CHECK(try_catch.HasCaught());
10385   try_catch.Reset();
10386   CHECK(result.IsEmpty());
10387 }
10388
10389
10390 static Handle<Value> ThrowingCallbackWithTryCatch(const Arguments& args) {
10391   TryCatch try_catch;
10392   // Verboseness is important: it triggers message delivery which can call into
10393   // external code.
10394   try_catch.SetVerbose(true);
10395   CompileRun("throw 'from JS';");
10396   CHECK(try_catch.HasCaught());
10397   CHECK(!i::Isolate::Current()->has_pending_exception());
10398   CHECK(!i::Isolate::Current()->has_scheduled_exception());
10399   return Undefined();
10400 }
10401
10402
10403 static int call_depth;
10404
10405
10406 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
10407   TryCatch try_catch;
10408 }
10409
10410
10411 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
10412   if (--call_depth) CompileRun("throw 'ThrowInJS';");
10413 }
10414
10415
10416 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
10417   if (--call_depth) ThrowException(v8_str("ThrowViaApi"));
10418 }
10419
10420
10421 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
10422   Handle<String> errorMessageString = message->Get();
10423   CHECK(!errorMessageString.IsEmpty());
10424   message->GetStackTrace();
10425   message->GetScriptResourceName();
10426 }
10427
10428 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
10429   HandleScope scope;
10430   LocalContext context;
10431
10432   Local<Function> func =
10433       FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction();
10434   context->Global()->Set(v8_str("func"), func);
10435
10436   MessageCallback callbacks[] =
10437       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
10438   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
10439     MessageCallback callback = callbacks[i];
10440     if (callback != NULL) {
10441       V8::AddMessageListener(callback);
10442     }
10443     // Some small number to control number of times message handler should
10444     // throw an exception.
10445     call_depth = 5;
10446     ExpectFalse(
10447         "var thrown = false;\n"
10448         "try { func(); } catch(e) { thrown = true; }\n"
10449         "thrown\n");
10450     if (callback != NULL) {
10451       V8::RemoveMessageListeners(callback);
10452     }
10453   }
10454 }
10455
10456
10457 static v8::Handle<Value> ParentGetter(Local<String> name,
10458                                       const AccessorInfo& info) {
10459   ApiTestFuzzer::Fuzz();
10460   return v8_num(1);
10461 }
10462
10463
10464 static v8::Handle<Value> ChildGetter(Local<String> name,
10465                                      const AccessorInfo& info) {
10466   ApiTestFuzzer::Fuzz();
10467   return v8_num(42);
10468 }
10469
10470
10471 THREADED_TEST(Overriding) {
10472   i::FLAG_es5_readonly = true;
10473   v8::HandleScope scope;
10474   LocalContext context;
10475
10476   // Parent template.
10477   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
10478   Local<ObjectTemplate> parent_instance_templ =
10479       parent_templ->InstanceTemplate();
10480   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
10481
10482   // Template that inherits from the parent template.
10483   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
10484   Local<ObjectTemplate> child_instance_templ =
10485       child_templ->InstanceTemplate();
10486   child_templ->Inherit(parent_templ);
10487   // Override 'f'.  The child version of 'f' should get called for child
10488   // instances.
10489   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
10490   // Add 'g' twice.  The 'g' added last should get called for instances.
10491   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
10492   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
10493
10494   // Add 'h' as an accessor to the proto template with ReadOnly attributes
10495   // so 'h' can be shadowed on the instance object.
10496   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
10497   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
10498       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
10499
10500   // Add 'i' as an accessor to the instance template with ReadOnly attributes
10501   // but the attribute does not have effect because it is duplicated with
10502   // NULL setter.
10503   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
10504       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
10505
10506
10507
10508   // Instantiate the child template.
10509   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
10510
10511   // Check that the child function overrides the parent one.
10512   context->Global()->Set(v8_str("o"), instance);
10513   Local<Value> value = v8_compile("o.f")->Run();
10514   // Check that the 'g' that was added last is hit.
10515   CHECK_EQ(42, value->Int32Value());
10516   value = v8_compile("o.g")->Run();
10517   CHECK_EQ(42, value->Int32Value());
10518
10519   // Check that 'h' cannot be shadowed.
10520   value = v8_compile("o.h = 3; o.h")->Run();
10521   CHECK_EQ(1, value->Int32Value());
10522
10523   // Check that 'i' cannot be shadowed or changed.
10524   value = v8_compile("o.i = 3; o.i")->Run();
10525   CHECK_EQ(42, value->Int32Value());
10526 }
10527
10528
10529 static v8::Handle<Value> IsConstructHandler(const v8::Arguments& args) {
10530   ApiTestFuzzer::Fuzz();
10531   return v8::Boolean::New(args.IsConstructCall());
10532 }
10533
10534
10535 THREADED_TEST(IsConstructCall) {
10536   v8::HandleScope scope;
10537
10538   // Function template with call handler.
10539   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
10540   templ->SetCallHandler(IsConstructHandler);
10541
10542   LocalContext context;
10543
10544   context->Global()->Set(v8_str("f"), templ->GetFunction());
10545   Local<Value> value = v8_compile("f()")->Run();
10546   CHECK(!value->BooleanValue());
10547   value = v8_compile("new f()")->Run();
10548   CHECK(value->BooleanValue());
10549 }
10550
10551
10552 THREADED_TEST(ObjectProtoToString) {
10553   v8::HandleScope scope;
10554   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
10555   templ->SetClassName(v8_str("MyClass"));
10556
10557   LocalContext context;
10558
10559   Local<String> customized_tostring = v8_str("customized toString");
10560
10561   // Replace Object.prototype.toString
10562   v8_compile("Object.prototype.toString = function() {"
10563                   "  return 'customized toString';"
10564                   "}")->Run();
10565
10566   // Normal ToString call should call replaced Object.prototype.toString
10567   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
10568   Local<String> value = instance->ToString();
10569   CHECK(value->IsString() && value->Equals(customized_tostring));
10570
10571   // ObjectProtoToString should not call replace toString function.
10572   value = instance->ObjectProtoToString();
10573   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
10574
10575   // Check global
10576   value = context->Global()->ObjectProtoToString();
10577   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
10578
10579   // Check ordinary object
10580   Local<Value> object = v8_compile("new Object()")->Run();
10581   value = object.As<v8::Object>()->ObjectProtoToString();
10582   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
10583 }
10584
10585
10586 THREADED_TEST(ObjectGetConstructorName) {
10587   v8::HandleScope scope;
10588   LocalContext context;
10589   v8_compile("function Parent() {};"
10590              "function Child() {};"
10591              "Child.prototype = new Parent();"
10592              "var outer = { inner: function() { } };"
10593              "var p = new Parent();"
10594              "var c = new Child();"
10595              "var x = new outer.inner();")->Run();
10596
10597   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
10598   CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
10599       v8_str("Parent")));
10600
10601   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
10602   CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
10603       v8_str("Child")));
10604
10605   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
10606   CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
10607       v8_str("outer.inner")));
10608 }
10609
10610
10611 bool ApiTestFuzzer::fuzzing_ = false;
10612 i::Semaphore* ApiTestFuzzer::all_tests_done_=
10613   i::OS::CreateSemaphore(0);
10614 int ApiTestFuzzer::active_tests_;
10615 int ApiTestFuzzer::tests_being_run_;
10616 int ApiTestFuzzer::current_;
10617
10618
10619 // We are in a callback and want to switch to another thread (if we
10620 // are currently running the thread fuzzing test).
10621 void ApiTestFuzzer::Fuzz() {
10622   if (!fuzzing_) return;
10623   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
10624   test->ContextSwitch();
10625 }
10626
10627
10628 // Let the next thread go.  Since it is also waiting on the V8 lock it may
10629 // not start immediately.
10630 bool ApiTestFuzzer::NextThread() {
10631   int test_position = GetNextTestNumber();
10632   const char* test_name = RegisterThreadedTest::nth(current_)->name();
10633   if (test_position == current_) {
10634     if (kLogThreading)
10635       printf("Stay with %s\n", test_name);
10636     return false;
10637   }
10638   if (kLogThreading) {
10639     printf("Switch from %s to %s\n",
10640            test_name,
10641            RegisterThreadedTest::nth(test_position)->name());
10642   }
10643   current_ = test_position;
10644   RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
10645   return true;
10646 }
10647
10648
10649 void ApiTestFuzzer::Run() {
10650   // When it is our turn...
10651   gate_->Wait();
10652   {
10653     // ... get the V8 lock and start running the test.
10654     v8::Locker locker;
10655     CallTest();
10656   }
10657   // This test finished.
10658   active_ = false;
10659   active_tests_--;
10660   // If it was the last then signal that fact.
10661   if (active_tests_ == 0) {
10662     all_tests_done_->Signal();
10663   } else {
10664     // Otherwise select a new test and start that.
10665     NextThread();
10666   }
10667 }
10668
10669
10670 static unsigned linear_congruential_generator;
10671
10672
10673 void ApiTestFuzzer::SetUp(PartOfTest part) {
10674   linear_congruential_generator = i::FLAG_testing_prng_seed;
10675   fuzzing_ = true;
10676   int count = RegisterThreadedTest::count();
10677   int start =  count * part / (LAST_PART + 1);
10678   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
10679   active_tests_ = tests_being_run_ = end - start + 1;
10680   for (int i = 0; i < tests_being_run_; i++) {
10681     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
10682   }
10683   for (int i = 0; i < active_tests_; i++) {
10684     RegisterThreadedTest::nth(i)->fuzzer_->Start();
10685   }
10686 }
10687
10688
10689 static void CallTestNumber(int test_number) {
10690   (RegisterThreadedTest::nth(test_number)->callback())();
10691 }
10692
10693
10694 void ApiTestFuzzer::RunAllTests() {
10695   // Set off the first test.
10696   current_ = -1;
10697   NextThread();
10698   // Wait till they are all done.
10699   all_tests_done_->Wait();
10700 }
10701
10702
10703 int ApiTestFuzzer::GetNextTestNumber() {
10704   int next_test;
10705   do {
10706     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
10707     linear_congruential_generator *= 1664525u;
10708     linear_congruential_generator += 1013904223u;
10709   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
10710   return next_test;
10711 }
10712
10713
10714 void ApiTestFuzzer::ContextSwitch() {
10715   // If the new thread is the same as the current thread there is nothing to do.
10716   if (NextThread()) {
10717     // Now it can start.
10718     v8::Unlocker unlocker;
10719     // Wait till someone starts us again.
10720     gate_->Wait();
10721     // And we're off.
10722   }
10723 }
10724
10725
10726 void ApiTestFuzzer::TearDown() {
10727   fuzzing_ = false;
10728   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
10729     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
10730     if (fuzzer != NULL) fuzzer->Join();
10731   }
10732 }
10733
10734
10735 // Lets not be needlessly self-referential.
10736 TEST(Threading) {
10737   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
10738   ApiTestFuzzer::RunAllTests();
10739   ApiTestFuzzer::TearDown();
10740 }
10741
10742 TEST(Threading2) {
10743   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
10744   ApiTestFuzzer::RunAllTests();
10745   ApiTestFuzzer::TearDown();
10746 }
10747
10748 TEST(Threading3) {
10749   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
10750   ApiTestFuzzer::RunAllTests();
10751   ApiTestFuzzer::TearDown();
10752 }
10753
10754 TEST(Threading4) {
10755   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
10756   ApiTestFuzzer::RunAllTests();
10757   ApiTestFuzzer::TearDown();
10758 }
10759
10760 void ApiTestFuzzer::CallTest() {
10761   if (kLogThreading)
10762     printf("Start test %d\n", test_number_);
10763   CallTestNumber(test_number_);
10764   if (kLogThreading)
10765     printf("End test %d\n", test_number_);
10766 }
10767
10768
10769 static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) {
10770   CHECK(v8::Locker::IsLocked());
10771   ApiTestFuzzer::Fuzz();
10772   v8::Unlocker unlocker;
10773   const char* code = "throw 7;";
10774   {
10775     v8::Locker nested_locker;
10776     v8::HandleScope scope;
10777     v8::Handle<Value> exception;
10778     { v8::TryCatch try_catch;
10779       v8::Handle<Value> value = CompileRun(code);
10780       CHECK(value.IsEmpty());
10781       CHECK(try_catch.HasCaught());
10782       // Make sure to wrap the exception in a new handle because
10783       // the handle returned from the TryCatch is destroyed
10784       // when the TryCatch is destroyed.
10785       exception = Local<Value>::New(try_catch.Exception());
10786     }
10787     return v8::ThrowException(exception);
10788   }
10789 }
10790
10791
10792 static v8::Handle<Value> ThrowInJSNoCatch(const v8::Arguments& args) {
10793   CHECK(v8::Locker::IsLocked());
10794   ApiTestFuzzer::Fuzz();
10795   v8::Unlocker unlocker;
10796   const char* code = "throw 7;";
10797   {
10798     v8::Locker nested_locker;
10799     v8::HandleScope scope;
10800     v8::Handle<Value> value = CompileRun(code);
10801     CHECK(value.IsEmpty());
10802     return v8_str("foo");
10803   }
10804 }
10805
10806
10807 // These are locking tests that don't need to be run again
10808 // as part of the locking aggregation tests.
10809 TEST(NestedLockers) {
10810   v8::Locker locker;
10811   CHECK(v8::Locker::IsLocked());
10812   v8::HandleScope scope;
10813   LocalContext env;
10814   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
10815   Local<Function> fun = fun_templ->GetFunction();
10816   env->Global()->Set(v8_str("throw_in_js"), fun);
10817   Local<Script> script = v8_compile("(function () {"
10818                                     "  try {"
10819                                     "    throw_in_js();"
10820                                     "    return 42;"
10821                                     "  } catch (e) {"
10822                                     "    return e * 13;"
10823                                     "  }"
10824                                     "})();");
10825   CHECK_EQ(91, script->Run()->Int32Value());
10826 }
10827
10828
10829 // These are locking tests that don't need to be run again
10830 // as part of the locking aggregation tests.
10831 TEST(NestedLockersNoTryCatch) {
10832   v8::Locker locker;
10833   v8::HandleScope scope;
10834   LocalContext env;
10835   Local<v8::FunctionTemplate> fun_templ =
10836       v8::FunctionTemplate::New(ThrowInJSNoCatch);
10837   Local<Function> fun = fun_templ->GetFunction();
10838   env->Global()->Set(v8_str("throw_in_js"), fun);
10839   Local<Script> script = v8_compile("(function () {"
10840                                     "  try {"
10841                                     "    throw_in_js();"
10842                                     "    return 42;"
10843                                     "  } catch (e) {"
10844                                     "    return e * 13;"
10845                                     "  }"
10846                                     "})();");
10847   CHECK_EQ(91, script->Run()->Int32Value());
10848 }
10849
10850
10851 THREADED_TEST(RecursiveLocking) {
10852   v8::Locker locker;
10853   {
10854     v8::Locker locker2;
10855     CHECK(v8::Locker::IsLocked());
10856   }
10857 }
10858
10859
10860 static v8::Handle<Value> UnlockForAMoment(const v8::Arguments& args) {
10861   ApiTestFuzzer::Fuzz();
10862   v8::Unlocker unlocker;
10863   return v8::Undefined();
10864 }
10865
10866
10867 THREADED_TEST(LockUnlockLock) {
10868   {
10869     v8::Locker locker;
10870     v8::HandleScope scope;
10871     LocalContext env;
10872     Local<v8::FunctionTemplate> fun_templ =
10873         v8::FunctionTemplate::New(UnlockForAMoment);
10874     Local<Function> fun = fun_templ->GetFunction();
10875     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
10876     Local<Script> script = v8_compile("(function () {"
10877                                       "  unlock_for_a_moment();"
10878                                       "  return 42;"
10879                                       "})();");
10880     CHECK_EQ(42, script->Run()->Int32Value());
10881   }
10882   {
10883     v8::Locker locker;
10884     v8::HandleScope scope;
10885     LocalContext env;
10886     Local<v8::FunctionTemplate> fun_templ =
10887         v8::FunctionTemplate::New(UnlockForAMoment);
10888     Local<Function> fun = fun_templ->GetFunction();
10889     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
10890     Local<Script> script = v8_compile("(function () {"
10891                                       "  unlock_for_a_moment();"
10892                                       "  return 42;"
10893                                       "})();");
10894     CHECK_EQ(42, script->Run()->Int32Value());
10895   }
10896 }
10897
10898
10899 static int GetGlobalObjectsCount() {
10900   i::Isolate::Current()->heap()->EnsureHeapIsIterable();
10901   int count = 0;
10902   i::HeapIterator it;
10903   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
10904     if (object->IsJSGlobalObject()) count++;
10905   return count;
10906 }
10907
10908
10909 static void CheckSurvivingGlobalObjectsCount(int expected) {
10910   // We need to collect all garbage twice to be sure that everything
10911   // has been collected.  This is because inline caches are cleared in
10912   // the first garbage collection but some of the maps have already
10913   // been marked at that point.  Therefore some of the maps are not
10914   // collected until the second garbage collection.
10915   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
10916   HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
10917   int count = GetGlobalObjectsCount();
10918 #ifdef DEBUG
10919   if (count != expected) HEAP->TracePathToGlobal();
10920 #endif
10921   CHECK_EQ(expected, count);
10922 }
10923
10924
10925 TEST(DontLeakGlobalObjects) {
10926   // Regression test for issues 1139850 and 1174891.
10927
10928   v8::V8::Initialize();
10929
10930   for (int i = 0; i < 5; i++) {
10931     { v8::HandleScope scope;
10932       LocalContext context;
10933     }
10934     v8::V8::ContextDisposedNotification();
10935     CheckSurvivingGlobalObjectsCount(0);
10936
10937     { v8::HandleScope scope;
10938       LocalContext context;
10939       v8_compile("Date")->Run();
10940     }
10941     v8::V8::ContextDisposedNotification();
10942     CheckSurvivingGlobalObjectsCount(0);
10943
10944     { v8::HandleScope scope;
10945       LocalContext context;
10946       v8_compile("/aaa/")->Run();
10947     }
10948     v8::V8::ContextDisposedNotification();
10949     CheckSurvivingGlobalObjectsCount(0);
10950
10951     { v8::HandleScope scope;
10952       const char* extension_list[] = { "v8/gc" };
10953       v8::ExtensionConfiguration extensions(1, extension_list);
10954       LocalContext context(&extensions);
10955       v8_compile("gc();")->Run();
10956     }
10957     v8::V8::ContextDisposedNotification();
10958     CheckSurvivingGlobalObjectsCount(0);
10959   }
10960 }
10961
10962
10963 v8::Persistent<v8::Object> some_object;
10964 v8::Persistent<v8::Object> bad_handle;
10965
10966 void NewPersistentHandleCallback(v8::Persistent<v8::Value> handle, void*) {
10967   v8::HandleScope scope;
10968   bad_handle = v8::Persistent<v8::Object>::New(some_object);
10969   handle.Dispose();
10970 }
10971
10972
10973 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
10974   LocalContext context;
10975
10976   v8::Persistent<v8::Object> handle1, handle2;
10977   {
10978     v8::HandleScope scope;
10979     some_object = v8::Persistent<v8::Object>::New(v8::Object::New());
10980     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
10981     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
10982   }
10983   // Note: order is implementation dependent alas: currently
10984   // global handle nodes are processed by PostGarbageCollectionProcessing
10985   // in reverse allocation order, so if second allocated handle is deleted,
10986   // weak callback of the first handle would be able to 'reallocate' it.
10987   handle1.MakeWeak(NULL, NewPersistentHandleCallback);
10988   handle2.Dispose();
10989   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
10990 }
10991
10992
10993 v8::Persistent<v8::Object> to_be_disposed;
10994
10995 void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) {
10996   to_be_disposed.Dispose();
10997   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
10998   handle.Dispose();
10999 }
11000
11001
11002 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
11003   LocalContext context;
11004
11005   v8::Persistent<v8::Object> handle1, handle2;
11006   {
11007     v8::HandleScope scope;
11008     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
11009     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
11010   }
11011   handle1.MakeWeak(NULL, DisposeAndForceGcCallback);
11012   to_be_disposed = handle2;
11013   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
11014 }
11015
11016 void DisposingCallback(v8::Persistent<v8::Value> handle, void*) {
11017   handle.Dispose();
11018 }
11019
11020 void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) {
11021   v8::HandleScope scope;
11022   v8::Persistent<v8::Object>::New(v8::Object::New());
11023   handle.Dispose();
11024 }
11025
11026
11027 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
11028   LocalContext context;
11029
11030   v8::Persistent<v8::Object> handle1, handle2, handle3;
11031   {
11032     v8::HandleScope scope;
11033     handle3 = v8::Persistent<v8::Object>::New(v8::Object::New());
11034     handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
11035     handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
11036   }
11037   handle2.MakeWeak(NULL, DisposingCallback);
11038   handle3.MakeWeak(NULL, HandleCreatingCallback);
11039   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
11040 }
11041
11042
11043 THREADED_TEST(CheckForCrossContextObjectLiterals) {
11044   v8::V8::Initialize();
11045
11046   const int nof = 2;
11047   const char* sources[nof] = {
11048     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
11049     "Object()"
11050   };
11051
11052   for (int i = 0; i < nof; i++) {
11053     const char* source = sources[i];
11054     { v8::HandleScope scope;
11055       LocalContext context;
11056       CompileRun(source);
11057     }
11058     { v8::HandleScope scope;
11059       LocalContext context;
11060       CompileRun(source);
11061     }
11062   }
11063 }
11064
11065
11066 static v8::Handle<Value> NestedScope(v8::Persistent<Context> env) {
11067   v8::HandleScope inner;
11068   env->Enter();
11069   v8::Handle<Value> three = v8_num(3);
11070   v8::Handle<Value> value = inner.Close(three);
11071   env->Exit();
11072   return value;
11073 }
11074
11075
11076 THREADED_TEST(NestedHandleScopeAndContexts) {
11077   v8::HandleScope outer;
11078   v8::Persistent<Context> env = Context::New();
11079   env->Enter();
11080   v8::Handle<Value> value = NestedScope(env);
11081   v8::Handle<String> str(value->ToString());
11082   CHECK(!str.IsEmpty());
11083   env->Exit();
11084   env.Dispose();
11085 }
11086
11087
11088 static i::Handle<i::JSFunction>* foo_ptr = NULL;
11089 static int foo_count = 0;
11090 static i::Handle<i::JSFunction>* bar_ptr = NULL;
11091 static int bar_count = 0;
11092
11093
11094 static void entry_hook(uintptr_t function,
11095                        uintptr_t return_addr_location) {
11096   i::Code* code = i::Code::GetCodeFromTargetAddress(
11097       reinterpret_cast<i::Address>(function));
11098   CHECK(code != NULL);
11099
11100   if (bar_ptr != NULL && code == (*bar_ptr)->code())
11101     ++bar_count;
11102
11103   if (foo_ptr != NULL && code == (*foo_ptr)->code())
11104     ++foo_count;
11105
11106   // TODO(siggi): Verify return_addr_location.
11107   //     This can be done by capturing JitCodeEvents, but requires an ordered
11108   //     collection.
11109 }
11110
11111
11112 static void RunLoopInNewEnv() {
11113   bar_ptr = NULL;
11114   foo_ptr = NULL;
11115
11116   v8::HandleScope outer;
11117   v8::Persistent<Context> env = Context::New();
11118   env->Enter();
11119
11120   const char* script =
11121       "function bar() {"
11122       "  var sum = 0;"
11123       "  for (i = 0; i < 100; ++i)"
11124       "    sum = foo(i);"
11125       "  return sum;"
11126       "}"
11127       "function foo(i) { return i * i; }";
11128   CompileRun(script);
11129   i::Handle<i::JSFunction> bar =
11130       i::Handle<i::JSFunction>::cast(
11131           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
11132   ASSERT(*bar);
11133
11134   i::Handle<i::JSFunction> foo =
11135       i::Handle<i::JSFunction>::cast(
11136            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
11137   ASSERT(*foo);
11138
11139   bar_ptr = &bar;
11140   foo_ptr = &foo;
11141
11142   v8::Handle<v8::Value> value = CompileRun("bar();");
11143   CHECK(value->IsNumber());
11144   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
11145
11146   // Test the optimized codegen path.
11147   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
11148                      "bar();");
11149   CHECK(value->IsNumber());
11150   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
11151
11152   env->Exit();
11153 }
11154
11155
11156 TEST(SetFunctionEntryHook) {
11157   i::FLAG_allow_natives_syntax = true;
11158
11159   // Test setting and resetting the entry hook.
11160   // Nulling it should always succeed.
11161   CHECK(v8::V8::SetFunctionEntryHook(NULL));
11162
11163   CHECK(v8::V8::SetFunctionEntryHook(entry_hook));
11164   // Setting a hook while one's active should fail.
11165   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(entry_hook));
11166
11167   CHECK(v8::V8::SetFunctionEntryHook(NULL));
11168
11169   // Reset the entry count to zero and set the entry hook.
11170   bar_count = 0;
11171   foo_count = 0;
11172   CHECK(v8::V8::SetFunctionEntryHook(entry_hook));
11173   RunLoopInNewEnv();
11174
11175   CHECK_EQ(2, bar_count);
11176   CHECK_EQ(200, foo_count);
11177
11178   // Clear the entry hook and count.
11179   bar_count = 0;
11180   foo_count = 0;
11181   v8::V8::SetFunctionEntryHook(NULL);
11182
11183   // Clear the compilation cache to make sure we don't reuse the
11184   // functions from the previous invocation.
11185   v8::internal::Isolate::Current()->compilation_cache()->Clear();
11186
11187   // Verify that entry hooking is now disabled.
11188   RunLoopInNewEnv();
11189   CHECK_EQ(0u, bar_count);
11190   CHECK_EQ(0u, foo_count);
11191 }
11192
11193
11194 static i::HashMap* code_map = NULL;
11195 static int saw_bar = 0;
11196 static int move_events = 0;
11197
11198
11199 static bool FunctionNameIs(const char* expected,
11200                            const v8::JitCodeEvent* event) {
11201   // Log lines for functions are of the general form:
11202   // "LazyCompile:<type><function_name>", where the type is one of
11203   // "*", "~" or "".
11204   static const char kPreamble[] = "LazyCompile:";
11205   static size_t kPreambleLen = sizeof(kPreamble) - 1;
11206
11207   if (event->name.len < sizeof(kPreamble) - 1 ||
11208       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
11209     return false;
11210   }
11211
11212   const char* tail = event->name.str + kPreambleLen;
11213   size_t tail_len = event->name.len - kPreambleLen;
11214   size_t expected_len = strlen(expected);
11215   if (tail_len == expected_len + 1) {
11216     if (*tail == '*' || *tail == '~') {
11217       --tail_len;
11218       ++tail;
11219     } else {
11220       return false;
11221     }
11222   }
11223
11224   if (tail_len != expected_len)
11225     return false;
11226
11227   return strncmp(tail, expected, expected_len) == 0;
11228 }
11229
11230
11231 static void event_handler(const v8::JitCodeEvent* event) {
11232   CHECK(event != NULL);
11233   CHECK(code_map != NULL);
11234
11235   switch (event->type) {
11236     case v8::JitCodeEvent::CODE_ADDED: {
11237         CHECK(event->code_start != NULL);
11238         CHECK_NE(0, static_cast<int>(event->code_len));
11239         CHECK(event->name.str != NULL);
11240         i::HashMap::Entry* entry =
11241             code_map->Lookup(event->code_start,
11242                              i::ComputePointerHash(event->code_start),
11243                              true);
11244         entry->value = reinterpret_cast<void*>(event->code_len);
11245
11246         if (FunctionNameIs("bar", event)) {
11247           ++saw_bar;
11248         }
11249       }
11250       break;
11251
11252     case v8::JitCodeEvent::CODE_MOVED: {
11253         uint32_t hash = i::ComputePointerHash(event->code_start);
11254         // We would like to never see code move that we haven't seen before,
11255         // but the code creation event does not happen until the line endings
11256         // have been calculated (this is so that we can report the line in the
11257         // script at which the function source is found, see
11258         // Compiler::RecordFunctionCompilation) and the line endings
11259         // calculations can cause a GC, which can move the newly created code
11260         // before its existence can be logged.
11261         i::HashMap::Entry* entry =
11262             code_map->Lookup(event->code_start, hash, false);
11263         if (entry != NULL) {
11264           ++move_events;
11265
11266           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
11267           code_map->Remove(event->code_start, hash);
11268
11269           entry = code_map->Lookup(event->new_code_start,
11270                                    i::ComputePointerHash(event->new_code_start),
11271                                    true);
11272           CHECK(entry != NULL);
11273           entry->value = reinterpret_cast<void*>(event->code_len);
11274         }
11275       }
11276       break;
11277
11278     case v8::JitCodeEvent::CODE_REMOVED:
11279       // Object/code removal events are currently not dispatched from the GC.
11280       CHECK(false);
11281       break;
11282     default:
11283       // Impossible event.
11284       CHECK(false);
11285       break;
11286   }
11287 }
11288
11289
11290 // Implemented in the test-alloc.cc test suite.
11291 void SimulateFullSpace(i::PagedSpace* space);
11292
11293
11294 static bool MatchPointers(void* key1, void* key2) {
11295   return key1 == key2;
11296 }
11297
11298
11299 TEST(SetJitCodeEventHandler) {
11300   const char* script =
11301     "function bar() {"
11302     "  var sum = 0;"
11303     "  for (i = 0; i < 100; ++i)"
11304     "    sum = foo(i);"
11305     "  return sum;"
11306     "}"
11307     "function foo(i) { return i * i; };"
11308     "bar();";
11309
11310   // Run this test in a new isolate to make sure we don't
11311   // have remnants of state from other code.
11312   v8::Isolate* isolate = v8::Isolate::New();
11313   isolate->Enter();
11314
11315   {
11316     i::HashMap code(MatchPointers);
11317     code_map = &code;
11318
11319     saw_bar = 0;
11320     move_events = 0;
11321
11322     i::FLAG_stress_compaction = true;
11323     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
11324
11325     v8::HandleScope scope;
11326     // Generate new code objects sparsely distributed across several
11327     // different fragmented code-space pages.
11328     const int kIterations = 10;
11329     for (int i = 0; i < kIterations; ++i) {
11330       LocalContext env;
11331
11332       v8::Handle<v8::Script> compiled_script;
11333       {
11334         i::AlwaysAllocateScope always_allocate;
11335         SimulateFullSpace(HEAP->code_space());
11336         compiled_script = v8_compile(script);
11337       }
11338       compiled_script->Run();
11339
11340       // Clear the compilation cache to get more wastage.
11341       ISOLATE->compilation_cache()->Clear();
11342     }
11343
11344     // Force code movement.
11345     HEAP->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
11346
11347     CHECK_LE(kIterations, saw_bar);
11348     CHECK_NE(0, move_events);
11349
11350     code_map = NULL;
11351     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
11352   }
11353
11354   isolate->Exit();
11355   isolate->Dispose();
11356
11357   // Do this in a new isolate.
11358   isolate = v8::Isolate::New();
11359   isolate->Enter();
11360
11361   // Verify that we get callbacks for existing code objects when we
11362   // request enumeration of existing code.
11363   {
11364     v8::HandleScope scope;
11365     LocalContext env;
11366     CompileRun(script);
11367
11368     // Now get code through initial iteration.
11369     i::HashMap code(MatchPointers);
11370     code_map = &code;
11371
11372     V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
11373     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
11374
11375     code_map = NULL;
11376
11377     // We expect that we got some events. Note that if we could get code removal
11378     // notifications, we could compare two collections, one created by listening
11379     // from the time of creation of an isolate, and the other by subscribing
11380     // with EnumExisting.
11381     CHECK_NE(0, code.occupancy());
11382   }
11383
11384   isolate->Exit();
11385   isolate->Dispose();
11386 }
11387
11388
11389 static int64_t cast(intptr_t x) { return static_cast<int64_t>(x); }
11390
11391
11392 THREADED_TEST(ExternalAllocatedMemory) {
11393   v8::HandleScope outer;
11394   v8::Persistent<Context> env(Context::New());
11395   CHECK(!env.IsEmpty());
11396   const intptr_t kSize = 1024*1024;
11397   CHECK_EQ(cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize)),
11398            cast(kSize));
11399   CHECK_EQ(cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize)),
11400            cast(0));
11401 }
11402
11403
11404 THREADED_TEST(DisposeEnteredContext) {
11405   v8::HandleScope scope;
11406   LocalContext outer;
11407   { v8::Persistent<v8::Context> inner = v8::Context::New();
11408     inner->Enter();
11409     inner.Dispose();
11410     inner.Clear();
11411     inner->Exit();
11412   }
11413 }
11414
11415
11416 // Regression test for issue 54, object templates with internal fields
11417 // but no accessors or interceptors did not get their internal field
11418 // count set on instances.
11419 THREADED_TEST(Regress54) {
11420   v8::HandleScope outer;
11421   LocalContext context;
11422   static v8::Persistent<v8::ObjectTemplate> templ;
11423   if (templ.IsEmpty()) {
11424     v8::HandleScope inner;
11425     v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
11426     local->SetInternalFieldCount(1);
11427     templ = v8::Persistent<v8::ObjectTemplate>::New(inner.Close(local));
11428   }
11429   v8::Handle<v8::Object> result = templ->NewInstance();
11430   CHECK_EQ(1, result->InternalFieldCount());
11431 }
11432
11433
11434 // If part of the threaded tests, this test makes ThreadingTest fail
11435 // on mac.
11436 TEST(CatchStackOverflow) {
11437   v8::HandleScope scope;
11438   LocalContext context;
11439   v8::TryCatch try_catch;
11440   v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
11441     "function f() {"
11442     "  return f();"
11443     "}"
11444     ""
11445     "f();"));
11446   v8::Handle<v8::Value> result = script->Run();
11447   CHECK(result.IsEmpty());
11448 }
11449
11450
11451 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
11452                                     const char* resource_name,
11453                                     int line_offset) {
11454   v8::HandleScope scope;
11455   v8::TryCatch try_catch;
11456   v8::Handle<v8::Value> result = script->Run();
11457   CHECK(result.IsEmpty());
11458   CHECK(try_catch.HasCaught());
11459   v8::Handle<v8::Message> message = try_catch.Message();
11460   CHECK(!message.IsEmpty());
11461   CHECK_EQ(10 + line_offset, message->GetLineNumber());
11462   CHECK_EQ(91, message->GetStartPosition());
11463   CHECK_EQ(92, message->GetEndPosition());
11464   CHECK_EQ(2, message->GetStartColumn());
11465   CHECK_EQ(3, message->GetEndColumn());
11466   v8::String::AsciiValue line(message->GetSourceLine());
11467   CHECK_EQ("  throw 'nirk';", *line);
11468   v8::String::AsciiValue name(message->GetScriptResourceName());
11469   CHECK_EQ(resource_name, *name);
11470 }
11471
11472
11473 THREADED_TEST(TryCatchSourceInfo) {
11474   v8::HandleScope scope;
11475   LocalContext context;
11476   v8::Handle<v8::String> source = v8::String::New(
11477       "function Foo() {\n"
11478       "  return Bar();\n"
11479       "}\n"
11480       "\n"
11481       "function Bar() {\n"
11482       "  return Baz();\n"
11483       "}\n"
11484       "\n"
11485       "function Baz() {\n"
11486       "  throw 'nirk';\n"
11487       "}\n"
11488       "\n"
11489       "Foo();\n");
11490
11491   const char* resource_name;
11492   v8::Handle<v8::Script> script;
11493   resource_name = "test.js";
11494   script = v8::Script::Compile(source, v8::String::New(resource_name));
11495   CheckTryCatchSourceInfo(script, resource_name, 0);
11496
11497   resource_name = "test1.js";
11498   v8::ScriptOrigin origin1(v8::String::New(resource_name));
11499   script = v8::Script::Compile(source, &origin1);
11500   CheckTryCatchSourceInfo(script, resource_name, 0);
11501
11502   resource_name = "test2.js";
11503   v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
11504   script = v8::Script::Compile(source, &origin2);
11505   CheckTryCatchSourceInfo(script, resource_name, 7);
11506 }
11507
11508
11509 THREADED_TEST(CompilationCache) {
11510   v8::HandleScope scope;
11511   LocalContext context;
11512   v8::Handle<v8::String> source0 = v8::String::New("1234");
11513   v8::Handle<v8::String> source1 = v8::String::New("1234");
11514   v8::Handle<v8::Script> script0 =
11515       v8::Script::Compile(source0, v8::String::New("test.js"));
11516   v8::Handle<v8::Script> script1 =
11517       v8::Script::Compile(source1, v8::String::New("test.js"));
11518   v8::Handle<v8::Script> script2 =
11519       v8::Script::Compile(source0);  // different origin
11520   CHECK_EQ(1234, script0->Run()->Int32Value());
11521   CHECK_EQ(1234, script1->Run()->Int32Value());
11522   CHECK_EQ(1234, script2->Run()->Int32Value());
11523 }
11524
11525
11526 static v8::Handle<Value> FunctionNameCallback(const v8::Arguments& args) {
11527   ApiTestFuzzer::Fuzz();
11528   return v8_num(42);
11529 }
11530
11531
11532 THREADED_TEST(CallbackFunctionName) {
11533   v8::HandleScope scope;
11534   LocalContext context;
11535   Local<ObjectTemplate> t = ObjectTemplate::New();
11536   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
11537   context->Global()->Set(v8_str("obj"), t->NewInstance());
11538   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
11539   CHECK(value->IsString());
11540   v8::String::AsciiValue name(value);
11541   CHECK_EQ("asdf", *name);
11542 }
11543
11544
11545 THREADED_TEST(DateAccess) {
11546   v8::HandleScope scope;
11547   LocalContext context;
11548   v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
11549   CHECK(date->IsDate());
11550   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->NumberValue());
11551 }
11552
11553
11554 void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
11555   v8::Handle<v8::Object> obj = val.As<v8::Object>();
11556   v8::Handle<v8::Array> props = obj->GetPropertyNames();
11557   CHECK_EQ(elmc, props->Length());
11558   for (int i = 0; i < elmc; i++) {
11559     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
11560     CHECK_EQ(elmv[i], *elm);
11561   }
11562 }
11563
11564
11565 void CheckOwnProperties(v8::Handle<v8::Value> val,
11566                         int elmc,
11567                         const char* elmv[]) {
11568   v8::Handle<v8::Object> obj = val.As<v8::Object>();
11569   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
11570   CHECK_EQ(elmc, props->Length());
11571   for (int i = 0; i < elmc; i++) {
11572     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
11573     CHECK_EQ(elmv[i], *elm);
11574   }
11575 }
11576
11577
11578 THREADED_TEST(PropertyEnumeration) {
11579   v8::HandleScope scope;
11580   LocalContext context;
11581   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
11582       "var result = [];"
11583       "result[0] = {};"
11584       "result[1] = {a: 1, b: 2};"
11585       "result[2] = [1, 2, 3];"
11586       "var proto = {x: 1, y: 2, z: 3};"
11587       "var x = { __proto__: proto, w: 0, z: 1 };"
11588       "result[3] = x;"
11589       "result;"))->Run();
11590   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
11591   CHECK_EQ(4, elms->Length());
11592   int elmc0 = 0;
11593   const char** elmv0 = NULL;
11594   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
11595   CheckOwnProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
11596   int elmc1 = 2;
11597   const char* elmv1[] = {"a", "b"};
11598   CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
11599   CheckOwnProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
11600   int elmc2 = 3;
11601   const char* elmv2[] = {"0", "1", "2"};
11602   CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
11603   CheckOwnProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
11604   int elmc3 = 4;
11605   const char* elmv3[] = {"w", "z", "x", "y"};
11606   CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
11607   int elmc4 = 2;
11608   const char* elmv4[] = {"w", "z"};
11609   CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4);
11610 }
11611
11612 THREADED_TEST(PropertyEnumeration2) {
11613   v8::HandleScope scope;
11614   LocalContext context;
11615   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
11616       "var result = [];"
11617       "result[0] = {};"
11618       "result[1] = {a: 1, b: 2};"
11619       "result[2] = [1, 2, 3];"
11620       "var proto = {x: 1, y: 2, z: 3};"
11621       "var x = { __proto__: proto, w: 0, z: 1 };"
11622       "result[3] = x;"
11623       "result;"))->Run();
11624   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
11625   CHECK_EQ(4, elms->Length());
11626   int elmc0 = 0;
11627   const char** elmv0 = NULL;
11628   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
11629
11630   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
11631   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
11632   CHECK_EQ(0, props->Length());
11633   for (uint32_t i = 0; i < props->Length(); i++) {
11634     printf("p[%d]\n", i);
11635   }
11636 }
11637
11638 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
11639                                   Local<Value> name,
11640                                   v8::AccessType type,
11641                                   Local<Value> data) {
11642   return type != v8::ACCESS_SET;
11643 }
11644
11645
11646 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
11647                                     uint32_t key,
11648                                     v8::AccessType type,
11649                                     Local<Value> data) {
11650   return type != v8::ACCESS_SET;
11651 }
11652
11653
11654 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
11655   v8::HandleScope scope;
11656   LocalContext context;
11657   Local<ObjectTemplate> templ = ObjectTemplate::New();
11658   templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
11659                                  IndexedSetAccessBlocker);
11660   templ->Set(v8_str("x"), v8::True());
11661   Local<v8::Object> instance = templ->NewInstance();
11662   context->Global()->Set(v8_str("obj"), instance);
11663   Local<Value> value = CompileRun("obj.x");
11664   CHECK(value->BooleanValue());
11665 }
11666
11667
11668 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
11669                                   Local<Value> name,
11670                                   v8::AccessType type,
11671                                   Local<Value> data) {
11672   return false;
11673 }
11674
11675
11676 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
11677                                     uint32_t key,
11678                                     v8::AccessType type,
11679                                     Local<Value> data) {
11680   return false;
11681 }
11682
11683
11684
11685 THREADED_TEST(AccessChecksReenabledCorrectly) {
11686   v8::HandleScope scope;
11687   LocalContext context;
11688   Local<ObjectTemplate> templ = ObjectTemplate::New();
11689   templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
11690                                  IndexedGetAccessBlocker);
11691   templ->Set(v8_str("a"), v8_str("a"));
11692   // Add more than 8 (see kMaxFastProperties) properties
11693   // so that the constructor will force copying map.
11694   // Cannot sprintf, gcc complains unsafety.
11695   char buf[4];
11696   for (char i = '0'; i <= '9' ; i++) {
11697     buf[0] = i;
11698     for (char j = '0'; j <= '9'; j++) {
11699       buf[1] = j;
11700       for (char k = '0'; k <= '9'; k++) {
11701         buf[2] = k;
11702         buf[3] = 0;
11703         templ->Set(v8_str(buf), v8::Number::New(k));
11704       }
11705     }
11706   }
11707
11708   Local<v8::Object> instance_1 = templ->NewInstance();
11709   context->Global()->Set(v8_str("obj_1"), instance_1);
11710
11711   Local<Value> value_1 = CompileRun("obj_1.a");
11712   CHECK(value_1->IsUndefined());
11713
11714   Local<v8::Object> instance_2 = templ->NewInstance();
11715   context->Global()->Set(v8_str("obj_2"), instance_2);
11716
11717   Local<Value> value_2 = CompileRun("obj_2.a");
11718   CHECK(value_2->IsUndefined());
11719 }
11720
11721
11722 // This tests that access check information remains on the global
11723 // object template when creating contexts.
11724 THREADED_TEST(AccessControlRepeatedContextCreation) {
11725   v8::HandleScope handle_scope;
11726   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
11727   global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
11728                                            IndexedSetAccessBlocker);
11729   i::Handle<i::ObjectTemplateInfo> internal_template =
11730       v8::Utils::OpenHandle(*global_template);
11731   CHECK(!internal_template->constructor()->IsUndefined());
11732   i::Handle<i::FunctionTemplateInfo> constructor(
11733       i::FunctionTemplateInfo::cast(internal_template->constructor()));
11734   CHECK(!constructor->access_check_info()->IsUndefined());
11735   v8::Persistent<Context> context0(Context::New(NULL, global_template));
11736   CHECK(!context0.IsEmpty());
11737   CHECK(!constructor->access_check_info()->IsUndefined());
11738 }
11739
11740
11741 THREADED_TEST(TurnOnAccessCheck) {
11742   v8::HandleScope handle_scope;
11743
11744   // Create an environment with access check to the global object disabled by
11745   // default.
11746   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
11747   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
11748                                            IndexedGetAccessBlocker,
11749                                            v8::Handle<v8::Value>(),
11750                                            false);
11751   v8::Persistent<Context> context = Context::New(NULL, global_template);
11752   Context::Scope context_scope(context);
11753
11754   // Set up a property and a number of functions.
11755   context->Global()->Set(v8_str("a"), v8_num(1));
11756   CompileRun("function f1() {return a;}"
11757              "function f2() {return a;}"
11758              "function g1() {return h();}"
11759              "function g2() {return h();}"
11760              "function h() {return 1;}");
11761   Local<Function> f1 =
11762       Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
11763   Local<Function> f2 =
11764       Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
11765   Local<Function> g1 =
11766       Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
11767   Local<Function> g2 =
11768       Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
11769   Local<Function> h =
11770       Local<Function>::Cast(context->Global()->Get(v8_str("h")));
11771
11772   // Get the global object.
11773   v8::Handle<v8::Object> global = context->Global();
11774
11775   // Call f1 one time and f2 a number of times. This will ensure that f1 still
11776   // uses the runtime system to retreive property a whereas f2 uses global load
11777   // inline cache.
11778   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
11779   for (int i = 0; i < 4; i++) {
11780     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
11781   }
11782
11783   // Same for g1 and g2.
11784   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
11785   for (int i = 0; i < 4; i++) {
11786     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
11787   }
11788
11789   // Detach the global and turn on access check.
11790   context->DetachGlobal();
11791   context->Global()->TurnOnAccessCheck();
11792
11793   // Failing access check to property get results in undefined.
11794   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
11795   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
11796
11797   // Failing access check to function call results in exception.
11798   CHECK(g1->Call(global, 0, NULL).IsEmpty());
11799   CHECK(g2->Call(global, 0, NULL).IsEmpty());
11800
11801   // No failing access check when just returning a constant.
11802   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
11803 }
11804
11805
11806 static const char* kPropertyA = "a";
11807 static const char* kPropertyH = "h";
11808
11809 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
11810                                        Local<Value> name,
11811                                        v8::AccessType type,
11812                                        Local<Value> data) {
11813   if (!name->IsString()) return false;
11814   i::Handle<i::String> name_handle =
11815       v8::Utils::OpenHandle(String::Cast(*name));
11816   return !name_handle->IsEqualTo(i::CStrVector(kPropertyA))
11817       && !name_handle->IsEqualTo(i::CStrVector(kPropertyH));
11818 }
11819
11820
11821 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
11822   v8::HandleScope handle_scope;
11823
11824   // Create an environment with access check to the global object disabled by
11825   // default. When the registered access checker will block access to properties
11826   // a and h.
11827   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
11828   global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
11829                                            IndexedGetAccessBlocker,
11830                                            v8::Handle<v8::Value>(),
11831                                            false);
11832   v8::Persistent<Context> context = Context::New(NULL, global_template);
11833   Context::Scope context_scope(context);
11834
11835   // Set up a property and a number of functions.
11836   context->Global()->Set(v8_str("a"), v8_num(1));
11837   static const char* source = "function f1() {return a;}"
11838                               "function f2() {return a;}"
11839                               "function g1() {return h();}"
11840                               "function g2() {return h();}"
11841                               "function h() {return 1;}";
11842
11843   CompileRun(source);
11844   Local<Function> f1;
11845   Local<Function> f2;
11846   Local<Function> g1;
11847   Local<Function> g2;
11848   Local<Function> h;
11849   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
11850   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
11851   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
11852   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
11853   h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
11854
11855   // Get the global object.
11856   v8::Handle<v8::Object> global = context->Global();
11857
11858   // Call f1 one time and f2 a number of times. This will ensure that f1 still
11859   // uses the runtime system to retreive property a whereas f2 uses global load
11860   // inline cache.
11861   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
11862   for (int i = 0; i < 4; i++) {
11863     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
11864   }
11865
11866   // Same for g1 and g2.
11867   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
11868   for (int i = 0; i < 4; i++) {
11869     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
11870   }
11871
11872   // Detach the global and turn on access check now blocking access to property
11873   // a and function h.
11874   context->DetachGlobal();
11875   context->Global()->TurnOnAccessCheck();
11876
11877   // Failing access check to property get results in undefined.
11878   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
11879   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
11880
11881   // Failing access check to function call results in exception.
11882   CHECK(g1->Call(global, 0, NULL).IsEmpty());
11883   CHECK(g2->Call(global, 0, NULL).IsEmpty());
11884
11885   // No failing access check when just returning a constant.
11886   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
11887
11888   // Now compile the source again. And get the newly compiled functions, except
11889   // for h for which access is blocked.
11890   CompileRun(source);
11891   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
11892   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
11893   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
11894   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
11895   CHECK(context->Global()->Get(v8_str("h"))->IsUndefined());
11896
11897   // Failing access check to property get results in undefined.
11898   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
11899   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
11900
11901   // Failing access check to function call results in exception.
11902   CHECK(g1->Call(global, 0, NULL).IsEmpty());
11903   CHECK(g2->Call(global, 0, NULL).IsEmpty());
11904 }
11905
11906
11907 // This test verifies that pre-compilation (aka preparsing) can be called
11908 // without initializing the whole VM. Thus we cannot run this test in a
11909 // multi-threaded setup.
11910 TEST(PreCompile) {
11911   // TODO(155): This test would break without the initialization of V8. This is
11912   // a workaround for now to make this test not fail.
11913   v8::V8::Initialize();
11914   const char* script = "function foo(a) { return a+1; }";
11915   v8::ScriptData* sd =
11916       v8::ScriptData::PreCompile(script, i::StrLength(script));
11917   CHECK_NE(sd->Length(), 0);
11918   CHECK_NE(sd->Data(), NULL);
11919   CHECK(!sd->HasError());
11920   delete sd;
11921 }
11922
11923
11924 TEST(PreCompileWithError) {
11925   v8::V8::Initialize();
11926   const char* script = "function foo(a) { return 1 * * 2; }";
11927   v8::ScriptData* sd =
11928       v8::ScriptData::PreCompile(script, i::StrLength(script));
11929   CHECK(sd->HasError());
11930   delete sd;
11931 }
11932
11933
11934 TEST(Regress31661) {
11935   v8::V8::Initialize();
11936   const char* script = " The Definintive Guide";
11937   v8::ScriptData* sd =
11938       v8::ScriptData::PreCompile(script, i::StrLength(script));
11939   CHECK(sd->HasError());
11940   delete sd;
11941 }
11942
11943
11944 // Tests that ScriptData can be serialized and deserialized.
11945 TEST(PreCompileSerialization) {
11946   v8::V8::Initialize();
11947   const char* script = "function foo(a) { return a+1; }";
11948   v8::ScriptData* sd =
11949       v8::ScriptData::PreCompile(script, i::StrLength(script));
11950
11951   // Serialize.
11952   int serialized_data_length = sd->Length();
11953   char* serialized_data = i::NewArray<char>(serialized_data_length);
11954   memcpy(serialized_data, sd->Data(), serialized_data_length);
11955
11956   // Deserialize.
11957   v8::ScriptData* deserialized_sd =
11958       v8::ScriptData::New(serialized_data, serialized_data_length);
11959
11960   // Verify that the original is the same as the deserialized.
11961   CHECK_EQ(sd->Length(), deserialized_sd->Length());
11962   CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
11963   CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
11964
11965   delete sd;
11966   delete deserialized_sd;
11967 }
11968
11969
11970 // Attempts to deserialize bad data.
11971 TEST(PreCompileDeserializationError) {
11972   v8::V8::Initialize();
11973   const char* data = "DONT CARE";
11974   int invalid_size = 3;
11975   v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
11976
11977   CHECK_EQ(0, sd->Length());
11978
11979   delete sd;
11980 }
11981
11982
11983 // Attempts to deserialize bad data.
11984 TEST(PreCompileInvalidPreparseDataError) {
11985   v8::V8::Initialize();
11986   v8::HandleScope scope;
11987   LocalContext context;
11988
11989   const char* script = "function foo(){ return 5;}\n"
11990       "function bar(){ return 6 + 7;}  foo();";
11991   v8::ScriptData* sd =
11992       v8::ScriptData::PreCompile(script, i::StrLength(script));
11993   CHECK(!sd->HasError());
11994   // ScriptDataImpl private implementation details
11995   const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
11996   const int kFunctionEntrySize = i::FunctionEntry::kSize;
11997   const int kFunctionEntryStartOffset = 0;
11998   const int kFunctionEntryEndOffset = 1;
11999   unsigned* sd_data =
12000       reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
12001
12002   // Overwrite function bar's end position with 0.
12003   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
12004   v8::TryCatch try_catch;
12005
12006   Local<String> source = String::New(script);
12007   Local<Script> compiled_script = Script::New(source, NULL, sd);
12008   CHECK(try_catch.HasCaught());
12009   String::AsciiValue exception_value(try_catch.Message()->Get());
12010   CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
12011            *exception_value);
12012
12013   try_catch.Reset();
12014
12015   // Overwrite function bar's start position with 200.  The function entry
12016   // will not be found when searching for it by position and we should fall
12017   // back on eager compilation.
12018   sd = v8::ScriptData::PreCompile(script, i::StrLength(script));
12019   sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
12020   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
12021       200;
12022   compiled_script = Script::New(source, NULL, sd);
12023   CHECK(!try_catch.HasCaught());
12024
12025   delete sd;
12026 }
12027
12028
12029 // Verifies that the Handle<String> and const char* versions of the API produce
12030 // the same results (at least for one trivial case).
12031 TEST(PreCompileAPIVariationsAreSame) {
12032   v8::V8::Initialize();
12033   v8::HandleScope scope;
12034
12035   const char* cstring = "function foo(a) { return a+1; }";
12036
12037   v8::ScriptData* sd_from_cstring =
12038       v8::ScriptData::PreCompile(cstring, i::StrLength(cstring));
12039
12040   TestAsciiResource* resource = new TestAsciiResource(cstring);
12041   v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
12042       v8::String::NewExternal(resource));
12043
12044   v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
12045       v8::String::New(cstring));
12046
12047   CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
12048   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
12049                      sd_from_external_string->Data(),
12050                      sd_from_cstring->Length()));
12051
12052   CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
12053   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
12054                      sd_from_string->Data(),
12055                      sd_from_cstring->Length()));
12056
12057
12058   delete sd_from_cstring;
12059   delete sd_from_external_string;
12060   delete sd_from_string;
12061 }
12062
12063
12064 // This tests that we do not allow dictionary load/call inline caches
12065 // to use functions that have not yet been compiled.  The potential
12066 // problem of loading a function that has not yet been compiled can
12067 // arise because we share code between contexts via the compilation
12068 // cache.
12069 THREADED_TEST(DictionaryICLoadedFunction) {
12070   v8::HandleScope scope;
12071   // Test LoadIC.
12072   for (int i = 0; i < 2; i++) {
12073     LocalContext context;
12074     context->Global()->Set(v8_str("tmp"), v8::True());
12075     context->Global()->Delete(v8_str("tmp"));
12076     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
12077   }
12078   // Test CallIC.
12079   for (int i = 0; i < 2; i++) {
12080     LocalContext context;
12081     context->Global()->Set(v8_str("tmp"), v8::True());
12082     context->Global()->Delete(v8_str("tmp"));
12083     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
12084   }
12085 }
12086
12087
12088 // Test that cross-context new calls use the context of the callee to
12089 // create the new JavaScript object.
12090 THREADED_TEST(CrossContextNew) {
12091   v8::HandleScope scope;
12092   v8::Persistent<Context> context0 = Context::New();
12093   v8::Persistent<Context> context1 = Context::New();
12094
12095   // Allow cross-domain access.
12096   Local<String> token = v8_str("<security token>");
12097   context0->SetSecurityToken(token);
12098   context1->SetSecurityToken(token);
12099
12100   // Set an 'x' property on the Object prototype and define a
12101   // constructor function in context0.
12102   context0->Enter();
12103   CompileRun("Object.prototype.x = 42; function C() {};");
12104   context0->Exit();
12105
12106   // Call the constructor function from context0 and check that the
12107   // result has the 'x' property.
12108   context1->Enter();
12109   context1->Global()->Set(v8_str("other"), context0->Global());
12110   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
12111   CHECK(value->IsInt32());
12112   CHECK_EQ(42, value->Int32Value());
12113   context1->Exit();
12114
12115   // Dispose the contexts to allow them to be garbage collected.
12116   context0.Dispose();
12117   context1.Dispose();
12118 }
12119
12120
12121 class RegExpInterruptTest {
12122  public:
12123   RegExpInterruptTest() : block_(NULL) {}
12124   ~RegExpInterruptTest() { delete block_; }
12125   void RunTest() {
12126     block_ = i::OS::CreateSemaphore(0);
12127     gc_count_ = 0;
12128     gc_during_regexp_ = 0;
12129     regexp_success_ = false;
12130     gc_success_ = false;
12131     GCThread gc_thread(this);
12132     gc_thread.Start();
12133     v8::Locker::StartPreemption(1);
12134
12135     LongRunningRegExp();
12136     {
12137       v8::Unlocker unlock;
12138       gc_thread.Join();
12139     }
12140     v8::Locker::StopPreemption();
12141     CHECK(regexp_success_);
12142     CHECK(gc_success_);
12143   }
12144
12145  private:
12146   // Number of garbage collections required.
12147   static const int kRequiredGCs = 5;
12148
12149   class GCThread : public i::Thread {
12150    public:
12151     explicit GCThread(RegExpInterruptTest* test)
12152         : Thread("GCThread"), test_(test) {}
12153     virtual void Run() {
12154       test_->CollectGarbage();
12155     }
12156    private:
12157      RegExpInterruptTest* test_;
12158   };
12159
12160   void CollectGarbage() {
12161     block_->Wait();
12162     while (gc_during_regexp_ < kRequiredGCs) {
12163       {
12164         v8::Locker lock;
12165         // TODO(lrn): Perhaps create some garbage before collecting.
12166         HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
12167         gc_count_++;
12168       }
12169       i::OS::Sleep(1);
12170     }
12171     gc_success_ = true;
12172   }
12173
12174   void LongRunningRegExp() {
12175     block_->Signal();  // Enable garbage collection thread on next preemption.
12176     int rounds = 0;
12177     while (gc_during_regexp_ < kRequiredGCs) {
12178       int gc_before = gc_count_;
12179       {
12180         // Match 15-30 "a"'s against 14 and a "b".
12181         const char* c_source =
12182             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
12183             ".exec('aaaaaaaaaaaaaaab') === null";
12184         Local<String> source = String::New(c_source);
12185         Local<Script> script = Script::Compile(source);
12186         Local<Value> result = script->Run();
12187         if (!result->BooleanValue()) {
12188           gc_during_regexp_ = kRequiredGCs;  // Allow gc thread to exit.
12189           return;
12190         }
12191       }
12192       {
12193         // Match 15-30 "a"'s against 15 and a "b".
12194         const char* c_source =
12195             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
12196             ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
12197         Local<String> source = String::New(c_source);
12198         Local<Script> script = Script::Compile(source);
12199         Local<Value> result = script->Run();
12200         if (!result->BooleanValue()) {
12201           gc_during_regexp_ = kRequiredGCs;
12202           return;
12203         }
12204       }
12205       int gc_after = gc_count_;
12206       gc_during_regexp_ += gc_after - gc_before;
12207       rounds++;
12208       i::OS::Sleep(1);
12209     }
12210     regexp_success_ = true;
12211   }
12212
12213   i::Semaphore* block_;
12214   int gc_count_;
12215   int gc_during_regexp_;
12216   bool regexp_success_;
12217   bool gc_success_;
12218 };
12219
12220
12221 // Test that a regular expression execution can be interrupted and
12222 // survive a garbage collection.
12223 TEST(RegExpInterruption) {
12224   v8::Locker lock;
12225   v8::V8::Initialize();
12226   v8::HandleScope scope;
12227   Local<Context> local_env;
12228   {
12229     LocalContext env;
12230     local_env = env.local();
12231   }
12232
12233   // Local context should still be live.
12234   CHECK(!local_env.IsEmpty());
12235   local_env->Enter();
12236
12237   // Should complete without problems.
12238   RegExpInterruptTest().RunTest();
12239
12240   local_env->Exit();
12241 }
12242
12243
12244 class ApplyInterruptTest {
12245  public:
12246   ApplyInterruptTest() : block_(NULL) {}
12247   ~ApplyInterruptTest() { delete block_; }
12248   void RunTest() {
12249     block_ = i::OS::CreateSemaphore(0);
12250     gc_count_ = 0;
12251     gc_during_apply_ = 0;
12252     apply_success_ = false;
12253     gc_success_ = false;
12254     GCThread gc_thread(this);
12255     gc_thread.Start();
12256     v8::Locker::StartPreemption(1);
12257
12258     LongRunningApply();
12259     {
12260       v8::Unlocker unlock;
12261       gc_thread.Join();
12262     }
12263     v8::Locker::StopPreemption();
12264     CHECK(apply_success_);
12265     CHECK(gc_success_);
12266   }
12267
12268  private:
12269   // Number of garbage collections required.
12270   static const int kRequiredGCs = 2;
12271
12272   class GCThread : public i::Thread {
12273    public:
12274     explicit GCThread(ApplyInterruptTest* test)
12275         : Thread("GCThread"), test_(test) {}
12276     virtual void Run() {
12277       test_->CollectGarbage();
12278     }
12279    private:
12280      ApplyInterruptTest* test_;
12281   };
12282
12283   void CollectGarbage() {
12284     block_->Wait();
12285     while (gc_during_apply_ < kRequiredGCs) {
12286       {
12287         v8::Locker lock;
12288         HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
12289         gc_count_++;
12290       }
12291       i::OS::Sleep(1);
12292     }
12293     gc_success_ = true;
12294   }
12295
12296   void LongRunningApply() {
12297     block_->Signal();
12298     int rounds = 0;
12299     while (gc_during_apply_ < kRequiredGCs) {
12300       int gc_before = gc_count_;
12301       {
12302         const char* c_source =
12303             "function do_very_little(bar) {"
12304             "  this.foo = bar;"
12305             "}"
12306             "for (var i = 0; i < 100000; i++) {"
12307             "  do_very_little.apply(this, ['bar']);"
12308             "}";
12309         Local<String> source = String::New(c_source);
12310         Local<Script> script = Script::Compile(source);
12311         Local<Value> result = script->Run();
12312         // Check that no exception was thrown.
12313         CHECK(!result.IsEmpty());
12314       }
12315       int gc_after = gc_count_;
12316       gc_during_apply_ += gc_after - gc_before;
12317       rounds++;
12318     }
12319     apply_success_ = true;
12320   }
12321
12322   i::Semaphore* block_;
12323   int gc_count_;
12324   int gc_during_apply_;
12325   bool apply_success_;
12326   bool gc_success_;
12327 };
12328
12329
12330 // Test that nothing bad happens if we get a preemption just when we were
12331 // about to do an apply().
12332 TEST(ApplyInterruption) {
12333   v8::Locker lock;
12334   v8::V8::Initialize();
12335   v8::HandleScope scope;
12336   Local<Context> local_env;
12337   {
12338     LocalContext env;
12339     local_env = env.local();
12340   }
12341
12342   // Local context should still be live.
12343   CHECK(!local_env.IsEmpty());
12344   local_env->Enter();
12345
12346   // Should complete without problems.
12347   ApplyInterruptTest().RunTest();
12348
12349   local_env->Exit();
12350 }
12351
12352
12353 // Verify that we can clone an object
12354 TEST(ObjectClone) {
12355   v8::HandleScope scope;
12356   LocalContext env;
12357
12358   const char* sample =
12359     "var rv = {};"      \
12360     "rv.alpha = 'hello';" \
12361     "rv.beta = 123;"     \
12362     "rv;";
12363
12364   // Create an object, verify basics.
12365   Local<Value> val = CompileRun(sample);
12366   CHECK(val->IsObject());
12367   Local<v8::Object> obj = val.As<v8::Object>();
12368   obj->Set(v8_str("gamma"), v8_str("cloneme"));
12369
12370   CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
12371   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
12372   CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
12373
12374   // Clone it.
12375   Local<v8::Object> clone = obj->Clone();
12376   CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
12377   CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
12378   CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
12379
12380   // Set a property on the clone, verify each object.
12381   clone->Set(v8_str("beta"), v8::Integer::New(456));
12382   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
12383   CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
12384 }
12385
12386
12387 class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
12388  public:
12389   explicit AsciiVectorResource(i::Vector<const char> vector)
12390       : data_(vector) {}
12391   virtual ~AsciiVectorResource() {}
12392   virtual size_t length() const { return data_.length(); }
12393   virtual const char* data() const { return data_.start(); }
12394  private:
12395   i::Vector<const char> data_;
12396 };
12397
12398
12399 class UC16VectorResource : public v8::String::ExternalStringResource {
12400  public:
12401   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
12402       : data_(vector) {}
12403   virtual ~UC16VectorResource() {}
12404   virtual size_t length() const { return data_.length(); }
12405   virtual const i::uc16* data() const { return data_.start(); }
12406  private:
12407   i::Vector<const i::uc16> data_;
12408 };
12409
12410
12411 static void MorphAString(i::String* string,
12412                          AsciiVectorResource* ascii_resource,
12413                          UC16VectorResource* uc16_resource) {
12414   CHECK(i::StringShape(string).IsExternal());
12415   if (string->IsAsciiRepresentation()) {
12416     // Check old map is not symbol or long.
12417     CHECK(string->map() == HEAP->external_ascii_string_map());
12418     // Morph external string to be TwoByte string.
12419     string->set_map(HEAP->external_string_map());
12420     i::ExternalTwoByteString* morphed =
12421          i::ExternalTwoByteString::cast(string);
12422     morphed->set_resource(uc16_resource);
12423   } else {
12424     // Check old map is not symbol or long.
12425     CHECK(string->map() == HEAP->external_string_map());
12426     // Morph external string to be ASCII string.
12427     string->set_map(HEAP->external_ascii_string_map());
12428     i::ExternalAsciiString* morphed =
12429          i::ExternalAsciiString::cast(string);
12430     morphed->set_resource(ascii_resource);
12431   }
12432 }
12433
12434
12435 // Test that we can still flatten a string if the components it is built up
12436 // from have been turned into 16 bit strings in the mean time.
12437 THREADED_TEST(MorphCompositeStringTest) {
12438   char utf_buffer[129];
12439   const char* c_string = "Now is the time for all good men"
12440                          " to come to the aid of the party";
12441   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
12442   {
12443     v8::HandleScope scope;
12444     LocalContext env;
12445     AsciiVectorResource ascii_resource(
12446         i::Vector<const char>(c_string, i::StrLength(c_string)));
12447     UC16VectorResource uc16_resource(
12448         i::Vector<const uint16_t>(two_byte_string,
12449                                   i::StrLength(c_string)));
12450
12451     Local<String> lhs(v8::Utils::ToLocal(
12452         FACTORY->NewExternalStringFromAscii(&ascii_resource)));
12453     Local<String> rhs(v8::Utils::ToLocal(
12454         FACTORY->NewExternalStringFromAscii(&ascii_resource)));
12455
12456     env->Global()->Set(v8_str("lhs"), lhs);
12457     env->Global()->Set(v8_str("rhs"), rhs);
12458
12459     CompileRun(
12460         "var cons = lhs + rhs;"
12461         "var slice = lhs.substring(1, lhs.length - 1);"
12462         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
12463
12464     CHECK(!lhs->MayContainNonAscii());
12465     CHECK(!rhs->MayContainNonAscii());
12466
12467     MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
12468     MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
12469
12470     // This should UTF-8 without flattening, since everything is ASCII.
12471     Handle<String> cons = v8_compile("cons")->Run().As<String>();
12472     CHECK_EQ(128, cons->Utf8Length());
12473     int nchars = -1;
12474     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
12475     CHECK_EQ(128, nchars);
12476     CHECK_EQ(0, strcmp(
12477         utf_buffer,
12478         "Now is the time for all good men to come to the aid of the party"
12479         "Now is the time for all good men to come to the aid of the party"));
12480
12481     // Now do some stuff to make sure the strings are flattened, etc.
12482     CompileRun(
12483         "/[^a-z]/.test(cons);"
12484         "/[^a-z]/.test(slice);"
12485         "/[^a-z]/.test(slice_on_cons);");
12486     const char* expected_cons =
12487         "Now is the time for all good men to come to the aid of the party"
12488         "Now is the time for all good men to come to the aid of the party";
12489     const char* expected_slice =
12490         "ow is the time for all good men to come to the aid of the part";
12491     const char* expected_slice_on_cons =
12492         "ow is the time for all good men to come to the aid of the party"
12493         "Now is the time for all good men to come to the aid of the part";
12494     CHECK_EQ(String::New(expected_cons),
12495              env->Global()->Get(v8_str("cons")));
12496     CHECK_EQ(String::New(expected_slice),
12497              env->Global()->Get(v8_str("slice")));
12498     CHECK_EQ(String::New(expected_slice_on_cons),
12499              env->Global()->Get(v8_str("slice_on_cons")));
12500   }
12501   i::DeleteArray(two_byte_string);
12502 }
12503
12504
12505 TEST(CompileExternalTwoByteSource) {
12506   v8::HandleScope scope;
12507   LocalContext context;
12508
12509   // This is a very short list of sources, which currently is to check for a
12510   // regression caused by r2703.
12511   const char* ascii_sources[] = {
12512     "0.5",
12513     "-0.5",   // This mainly testes PushBack in the Scanner.
12514     "--0.5",  // This mainly testes PushBack in the Scanner.
12515     NULL
12516   };
12517
12518   // Compile the sources as external two byte strings.
12519   for (int i = 0; ascii_sources[i] != NULL; i++) {
12520     uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
12521     UC16VectorResource uc16_resource(
12522         i::Vector<const uint16_t>(two_byte_string,
12523                                   i::StrLength(ascii_sources[i])));
12524     v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
12525     v8::Script::Compile(source);
12526     i::DeleteArray(two_byte_string);
12527   }
12528 }
12529
12530
12531 class RegExpStringModificationTest {
12532  public:
12533   RegExpStringModificationTest()
12534       : block_(i::OS::CreateSemaphore(0)),
12535         morphs_(0),
12536         morphs_during_regexp_(0),
12537         ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
12538         uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
12539   ~RegExpStringModificationTest() { delete block_; }
12540   void RunTest() {
12541     regexp_success_ = false;
12542     morph_success_ = false;
12543
12544     // Initialize the contents of two_byte_content_ to be a uc16 representation
12545     // of "aaaaaaaaaaaaaab".
12546     for (int i = 0; i < 14; i++) {
12547       two_byte_content_[i] = 'a';
12548     }
12549     two_byte_content_[14] = 'b';
12550
12551     // Create the input string for the regexp - the one we are going to change
12552     // properties of.
12553     input_ = FACTORY->NewExternalStringFromAscii(&ascii_resource_);
12554
12555     // Inject the input as a global variable.
12556     i::Handle<i::String> input_name =
12557         FACTORY->NewStringFromAscii(i::Vector<const char>("input", 5));
12558     i::Isolate::Current()->native_context()->global_object()->SetProperty(
12559         *input_name,
12560         *input_,
12561         NONE,
12562         i::kNonStrictMode)->ToObjectChecked();
12563
12564     MorphThread morph_thread(this);
12565     morph_thread.Start();
12566     v8::Locker::StartPreemption(1);
12567     LongRunningRegExp();
12568     {
12569       v8::Unlocker unlock;
12570       morph_thread.Join();
12571     }
12572     v8::Locker::StopPreemption();
12573     CHECK(regexp_success_);
12574     CHECK(morph_success_);
12575   }
12576
12577  private:
12578   // Number of string modifications required.
12579   static const int kRequiredModifications = 5;
12580   static const int kMaxModifications = 100;
12581
12582   class MorphThread : public i::Thread {
12583    public:
12584     explicit MorphThread(RegExpStringModificationTest* test)
12585         : Thread("MorphThread"), test_(test) {}
12586     virtual void Run() {
12587       test_->MorphString();
12588     }
12589    private:
12590      RegExpStringModificationTest* test_;
12591   };
12592
12593   void MorphString() {
12594     block_->Wait();
12595     while (morphs_during_regexp_ < kRequiredModifications &&
12596            morphs_ < kMaxModifications) {
12597       {
12598         v8::Locker lock;
12599         // Swap string between ascii and two-byte representation.
12600         i::String* string = *input_;
12601         MorphAString(string, &ascii_resource_, &uc16_resource_);
12602         morphs_++;
12603       }
12604       i::OS::Sleep(1);
12605     }
12606     morph_success_ = true;
12607   }
12608
12609   void LongRunningRegExp() {
12610     block_->Signal();  // Enable morphing thread on next preemption.
12611     while (morphs_during_regexp_ < kRequiredModifications &&
12612            morphs_ < kMaxModifications) {
12613       int morphs_before = morphs_;
12614       {
12615         v8::HandleScope scope;
12616         // Match 15-30 "a"'s against 14 and a "b".
12617         const char* c_source =
12618             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
12619             ".exec(input) === null";
12620         Local<String> source = String::New(c_source);
12621         Local<Script> script = Script::Compile(source);
12622         Local<Value> result = script->Run();
12623         CHECK(result->IsTrue());
12624       }
12625       int morphs_after = morphs_;
12626       morphs_during_regexp_ += morphs_after - morphs_before;
12627     }
12628     regexp_success_ = true;
12629   }
12630
12631   i::uc16 two_byte_content_[15];
12632   i::Semaphore* block_;
12633   int morphs_;
12634   int morphs_during_regexp_;
12635   bool regexp_success_;
12636   bool morph_success_;
12637   i::Handle<i::String> input_;
12638   AsciiVectorResource ascii_resource_;
12639   UC16VectorResource uc16_resource_;
12640 };
12641
12642
12643 // Test that a regular expression execution can be interrupted and
12644 // the string changed without failing.
12645 TEST(RegExpStringModification) {
12646   v8::Locker lock;
12647   v8::V8::Initialize();
12648   v8::HandleScope scope;
12649   Local<Context> local_env;
12650   {
12651     LocalContext env;
12652     local_env = env.local();
12653   }
12654
12655   // Local context should still be live.
12656   CHECK(!local_env.IsEmpty());
12657   local_env->Enter();
12658
12659   // Should complete without problems.
12660   RegExpStringModificationTest().RunTest();
12661
12662   local_env->Exit();
12663 }
12664
12665
12666 // Test that we cannot set a property on the global object if there
12667 // is a read-only property in the prototype chain.
12668 TEST(ReadOnlyPropertyInGlobalProto) {
12669   i::FLAG_es5_readonly = true;
12670   v8::HandleScope scope;
12671   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
12672   LocalContext context(0, templ);
12673   v8::Handle<v8::Object> global = context->Global();
12674   v8::Handle<v8::Object> global_proto =
12675       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
12676   global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
12677   global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
12678   // Check without 'eval' or 'with'.
12679   v8::Handle<v8::Value> res =
12680       CompileRun("function f() { x = 42; return x; }; f()");
12681   CHECK_EQ(v8::Integer::New(0), res);
12682   // Check with 'eval'.
12683   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
12684   CHECK_EQ(v8::Integer::New(0), res);
12685   // Check with 'with'.
12686   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
12687   CHECK_EQ(v8::Integer::New(0), res);
12688 }
12689
12690 static int force_set_set_count = 0;
12691 static int force_set_get_count = 0;
12692 bool pass_on_get = false;
12693
12694 static v8::Handle<v8::Value> ForceSetGetter(v8::Local<v8::String> name,
12695                                             const v8::AccessorInfo& info) {
12696   force_set_get_count++;
12697   if (pass_on_get) {
12698     return v8::Handle<v8::Value>();
12699   } else {
12700     return v8::Int32::New(3);
12701   }
12702 }
12703
12704 static void ForceSetSetter(v8::Local<v8::String> name,
12705                            v8::Local<v8::Value> value,
12706                            const v8::AccessorInfo& info) {
12707   force_set_set_count++;
12708 }
12709
12710 static v8::Handle<v8::Value> ForceSetInterceptSetter(
12711     v8::Local<v8::String> name,
12712     v8::Local<v8::Value> value,
12713     const v8::AccessorInfo& info) {
12714   force_set_set_count++;
12715   return v8::Undefined();
12716 }
12717
12718 TEST(ForceSet) {
12719   force_set_get_count = 0;
12720   force_set_set_count = 0;
12721   pass_on_get = false;
12722
12723   v8::HandleScope scope;
12724   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
12725   v8::Handle<v8::String> access_property = v8::String::New("a");
12726   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
12727   LocalContext context(NULL, templ);
12728   v8::Handle<v8::Object> global = context->Global();
12729
12730   // Ordinary properties
12731   v8::Handle<v8::String> simple_property = v8::String::New("p");
12732   global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
12733   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
12734   // This should fail because the property is read-only
12735   global->Set(simple_property, v8::Int32::New(5));
12736   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
12737   // This should succeed even though the property is read-only
12738   global->ForceSet(simple_property, v8::Int32::New(6));
12739   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
12740
12741   // Accessors
12742   CHECK_EQ(0, force_set_set_count);
12743   CHECK_EQ(0, force_set_get_count);
12744   CHECK_EQ(3, global->Get(access_property)->Int32Value());
12745   // CHECK_EQ the property shouldn't override it, just call the setter
12746   // which in this case does nothing.
12747   global->Set(access_property, v8::Int32::New(7));
12748   CHECK_EQ(3, global->Get(access_property)->Int32Value());
12749   CHECK_EQ(1, force_set_set_count);
12750   CHECK_EQ(2, force_set_get_count);
12751   // Forcing the property to be set should override the accessor without
12752   // calling it
12753   global->ForceSet(access_property, v8::Int32::New(8));
12754   CHECK_EQ(8, global->Get(access_property)->Int32Value());
12755   CHECK_EQ(1, force_set_set_count);
12756   CHECK_EQ(2, force_set_get_count);
12757 }
12758
12759 TEST(ForceSetWithInterceptor) {
12760   force_set_get_count = 0;
12761   force_set_set_count = 0;
12762   pass_on_get = false;
12763
12764   v8::HandleScope scope;
12765   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
12766   templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
12767   LocalContext context(NULL, templ);
12768   v8::Handle<v8::Object> global = context->Global();
12769
12770   v8::Handle<v8::String> some_property = v8::String::New("a");
12771   CHECK_EQ(0, force_set_set_count);
12772   CHECK_EQ(0, force_set_get_count);
12773   CHECK_EQ(3, global->Get(some_property)->Int32Value());
12774   // Setting the property shouldn't override it, just call the setter
12775   // which in this case does nothing.
12776   global->Set(some_property, v8::Int32::New(7));
12777   CHECK_EQ(3, global->Get(some_property)->Int32Value());
12778   CHECK_EQ(1, force_set_set_count);
12779   CHECK_EQ(2, force_set_get_count);
12780   // Getting the property when the interceptor returns an empty handle
12781   // should yield undefined, since the property isn't present on the
12782   // object itself yet.
12783   pass_on_get = true;
12784   CHECK(global->Get(some_property)->IsUndefined());
12785   CHECK_EQ(1, force_set_set_count);
12786   CHECK_EQ(3, force_set_get_count);
12787   // Forcing the property to be set should cause the value to be
12788   // set locally without calling the interceptor.
12789   global->ForceSet(some_property, v8::Int32::New(8));
12790   CHECK_EQ(8, global->Get(some_property)->Int32Value());
12791   CHECK_EQ(1, force_set_set_count);
12792   CHECK_EQ(4, force_set_get_count);
12793   // Reenabling the interceptor should cause it to take precedence over
12794   // the property
12795   pass_on_get = false;
12796   CHECK_EQ(3, global->Get(some_property)->Int32Value());
12797   CHECK_EQ(1, force_set_set_count);
12798   CHECK_EQ(5, force_set_get_count);
12799   // The interceptor should also work for other properties
12800   CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
12801   CHECK_EQ(1, force_set_set_count);
12802   CHECK_EQ(6, force_set_get_count);
12803 }
12804
12805
12806 THREADED_TEST(ForceDelete) {
12807   v8::HandleScope scope;
12808   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
12809   LocalContext context(NULL, templ);
12810   v8::Handle<v8::Object> global = context->Global();
12811
12812   // Ordinary properties
12813   v8::Handle<v8::String> simple_property = v8::String::New("p");
12814   global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
12815   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
12816   // This should fail because the property is dont-delete.
12817   CHECK(!global->Delete(simple_property));
12818   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
12819   // This should succeed even though the property is dont-delete.
12820   CHECK(global->ForceDelete(simple_property));
12821   CHECK(global->Get(simple_property)->IsUndefined());
12822 }
12823
12824
12825 static int force_delete_interceptor_count = 0;
12826 static bool pass_on_delete = false;
12827
12828
12829 static v8::Handle<v8::Boolean> ForceDeleteDeleter(
12830     v8::Local<v8::String> name,
12831     const v8::AccessorInfo& info) {
12832   force_delete_interceptor_count++;
12833   if (pass_on_delete) {
12834     return v8::Handle<v8::Boolean>();
12835   } else {
12836     return v8::True();
12837   }
12838 }
12839
12840
12841 THREADED_TEST(ForceDeleteWithInterceptor) {
12842   force_delete_interceptor_count = 0;
12843   pass_on_delete = false;
12844
12845   v8::HandleScope scope;
12846   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
12847   templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
12848   LocalContext context(NULL, templ);
12849   v8::Handle<v8::Object> global = context->Global();
12850
12851   v8::Handle<v8::String> some_property = v8::String::New("a");
12852   global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
12853
12854   // Deleting a property should get intercepted and nothing should
12855   // happen.
12856   CHECK_EQ(0, force_delete_interceptor_count);
12857   CHECK(global->Delete(some_property));
12858   CHECK_EQ(1, force_delete_interceptor_count);
12859   CHECK_EQ(42, global->Get(some_property)->Int32Value());
12860   // Deleting the property when the interceptor returns an empty
12861   // handle should not delete the property since it is DontDelete.
12862   pass_on_delete = true;
12863   CHECK(!global->Delete(some_property));
12864   CHECK_EQ(2, force_delete_interceptor_count);
12865   CHECK_EQ(42, global->Get(some_property)->Int32Value());
12866   // Forcing the property to be deleted should delete the value
12867   // without calling the interceptor.
12868   CHECK(global->ForceDelete(some_property));
12869   CHECK(global->Get(some_property)->IsUndefined());
12870   CHECK_EQ(2, force_delete_interceptor_count);
12871 }
12872
12873
12874 // Make sure that forcing a delete invalidates any IC stubs, so we
12875 // don't read the hole value.
12876 THREADED_TEST(ForceDeleteIC) {
12877   v8::HandleScope scope;
12878   LocalContext context;
12879   // Create a DontDelete variable on the global object.
12880   CompileRun("this.__proto__ = { foo: 'horse' };"
12881              "var foo = 'fish';"
12882              "function f() { return foo.length; }");
12883   // Initialize the IC for foo in f.
12884   CompileRun("for (var i = 0; i < 4; i++) f();");
12885   // Make sure the value of foo is correct before the deletion.
12886   CHECK_EQ(4, CompileRun("f()")->Int32Value());
12887   // Force the deletion of foo.
12888   CHECK(context->Global()->ForceDelete(v8_str("foo")));
12889   // Make sure the value for foo is read from the prototype, and that
12890   // we don't get in trouble with reading the deleted cell value
12891   // sentinel.
12892   CHECK_EQ(5, CompileRun("f()")->Int32Value());
12893 }
12894
12895
12896 TEST(InlinedFunctionAcrossContexts) {
12897   i::FLAG_allow_natives_syntax = true;
12898   v8::HandleScope outer_scope;
12899   v8::Persistent<v8::Context> ctx1 = v8::Context::New();
12900   v8::Persistent<v8::Context> ctx2 = v8::Context::New();
12901   ctx1->Enter();
12902
12903   {
12904     v8::HandleScope inner_scope;
12905     CompileRun("var G = 42; function foo() { return G; }");
12906     v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
12907     ctx2->Enter();
12908     ctx2->Global()->Set(v8_str("o"), foo);
12909     v8::Local<v8::Value> res = CompileRun(
12910         "function f() { return o(); }"
12911         "for (var i = 0; i < 10; ++i) f();"
12912         "%OptimizeFunctionOnNextCall(f);"
12913         "f();");
12914     CHECK_EQ(42, res->Int32Value());
12915     ctx2->Exit();
12916     v8::Handle<v8::String> G_property = v8::String::New("G");
12917     CHECK(ctx1->Global()->ForceDelete(G_property));
12918     ctx2->Enter();
12919     ExpectString(
12920         "(function() {"
12921         "  try {"
12922         "    return f();"
12923         "  } catch(e) {"
12924         "    return e.toString();"
12925         "  }"
12926         " })()",
12927         "ReferenceError: G is not defined");
12928     ctx2->Exit();
12929     ctx1->Exit();
12930     ctx1.Dispose();
12931   }
12932   ctx2.Dispose();
12933 }
12934
12935
12936 v8::Persistent<Context> calling_context0;
12937 v8::Persistent<Context> calling_context1;
12938 v8::Persistent<Context> calling_context2;
12939
12940
12941 // Check that the call to the callback is initiated in
12942 // calling_context2, the directly calling context is calling_context1
12943 // and the callback itself is in calling_context0.
12944 static v8::Handle<Value> GetCallingContextCallback(const v8::Arguments& args) {
12945   ApiTestFuzzer::Fuzz();
12946   CHECK(Context::GetCurrent() == calling_context0);
12947   CHECK(Context::GetCalling() == calling_context1);
12948   CHECK(Context::GetEntered() == calling_context2);
12949   return v8::Integer::New(42);
12950 }
12951
12952
12953 THREADED_TEST(GetCallingContext) {
12954   v8::HandleScope scope;
12955
12956   calling_context0 = Context::New();
12957   calling_context1 = Context::New();
12958   calling_context2 = Context::New();
12959
12960   // Allow cross-domain access.
12961   Local<String> token = v8_str("<security token>");
12962   calling_context0->SetSecurityToken(token);
12963   calling_context1->SetSecurityToken(token);
12964   calling_context2->SetSecurityToken(token);
12965
12966   // Create an object with a C++ callback in context0.
12967   calling_context0->Enter();
12968   Local<v8::FunctionTemplate> callback_templ =
12969       v8::FunctionTemplate::New(GetCallingContextCallback);
12970   calling_context0->Global()->Set(v8_str("callback"),
12971                                   callback_templ->GetFunction());
12972   calling_context0->Exit();
12973
12974   // Expose context0 in context1 and set up a function that calls the
12975   // callback function.
12976   calling_context1->Enter();
12977   calling_context1->Global()->Set(v8_str("context0"),
12978                                   calling_context0->Global());
12979   CompileRun("function f() { context0.callback() }");
12980   calling_context1->Exit();
12981
12982   // Expose context1 in context2 and call the callback function in
12983   // context0 indirectly through f in context1.
12984   calling_context2->Enter();
12985   calling_context2->Global()->Set(v8_str("context1"),
12986                                   calling_context1->Global());
12987   CompileRun("context1.f()");
12988   calling_context2->Exit();
12989
12990   // Dispose the contexts to allow them to be garbage collected.
12991   calling_context0.Dispose();
12992   calling_context1.Dispose();
12993   calling_context2.Dispose();
12994   calling_context0.Clear();
12995   calling_context1.Clear();
12996   calling_context2.Clear();
12997 }
12998
12999
13000 // Check that a variable declaration with no explicit initialization
13001 // value does shadow an existing property in the prototype chain.
13002 THREADED_TEST(InitGlobalVarInProtoChain) {
13003   i::FLAG_es52_globals = true;
13004   v8::HandleScope scope;
13005   LocalContext context;
13006   // Introduce a variable in the prototype chain.
13007   CompileRun("__proto__.x = 42");
13008   v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
13009   CHECK(!result->IsUndefined());
13010   CHECK_EQ(43, result->Int32Value());
13011 }
13012
13013
13014 // Regression test for issue 398.
13015 // If a function is added to an object, creating a constant function
13016 // field, and the result is cloned, replacing the constant function on the
13017 // original should not affect the clone.
13018 // See http://code.google.com/p/v8/issues/detail?id=398
13019 THREADED_TEST(ReplaceConstantFunction) {
13020   v8::HandleScope scope;
13021   LocalContext context;
13022   v8::Handle<v8::Object> obj = v8::Object::New();
13023   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
13024   v8::Handle<v8::String> foo_string = v8::String::New("foo");
13025   obj->Set(foo_string, func_templ->GetFunction());
13026   v8::Handle<v8::Object> obj_clone = obj->Clone();
13027   obj_clone->Set(foo_string, v8::String::New("Hello"));
13028   CHECK(!obj->Get(foo_string)->IsUndefined());
13029 }
13030
13031
13032 // Regression test for http://crbug.com/16276.
13033 THREADED_TEST(Regress16276) {
13034   v8::HandleScope scope;
13035   LocalContext context;
13036   // Force the IC in f to be a dictionary load IC.
13037   CompileRun("function f(obj) { return obj.x; }\n"
13038              "var obj = { x: { foo: 42 }, y: 87 };\n"
13039              "var x = obj.x;\n"
13040              "delete obj.y;\n"
13041              "for (var i = 0; i < 5; i++) f(obj);");
13042   // Detach the global object to make 'this' refer directly to the
13043   // global object (not the proxy), and make sure that the dictionary
13044   // load IC doesn't mess up loading directly from the global object.
13045   context->DetachGlobal();
13046   CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
13047 }
13048
13049
13050 THREADED_TEST(PixelArray) {
13051   v8::HandleScope scope;
13052   LocalContext context;
13053   const int kElementCount = 260;
13054   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
13055   i::Handle<i::ExternalPixelArray> pixels =
13056       i::Handle<i::ExternalPixelArray>::cast(
13057           FACTORY->NewExternalArray(kElementCount,
13058                                     v8::kExternalPixelArray,
13059                                     pixel_data));
13060   // Force GC to trigger verification.
13061   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13062   for (int i = 0; i < kElementCount; i++) {
13063     pixels->set(i, i % 256);
13064   }
13065   // Force GC to trigger verification.
13066   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13067   for (int i = 0; i < kElementCount; i++) {
13068     CHECK_EQ(i % 256, pixels->get_scalar(i));
13069     CHECK_EQ(i % 256, pixel_data[i]);
13070   }
13071
13072   v8::Handle<v8::Object> obj = v8::Object::New();
13073   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
13074   // Set the elements to be the pixels.
13075   // jsobj->set_elements(*pixels);
13076   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
13077   CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
13078   obj->Set(v8_str("field"), v8::Int32::New(1503));
13079   context->Global()->Set(v8_str("pixels"), obj);
13080   v8::Handle<v8::Value> result = CompileRun("pixels.field");
13081   CHECK_EQ(1503, result->Int32Value());
13082   result = CompileRun("pixels[1]");
13083   CHECK_EQ(1, result->Int32Value());
13084
13085   result = CompileRun("var sum = 0;"
13086                       "for (var i = 0; i < 8; i++) {"
13087                       "  sum += pixels[i] = pixels[i] = -i;"
13088                       "}"
13089                       "sum;");
13090   CHECK_EQ(-28, result->Int32Value());
13091
13092   result = CompileRun("var sum = 0;"
13093                       "for (var i = 0; i < 8; i++) {"
13094                       "  sum += pixels[i] = pixels[i] = 0;"
13095                       "}"
13096                       "sum;");
13097   CHECK_EQ(0, result->Int32Value());
13098
13099   result = CompileRun("var sum = 0;"
13100                       "for (var i = 0; i < 8; i++) {"
13101                       "  sum += pixels[i] = pixels[i] = 255;"
13102                       "}"
13103                       "sum;");
13104   CHECK_EQ(8 * 255, result->Int32Value());
13105
13106   result = CompileRun("var sum = 0;"
13107                       "for (var i = 0; i < 8; i++) {"
13108                       "  sum += pixels[i] = pixels[i] = 256 + i;"
13109                       "}"
13110                       "sum;");
13111   CHECK_EQ(2076, result->Int32Value());
13112
13113   result = CompileRun("var sum = 0;"
13114                       "for (var i = 0; i < 8; i++) {"
13115                       "  sum += pixels[i] = pixels[i] = i;"
13116                       "}"
13117                       "sum;");
13118   CHECK_EQ(28, result->Int32Value());
13119
13120   result = CompileRun("var sum = 0;"
13121                       "for (var i = 0; i < 8; i++) {"
13122                       "  sum += pixels[i];"
13123                       "}"
13124                       "sum;");
13125   CHECK_EQ(28, result->Int32Value());
13126
13127   i::Handle<i::Smi> value(i::Smi::FromInt(2));
13128   i::Handle<i::Object> no_failure;
13129   no_failure =
13130       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
13131   ASSERT(!no_failure.is_null());
13132   i::USE(no_failure);
13133   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
13134   *value.location() = i::Smi::FromInt(256);
13135   no_failure =
13136       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
13137   ASSERT(!no_failure.is_null());
13138   i::USE(no_failure);
13139   CHECK_EQ(255,
13140            i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
13141   *value.location() = i::Smi::FromInt(-1);
13142   no_failure =
13143       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
13144   ASSERT(!no_failure.is_null());
13145   i::USE(no_failure);
13146   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
13147
13148   result = CompileRun("for (var i = 0; i < 8; i++) {"
13149                       "  pixels[i] = (i * 65) - 109;"
13150                       "}"
13151                       "pixels[1] + pixels[6];");
13152   CHECK_EQ(255, result->Int32Value());
13153   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
13154   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
13155   CHECK_EQ(21,
13156            i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
13157   CHECK_EQ(86,
13158            i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
13159   CHECK_EQ(151,
13160            i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
13161   CHECK_EQ(216,
13162            i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
13163   CHECK_EQ(255,
13164            i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
13165   CHECK_EQ(255,
13166            i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
13167   result = CompileRun("var sum = 0;"
13168                       "for (var i = 0; i < 8; i++) {"
13169                       "  sum += pixels[i];"
13170                       "}"
13171                       "sum;");
13172   CHECK_EQ(984, result->Int32Value());
13173
13174   result = CompileRun("for (var i = 0; i < 8; i++) {"
13175                       "  pixels[i] = (i * 1.1);"
13176                       "}"
13177                       "pixels[1] + pixels[6];");
13178   CHECK_EQ(8, result->Int32Value());
13179   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
13180   CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
13181   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
13182   CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
13183   CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
13184   CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
13185   CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
13186   CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
13187
13188   result = CompileRun("for (var i = 0; i < 8; i++) {"
13189                       "  pixels[7] = undefined;"
13190                       "}"
13191                       "pixels[7];");
13192   CHECK_EQ(0, result->Int32Value());
13193   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
13194
13195   result = CompileRun("for (var i = 0; i < 8; i++) {"
13196                       "  pixels[6] = '2.3';"
13197                       "}"
13198                       "pixels[6];");
13199   CHECK_EQ(2, result->Int32Value());
13200   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
13201
13202   result = CompileRun("for (var i = 0; i < 8; i++) {"
13203                       "  pixels[5] = NaN;"
13204                       "}"
13205                       "pixels[5];");
13206   CHECK_EQ(0, result->Int32Value());
13207   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
13208
13209   result = CompileRun("for (var i = 0; i < 8; i++) {"
13210                       "  pixels[8] = Infinity;"
13211                       "}"
13212                       "pixels[8];");
13213   CHECK_EQ(255, result->Int32Value());
13214   CHECK_EQ(255,
13215            i::Smi::cast(jsobj->GetElement(8)->ToObjectChecked())->value());
13216
13217   result = CompileRun("for (var i = 0; i < 8; i++) {"
13218                       "  pixels[9] = -Infinity;"
13219                       "}"
13220                       "pixels[9];");
13221   CHECK_EQ(0, result->Int32Value());
13222   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9)->ToObjectChecked())->value());
13223
13224   result = CompileRun("pixels[3] = 33;"
13225                       "delete pixels[3];"
13226                       "pixels[3];");
13227   CHECK_EQ(33, result->Int32Value());
13228
13229   result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
13230                       "pixels[2] = 12; pixels[3] = 13;"
13231                       "pixels.__defineGetter__('2',"
13232                       "function() { return 120; });"
13233                       "pixels[2];");
13234   CHECK_EQ(12, result->Int32Value());
13235
13236   result = CompileRun("var js_array = new Array(40);"
13237                       "js_array[0] = 77;"
13238                       "js_array;");
13239   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13240
13241   result = CompileRun("pixels[1] = 23;"
13242                       "pixels.__proto__ = [];"
13243                       "js_array.__proto__ = pixels;"
13244                       "js_array.concat(pixels);");
13245   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13246   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
13247
13248   result = CompileRun("pixels[1] = 23;");
13249   CHECK_EQ(23, result->Int32Value());
13250
13251   // Test for index greater than 255.  Regression test for:
13252   // http://code.google.com/p/chromium/issues/detail?id=26337.
13253   result = CompileRun("pixels[256] = 255;");
13254   CHECK_EQ(255, result->Int32Value());
13255   result = CompileRun("var i = 0;"
13256                       "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
13257                       "i");
13258   CHECK_EQ(255, result->Int32Value());
13259
13260   // Make sure that pixel array ICs recognize when a non-pixel array
13261   // is passed to it.
13262   result = CompileRun("function pa_load(p) {"
13263                       "  var sum = 0;"
13264                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
13265                       "  return sum;"
13266                       "}"
13267                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13268                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
13269                       "just_ints = new Object();"
13270                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13271                       "for (var i = 0; i < 10; ++i) {"
13272                       "  result = pa_load(just_ints);"
13273                       "}"
13274                       "result");
13275   CHECK_EQ(32640, result->Int32Value());
13276
13277   // Make sure that pixel array ICs recognize out-of-bound accesses.
13278   result = CompileRun("function pa_load(p, start) {"
13279                       "  var sum = 0;"
13280                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
13281                       "  return sum;"
13282                       "}"
13283                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13284                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
13285                       "for (var i = 0; i < 10; ++i) {"
13286                       "  result = pa_load(pixels,-10);"
13287                       "}"
13288                       "result");
13289   CHECK_EQ(0, result->Int32Value());
13290
13291   // Make sure that generic ICs properly handles a pixel array.
13292   result = CompileRun("function pa_load(p) {"
13293                       "  var sum = 0;"
13294                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
13295                       "  return sum;"
13296                       "}"
13297                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13298                       "just_ints = new Object();"
13299                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13300                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
13301                       "for (var i = 0; i < 10; ++i) {"
13302                       "  result = pa_load(pixels);"
13303                       "}"
13304                       "result");
13305   CHECK_EQ(32640, result->Int32Value());
13306
13307   // Make sure that generic load ICs recognize out-of-bound accesses in
13308   // pixel arrays.
13309   result = CompileRun("function pa_load(p, start) {"
13310                       "  var sum = 0;"
13311                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
13312                       "  return sum;"
13313                       "}"
13314                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13315                       "just_ints = new Object();"
13316                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13317                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
13318                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
13319                       "for (var i = 0; i < 10; ++i) {"
13320                       "  result = pa_load(pixels,-10);"
13321                       "}"
13322                       "result");
13323   CHECK_EQ(0, result->Int32Value());
13324
13325   // Make sure that generic ICs properly handles other types than pixel
13326   // arrays (that the inlined fast pixel array test leaves the right information
13327   // in the right registers).
13328   result = CompileRun("function pa_load(p) {"
13329                       "  var sum = 0;"
13330                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
13331                       "  return sum;"
13332                       "}"
13333                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13334                       "just_ints = new Object();"
13335                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13336                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
13337                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
13338                       "sparse_array = new Object();"
13339                       "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
13340                       "sparse_array[1000000] = 3;"
13341                       "for (var i = 0; i < 10; ++i) {"
13342                       "  result = pa_load(sparse_array);"
13343                       "}"
13344                       "result");
13345   CHECK_EQ(32640, result->Int32Value());
13346
13347   // Make sure that pixel array store ICs clamp values correctly.
13348   result = CompileRun("function pa_store(p) {"
13349                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
13350                       "}"
13351                       "pa_store(pixels);"
13352                       "var sum = 0;"
13353                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13354                       "sum");
13355   CHECK_EQ(48896, result->Int32Value());
13356
13357   // Make sure that pixel array stores correctly handle accesses outside
13358   // of the pixel array..
13359   result = CompileRun("function pa_store(p,start) {"
13360                       "  for (var j = 0; j < 256; j++) {"
13361                       "    p[j+start] = j * 2;"
13362                       "  }"
13363                       "}"
13364                       "pa_store(pixels,0);"
13365                       "pa_store(pixels,-128);"
13366                       "var sum = 0;"
13367                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13368                       "sum");
13369   CHECK_EQ(65280, result->Int32Value());
13370
13371   // Make sure that the generic store stub correctly handle accesses outside
13372   // of the pixel array..
13373   result = CompileRun("function pa_store(p,start) {"
13374                       "  for (var j = 0; j < 256; j++) {"
13375                       "    p[j+start] = j * 2;"
13376                       "  }"
13377                       "}"
13378                       "pa_store(pixels,0);"
13379                       "just_ints = new Object();"
13380                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13381                       "pa_store(just_ints, 0);"
13382                       "pa_store(pixels,-128);"
13383                       "var sum = 0;"
13384                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13385                       "sum");
13386   CHECK_EQ(65280, result->Int32Value());
13387
13388   // Make sure that the generic keyed store stub clamps pixel array values
13389   // correctly.
13390   result = CompileRun("function pa_store(p) {"
13391                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
13392                       "}"
13393                       "pa_store(pixels);"
13394                       "just_ints = new Object();"
13395                       "pa_store(just_ints);"
13396                       "pa_store(pixels);"
13397                       "var sum = 0;"
13398                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13399                       "sum");
13400   CHECK_EQ(48896, result->Int32Value());
13401
13402   // Make sure that pixel array loads are optimized by crankshaft.
13403   result = CompileRun("function pa_load(p) {"
13404                       "  var sum = 0;"
13405                       "  for (var i=0; i<256; ++i) {"
13406                       "    sum += p[i];"
13407                       "  }"
13408                       "  return sum; "
13409                       "}"
13410                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13411                       "for (var i = 0; i < 5000; ++i) {"
13412                       "  result = pa_load(pixels);"
13413                       "}"
13414                       "result");
13415   CHECK_EQ(32640, result->Int32Value());
13416
13417   // Make sure that pixel array stores are optimized by crankshaft.
13418   result = CompileRun("function pa_init(p) {"
13419                       "for (var i = 0; i < 256; ++i) { p[i] = i; }"
13420                       "}"
13421                       "function pa_load(p) {"
13422                       "  var sum = 0;"
13423                       "  for (var i=0; i<256; ++i) {"
13424                       "    sum += p[i];"
13425                       "  }"
13426                       "  return sum; "
13427                       "}"
13428                       "for (var i = 0; i < 5000; ++i) {"
13429                       "  pa_init(pixels);"
13430                       "}"
13431                       "result = pa_load(pixels);"
13432                       "result");
13433   CHECK_EQ(32640, result->Int32Value());
13434
13435   free(pixel_data);
13436 }
13437
13438
13439 THREADED_TEST(PixelArrayInfo) {
13440   v8::HandleScope scope;
13441   LocalContext context;
13442   for (int size = 0; size < 100; size += 10) {
13443     uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
13444     v8::Handle<v8::Object> obj = v8::Object::New();
13445     obj->SetIndexedPropertiesToPixelData(pixel_data, size);
13446     CHECK(obj->HasIndexedPropertiesInPixelData());
13447     CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
13448     CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
13449     free(pixel_data);
13450   }
13451 }
13452
13453
13454 static v8::Handle<Value> NotHandledIndexedPropertyGetter(
13455     uint32_t index,
13456     const AccessorInfo& info) {
13457   ApiTestFuzzer::Fuzz();
13458   return v8::Handle<Value>();
13459 }
13460
13461
13462 static v8::Handle<Value> NotHandledIndexedPropertySetter(
13463     uint32_t index,
13464     Local<Value> value,
13465     const AccessorInfo& info) {
13466   ApiTestFuzzer::Fuzz();
13467   return v8::Handle<Value>();
13468 }
13469
13470
13471 THREADED_TEST(PixelArrayWithInterceptor) {
13472   v8::HandleScope scope;
13473   LocalContext context;
13474   const int kElementCount = 260;
13475   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
13476   i::Handle<i::ExternalPixelArray> pixels =
13477       i::Handle<i::ExternalPixelArray>::cast(
13478           FACTORY->NewExternalArray(kElementCount,
13479                                     v8::kExternalPixelArray,
13480                                     pixel_data));
13481   for (int i = 0; i < kElementCount; i++) {
13482     pixels->set(i, i % 256);
13483   }
13484   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
13485   templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
13486                                    NotHandledIndexedPropertySetter);
13487   v8::Handle<v8::Object> obj = templ->NewInstance();
13488   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
13489   context->Global()->Set(v8_str("pixels"), obj);
13490   v8::Handle<v8::Value> result = CompileRun("pixels[1]");
13491   CHECK_EQ(1, result->Int32Value());
13492   result = CompileRun("var sum = 0;"
13493                       "for (var i = 0; i < 8; i++) {"
13494                       "  sum += pixels[i] = pixels[i] = -i;"
13495                       "}"
13496                       "sum;");
13497   CHECK_EQ(-28, result->Int32Value());
13498   result = CompileRun("pixels.hasOwnProperty('1')");
13499   CHECK(result->BooleanValue());
13500   free(pixel_data);
13501 }
13502
13503
13504 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
13505   switch (array_type) {
13506     case v8::kExternalByteArray:
13507     case v8::kExternalUnsignedByteArray:
13508     case v8::kExternalPixelArray:
13509       return 1;
13510       break;
13511     case v8::kExternalShortArray:
13512     case v8::kExternalUnsignedShortArray:
13513       return 2;
13514       break;
13515     case v8::kExternalIntArray:
13516     case v8::kExternalUnsignedIntArray:
13517     case v8::kExternalFloatArray:
13518       return 4;
13519       break;
13520     case v8::kExternalDoubleArray:
13521       return 8;
13522       break;
13523     default:
13524       UNREACHABLE();
13525       return -1;
13526   }
13527   UNREACHABLE();
13528   return -1;
13529 }
13530
13531
13532 template <class ExternalArrayClass, class ElementType>
13533 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
13534                                     int64_t low,
13535                                     int64_t high) {
13536   v8::HandleScope scope;
13537   LocalContext context;
13538   const int kElementCount = 40;
13539   int element_size = ExternalArrayElementSize(array_type);
13540   ElementType* array_data =
13541       static_cast<ElementType*>(malloc(kElementCount * element_size));
13542   i::Handle<ExternalArrayClass> array =
13543       i::Handle<ExternalArrayClass>::cast(
13544           FACTORY->NewExternalArray(kElementCount, array_type, array_data));
13545   // Force GC to trigger verification.
13546   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13547   for (int i = 0; i < kElementCount; i++) {
13548     array->set(i, static_cast<ElementType>(i));
13549   }
13550   // Force GC to trigger verification.
13551   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13552   for (int i = 0; i < kElementCount; i++) {
13553     CHECK_EQ(static_cast<int64_t>(i),
13554              static_cast<int64_t>(array->get_scalar(i)));
13555     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
13556   }
13557
13558   v8::Handle<v8::Object> obj = v8::Object::New();
13559   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
13560   // Set the elements to be the external array.
13561   obj->SetIndexedPropertiesToExternalArrayData(array_data,
13562                                                array_type,
13563                                                kElementCount);
13564   CHECK_EQ(
13565       1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
13566   obj->Set(v8_str("field"), v8::Int32::New(1503));
13567   context->Global()->Set(v8_str("ext_array"), obj);
13568   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
13569   CHECK_EQ(1503, result->Int32Value());
13570   result = CompileRun("ext_array[1]");
13571   CHECK_EQ(1, result->Int32Value());
13572
13573   // Check pass through of assigned smis
13574   result = CompileRun("var sum = 0;"
13575                       "for (var i = 0; i < 8; i++) {"
13576                       "  sum += ext_array[i] = ext_array[i] = -i;"
13577                       "}"
13578                       "sum;");
13579   CHECK_EQ(-28, result->Int32Value());
13580
13581   // Check assigned smis
13582   result = CompileRun("for (var i = 0; i < 8; i++) {"
13583                       "  ext_array[i] = i;"
13584                       "}"
13585                       "var sum = 0;"
13586                       "for (var i = 0; i < 8; i++) {"
13587                       "  sum += ext_array[i];"
13588                       "}"
13589                       "sum;");
13590   CHECK_EQ(28, result->Int32Value());
13591
13592   // Check assigned smis in reverse order
13593   result = CompileRun("for (var i = 8; --i >= 0; ) {"
13594                       "  ext_array[i] = i;"
13595                       "}"
13596                       "var sum = 0;"
13597                       "for (var i = 0; i < 8; i++) {"
13598                       "  sum += ext_array[i];"
13599                       "}"
13600                       "sum;");
13601   CHECK_EQ(28, result->Int32Value());
13602
13603   // Check pass through of assigned HeapNumbers
13604   result = CompileRun("var sum = 0;"
13605                       "for (var i = 0; i < 16; i+=2) {"
13606                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
13607                       "}"
13608                       "sum;");
13609   CHECK_EQ(-28, result->Int32Value());
13610
13611   // Check assigned HeapNumbers
13612   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
13613                       "  ext_array[i] = (i * 0.5);"
13614                       "}"
13615                       "var sum = 0;"
13616                       "for (var i = 0; i < 16; i+=2) {"
13617                       "  sum += ext_array[i];"
13618                       "}"
13619                       "sum;");
13620   CHECK_EQ(28, result->Int32Value());
13621
13622   // Check assigned HeapNumbers in reverse order
13623   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
13624                       "  ext_array[i] = (i * 0.5);"
13625                       "}"
13626                       "var sum = 0;"
13627                       "for (var i = 0; i < 16; i+=2) {"
13628                       "  sum += ext_array[i];"
13629                       "}"
13630                       "sum;");
13631   CHECK_EQ(28, result->Int32Value());
13632
13633   i::ScopedVector<char> test_buf(1024);
13634
13635   // Check legal boundary conditions.
13636   // The repeated loads and stores ensure the ICs are exercised.
13637   const char* boundary_program =
13638       "var res = 0;"
13639       "for (var i = 0; i < 16; i++) {"
13640       "  ext_array[i] = %lld;"
13641       "  if (i > 8) {"
13642       "    res = ext_array[i];"
13643       "  }"
13644       "}"
13645       "res;";
13646   i::OS::SNPrintF(test_buf,
13647                   boundary_program,
13648                   low);
13649   result = CompileRun(test_buf.start());
13650   CHECK_EQ(low, result->IntegerValue());
13651
13652   i::OS::SNPrintF(test_buf,
13653                   boundary_program,
13654                   high);
13655   result = CompileRun(test_buf.start());
13656   CHECK_EQ(high, result->IntegerValue());
13657
13658   // Check misprediction of type in IC.
13659   result = CompileRun("var tmp_array = ext_array;"
13660                       "var sum = 0;"
13661                       "for (var i = 0; i < 8; i++) {"
13662                       "  tmp_array[i] = i;"
13663                       "  sum += tmp_array[i];"
13664                       "  if (i == 4) {"
13665                       "    tmp_array = {};"
13666                       "  }"
13667                       "}"
13668                       "sum;");
13669   // Force GC to trigger verification.
13670   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
13671   CHECK_EQ(28, result->Int32Value());
13672
13673   // Make sure out-of-range loads do not throw.
13674   i::OS::SNPrintF(test_buf,
13675                   "var caught_exception = false;"
13676                   "try {"
13677                   "  ext_array[%d];"
13678                   "} catch (e) {"
13679                   "  caught_exception = true;"
13680                   "}"
13681                   "caught_exception;",
13682                   kElementCount);
13683   result = CompileRun(test_buf.start());
13684   CHECK_EQ(false, result->BooleanValue());
13685
13686   // Make sure out-of-range stores do not throw.
13687   i::OS::SNPrintF(test_buf,
13688                   "var caught_exception = false;"
13689                   "try {"
13690                   "  ext_array[%d] = 1;"
13691                   "} catch (e) {"
13692                   "  caught_exception = true;"
13693                   "}"
13694                   "caught_exception;",
13695                   kElementCount);
13696   result = CompileRun(test_buf.start());
13697   CHECK_EQ(false, result->BooleanValue());
13698
13699   // Check other boundary conditions, values and operations.
13700   result = CompileRun("for (var i = 0; i < 8; i++) {"
13701                       "  ext_array[7] = undefined;"
13702                       "}"
13703                       "ext_array[7];");
13704   CHECK_EQ(0, result->Int32Value());
13705   if (array_type == v8::kExternalDoubleArray ||
13706       array_type == v8::kExternalFloatArray) {
13707     CHECK_EQ(
13708         static_cast<int>(i::OS::nan_value()),
13709         static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number()));
13710   } else {
13711     CHECK_EQ(0, static_cast<int>(
13712         jsobj->GetElement(7)->ToObjectChecked()->Number()));
13713   }
13714
13715   result = CompileRun("for (var i = 0; i < 8; i++) {"
13716                       "  ext_array[6] = '2.3';"
13717                       "}"
13718                       "ext_array[6];");
13719   CHECK_EQ(2, result->Int32Value());
13720   CHECK_EQ(
13721       2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number()));
13722
13723   if (array_type != v8::kExternalFloatArray &&
13724       array_type != v8::kExternalDoubleArray) {
13725     // Though the specification doesn't state it, be explicit about
13726     // converting NaNs and +/-Infinity to zero.
13727     result = CompileRun("for (var i = 0; i < 8; i++) {"
13728                         "  ext_array[i] = 5;"
13729                         "}"
13730                         "for (var i = 0; i < 8; i++) {"
13731                         "  ext_array[i] = NaN;"
13732                         "}"
13733                         "ext_array[5];");
13734     CHECK_EQ(0, result->Int32Value());
13735     CHECK_EQ(0,
13736              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
13737
13738     result = CompileRun("for (var i = 0; i < 8; i++) {"
13739                         "  ext_array[i] = 5;"
13740                         "}"
13741                         "for (var i = 0; i < 8; i++) {"
13742                         "  ext_array[i] = Infinity;"
13743                         "}"
13744                         "ext_array[5];");
13745     int expected_value =
13746         (array_type == v8::kExternalPixelArray) ? 255 : 0;
13747     CHECK_EQ(expected_value, result->Int32Value());
13748     CHECK_EQ(expected_value,
13749              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
13750
13751     result = CompileRun("for (var i = 0; i < 8; i++) {"
13752                         "  ext_array[i] = 5;"
13753                         "}"
13754                         "for (var i = 0; i < 8; i++) {"
13755                         "  ext_array[i] = -Infinity;"
13756                         "}"
13757                         "ext_array[5];");
13758     CHECK_EQ(0, result->Int32Value());
13759     CHECK_EQ(0,
13760              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
13761
13762     // Check truncation behavior of integral arrays.
13763     const char* unsigned_data =
13764         "var source_data = [0.6, 10.6];"
13765         "var expected_results = [0, 10];";
13766     const char* signed_data =
13767         "var source_data = [0.6, 10.6, -0.6, -10.6];"
13768         "var expected_results = [0, 10, 0, -10];";
13769     const char* pixel_data =
13770         "var source_data = [0.6, 10.6];"
13771         "var expected_results = [1, 11];";
13772     bool is_unsigned =
13773         (array_type == v8::kExternalUnsignedByteArray ||
13774          array_type == v8::kExternalUnsignedShortArray ||
13775          array_type == v8::kExternalUnsignedIntArray);
13776     bool is_pixel_data = array_type == v8::kExternalPixelArray;
13777
13778     i::OS::SNPrintF(test_buf,
13779                     "%s"
13780                     "var all_passed = true;"
13781                     "for (var i = 0; i < source_data.length; i++) {"
13782                     "  for (var j = 0; j < 8; j++) {"
13783                     "    ext_array[j] = source_data[i];"
13784                     "  }"
13785                     "  all_passed = all_passed &&"
13786                     "               (ext_array[5] == expected_results[i]);"
13787                     "}"
13788                     "all_passed;",
13789                     (is_unsigned ?
13790                          unsigned_data :
13791                          (is_pixel_data ? pixel_data : signed_data)));
13792     result = CompileRun(test_buf.start());
13793     CHECK_EQ(true, result->BooleanValue());
13794   }
13795
13796   for (int i = 0; i < kElementCount; i++) {
13797     array->set(i, static_cast<ElementType>(i));
13798   }
13799   // Test complex assignments
13800   result = CompileRun("function ee_op_test_complex_func(sum) {"
13801                       " for (var i = 0; i < 40; ++i) {"
13802                       "   sum += (ext_array[i] += 1);"
13803                       "   sum += (ext_array[i] -= 1);"
13804                       " } "
13805                       " return sum;"
13806                       "}"
13807                       "sum=0;"
13808                       "for (var i=0;i<10000;++i) {"
13809                       "  sum=ee_op_test_complex_func(sum);"
13810                       "}"
13811                       "sum;");
13812   CHECK_EQ(16000000, result->Int32Value());
13813
13814   // Test count operations
13815   result = CompileRun("function ee_op_test_count_func(sum) {"
13816                       " for (var i = 0; i < 40; ++i) {"
13817                       "   sum += (++ext_array[i]);"
13818                       "   sum += (--ext_array[i]);"
13819                       " } "
13820                       " return sum;"
13821                       "}"
13822                       "sum=0;"
13823                       "for (var i=0;i<10000;++i) {"
13824                       "  sum=ee_op_test_count_func(sum);"
13825                       "}"
13826                       "sum;");
13827   CHECK_EQ(16000000, result->Int32Value());
13828
13829   result = CompileRun("ext_array[3] = 33;"
13830                       "delete ext_array[3];"
13831                       "ext_array[3];");
13832   CHECK_EQ(33, result->Int32Value());
13833
13834   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
13835                       "ext_array[2] = 12; ext_array[3] = 13;"
13836                       "ext_array.__defineGetter__('2',"
13837                       "function() { return 120; });"
13838                       "ext_array[2];");
13839   CHECK_EQ(12, result->Int32Value());
13840
13841   result = CompileRun("var js_array = new Array(40);"
13842                       "js_array[0] = 77;"
13843                       "js_array;");
13844   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13845
13846   result = CompileRun("ext_array[1] = 23;"
13847                       "ext_array.__proto__ = [];"
13848                       "js_array.__proto__ = ext_array;"
13849                       "js_array.concat(ext_array);");
13850   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13851   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
13852
13853   result = CompileRun("ext_array[1] = 23;");
13854   CHECK_EQ(23, result->Int32Value());
13855
13856   // Test more complex manipulations which cause eax to contain values
13857   // that won't be completely overwritten by loads from the arrays.
13858   // This catches bugs in the instructions used for the KeyedLoadIC
13859   // for byte and word types.
13860   {
13861     const int kXSize = 300;
13862     const int kYSize = 300;
13863     const int kLargeElementCount = kXSize * kYSize * 4;
13864     ElementType* large_array_data =
13865         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
13866     v8::Handle<v8::Object> large_obj = v8::Object::New();
13867     // Set the elements to be the external array.
13868     large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
13869                                                        array_type,
13870                                                        kLargeElementCount);
13871     context->Global()->Set(v8_str("large_array"), large_obj);
13872     // Initialize contents of a few rows.
13873     for (int x = 0; x < 300; x++) {
13874       int row = 0;
13875       int offset = row * 300 * 4;
13876       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
13877       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
13878       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
13879       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
13880       row = 150;
13881       offset = row * 300 * 4;
13882       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
13883       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
13884       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
13885       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
13886       row = 298;
13887       offset = row * 300 * 4;
13888       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
13889       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
13890       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
13891       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
13892     }
13893     // The goal of the code below is to make "offset" large enough
13894     // that the computation of the index (which goes into eax) has
13895     // high bits set which will not be overwritten by a byte or short
13896     // load.
13897     result = CompileRun("var failed = false;"
13898                         "var offset = 0;"
13899                         "for (var i = 0; i < 300; i++) {"
13900                         "  if (large_array[4 * i] != 127 ||"
13901                         "      large_array[4 * i + 1] != 0 ||"
13902                         "      large_array[4 * i + 2] != 0 ||"
13903                         "      large_array[4 * i + 3] != 127) {"
13904                         "    failed = true;"
13905                         "  }"
13906                         "}"
13907                         "offset = 150 * 300 * 4;"
13908                         "for (var i = 0; i < 300; i++) {"
13909                         "  if (large_array[offset + 4 * i] != 127 ||"
13910                         "      large_array[offset + 4 * i + 1] != 0 ||"
13911                         "      large_array[offset + 4 * i + 2] != 0 ||"
13912                         "      large_array[offset + 4 * i + 3] != 127) {"
13913                         "    failed = true;"
13914                         "  }"
13915                         "}"
13916                         "offset = 298 * 300 * 4;"
13917                         "for (var i = 0; i < 300; i++) {"
13918                         "  if (large_array[offset + 4 * i] != 127 ||"
13919                         "      large_array[offset + 4 * i + 1] != 0 ||"
13920                         "      large_array[offset + 4 * i + 2] != 0 ||"
13921                         "      large_array[offset + 4 * i + 3] != 127) {"
13922                         "    failed = true;"
13923                         "  }"
13924                         "}"
13925                         "!failed;");
13926     CHECK_EQ(true, result->BooleanValue());
13927     free(large_array_data);
13928   }
13929
13930   // The "" property descriptor is overloaded to store information about
13931   // the external array. Ensure that setting and accessing the "" property
13932   // works (it should overwrite the information cached about the external
13933   // array in the DescriptorArray) in various situations.
13934   result = CompileRun("ext_array[''] = 23; ext_array['']");
13935   CHECK_EQ(23, result->Int32Value());
13936
13937   // Property "" set after the external array is associated with the object.
13938   {
13939     v8::Handle<v8::Object> obj2 = v8::Object::New();
13940     obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
13941     obj2->Set(v8_str(""), v8::Int32::New(1503));
13942     // Set the elements to be the external array.
13943     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
13944                                                   array_type,
13945                                                   kElementCount);
13946     context->Global()->Set(v8_str("ext_array"), obj2);
13947     result = CompileRun("ext_array['']");
13948     CHECK_EQ(1503, result->Int32Value());
13949   }
13950
13951   // Property "" set after the external array is associated with the object.
13952   {
13953     v8::Handle<v8::Object> obj2 = v8::Object::New();
13954     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
13955     // Set the elements to be the external array.
13956     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
13957                                                   array_type,
13958                                                   kElementCount);
13959     obj2->Set(v8_str(""), v8::Int32::New(1503));
13960     context->Global()->Set(v8_str("ext_array"), obj2);
13961     result = CompileRun("ext_array['']");
13962     CHECK_EQ(1503, result->Int32Value());
13963   }
13964
13965   // Should reuse the map from previous test.
13966   {
13967     v8::Handle<v8::Object> obj2 = v8::Object::New();
13968     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
13969     // Set the elements to be the external array. Should re-use the map
13970     // from previous test.
13971     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
13972                                                   array_type,
13973                                                   kElementCount);
13974     context->Global()->Set(v8_str("ext_array"), obj2);
13975     result = CompileRun("ext_array['']");
13976   }
13977
13978   // Property "" is a constant function that shouldn't not be interfered with
13979   // when an external array is set.
13980   {
13981     v8::Handle<v8::Object> obj2 = v8::Object::New();
13982     // Start
13983     obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
13984
13985     // Add a constant function to an object.
13986     context->Global()->Set(v8_str("ext_array"), obj2);
13987     result = CompileRun("ext_array[''] = function() {return 1503;};"
13988                         "ext_array['']();");
13989
13990     // Add an external array transition to the same map that
13991     // has the constant transition.
13992     v8::Handle<v8::Object> obj3 = v8::Object::New();
13993     obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
13994     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
13995                                                   array_type,
13996                                                   kElementCount);
13997     context->Global()->Set(v8_str("ext_array"), obj3);
13998   }
13999
14000   // If a external array transition is in the map, it should get clobbered
14001   // by a constant function.
14002   {
14003     // Add an external array transition.
14004     v8::Handle<v8::Object> obj3 = v8::Object::New();
14005     obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
14006     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
14007                                                   array_type,
14008                                                   kElementCount);
14009
14010     // Add a constant function to the same map that just got an external array
14011     // transition.
14012     v8::Handle<v8::Object> obj2 = v8::Object::New();
14013     obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
14014     context->Global()->Set(v8_str("ext_array"), obj2);
14015     result = CompileRun("ext_array[''] = function() {return 1503;};"
14016                         "ext_array['']();");
14017   }
14018
14019   free(array_data);
14020 }
14021
14022
14023 THREADED_TEST(ExternalByteArray) {
14024   ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
14025       v8::kExternalByteArray,
14026       -128,
14027       127);
14028 }
14029
14030
14031 THREADED_TEST(ExternalUnsignedByteArray) {
14032   ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
14033       v8::kExternalUnsignedByteArray,
14034       0,
14035       255);
14036 }
14037
14038
14039 THREADED_TEST(ExternalPixelArray) {
14040   ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
14041       v8::kExternalPixelArray,
14042       0,
14043       255);
14044 }
14045
14046
14047 THREADED_TEST(ExternalShortArray) {
14048   ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
14049       v8::kExternalShortArray,
14050       -32768,
14051       32767);
14052 }
14053
14054
14055 THREADED_TEST(ExternalUnsignedShortArray) {
14056   ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
14057       v8::kExternalUnsignedShortArray,
14058       0,
14059       65535);
14060 }
14061
14062
14063 THREADED_TEST(ExternalIntArray) {
14064   ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
14065       v8::kExternalIntArray,
14066       INT_MIN,   // -2147483648
14067       INT_MAX);  //  2147483647
14068 }
14069
14070
14071 THREADED_TEST(ExternalUnsignedIntArray) {
14072   ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
14073       v8::kExternalUnsignedIntArray,
14074       0,
14075       UINT_MAX);  // 4294967295
14076 }
14077
14078
14079 THREADED_TEST(ExternalFloatArray) {
14080   ExternalArrayTestHelper<i::ExternalFloatArray, float>(
14081       v8::kExternalFloatArray,
14082       -500,
14083       500);
14084 }
14085
14086
14087 THREADED_TEST(ExternalDoubleArray) {
14088   ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
14089       v8::kExternalDoubleArray,
14090       -500,
14091       500);
14092 }
14093
14094
14095 THREADED_TEST(ExternalArrays) {
14096   TestExternalByteArray();
14097   TestExternalUnsignedByteArray();
14098   TestExternalShortArray();
14099   TestExternalUnsignedShortArray();
14100   TestExternalIntArray();
14101   TestExternalUnsignedIntArray();
14102   TestExternalFloatArray();
14103 }
14104
14105
14106 void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
14107   v8::HandleScope scope;
14108   LocalContext context;
14109   for (int size = 0; size < 100; size += 10) {
14110     int element_size = ExternalArrayElementSize(array_type);
14111     void* external_data = malloc(size * element_size);
14112     v8::Handle<v8::Object> obj = v8::Object::New();
14113     obj->SetIndexedPropertiesToExternalArrayData(
14114         external_data, array_type, size);
14115     CHECK(obj->HasIndexedPropertiesInExternalArrayData());
14116     CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
14117     CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
14118     CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
14119     free(external_data);
14120   }
14121 }
14122
14123
14124 THREADED_TEST(ExternalArrayInfo) {
14125   ExternalArrayInfoTestHelper(v8::kExternalByteArray);
14126   ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
14127   ExternalArrayInfoTestHelper(v8::kExternalShortArray);
14128   ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
14129   ExternalArrayInfoTestHelper(v8::kExternalIntArray);
14130   ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
14131   ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
14132   ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
14133   ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
14134 }
14135
14136
14137 void ExternalArrayLimitTestHelper(v8::ExternalArrayType array_type, int size) {
14138   v8::Handle<v8::Object> obj = v8::Object::New();
14139   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
14140   last_location = last_message = NULL;
14141   obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
14142   CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
14143   CHECK_NE(NULL, last_location);
14144   CHECK_NE(NULL, last_message);
14145 }
14146
14147
14148 TEST(ExternalArrayLimits) {
14149   v8::HandleScope scope;
14150   LocalContext context;
14151   ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0x40000000);
14152   ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0xffffffff);
14153   ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0x40000000);
14154   ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0xffffffff);
14155   ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0x40000000);
14156   ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0xffffffff);
14157   ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0x40000000);
14158   ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0xffffffff);
14159   ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0x40000000);
14160   ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0xffffffff);
14161   ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0x40000000);
14162   ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0xffffffff);
14163   ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0x40000000);
14164   ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0xffffffff);
14165   ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0x40000000);
14166   ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0xffffffff);
14167   ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0x40000000);
14168   ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0xffffffff);
14169 }
14170
14171
14172 THREADED_TEST(ScriptContextDependence) {
14173   v8::HandleScope scope;
14174   LocalContext c1;
14175   const char *source = "foo";
14176   v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
14177   v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
14178   c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
14179   CHECK_EQ(dep->Run()->Int32Value(), 100);
14180   CHECK_EQ(indep->Run()->Int32Value(), 100);
14181   LocalContext c2;
14182   c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
14183   CHECK_EQ(dep->Run()->Int32Value(), 100);
14184   CHECK_EQ(indep->Run()->Int32Value(), 101);
14185 }
14186
14187
14188 THREADED_TEST(StackTrace) {
14189   v8::HandleScope scope;
14190   LocalContext context;
14191   v8::TryCatch try_catch;
14192   const char *source = "function foo() { FAIL.FAIL; }; foo();";
14193   v8::Handle<v8::String> src = v8::String::New(source);
14194   v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
14195   v8::Script::New(src, origin)->Run();
14196   CHECK(try_catch.HasCaught());
14197   v8::String::Utf8Value stack(try_catch.StackTrace());
14198   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
14199 }
14200
14201
14202 // Checks that a StackFrame has certain expected values.
14203 void checkStackFrame(const char* expected_script_name,
14204     const char* expected_func_name, int expected_line_number,
14205     int expected_column, bool is_eval, bool is_constructor,
14206     v8::Handle<v8::StackFrame> frame) {
14207   v8::HandleScope scope;
14208   v8::String::Utf8Value func_name(frame->GetFunctionName());
14209   v8::String::Utf8Value script_name(frame->GetScriptName());
14210   if (*script_name == NULL) {
14211     // The situation where there is no associated script, like for evals.
14212     CHECK(expected_script_name == NULL);
14213   } else {
14214     CHECK(strstr(*script_name, expected_script_name) != NULL);
14215   }
14216   CHECK(strstr(*func_name, expected_func_name) != NULL);
14217   CHECK_EQ(expected_line_number, frame->GetLineNumber());
14218   CHECK_EQ(expected_column, frame->GetColumn());
14219   CHECK_EQ(is_eval, frame->IsEval());
14220   CHECK_EQ(is_constructor, frame->IsConstructor());
14221 }
14222
14223
14224 v8::Handle<Value> AnalyzeStackInNativeCode(const v8::Arguments& args) {
14225   v8::HandleScope scope;
14226   const char* origin = "capture-stack-trace-test";
14227   const int kOverviewTest = 1;
14228   const int kDetailedTest = 2;
14229
14230   ASSERT(args.Length() == 1);
14231
14232   int testGroup = args[0]->Int32Value();
14233   if (testGroup == kOverviewTest) {
14234     v8::Handle<v8::StackTrace> stackTrace =
14235         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
14236     CHECK_EQ(4, stackTrace->GetFrameCount());
14237     checkStackFrame(origin, "bar", 2, 10, false, false,
14238                     stackTrace->GetFrame(0));
14239     checkStackFrame(origin, "foo", 6, 3, false, false,
14240                     stackTrace->GetFrame(1));
14241     // This is the source string inside the eval which has the call to foo.
14242     checkStackFrame(NULL, "", 1, 5, false, false,
14243                     stackTrace->GetFrame(2));
14244     // The last frame is an anonymous function which has the initial eval call.
14245     checkStackFrame(origin, "", 8, 7, false, false,
14246                     stackTrace->GetFrame(3));
14247
14248     CHECK(stackTrace->AsArray()->IsArray());
14249   } else if (testGroup == kDetailedTest) {
14250     v8::Handle<v8::StackTrace> stackTrace =
14251         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
14252     CHECK_EQ(4, stackTrace->GetFrameCount());
14253     checkStackFrame(origin, "bat", 4, 22, false, false,
14254                     stackTrace->GetFrame(0));
14255     checkStackFrame(origin, "baz", 8, 3, false, true,
14256                     stackTrace->GetFrame(1));
14257 #ifdef ENABLE_DEBUGGER_SUPPORT
14258     bool is_eval = true;
14259 #else  // ENABLE_DEBUGGER_SUPPORT
14260     bool is_eval = false;
14261 #endif  // ENABLE_DEBUGGER_SUPPORT
14262
14263     // This is the source string inside the eval which has the call to baz.
14264     checkStackFrame(NULL, "", 1, 5, is_eval, false,
14265                     stackTrace->GetFrame(2));
14266     // The last frame is an anonymous function which has the initial eval call.
14267     checkStackFrame(origin, "", 10, 1, false, false,
14268                     stackTrace->GetFrame(3));
14269
14270     CHECK(stackTrace->AsArray()->IsArray());
14271   }
14272   return v8::Undefined();
14273 }
14274
14275
14276 // Tests the C++ StackTrace API.
14277 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
14278 // THREADED_TEST(CaptureStackTrace) {
14279 TEST(CaptureStackTrace) {
14280   v8::HandleScope scope;
14281   v8::Handle<v8::String> origin = v8::String::New("capture-stack-trace-test");
14282   Local<ObjectTemplate> templ = ObjectTemplate::New();
14283   templ->Set(v8_str("AnalyzeStackInNativeCode"),
14284              v8::FunctionTemplate::New(AnalyzeStackInNativeCode));
14285   LocalContext context(0, templ);
14286
14287   // Test getting OVERVIEW information. Should ignore information that is not
14288   // script name, function name, line number, and column offset.
14289   const char *overview_source =
14290     "function bar() {\n"
14291     "  var y; AnalyzeStackInNativeCode(1);\n"
14292     "}\n"
14293     "function foo() {\n"
14294     "\n"
14295     "  bar();\n"
14296     "}\n"
14297     "var x;eval('new foo();');";
14298   v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
14299   v8::Handle<Value> overview_result(
14300       v8::Script::New(overview_src, origin)->Run());
14301   CHECK(!overview_result.IsEmpty());
14302   CHECK(overview_result->IsObject());
14303
14304   // Test getting DETAILED information.
14305   const char *detailed_source =
14306     "function bat() {AnalyzeStackInNativeCode(2);\n"
14307     "}\n"
14308     "\n"
14309     "function baz() {\n"
14310     "  bat();\n"
14311     "}\n"
14312     "eval('new baz();');";
14313   v8::Handle<v8::String> detailed_src = v8::String::New(detailed_source);
14314   // Make the script using a non-zero line and column offset.
14315   v8::Handle<v8::Integer> line_offset = v8::Integer::New(3);
14316   v8::Handle<v8::Integer> column_offset = v8::Integer::New(5);
14317   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
14318   v8::Handle<v8::Script> detailed_script(
14319       v8::Script::New(detailed_src, &detailed_origin));
14320   v8::Handle<Value> detailed_result(detailed_script->Run());
14321   CHECK(!detailed_result.IsEmpty());
14322   CHECK(detailed_result->IsObject());
14323 }
14324
14325
14326 static void StackTraceForUncaughtExceptionListener(
14327     v8::Handle<v8::Message> message,
14328     v8::Handle<Value>) {
14329   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14330   CHECK_EQ(2, stack_trace->GetFrameCount());
14331   checkStackFrame("origin", "foo", 2, 3, false, false,
14332                   stack_trace->GetFrame(0));
14333   checkStackFrame("origin", "bar", 5, 3, false, false,
14334                   stack_trace->GetFrame(1));
14335 }
14336
14337 TEST(CaptureStackTraceForUncaughtException) {
14338   report_count = 0;
14339   v8::HandleScope scope;
14340   LocalContext env;
14341   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
14342   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14343
14344   Script::Compile(v8_str("function foo() {\n"
14345                          "  throw 1;\n"
14346                          "};\n"
14347                          "function bar() {\n"
14348                          "  foo();\n"
14349                          "};"),
14350                   v8_str("origin"))->Run();
14351   v8::Local<v8::Object> global = env->Global();
14352   Local<Value> trouble = global->Get(v8_str("bar"));
14353   CHECK(trouble->IsFunction());
14354   Function::Cast(*trouble)->Call(global, 0, NULL);
14355   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14356   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
14357 }
14358
14359
14360 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
14361   v8::HandleScope scope;
14362   LocalContext env;
14363   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
14364                                                     1024,
14365                                                     v8::StackTrace::kDetailed);
14366
14367   CompileRun(
14368       "var setters = ['column', 'lineNumber', 'scriptName',\n"
14369       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
14370       "    'isConstructor'];\n"
14371       "for (var i = 0; i < setters.length; i++) {\n"
14372       "  var prop = setters[i];\n"
14373       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
14374       "}\n");
14375   CompileRun("throw 'exception';");
14376   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14377 }
14378
14379
14380 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
14381                                      v8::Handle<v8::Value> data) {
14382   // Use the frame where JavaScript is called from.
14383   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14384   CHECK(!stack_trace.IsEmpty());
14385   int frame_count = stack_trace->GetFrameCount();
14386   CHECK_EQ(3, frame_count);
14387   int line_number[] = {1, 2, 5};
14388   for (int i = 0; i < frame_count; i++) {
14389     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14390   }
14391 }
14392
14393
14394 // Test that we only return the stack trace at the site where the exception
14395 // is first thrown (not where it is rethrown).
14396 TEST(RethrowStackTrace) {
14397   v8::HandleScope scope;
14398   LocalContext env;
14399   // We make sure that
14400   // - the stack trace of the ReferenceError in g() is reported.
14401   // - the stack trace is not overwritten when e1 is rethrown by t().
14402   // - the stack trace of e2 does not overwrite that of e1.
14403   const char* source =
14404       "function g() { error; }          \n"
14405       "function f() { g(); }            \n"
14406       "function t(e) { throw e; }       \n"
14407       "try {                            \n"
14408       "  f();                           \n"
14409       "} catch (e1) {                   \n"
14410       "  try {                          \n"
14411       "    error;                       \n"
14412       "  } catch (e2) {                 \n"
14413       "    t(e1);                       \n"
14414       "  }                              \n"
14415       "}                                \n";
14416   v8::V8::AddMessageListener(RethrowStackTraceHandler);
14417   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14418   CompileRun(source);
14419   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14420   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
14421 }
14422
14423
14424 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
14425                                               v8::Handle<v8::Value> data) {
14426   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14427   CHECK(!stack_trace.IsEmpty());
14428   int frame_count = stack_trace->GetFrameCount();
14429   CHECK_EQ(2, frame_count);
14430   int line_number[] = {3, 7};
14431   for (int i = 0; i < frame_count; i++) {
14432     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14433   }
14434 }
14435
14436
14437 // Test that we do not recognize identity for primitive exceptions.
14438 TEST(RethrowPrimitiveStackTrace) {
14439   v8::HandleScope scope;
14440   LocalContext env;
14441   // We do not capture stack trace for non Error objects on creation time.
14442   // Instead, we capture the stack trace on last throw.
14443   const char* source =
14444       "function g() { throw 404; }      \n"
14445       "function f() { g(); }            \n"
14446       "function t(e) { throw e; }       \n"
14447       "try {                            \n"
14448       "  f();                           \n"
14449       "} catch (e1) {                   \n"
14450       "  t(e1)                          \n"
14451       "}                                \n";
14452   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
14453   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14454   CompileRun(source);
14455   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14456   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
14457 }
14458
14459
14460 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
14461                                               v8::Handle<v8::Value> data) {
14462   // Use the frame where JavaScript is called from.
14463   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14464   CHECK(!stack_trace.IsEmpty());
14465   CHECK_EQ(1, stack_trace->GetFrameCount());
14466   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
14467 }
14468
14469
14470 // Test that the stack trace is captured when the error object is created and
14471 // not where it is thrown.
14472 TEST(RethrowExistingStackTrace) {
14473   v8::HandleScope scope;
14474   LocalContext env;
14475   const char* source =
14476       "var e = new Error();           \n"
14477       "throw e;                       \n";
14478   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
14479   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14480   CompileRun(source);
14481   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14482   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
14483 }
14484
14485
14486 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
14487                                                v8::Handle<v8::Value> data) {
14488   // Use the frame where JavaScript is called from.
14489   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14490   CHECK(!stack_trace.IsEmpty());
14491   CHECK_EQ(1, stack_trace->GetFrameCount());
14492   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
14493 }
14494
14495
14496 // Test that the stack trace is captured where the bogus Error object is thrown.
14497 TEST(RethrowBogusErrorStackTrace) {
14498   v8::HandleScope scope;
14499   LocalContext env;
14500   const char* source =
14501       "var e = {__proto__: new Error()} \n"
14502       "throw e;                         \n";
14503   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
14504   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14505   CompileRun(source);
14506   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14507   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
14508 }
14509
14510
14511 v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) {
14512   v8::HandleScope scope;
14513   v8::Handle<v8::StackTrace> stackTrace =
14514       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
14515   CHECK_EQ(5, stackTrace->GetFrameCount());
14516   v8::Handle<v8::String> url = v8_str("eval_url");
14517   for (int i = 0; i < 3; i++) {
14518     v8::Handle<v8::String> name =
14519         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
14520     CHECK(!name.IsEmpty());
14521     CHECK_EQ(url, name);
14522   }
14523   return v8::Undefined();
14524 }
14525
14526
14527 TEST(SourceURLInStackTrace) {
14528   v8::HandleScope scope;
14529   Local<ObjectTemplate> templ = ObjectTemplate::New();
14530   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
14531              v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
14532   LocalContext context(0, templ);
14533
14534   const char *source =
14535     "function outer() {\n"
14536     "function bar() {\n"
14537     "  AnalyzeStackOfEvalWithSourceURL();\n"
14538     "}\n"
14539     "function foo() {\n"
14540     "\n"
14541     "  bar();\n"
14542     "}\n"
14543     "foo();\n"
14544     "}\n"
14545     "eval('(' + outer +')()//@ sourceURL=eval_url');";
14546   CHECK(CompileRun(source)->IsUndefined());
14547 }
14548
14549
14550 v8::Handle<Value> AnalyzeStackOfInlineScriptWithSourceURL(
14551     const v8::Arguments& args) {
14552   v8::HandleScope scope;
14553   v8::Handle<v8::StackTrace> stackTrace =
14554       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
14555   CHECK_EQ(4, stackTrace->GetFrameCount());
14556   v8::Handle<v8::String> url = v8_str("url");
14557   for (int i = 0; i < 3; i++) {
14558     v8::Handle<v8::String> name =
14559         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
14560     CHECK(!name.IsEmpty());
14561     CHECK_EQ(url, name);
14562   }
14563   return v8::Undefined();
14564 }
14565
14566
14567 TEST(InlineScriptWithSourceURLInStackTrace) {
14568   v8::HandleScope scope;
14569   Local<ObjectTemplate> templ = ObjectTemplate::New();
14570   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
14571              v8::FunctionTemplate::New(
14572                  AnalyzeStackOfInlineScriptWithSourceURL));
14573   LocalContext context(0, templ);
14574
14575   const char *source =
14576     "function outer() {\n"
14577     "function bar() {\n"
14578     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
14579     "}\n"
14580     "function foo() {\n"
14581     "\n"
14582     "  bar();\n"
14583     "}\n"
14584     "foo();\n"
14585     "}\n"
14586     "outer()\n"
14587     "//@ sourceURL=source_url";
14588   CHECK(CompileRunWithOrigin(source, "url", 0, 1)->IsUndefined());
14589 }
14590
14591
14592 v8::Handle<Value> AnalyzeStackOfDynamicScriptWithSourceURL(
14593     const v8::Arguments& args) {
14594   v8::HandleScope scope;
14595   v8::Handle<v8::StackTrace> stackTrace =
14596       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
14597   CHECK_EQ(4, stackTrace->GetFrameCount());
14598   v8::Handle<v8::String> url = v8_str("source_url");
14599   for (int i = 0; i < 3; i++) {
14600     v8::Handle<v8::String> name =
14601         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
14602     CHECK(!name.IsEmpty());
14603     CHECK_EQ(url, name);
14604   }
14605   return v8::Undefined();
14606 }
14607
14608
14609 TEST(DynamicWithSourceURLInStackTrace) {
14610   v8::HandleScope scope;
14611   Local<ObjectTemplate> templ = ObjectTemplate::New();
14612   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
14613              v8::FunctionTemplate::New(
14614                  AnalyzeStackOfDynamicScriptWithSourceURL));
14615   LocalContext context(0, templ);
14616
14617   const char *source =
14618     "function outer() {\n"
14619     "function bar() {\n"
14620     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
14621     "}\n"
14622     "function foo() {\n"
14623     "\n"
14624     "  bar();\n"
14625     "}\n"
14626     "foo();\n"
14627     "}\n"
14628     "outer()\n"
14629     "//@ sourceURL=source_url";
14630   CHECK(CompileRunWithOrigin(source, "url", 0, 0)->IsUndefined());
14631 }
14632
14633 static void CreateGarbageInOldSpace() {
14634   v8::HandleScope scope;
14635   i::AlwaysAllocateScope always_allocate;
14636   for (int i = 0; i < 1000; i++) {
14637     FACTORY->NewFixedArray(1000, i::TENURED);
14638   }
14639 }
14640
14641 // Test that idle notification can be handled and eventually returns true.
14642 TEST(IdleNotification) {
14643   const intptr_t MB = 1024 * 1024;
14644   v8::HandleScope scope;
14645   LocalContext env;
14646   intptr_t initial_size = HEAP->SizeOfObjects();
14647   CreateGarbageInOldSpace();
14648   intptr_t size_with_garbage = HEAP->SizeOfObjects();
14649   CHECK_GT(size_with_garbage, initial_size + MB);
14650   bool finished = false;
14651   for (int i = 0; i < 200 && !finished; i++) {
14652     finished = v8::V8::IdleNotification();
14653   }
14654   intptr_t final_size = HEAP->SizeOfObjects();
14655   CHECK(finished);
14656   CHECK_LT(final_size, initial_size + 1);
14657 }
14658
14659
14660 // Test that idle notification can be handled and eventually collects garbage.
14661 TEST(IdleNotificationWithSmallHint) {
14662   const intptr_t MB = 1024 * 1024;
14663   const int IdlePauseInMs = 900;
14664   v8::HandleScope scope;
14665   LocalContext env;
14666   intptr_t initial_size = HEAP->SizeOfObjects();
14667   CreateGarbageInOldSpace();
14668   intptr_t size_with_garbage = HEAP->SizeOfObjects();
14669   CHECK_GT(size_with_garbage, initial_size + MB);
14670   bool finished = false;
14671   for (int i = 0; i < 200 && !finished; i++) {
14672     finished = v8::V8::IdleNotification(IdlePauseInMs);
14673   }
14674   intptr_t final_size = HEAP->SizeOfObjects();
14675   CHECK(finished);
14676   CHECK_LT(final_size, initial_size + 1);
14677 }
14678
14679
14680 // Test that idle notification can be handled and eventually collects garbage.
14681 TEST(IdleNotificationWithLargeHint) {
14682   const intptr_t MB = 1024 * 1024;
14683   const int IdlePauseInMs = 900;
14684   v8::HandleScope scope;
14685   LocalContext env;
14686   intptr_t initial_size = HEAP->SizeOfObjects();
14687   CreateGarbageInOldSpace();
14688   intptr_t size_with_garbage = HEAP->SizeOfObjects();
14689   CHECK_GT(size_with_garbage, initial_size + MB);
14690   bool finished = false;
14691   for (int i = 0; i < 200 && !finished; i++) {
14692     finished = v8::V8::IdleNotification(IdlePauseInMs);
14693   }
14694   intptr_t final_size = HEAP->SizeOfObjects();
14695   CHECK(finished);
14696   CHECK_LT(final_size, initial_size + 1);
14697 }
14698
14699
14700 TEST(Regress2107) {
14701   const intptr_t MB = 1024 * 1024;
14702   const int kShortIdlePauseInMs = 100;
14703   const int kLongIdlePauseInMs = 1000;
14704   v8::HandleScope scope;
14705   LocalContext env;
14706   intptr_t initial_size = HEAP->SizeOfObjects();
14707   // Send idle notification to start a round of incremental GCs.
14708   v8::V8::IdleNotification(kShortIdlePauseInMs);
14709   // Emulate 7 page reloads.
14710   for (int i = 0; i < 7; i++) {
14711     v8::Persistent<v8::Context> ctx = v8::Context::New();
14712     ctx->Enter();
14713     CreateGarbageInOldSpace();
14714     ctx->Exit();
14715     ctx.Dispose();
14716     v8::V8::ContextDisposedNotification();
14717     v8::V8::IdleNotification(kLongIdlePauseInMs);
14718   }
14719   // Create garbage and check that idle notification still collects it.
14720   CreateGarbageInOldSpace();
14721   intptr_t size_with_garbage = HEAP->SizeOfObjects();
14722   CHECK_GT(size_with_garbage, initial_size + MB);
14723   bool finished = false;
14724   for (int i = 0; i < 200 && !finished; i++) {
14725     finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
14726   }
14727   intptr_t final_size = HEAP->SizeOfObjects();
14728   CHECK_LT(final_size, initial_size + 1);
14729 }
14730
14731 static uint32_t* stack_limit;
14732
14733 static v8::Handle<Value> GetStackLimitCallback(const v8::Arguments& args) {
14734   stack_limit = reinterpret_cast<uint32_t*>(
14735       i::Isolate::Current()->stack_guard()->real_climit());
14736   return v8::Undefined();
14737 }
14738
14739
14740 // Uses the address of a local variable to determine the stack top now.
14741 // Given a size, returns an address that is that far from the current
14742 // top of stack.
14743 static uint32_t* ComputeStackLimit(uint32_t size) {
14744   uint32_t* answer = &size - (size / sizeof(size));
14745   // If the size is very large and the stack is very near the bottom of
14746   // memory then the calculation above may wrap around and give an address
14747   // that is above the (downwards-growing) stack.  In that case we return
14748   // a very low address.
14749   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
14750   return answer;
14751 }
14752
14753
14754 TEST(SetResourceConstraints) {
14755   static const int K = 1024;
14756   uint32_t* set_limit = ComputeStackLimit(128 * K);
14757
14758   // Set stack limit.
14759   v8::ResourceConstraints constraints;
14760   constraints.set_stack_limit(set_limit);
14761   CHECK(v8::SetResourceConstraints(&constraints));
14762
14763   // Execute a script.
14764   v8::HandleScope scope;
14765   LocalContext env;
14766   Local<v8::FunctionTemplate> fun_templ =
14767       v8::FunctionTemplate::New(GetStackLimitCallback);
14768   Local<Function> fun = fun_templ->GetFunction();
14769   env->Global()->Set(v8_str("get_stack_limit"), fun);
14770   CompileRun("get_stack_limit();");
14771
14772   CHECK(stack_limit == set_limit);
14773 }
14774
14775
14776 TEST(SetResourceConstraintsInThread) {
14777   uint32_t* set_limit;
14778   {
14779     v8::Locker locker;
14780     static const int K = 1024;
14781     set_limit = ComputeStackLimit(128 * K);
14782
14783     // Set stack limit.
14784     v8::ResourceConstraints constraints;
14785     constraints.set_stack_limit(set_limit);
14786     CHECK(v8::SetResourceConstraints(&constraints));
14787
14788     // Execute a script.
14789     v8::HandleScope scope;
14790     LocalContext env;
14791     Local<v8::FunctionTemplate> fun_templ =
14792         v8::FunctionTemplate::New(GetStackLimitCallback);
14793     Local<Function> fun = fun_templ->GetFunction();
14794     env->Global()->Set(v8_str("get_stack_limit"), fun);
14795     CompileRun("get_stack_limit();");
14796
14797     CHECK(stack_limit == set_limit);
14798   }
14799   {
14800     v8::Locker locker;
14801     CHECK(stack_limit == set_limit);
14802   }
14803 }
14804
14805
14806 THREADED_TEST(GetHeapStatistics) {
14807   v8::HandleScope scope;
14808   LocalContext c1;
14809   v8::HeapStatistics heap_statistics;
14810   CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
14811   CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
14812   v8::V8::GetHeapStatistics(&heap_statistics);
14813   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
14814   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
14815 }
14816
14817
14818 class VisitorImpl : public v8::ExternalResourceVisitor {
14819  public:
14820   VisitorImpl(TestResource* r1, TestResource* r2)
14821       : resource1_(r1),
14822         resource2_(r2),
14823         found_resource1_(false),
14824         found_resource2_(false) {}
14825   virtual ~VisitorImpl() {}
14826   virtual void VisitExternalString(v8::Handle<v8::String> string) {
14827     if (!string->IsExternal()) {
14828       CHECK(string->IsExternalAscii());
14829       return;
14830     }
14831     v8::String::ExternalStringResource* resource =
14832         string->GetExternalStringResource();
14833     CHECK(resource);
14834     if (resource1_ == resource) {
14835       CHECK(!found_resource1_);
14836       found_resource1_ = true;
14837     }
14838     if (resource2_ == resource) {
14839       CHECK(!found_resource2_);
14840       found_resource2_ = true;
14841     }
14842   }
14843   void CheckVisitedResources() {
14844     CHECK(found_resource1_);
14845     CHECK(found_resource2_);
14846   }
14847
14848  private:
14849   v8::String::ExternalStringResource* resource1_;
14850   v8::String::ExternalStringResource* resource2_;
14851   bool found_resource1_;
14852   bool found_resource2_;
14853 };
14854
14855 TEST(VisitExternalStrings) {
14856   v8::HandleScope scope;
14857   LocalContext env;
14858   const char* string = "Some string";
14859   uint16_t* two_byte_string = AsciiToTwoByteString(string);
14860   TestResource* resource1 = new TestResource(two_byte_string);
14861   v8::Local<v8::String> string1 = v8::String::NewExternal(resource1);
14862   TestResource* resource2 = new TestResource(two_byte_string);
14863   v8::Local<v8::String> string2 = v8::String::NewExternal(resource2);
14864
14865   // We need to add usages for string1 and string2 to avoid warnings in GCC 4.7
14866   CHECK(string1->IsExternal());
14867   CHECK(string2->IsExternal());
14868
14869   VisitorImpl visitor(resource1, resource2);
14870   v8::V8::VisitExternalResources(&visitor);
14871   visitor.CheckVisitedResources();
14872 }
14873
14874
14875 static double DoubleFromBits(uint64_t value) {
14876   double target;
14877   memcpy(&target, &value, sizeof(target));
14878   return target;
14879 }
14880
14881
14882 static uint64_t DoubleToBits(double value) {
14883   uint64_t target;
14884   memcpy(&target, &value, sizeof(target));
14885   return target;
14886 }
14887
14888
14889 static double DoubleToDateTime(double input) {
14890   double date_limit = 864e13;
14891   if (IsNaN(input) || input < -date_limit || input > date_limit) {
14892     return i::OS::nan_value();
14893   }
14894   return (input < 0) ? -(floor(-input)) : floor(input);
14895 }
14896
14897 // We don't have a consistent way to write 64-bit constants syntactically, so we
14898 // split them into two 32-bit constants and combine them programmatically.
14899 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
14900   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
14901 }
14902
14903
14904 THREADED_TEST(QuietSignalingNaNs) {
14905   v8::HandleScope scope;
14906   LocalContext context;
14907   v8::TryCatch try_catch;
14908
14909   // Special double values.
14910   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
14911   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
14912   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
14913   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
14914   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
14915   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
14916   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
14917
14918   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
14919   // on either side of the epoch.
14920   double date_limit = 864e13;
14921
14922   double test_values[] = {
14923       snan,
14924       qnan,
14925       infinity,
14926       max_normal,
14927       date_limit + 1,
14928       date_limit,
14929       min_normal,
14930       max_denormal,
14931       min_denormal,
14932       0,
14933       -0,
14934       -min_denormal,
14935       -max_denormal,
14936       -min_normal,
14937       -date_limit,
14938       -date_limit - 1,
14939       -max_normal,
14940       -infinity,
14941       -qnan,
14942       -snan
14943   };
14944   int num_test_values = 20;
14945
14946   for (int i = 0; i < num_test_values; i++) {
14947     double test_value = test_values[i];
14948
14949     // Check that Number::New preserves non-NaNs and quiets SNaNs.
14950     v8::Handle<v8::Value> number = v8::Number::New(test_value);
14951     double stored_number = number->NumberValue();
14952     if (!IsNaN(test_value)) {
14953       CHECK_EQ(test_value, stored_number);
14954     } else {
14955       uint64_t stored_bits = DoubleToBits(stored_number);
14956       // Check if quiet nan (bits 51..62 all set).
14957 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
14958       // Most significant fraction bit for quiet nan is set to 0
14959       // on MIPS architecture. Allowed by IEEE-754.
14960       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
14961 #else
14962       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
14963 #endif
14964     }
14965
14966     // Check that Date::New preserves non-NaNs in the date range and
14967     // quiets SNaNs.
14968     v8::Handle<v8::Value> date = v8::Date::New(test_value);
14969     double expected_stored_date = DoubleToDateTime(test_value);
14970     double stored_date = date->NumberValue();
14971     if (!IsNaN(expected_stored_date)) {
14972       CHECK_EQ(expected_stored_date, stored_date);
14973     } else {
14974       uint64_t stored_bits = DoubleToBits(stored_date);
14975       // Check if quiet nan (bits 51..62 all set).
14976 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
14977       // Most significant fraction bit for quiet nan is set to 0
14978       // on MIPS architecture. Allowed by IEEE-754.
14979       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
14980 #else
14981       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
14982 #endif
14983     }
14984   }
14985 }
14986
14987
14988 static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) {
14989   v8::HandleScope scope;
14990   v8::TryCatch tc;
14991   v8::Handle<v8::String> str(args[0]->ToString());
14992   USE(str);
14993   if (tc.HasCaught())
14994     return tc.ReThrow();
14995   return v8::Undefined();
14996 }
14997
14998
14999 // Test that an exception can be propagated down through a spaghetti
15000 // stack using ReThrow.
15001 THREADED_TEST(SpaghettiStackReThrow) {
15002   v8::HandleScope scope;
15003   LocalContext context;
15004   context->Global()->Set(
15005       v8::String::New("s"),
15006       v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
15007   v8::TryCatch try_catch;
15008   CompileRun(
15009       "var i = 0;"
15010       "var o = {"
15011       "  toString: function () {"
15012       "    if (i == 10) {"
15013       "      throw 'Hey!';"
15014       "    } else {"
15015       "      i++;"
15016       "      return s(o);"
15017       "    }"
15018       "  }"
15019       "};"
15020       "s(o);");
15021   CHECK(try_catch.HasCaught());
15022   v8::String::Utf8Value value(try_catch.Exception());
15023   CHECK_EQ(0, strcmp(*value, "Hey!"));
15024 }
15025
15026
15027 TEST(Regress528) {
15028   v8::V8::Initialize();
15029
15030   v8::HandleScope scope;
15031   v8::Persistent<Context> context;
15032   v8::Persistent<Context> other_context;
15033   int gc_count;
15034
15035   // Create a context used to keep the code from aging in the compilation
15036   // cache.
15037   other_context = Context::New();
15038
15039   // Context-dependent context data creates reference from the compilation
15040   // cache to the global object.
15041   const char* source_simple = "1";
15042   context = Context::New();
15043   {
15044     v8::HandleScope scope;
15045
15046     context->Enter();
15047     Local<v8::String> obj = v8::String::New("");
15048     context->SetData(obj);
15049     CompileRun(source_simple);
15050     context->Exit();
15051   }
15052   context.Dispose();
15053   v8::V8::ContextDisposedNotification();
15054   for (gc_count = 1; gc_count < 10; gc_count++) {
15055     other_context->Enter();
15056     CompileRun(source_simple);
15057     other_context->Exit();
15058     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15059     if (GetGlobalObjectsCount() == 1) break;
15060   }
15061   CHECK_GE(2, gc_count);
15062   CHECK_EQ(1, GetGlobalObjectsCount());
15063
15064   // Eval in a function creates reference from the compilation cache to the
15065   // global object.
15066   const char* source_eval = "function f(){eval('1')}; f()";
15067   context = Context::New();
15068   {
15069     v8::HandleScope scope;
15070
15071     context->Enter();
15072     CompileRun(source_eval);
15073     context->Exit();
15074   }
15075   context.Dispose();
15076   v8::V8::ContextDisposedNotification();
15077   for (gc_count = 1; gc_count < 10; gc_count++) {
15078     other_context->Enter();
15079     CompileRun(source_eval);
15080     other_context->Exit();
15081     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15082     if (GetGlobalObjectsCount() == 1) break;
15083   }
15084   CHECK_GE(2, gc_count);
15085   CHECK_EQ(1, GetGlobalObjectsCount());
15086
15087   // Looking up the line number for an exception creates reference from the
15088   // compilation cache to the global object.
15089   const char* source_exception = "function f(){throw 1;} f()";
15090   context = Context::New();
15091   {
15092     v8::HandleScope scope;
15093
15094     context->Enter();
15095     v8::TryCatch try_catch;
15096     CompileRun(source_exception);
15097     CHECK(try_catch.HasCaught());
15098     v8::Handle<v8::Message> message = try_catch.Message();
15099     CHECK(!message.IsEmpty());
15100     CHECK_EQ(1, message->GetLineNumber());
15101     context->Exit();
15102   }
15103   context.Dispose();
15104   v8::V8::ContextDisposedNotification();
15105   for (gc_count = 1; gc_count < 10; gc_count++) {
15106     other_context->Enter();
15107     CompileRun(source_exception);
15108     other_context->Exit();
15109     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15110     if (GetGlobalObjectsCount() == 1) break;
15111   }
15112   CHECK_GE(2, gc_count);
15113   CHECK_EQ(1, GetGlobalObjectsCount());
15114
15115   other_context.Dispose();
15116   v8::V8::ContextDisposedNotification();
15117 }
15118
15119
15120 THREADED_TEST(ScriptOrigin) {
15121   v8::HandleScope scope;
15122   LocalContext env;
15123   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
15124   v8::Handle<v8::String> script = v8::String::New(
15125       "function f() {}\n\nfunction g() {}");
15126   v8::Script::Compile(script, &origin)->Run();
15127   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15128       env->Global()->Get(v8::String::New("f")));
15129   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
15130       env->Global()->Get(v8::String::New("g")));
15131
15132   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
15133   CHECK_EQ("test", *v8::String::AsciiValue(script_origin_f.ResourceName()));
15134   CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
15135
15136   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
15137   CHECK_EQ("test", *v8::String::AsciiValue(script_origin_g.ResourceName()));
15138   CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
15139 }
15140
15141 THREADED_TEST(FunctionGetInferredName) {
15142   v8::HandleScope scope;
15143   LocalContext env;
15144   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
15145   v8::Handle<v8::String> script = v8::String::New(
15146       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
15147   v8::Script::Compile(script, &origin)->Run();
15148   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15149       env->Global()->Get(v8::String::New("f")));
15150   CHECK_EQ("foo.bar.baz", *v8::String::AsciiValue(f->GetInferredName()));
15151 }
15152
15153 THREADED_TEST(ScriptLineNumber) {
15154   v8::HandleScope scope;
15155   LocalContext env;
15156   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
15157   v8::Handle<v8::String> script = v8::String::New(
15158       "function f() {}\n\nfunction g() {}");
15159   v8::Script::Compile(script, &origin)->Run();
15160   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15161       env->Global()->Get(v8::String::New("f")));
15162   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
15163       env->Global()->Get(v8::String::New("g")));
15164   CHECK_EQ(0, f->GetScriptLineNumber());
15165   CHECK_EQ(2, g->GetScriptLineNumber());
15166 }
15167
15168
15169 THREADED_TEST(ScriptColumnNumber) {
15170   v8::HandleScope scope;
15171   LocalContext env;
15172   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
15173       v8::Integer::New(3), v8::Integer::New(2));
15174   v8::Handle<v8::String> script = v8::String::New(
15175       "function foo() {}\n\n     function bar() {}");
15176   v8::Script::Compile(script, &origin)->Run();
15177   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
15178       env->Global()->Get(v8::String::New("foo")));
15179   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
15180       env->Global()->Get(v8::String::New("bar")));
15181   CHECK_EQ(14, foo->GetScriptColumnNumber());
15182   CHECK_EQ(17, bar->GetScriptColumnNumber());
15183 }
15184
15185
15186 THREADED_TEST(FunctionGetScriptId) {
15187   v8::HandleScope scope;
15188   LocalContext env;
15189   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
15190       v8::Integer::New(3), v8::Integer::New(2));
15191   v8::Handle<v8::String> scriptSource = v8::String::New(
15192       "function foo() {}\n\n     function bar() {}");
15193   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
15194   script->Run();
15195   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
15196       env->Global()->Get(v8::String::New("foo")));
15197   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
15198       env->Global()->Get(v8::String::New("bar")));
15199   CHECK_EQ(script->Id(), foo->GetScriptId());
15200   CHECK_EQ(script->Id(), bar->GetScriptId());
15201 }
15202
15203
15204 static v8::Handle<Value> GetterWhichReturns42(Local<String> name,
15205                                               const AccessorInfo& info) {
15206   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
15207   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
15208   return v8_num(42);
15209 }
15210
15211
15212 static void SetterWhichSetsYOnThisTo23(Local<String> name,
15213                                        Local<Value> value,
15214                                        const AccessorInfo& info) {
15215   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
15216   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
15217   info.This()->Set(v8_str("y"), v8_num(23));
15218 }
15219
15220
15221 Handle<Value> FooGetInterceptor(Local<String> name,
15222                                 const AccessorInfo& info) {
15223   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
15224   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
15225   if (!name->Equals(v8_str("foo"))) return Handle<Value>();
15226   return v8_num(42);
15227 }
15228
15229
15230 Handle<Value> FooSetInterceptor(Local<String> name,
15231                                 Local<Value> value,
15232                                 const AccessorInfo& info) {
15233   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
15234   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
15235   if (!name->Equals(v8_str("foo"))) return Handle<Value>();
15236   info.This()->Set(v8_str("y"), v8_num(23));
15237   return v8_num(23);
15238 }
15239
15240
15241 TEST(SetterOnConstructorPrototype) {
15242   v8::HandleScope scope;
15243   Local<ObjectTemplate> templ = ObjectTemplate::New();
15244   templ->SetAccessor(v8_str("x"),
15245                      GetterWhichReturns42,
15246                      SetterWhichSetsYOnThisTo23);
15247   LocalContext context;
15248   context->Global()->Set(v8_str("P"), templ->NewInstance());
15249   CompileRun("function C1() {"
15250              "  this.x = 23;"
15251              "};"
15252              "C1.prototype = P;"
15253              "function C2() {"
15254              "  this.x = 23"
15255              "};"
15256              "C2.prototype = { };"
15257              "C2.prototype.__proto__ = P;");
15258
15259   v8::Local<v8::Script> script;
15260   script = v8::Script::Compile(v8_str("new C1();"));
15261   for (int i = 0; i < 10; i++) {
15262     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
15263     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
15264     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
15265   }
15266
15267   script = v8::Script::Compile(v8_str("new C2();"));
15268   for (int i = 0; i < 10; i++) {
15269     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
15270     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
15271     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
15272   }
15273 }
15274
15275
15276 static v8::Handle<Value> NamedPropertyGetterWhichReturns42(
15277     Local<String> name, const AccessorInfo& info) {
15278   return v8_num(42);
15279 }
15280
15281
15282 static v8::Handle<Value> NamedPropertySetterWhichSetsYOnThisTo23(
15283     Local<String> name, Local<Value> value, const AccessorInfo& info) {
15284   if (name->Equals(v8_str("x"))) {
15285     info.This()->Set(v8_str("y"), v8_num(23));
15286   }
15287   return v8::Handle<Value>();
15288 }
15289
15290
15291 THREADED_TEST(InterceptorOnConstructorPrototype) {
15292   v8::HandleScope scope;
15293   Local<ObjectTemplate> templ = ObjectTemplate::New();
15294   templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
15295                                  NamedPropertySetterWhichSetsYOnThisTo23);
15296   LocalContext context;
15297   context->Global()->Set(v8_str("P"), templ->NewInstance());
15298   CompileRun("function C1() {"
15299              "  this.x = 23;"
15300              "};"
15301              "C1.prototype = P;"
15302              "function C2() {"
15303              "  this.x = 23"
15304              "};"
15305              "C2.prototype = { };"
15306              "C2.prototype.__proto__ = P;");
15307
15308   v8::Local<v8::Script> script;
15309   script = v8::Script::Compile(v8_str("new C1();"));
15310   for (int i = 0; i < 10; i++) {
15311     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
15312     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
15313     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
15314   }
15315
15316   script = v8::Script::Compile(v8_str("new C2();"));
15317   for (int i = 0; i < 10; i++) {
15318     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
15319     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
15320     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
15321   }
15322 }
15323
15324
15325 TEST(Bug618) {
15326   const char* source = "function C1() {"
15327                        "  this.x = 23;"
15328                        "};"
15329                        "C1.prototype = P;";
15330
15331   v8::HandleScope scope;
15332   LocalContext context;
15333   v8::Local<v8::Script> script;
15334
15335   // Use a simple object as prototype.
15336   v8::Local<v8::Object> prototype = v8::Object::New();
15337   prototype->Set(v8_str("y"), v8_num(42));
15338   context->Global()->Set(v8_str("P"), prototype);
15339
15340   // This compile will add the code to the compilation cache.
15341   CompileRun(source);
15342
15343   script = v8::Script::Compile(v8_str("new C1();"));
15344   // Allow enough iterations for the inobject slack tracking logic
15345   // to finalize instance size and install the fast construct stub.
15346   for (int i = 0; i < 256; i++) {
15347     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
15348     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
15349     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
15350   }
15351
15352   // Use an API object with accessors as prototype.
15353   Local<ObjectTemplate> templ = ObjectTemplate::New();
15354   templ->SetAccessor(v8_str("x"),
15355                      GetterWhichReturns42,
15356                      SetterWhichSetsYOnThisTo23);
15357   context->Global()->Set(v8_str("P"), templ->NewInstance());
15358
15359   // This compile will get the code from the compilation cache.
15360   CompileRun(source);
15361
15362   script = v8::Script::Compile(v8_str("new C1();"));
15363   for (int i = 0; i < 10; i++) {
15364     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
15365     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
15366     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
15367   }
15368 }
15369
15370 int prologue_call_count = 0;
15371 int epilogue_call_count = 0;
15372 int prologue_call_count_second = 0;
15373 int epilogue_call_count_second = 0;
15374
15375 void PrologueCallback(v8::GCType, v8::GCCallbackFlags) {
15376   ++prologue_call_count;
15377 }
15378
15379 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags) {
15380   ++epilogue_call_count;
15381 }
15382
15383 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
15384   ++prologue_call_count_second;
15385 }
15386
15387 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
15388   ++epilogue_call_count_second;
15389 }
15390
15391 TEST(GCCallbacks) {
15392   LocalContext context;
15393
15394   v8::V8::AddGCPrologueCallback(PrologueCallback);
15395   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
15396   CHECK_EQ(0, prologue_call_count);
15397   CHECK_EQ(0, epilogue_call_count);
15398   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15399   CHECK_EQ(1, prologue_call_count);
15400   CHECK_EQ(1, epilogue_call_count);
15401   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
15402   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
15403   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15404   CHECK_EQ(2, prologue_call_count);
15405   CHECK_EQ(2, epilogue_call_count);
15406   CHECK_EQ(1, prologue_call_count_second);
15407   CHECK_EQ(1, epilogue_call_count_second);
15408   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
15409   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
15410   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15411   CHECK_EQ(2, prologue_call_count);
15412   CHECK_EQ(2, epilogue_call_count);
15413   CHECK_EQ(2, prologue_call_count_second);
15414   CHECK_EQ(2, epilogue_call_count_second);
15415   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
15416   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
15417   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15418   CHECK_EQ(2, prologue_call_count);
15419   CHECK_EQ(2, epilogue_call_count);
15420   CHECK_EQ(2, prologue_call_count_second);
15421   CHECK_EQ(2, epilogue_call_count_second);
15422 }
15423
15424
15425 THREADED_TEST(AddToJSFunctionResultCache) {
15426   i::FLAG_allow_natives_syntax = true;
15427   v8::HandleScope scope;
15428
15429   LocalContext context;
15430
15431   const char* code =
15432       "(function() {"
15433       "  var key0 = 'a';"
15434       "  var key1 = 'b';"
15435       "  var r0 = %_GetFromCache(0, key0);"
15436       "  var r1 = %_GetFromCache(0, key1);"
15437       "  var r0_ = %_GetFromCache(0, key0);"
15438       "  if (r0 !== r0_)"
15439       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
15440       "  var r1_ = %_GetFromCache(0, key1);"
15441       "  if (r1 !== r1_)"
15442       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
15443       "  return 'PASSED';"
15444       "})()";
15445   HEAP->ClearJSFunctionResultCaches();
15446   ExpectString(code, "PASSED");
15447 }
15448
15449
15450 static const int k0CacheSize = 16;
15451
15452 THREADED_TEST(FillJSFunctionResultCache) {
15453   i::FLAG_allow_natives_syntax = true;
15454   v8::HandleScope scope;
15455
15456   LocalContext context;
15457
15458   const char* code =
15459       "(function() {"
15460       "  var k = 'a';"
15461       "  var r = %_GetFromCache(0, k);"
15462       "  for (var i = 0; i < 16; i++) {"
15463       "    %_GetFromCache(0, 'a' + i);"
15464       "  };"
15465       "  if (r === %_GetFromCache(0, k))"
15466       "    return 'FAILED: k0CacheSize is too small';"
15467       "  return 'PASSED';"
15468       "})()";
15469   HEAP->ClearJSFunctionResultCaches();
15470   ExpectString(code, "PASSED");
15471 }
15472
15473
15474 THREADED_TEST(RoundRobinGetFromCache) {
15475   i::FLAG_allow_natives_syntax = true;
15476   v8::HandleScope scope;
15477
15478   LocalContext context;
15479
15480   const char* code =
15481       "(function() {"
15482       "  var keys = [];"
15483       "  for (var i = 0; i < 16; i++) keys.push(i);"
15484       "  var values = [];"
15485       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
15486       "  for (var i = 0; i < 16; i++) {"
15487       "    var v = %_GetFromCache(0, keys[i]);"
15488       "    if (v.toString() !== values[i].toString())"
15489       "      return 'Wrong value for ' + "
15490       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
15491       "  };"
15492       "  return 'PASSED';"
15493       "})()";
15494   HEAP->ClearJSFunctionResultCaches();
15495   ExpectString(code, "PASSED");
15496 }
15497
15498
15499 THREADED_TEST(ReverseGetFromCache) {
15500   i::FLAG_allow_natives_syntax = true;
15501   v8::HandleScope scope;
15502
15503   LocalContext context;
15504
15505   const char* code =
15506       "(function() {"
15507       "  var keys = [];"
15508       "  for (var i = 0; i < 16; i++) keys.push(i);"
15509       "  var values = [];"
15510       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
15511       "  for (var i = 15; i >= 16; i--) {"
15512       "    var v = %_GetFromCache(0, keys[i]);"
15513       "    if (v !== values[i])"
15514       "      return 'Wrong value for ' + "
15515       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
15516       "  };"
15517       "  return 'PASSED';"
15518       "})()";
15519   HEAP->ClearJSFunctionResultCaches();
15520   ExpectString(code, "PASSED");
15521 }
15522
15523
15524 THREADED_TEST(TestEviction) {
15525   i::FLAG_allow_natives_syntax = true;
15526   v8::HandleScope scope;
15527
15528   LocalContext context;
15529
15530   const char* code =
15531       "(function() {"
15532       "  for (var i = 0; i < 2*16; i++) {"
15533       "    %_GetFromCache(0, 'a' + i);"
15534       "  };"
15535       "  return 'PASSED';"
15536       "})()";
15537   HEAP->ClearJSFunctionResultCaches();
15538   ExpectString(code, "PASSED");
15539 }
15540
15541
15542 THREADED_TEST(TwoByteStringInAsciiCons) {
15543   // See Chromium issue 47824.
15544   v8::HandleScope scope;
15545
15546   LocalContext context;
15547   const char* init_code =
15548       "var str1 = 'abelspendabel';"
15549       "var str2 = str1 + str1 + str1;"
15550       "str2;";
15551   Local<Value> result = CompileRun(init_code);
15552
15553   Local<Value> indexof = CompileRun("str2.indexOf('els')");
15554   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
15555
15556   CHECK(result->IsString());
15557   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
15558   int length = string->length();
15559   CHECK(string->IsAsciiRepresentation());
15560
15561   FlattenString(string);
15562   i::Handle<i::String> flat_string = FlattenGetString(string);
15563
15564   CHECK(string->IsAsciiRepresentation());
15565   CHECK(flat_string->IsAsciiRepresentation());
15566
15567   // Create external resource.
15568   uint16_t* uc16_buffer = new uint16_t[length + 1];
15569
15570   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
15571   uc16_buffer[length] = 0;
15572
15573   TestResource resource(uc16_buffer);
15574
15575   flat_string->MakeExternal(&resource);
15576
15577   CHECK(flat_string->IsTwoByteRepresentation());
15578
15579   // At this point, we should have a Cons string which is flat and ASCII,
15580   // with a first half that is a two-byte string (although it only contains
15581   // ASCII characters). This is a valid sequence of steps, and it can happen
15582   // in real pages.
15583
15584   CHECK(string->IsAsciiRepresentation());
15585   i::ConsString* cons = i::ConsString::cast(*string);
15586   CHECK_EQ(0, cons->second()->length());
15587   CHECK(cons->first()->IsTwoByteRepresentation());
15588
15589   // Check that some string operations work.
15590
15591   // Atom RegExp.
15592   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
15593   CHECK_EQ(6, reresult->Int32Value());
15594
15595   // Nonatom RegExp.
15596   reresult = CompileRun("str2.match(/abe./g).length;");
15597   CHECK_EQ(6, reresult->Int32Value());
15598
15599   reresult = CompileRun("str2.search(/bel/g);");
15600   CHECK_EQ(1, reresult->Int32Value());
15601
15602   reresult = CompileRun("str2.search(/be./g);");
15603   CHECK_EQ(1, reresult->Int32Value());
15604
15605   ExpectTrue("/bel/g.test(str2);");
15606
15607   ExpectTrue("/be./g.test(str2);");
15608
15609   reresult = CompileRun("/bel/g.exec(str2);");
15610   CHECK(!reresult->IsNull());
15611
15612   reresult = CompileRun("/be./g.exec(str2);");
15613   CHECK(!reresult->IsNull());
15614
15615   ExpectString("str2.substring(2, 10);", "elspenda");
15616
15617   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
15618
15619   ExpectString("str2.charAt(2);", "e");
15620
15621   ExpectObject("str2.indexOf('els');", indexof);
15622
15623   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
15624
15625   reresult = CompileRun("str2.charCodeAt(2);");
15626   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
15627 }
15628
15629
15630 // Failed access check callback that performs a GC on each invocation.
15631 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
15632                                  v8::AccessType type,
15633                                  Local<v8::Value> data) {
15634   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15635 }
15636
15637
15638 TEST(GCInFailedAccessCheckCallback) {
15639   // Install a failed access check callback that performs a GC on each
15640   // invocation. Then force the callback to be called from va
15641
15642   v8::V8::Initialize();
15643   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
15644
15645   v8::HandleScope scope;
15646
15647   // Create an ObjectTemplate for global objects and install access
15648   // check callbacks that will block access.
15649   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
15650   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
15651                                            IndexedGetAccessBlocker,
15652                                            v8::Handle<v8::Value>(),
15653                                            false);
15654
15655   // Create a context and set an x property on it's global object.
15656   LocalContext context0(NULL, global_template);
15657   context0->Global()->Set(v8_str("x"), v8_num(42));
15658   v8::Handle<v8::Object> global0 = context0->Global();
15659
15660   // Create a context with a different security token so that the
15661   // failed access check callback will be called on each access.
15662   LocalContext context1(NULL, global_template);
15663   context1->Global()->Set(v8_str("other"), global0);
15664
15665   // Get property with failed access check.
15666   ExpectUndefined("other.x");
15667
15668   // Get element with failed access check.
15669   ExpectUndefined("other[0]");
15670
15671   // Set property with failed access check.
15672   v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
15673   CHECK(result->IsObject());
15674
15675   // Set element with failed access check.
15676   result = CompileRun("other[0] = new Object()");
15677   CHECK(result->IsObject());
15678
15679   // Get property attribute with failed access check.
15680   ExpectFalse("\'x\' in other");
15681
15682   // Get property attribute for element with failed access check.
15683   ExpectFalse("0 in other");
15684
15685   // Delete property.
15686   ExpectFalse("delete other.x");
15687
15688   // Delete element.
15689   CHECK_EQ(false, global0->Delete(0));
15690
15691   // DefineAccessor.
15692   CHECK_EQ(false,
15693            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
15694
15695   // Define JavaScript accessor.
15696   ExpectUndefined("Object.prototype.__defineGetter__.call("
15697                   "    other, \'x\', function() { return 42; })");
15698
15699   // LookupAccessor.
15700   ExpectUndefined("Object.prototype.__lookupGetter__.call("
15701                   "    other, \'x\')");
15702
15703   // HasLocalElement.
15704   ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
15705
15706   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
15707   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
15708   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
15709
15710   // Reset the failed access check callback so it does not influence
15711   // the other tests.
15712   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
15713 }
15714
15715 TEST(DefaultIsolateGetCurrent) {
15716   CHECK(v8::Isolate::GetCurrent() != NULL);
15717   v8::Isolate* isolate = v8::Isolate::GetCurrent();
15718   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
15719   printf("*** %s\n", "DefaultIsolateGetCurrent success");
15720 }
15721
15722 TEST(IsolateNewDispose) {
15723   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
15724   v8::Isolate* isolate = v8::Isolate::New();
15725   CHECK(isolate != NULL);
15726   CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
15727   CHECK(current_isolate != isolate);
15728   CHECK(current_isolate == v8::Isolate::GetCurrent());
15729
15730   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
15731   last_location = last_message = NULL;
15732   isolate->Dispose();
15733   CHECK_EQ(last_location, NULL);
15734   CHECK_EQ(last_message, NULL);
15735 }
15736
15737 TEST(IsolateEnterExitDefault) {
15738   v8::HandleScope scope;
15739   LocalContext context;
15740   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
15741   CHECK(current_isolate != NULL);  // Default isolate.
15742   ExpectString("'hello'", "hello");
15743   current_isolate->Enter();
15744   ExpectString("'still working'", "still working");
15745   current_isolate->Exit();
15746   ExpectString("'still working 2'", "still working 2");
15747   current_isolate->Exit();
15748   // Default isolate is always, well, 'default current'.
15749   CHECK_EQ(v8::Isolate::GetCurrent(), current_isolate);
15750   // Still working since default isolate is auto-entering any thread
15751   // that has no isolate and attempts to execute V8 APIs.
15752   ExpectString("'still working 3'", "still working 3");
15753 }
15754
15755 TEST(DisposeDefaultIsolate) {
15756   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
15757
15758   // Run some V8 code to trigger default isolate to become 'current'.
15759   v8::HandleScope scope;
15760   LocalContext context;
15761   ExpectString("'run some V8'", "run some V8");
15762
15763   v8::Isolate* isolate = v8::Isolate::GetCurrent();
15764   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
15765   last_location = last_message = NULL;
15766   isolate->Dispose();
15767   // It is not possible to dispose default isolate via Isolate API.
15768   CHECK_NE(last_location, NULL);
15769   CHECK_NE(last_message, NULL);
15770 }
15771
15772 TEST(RunDefaultAndAnotherIsolate) {
15773   v8::HandleScope scope;
15774   LocalContext context;
15775
15776   // Enter new isolate.
15777   v8::Isolate* isolate = v8::Isolate::New();
15778   CHECK(isolate);
15779   isolate->Enter();
15780   { // Need this block because subsequent Exit() will deallocate Heap,
15781     // so we need all scope objects to be deconstructed when it happens.
15782     v8::HandleScope scope_new;
15783     LocalContext context_new;
15784
15785     // Run something in new isolate.
15786     CompileRun("var foo = 153;");
15787     ExpectTrue("function f() { return foo == 153; }; f()");
15788   }
15789   isolate->Exit();
15790
15791   // This runs automatically in default isolate.
15792   // Variables in another isolate should be not available.
15793   ExpectTrue("function f() {"
15794              "  try {"
15795              "    foo;"
15796              "    return false;"
15797              "  } catch(e) {"
15798              "    return true;"
15799              "  }"
15800              "};"
15801              "var bar = 371;"
15802              "f()");
15803
15804   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
15805   last_location = last_message = NULL;
15806   isolate->Dispose();
15807   CHECK_EQ(last_location, NULL);
15808   CHECK_EQ(last_message, NULL);
15809
15810   // Check that default isolate still runs.
15811   ExpectTrue("function f() { return bar == 371; }; f()");
15812 }
15813
15814 TEST(DisposeIsolateWhenInUse) {
15815   v8::Isolate* isolate = v8::Isolate::New();
15816   CHECK(isolate);
15817   isolate->Enter();
15818   v8::HandleScope scope;
15819   LocalContext context;
15820   // Run something in this isolate.
15821   ExpectTrue("true");
15822   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
15823   last_location = last_message = NULL;
15824   // Still entered, should fail.
15825   isolate->Dispose();
15826   CHECK_NE(last_location, NULL);
15827   CHECK_NE(last_message, NULL);
15828 }
15829
15830 TEST(RunTwoIsolatesOnSingleThread) {
15831   // Run isolate 1.
15832   v8::Isolate* isolate1 = v8::Isolate::New();
15833   isolate1->Enter();
15834   v8::Persistent<v8::Context> context1 = v8::Context::New();
15835
15836   {
15837     v8::Context::Scope cscope(context1);
15838     v8::HandleScope scope;
15839     // Run something in new isolate.
15840     CompileRun("var foo = 'isolate 1';");
15841     ExpectString("function f() { return foo; }; f()", "isolate 1");
15842   }
15843
15844   // Run isolate 2.
15845   v8::Isolate* isolate2 = v8::Isolate::New();
15846   v8::Persistent<v8::Context> context2;
15847
15848   {
15849     v8::Isolate::Scope iscope(isolate2);
15850     context2 = v8::Context::New();
15851     v8::Context::Scope cscope(context2);
15852     v8::HandleScope scope;
15853
15854     // Run something in new isolate.
15855     CompileRun("var foo = 'isolate 2';");
15856     ExpectString("function f() { return foo; }; f()", "isolate 2");
15857   }
15858
15859   {
15860     v8::Context::Scope cscope(context1);
15861     v8::HandleScope scope;
15862     // Now again in isolate 1
15863     ExpectString("function f() { return foo; }; f()", "isolate 1");
15864   }
15865
15866   isolate1->Exit();
15867
15868   // Run some stuff in default isolate.
15869   v8::Persistent<v8::Context> context_default = v8::Context::New();
15870
15871   {
15872     v8::Context::Scope cscope(context_default);
15873     v8::HandleScope scope;
15874     // Variables in other isolates should be not available, verify there
15875     // is an exception.
15876     ExpectTrue("function f() {"
15877                "  try {"
15878                "    foo;"
15879                "    return false;"
15880                "  } catch(e) {"
15881                "    return true;"
15882                "  }"
15883                "};"
15884                "var isDefaultIsolate = true;"
15885                "f()");
15886   }
15887
15888   isolate1->Enter();
15889
15890   {
15891     v8::Isolate::Scope iscope(isolate2);
15892     v8::Context::Scope cscope(context2);
15893     v8::HandleScope scope;
15894     ExpectString("function f() { return foo; }; f()", "isolate 2");
15895   }
15896
15897   {
15898     v8::Context::Scope cscope(context1);
15899     v8::HandleScope scope;
15900     ExpectString("function f() { return foo; }; f()", "isolate 1");
15901   }
15902
15903   {
15904     v8::Isolate::Scope iscope(isolate2);
15905     context2.Dispose();
15906   }
15907
15908   context1.Dispose();
15909   isolate1->Exit();
15910
15911   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
15912   last_location = last_message = NULL;
15913
15914   isolate1->Dispose();
15915   CHECK_EQ(last_location, NULL);
15916   CHECK_EQ(last_message, NULL);
15917
15918   isolate2->Dispose();
15919   CHECK_EQ(last_location, NULL);
15920   CHECK_EQ(last_message, NULL);
15921
15922   // Check that default isolate still runs.
15923   {
15924     v8::Context::Scope cscope(context_default);
15925     v8::HandleScope scope;
15926     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
15927   }
15928 }
15929
15930 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
15931   v8::Isolate::Scope isolate_scope(isolate);
15932   v8::HandleScope scope;
15933   LocalContext context;
15934   i::ScopedVector<char> code(1024);
15935   i::OS::SNPrintF(code, "function fib(n) {"
15936                         "  if (n <= 2) return 1;"
15937                         "  return fib(n-1) + fib(n-2);"
15938                         "}"
15939                         "fib(%d)", limit);
15940   Local<Value> value = CompileRun(code.start());
15941   CHECK(value->IsNumber());
15942   return static_cast<int>(value->NumberValue());
15943 }
15944
15945 class IsolateThread : public v8::internal::Thread {
15946  public:
15947   IsolateThread(v8::Isolate* isolate, int fib_limit)
15948       : Thread("IsolateThread"),
15949         isolate_(isolate),
15950         fib_limit_(fib_limit),
15951         result_(0) { }
15952
15953   void Run() {
15954     result_ = CalcFibonacci(isolate_, fib_limit_);
15955   }
15956
15957   int result() { return result_; }
15958
15959  private:
15960   v8::Isolate* isolate_;
15961   int fib_limit_;
15962   int result_;
15963 };
15964
15965 TEST(MultipleIsolatesOnIndividualThreads) {
15966   v8::Isolate* isolate1 = v8::Isolate::New();
15967   v8::Isolate* isolate2 = v8::Isolate::New();
15968
15969   IsolateThread thread1(isolate1, 21);
15970   IsolateThread thread2(isolate2, 12);
15971
15972   // Compute some fibonacci numbers on 3 threads in 3 isolates.
15973   thread1.Start();
15974   thread2.Start();
15975
15976   int result1 = CalcFibonacci(v8::Isolate::GetCurrent(), 21);
15977   int result2 = CalcFibonacci(v8::Isolate::GetCurrent(), 12);
15978
15979   thread1.Join();
15980   thread2.Join();
15981
15982   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
15983   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
15984   CHECK_EQ(result1, 10946);
15985   CHECK_EQ(result2, 144);
15986   CHECK_EQ(result1, thread1.result());
15987   CHECK_EQ(result2, thread2.result());
15988
15989   isolate1->Dispose();
15990   isolate2->Dispose();
15991 }
15992
15993 TEST(IsolateDifferentContexts) {
15994   v8::Isolate* isolate = v8::Isolate::New();
15995   Persistent<v8::Context> context;
15996   {
15997     v8::Isolate::Scope isolate_scope(isolate);
15998     v8::HandleScope handle_scope;
15999     context = v8::Context::New();
16000     v8::Context::Scope context_scope(context);
16001     Local<Value> v = CompileRun("2");
16002     CHECK(v->IsNumber());
16003     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
16004   }
16005   {
16006     v8::Isolate::Scope isolate_scope(isolate);
16007     v8::HandleScope handle_scope;
16008     context = v8::Context::New();
16009     v8::Context::Scope context_scope(context);
16010     Local<Value> v = CompileRun("22");
16011     CHECK(v->IsNumber());
16012     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
16013   }
16014 }
16015
16016 class InitDefaultIsolateThread : public v8::internal::Thread {
16017  public:
16018   enum TestCase {
16019     IgnoreOOM,
16020     SetResourceConstraints,
16021     SetFatalHandler,
16022     SetCounterFunction,
16023     SetCreateHistogramFunction,
16024     SetAddHistogramSampleFunction
16025   };
16026
16027   explicit InitDefaultIsolateThread(TestCase testCase)
16028       : Thread("InitDefaultIsolateThread"),
16029         testCase_(testCase),
16030         result_(false) { }
16031
16032   void Run() {
16033     switch (testCase_) {
16034     case IgnoreOOM:
16035       v8::V8::IgnoreOutOfMemoryException();
16036       break;
16037
16038     case SetResourceConstraints: {
16039       static const int K = 1024;
16040       v8::ResourceConstraints constraints;
16041       constraints.set_max_young_space_size(256 * K);
16042       constraints.set_max_old_space_size(4 * K * K);
16043       v8::SetResourceConstraints(&constraints);
16044       break;
16045     }
16046
16047     case SetFatalHandler:
16048       v8::V8::SetFatalErrorHandler(NULL);
16049       break;
16050
16051     case SetCounterFunction:
16052       v8::V8::SetCounterFunction(NULL);
16053       break;
16054
16055     case SetCreateHistogramFunction:
16056       v8::V8::SetCreateHistogramFunction(NULL);
16057       break;
16058
16059     case SetAddHistogramSampleFunction:
16060       v8::V8::SetAddHistogramSampleFunction(NULL);
16061       break;
16062     }
16063     result_ = true;
16064   }
16065
16066   bool result() { return result_; }
16067
16068  private:
16069   TestCase testCase_;
16070   bool result_;
16071 };
16072
16073
16074 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
16075   InitDefaultIsolateThread thread(testCase);
16076   thread.Start();
16077   thread.Join();
16078   CHECK_EQ(thread.result(), true);
16079 }
16080
16081 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
16082   InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
16083 }
16084
16085 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
16086   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
16087 }
16088
16089 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
16090   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
16091 }
16092
16093 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
16094   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
16095 }
16096
16097 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
16098   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
16099 }
16100
16101 TEST(InitializeDefaultIsolateOnSecondaryThread6) {
16102   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
16103 }
16104
16105
16106 TEST(StringCheckMultipleContexts) {
16107   const char* code =
16108       "(function() { return \"a\".charAt(0); })()";
16109
16110   {
16111     // Run the code twice in the first context to initialize the call IC.
16112     v8::HandleScope scope;
16113     LocalContext context1;
16114     ExpectString(code, "a");
16115     ExpectString(code, "a");
16116   }
16117
16118   {
16119     // Change the String.prototype in the second context and check
16120     // that the right function gets called.
16121     v8::HandleScope scope;
16122     LocalContext context2;
16123     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
16124     ExpectString(code, "not a");
16125   }
16126 }
16127
16128
16129 TEST(NumberCheckMultipleContexts) {
16130   const char* code =
16131       "(function() { return (42).toString(); })()";
16132
16133   {
16134     // Run the code twice in the first context to initialize the call IC.
16135     v8::HandleScope scope;
16136     LocalContext context1;
16137     ExpectString(code, "42");
16138     ExpectString(code, "42");
16139   }
16140
16141   {
16142     // Change the Number.prototype in the second context and check
16143     // that the right function gets called.
16144     v8::HandleScope scope;
16145     LocalContext context2;
16146     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
16147     ExpectString(code, "not 42");
16148   }
16149 }
16150
16151
16152 TEST(BooleanCheckMultipleContexts) {
16153   const char* code =
16154       "(function() { return true.toString(); })()";
16155
16156   {
16157     // Run the code twice in the first context to initialize the call IC.
16158     v8::HandleScope scope;
16159     LocalContext context1;
16160     ExpectString(code, "true");
16161     ExpectString(code, "true");
16162   }
16163
16164   {
16165     // Change the Boolean.prototype in the second context and check
16166     // that the right function gets called.
16167     v8::HandleScope scope;
16168     LocalContext context2;
16169     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
16170     ExpectString(code, "");
16171   }
16172 }
16173
16174
16175 TEST(DontDeleteCellLoadIC) {
16176   const char* function_code =
16177       "function readCell() { while (true) { return cell; } }";
16178
16179   {
16180     // Run the code twice in the first context to initialize the load
16181     // IC for a don't delete cell.
16182     v8::HandleScope scope;
16183     LocalContext context1;
16184     CompileRun("var cell = \"first\";");
16185     ExpectBoolean("delete cell", false);
16186     CompileRun(function_code);
16187     ExpectString("readCell()", "first");
16188     ExpectString("readCell()", "first");
16189   }
16190
16191   {
16192     // Use a deletable cell in the second context.
16193     v8::HandleScope scope;
16194     LocalContext context2;
16195     CompileRun("cell = \"second\";");
16196     CompileRun(function_code);
16197     ExpectString("readCell()", "second");
16198     ExpectBoolean("delete cell", true);
16199     ExpectString("(function() {"
16200                  "  try {"
16201                  "    return readCell();"
16202                  "  } catch(e) {"
16203                  "    return e.toString();"
16204                  "  }"
16205                  "})()",
16206                  "ReferenceError: cell is not defined");
16207     CompileRun("cell = \"new_second\";");
16208     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
16209     ExpectString("readCell()", "new_second");
16210     ExpectString("readCell()", "new_second");
16211   }
16212 }
16213
16214
16215 TEST(DontDeleteCellLoadICForceDelete) {
16216   const char* function_code =
16217       "function readCell() { while (true) { return cell; } }";
16218
16219   // Run the code twice to initialize the load IC for a don't delete
16220   // cell.
16221   v8::HandleScope scope;
16222   LocalContext context;
16223   CompileRun("var cell = \"value\";");
16224   ExpectBoolean("delete cell", false);
16225   CompileRun(function_code);
16226   ExpectString("readCell()", "value");
16227   ExpectString("readCell()", "value");
16228
16229   // Delete the cell using the API and check the inlined code works
16230   // correctly.
16231   CHECK(context->Global()->ForceDelete(v8_str("cell")));
16232   ExpectString("(function() {"
16233                "  try {"
16234                "    return readCell();"
16235                "  } catch(e) {"
16236                "    return e.toString();"
16237                "  }"
16238                "})()",
16239                "ReferenceError: cell is not defined");
16240 }
16241
16242
16243 TEST(DontDeleteCellLoadICAPI) {
16244   const char* function_code =
16245       "function readCell() { while (true) { return cell; } }";
16246
16247   // Run the code twice to initialize the load IC for a don't delete
16248   // cell created using the API.
16249   v8::HandleScope scope;
16250   LocalContext context;
16251   context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
16252   ExpectBoolean("delete cell", false);
16253   CompileRun(function_code);
16254   ExpectString("readCell()", "value");
16255   ExpectString("readCell()", "value");
16256
16257   // Delete the cell using the API and check the inlined code works
16258   // correctly.
16259   CHECK(context->Global()->ForceDelete(v8_str("cell")));
16260   ExpectString("(function() {"
16261                "  try {"
16262                "    return readCell();"
16263                "  } catch(e) {"
16264                "    return e.toString();"
16265                "  }"
16266                "})()",
16267                "ReferenceError: cell is not defined");
16268 }
16269
16270
16271 class Visitor42 : public v8::PersistentHandleVisitor {
16272  public:
16273   explicit Visitor42(v8::Persistent<v8::Object> object)
16274       : counter_(0), object_(object) { }
16275
16276   virtual void VisitPersistentHandle(Persistent<Value> value,
16277                                      uint16_t class_id) {
16278     if (class_id == 42) {
16279       CHECK(value->IsObject());
16280       v8::Persistent<v8::Object> visited =
16281           v8::Persistent<v8::Object>::Cast(value);
16282       CHECK_EQ(42, visited.WrapperClassId());
16283       CHECK_EQ(object_, visited);
16284       ++counter_;
16285     }
16286   }
16287
16288   int counter_;
16289   v8::Persistent<v8::Object> object_;
16290 };
16291
16292
16293 TEST(PersistentHandleVisitor) {
16294   v8::HandleScope scope;
16295   LocalContext context;
16296   v8::Persistent<v8::Object> object =
16297       v8::Persistent<v8::Object>::New(v8::Object::New());
16298   CHECK_EQ(0, object.WrapperClassId());
16299   object.SetWrapperClassId(42);
16300   CHECK_EQ(42, object.WrapperClassId());
16301
16302   Visitor42 visitor(object);
16303   v8::V8::VisitHandlesWithClassIds(&visitor);
16304   CHECK_EQ(1, visitor.counter_);
16305
16306   object.Dispose();
16307 }
16308
16309
16310 TEST(RegExp) {
16311   v8::HandleScope scope;
16312   LocalContext context;
16313
16314   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
16315   CHECK(re->IsRegExp());
16316   CHECK(re->GetSource()->Equals(v8_str("foo")));
16317   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
16318
16319   re = v8::RegExp::New(v8_str("bar"),
16320                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
16321                                                       v8::RegExp::kGlobal));
16322   CHECK(re->IsRegExp());
16323   CHECK(re->GetSource()->Equals(v8_str("bar")));
16324   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
16325            static_cast<int>(re->GetFlags()));
16326
16327   re = v8::RegExp::New(v8_str("baz"),
16328                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
16329                                                       v8::RegExp::kMultiline));
16330   CHECK(re->IsRegExp());
16331   CHECK(re->GetSource()->Equals(v8_str("baz")));
16332   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
16333            static_cast<int>(re->GetFlags()));
16334
16335   re = CompileRun("/quux/").As<v8::RegExp>();
16336   CHECK(re->IsRegExp());
16337   CHECK(re->GetSource()->Equals(v8_str("quux")));
16338   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
16339
16340   re = CompileRun("/quux/gm").As<v8::RegExp>();
16341   CHECK(re->IsRegExp());
16342   CHECK(re->GetSource()->Equals(v8_str("quux")));
16343   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
16344            static_cast<int>(re->GetFlags()));
16345
16346   // Override the RegExp constructor and check the API constructor
16347   // still works.
16348   CompileRun("RegExp = function() {}");
16349
16350   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
16351   CHECK(re->IsRegExp());
16352   CHECK(re->GetSource()->Equals(v8_str("foobar")));
16353   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
16354
16355   re = v8::RegExp::New(v8_str("foobarbaz"),
16356                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
16357                                                       v8::RegExp::kMultiline));
16358   CHECK(re->IsRegExp());
16359   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
16360   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
16361            static_cast<int>(re->GetFlags()));
16362
16363   context->Global()->Set(v8_str("re"), re);
16364   ExpectTrue("re.test('FoobarbaZ')");
16365
16366   // RegExps are objects on which you can set properties.
16367   re->Set(v8_str("property"), v8::Integer::New(32));
16368   v8::Handle<v8::Value> value(CompileRun("re.property"));
16369   CHECK_EQ(32, value->Int32Value());
16370
16371   v8::TryCatch try_catch;
16372   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
16373   CHECK(re.IsEmpty());
16374   CHECK(try_catch.HasCaught());
16375   context->Global()->Set(v8_str("ex"), try_catch.Exception());
16376   ExpectTrue("ex instanceof SyntaxError");
16377 }
16378
16379
16380 THREADED_TEST(Equals) {
16381   v8::HandleScope handleScope;
16382   LocalContext localContext;
16383
16384   v8::Handle<v8::Object> globalProxy = localContext->Global();
16385   v8::Handle<Value> global = globalProxy->GetPrototype();
16386
16387   CHECK(global->StrictEquals(global));
16388   CHECK(!global->StrictEquals(globalProxy));
16389   CHECK(!globalProxy->StrictEquals(global));
16390   CHECK(globalProxy->StrictEquals(globalProxy));
16391
16392   CHECK(global->Equals(global));
16393   CHECK(!global->Equals(globalProxy));
16394   CHECK(!globalProxy->Equals(global));
16395   CHECK(globalProxy->Equals(globalProxy));
16396 }
16397
16398
16399 static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
16400                                     const v8::AccessorInfo& info ) {
16401   return v8_str("42!");
16402 }
16403
16404
16405 static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo& info) {
16406   v8::Handle<v8::Array> result = v8::Array::New();
16407   result->Set(0, v8_str("universalAnswer"));
16408   return result;
16409 }
16410
16411
16412 TEST(NamedEnumeratorAndForIn) {
16413   v8::HandleScope handle_scope;
16414   LocalContext context;
16415   v8::Context::Scope context_scope(context.local());
16416
16417   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
16418   tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
16419   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
16420   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
16421         "var result = []; for (var k in o) result.push(k); result"));
16422   CHECK_EQ(1, result->Length());
16423   CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
16424 }
16425
16426
16427 TEST(DefinePropertyPostDetach) {
16428   v8::HandleScope scope;
16429   LocalContext context;
16430   v8::Handle<v8::Object> proxy = context->Global();
16431   v8::Handle<v8::Function> define_property =
16432       CompileRun("(function() {"
16433                  "  Object.defineProperty("
16434                  "    this,"
16435                  "    1,"
16436                  "    { configurable: true, enumerable: true, value: 3 });"
16437                  "})").As<Function>();
16438   context->DetachGlobal();
16439   define_property->Call(proxy, 0, NULL);
16440 }
16441
16442
16443 static void InstallContextId(v8::Handle<Context> context, int id) {
16444   Context::Scope scope(context);
16445   CompileRun("Object.prototype").As<Object>()->
16446       Set(v8_str("context_id"), v8::Integer::New(id));
16447 }
16448
16449
16450 static void CheckContextId(v8::Handle<Object> object, int expected) {
16451   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
16452 }
16453
16454
16455 THREADED_TEST(CreationContext) {
16456   HandleScope handle_scope;
16457   Persistent<Context> context1 = Context::New();
16458   InstallContextId(context1, 1);
16459   Persistent<Context> context2 = Context::New();
16460   InstallContextId(context2, 2);
16461   Persistent<Context> context3 = Context::New();
16462   InstallContextId(context3, 3);
16463
16464   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
16465
16466   Local<Object> object1;
16467   Local<Function> func1;
16468   {
16469     Context::Scope scope(context1);
16470     object1 = Object::New();
16471     func1 = tmpl->GetFunction();
16472   }
16473
16474   Local<Object> object2;
16475   Local<Function> func2;
16476   {
16477     Context::Scope scope(context2);
16478     object2 = Object::New();
16479     func2 = tmpl->GetFunction();
16480   }
16481
16482   Local<Object> instance1;
16483   Local<Object> instance2;
16484
16485   {
16486     Context::Scope scope(context3);
16487     instance1 = func1->NewInstance();
16488     instance2 = func2->NewInstance();
16489   }
16490
16491   CHECK(object1->CreationContext() == context1);
16492   CheckContextId(object1, 1);
16493   CHECK(func1->CreationContext() == context1);
16494   CheckContextId(func1, 1);
16495   CHECK(instance1->CreationContext() == context1);
16496   CheckContextId(instance1, 1);
16497   CHECK(object2->CreationContext() == context2);
16498   CheckContextId(object2, 2);
16499   CHECK(func2->CreationContext() == context2);
16500   CheckContextId(func2, 2);
16501   CHECK(instance2->CreationContext() == context2);
16502   CheckContextId(instance2, 2);
16503
16504   {
16505     Context::Scope scope(context1);
16506     CHECK(object1->CreationContext() == context1);
16507     CheckContextId(object1, 1);
16508     CHECK(func1->CreationContext() == context1);
16509     CheckContextId(func1, 1);
16510     CHECK(instance1->CreationContext() == context1);
16511     CheckContextId(instance1, 1);
16512     CHECK(object2->CreationContext() == context2);
16513     CheckContextId(object2, 2);
16514     CHECK(func2->CreationContext() == context2);
16515     CheckContextId(func2, 2);
16516     CHECK(instance2->CreationContext() == context2);
16517     CheckContextId(instance2, 2);
16518   }
16519
16520   {
16521     Context::Scope scope(context2);
16522     CHECK(object1->CreationContext() == context1);
16523     CheckContextId(object1, 1);
16524     CHECK(func1->CreationContext() == context1);
16525     CheckContextId(func1, 1);
16526     CHECK(instance1->CreationContext() == context1);
16527     CheckContextId(instance1, 1);
16528     CHECK(object2->CreationContext() == context2);
16529     CheckContextId(object2, 2);
16530     CHECK(func2->CreationContext() == context2);
16531     CheckContextId(func2, 2);
16532     CHECK(instance2->CreationContext() == context2);
16533     CheckContextId(instance2, 2);
16534   }
16535
16536   context1.Dispose();
16537   context2.Dispose();
16538   context3.Dispose();
16539 }
16540
16541
16542 THREADED_TEST(CreationContextOfJsFunction) {
16543   HandleScope handle_scope;
16544   Persistent<Context> context = Context::New();
16545   InstallContextId(context, 1);
16546
16547   Local<Object> function;
16548   {
16549     Context::Scope scope(context);
16550     function = CompileRun("function foo() {}; foo").As<Object>();
16551   }
16552
16553   CHECK(function->CreationContext() == context);
16554   CheckContextId(function, 1);
16555
16556   context.Dispose();
16557 }
16558
16559
16560 Handle<Value> HasOwnPropertyIndexedPropertyGetter(uint32_t index,
16561                                                   const AccessorInfo& info) {
16562   if (index == 42) return v8_str("yes");
16563   return Handle<v8::Integer>();
16564 }
16565
16566
16567 Handle<Value> HasOwnPropertyNamedPropertyGetter(Local<String> property,
16568                                                 const AccessorInfo& info) {
16569   if (property->Equals(v8_str("foo"))) return v8_str("yes");
16570   return Handle<Value>();
16571 }
16572
16573
16574 Handle<v8::Integer> HasOwnPropertyIndexedPropertyQuery(
16575     uint32_t index, const AccessorInfo& info) {
16576   if (index == 42) return v8_num(1).As<v8::Integer>();
16577   return Handle<v8::Integer>();
16578 }
16579
16580
16581 Handle<v8::Integer> HasOwnPropertyNamedPropertyQuery(
16582     Local<String> property, const AccessorInfo& info) {
16583   if (property->Equals(v8_str("foo"))) return v8_num(1).As<v8::Integer>();
16584   return Handle<v8::Integer>();
16585 }
16586
16587
16588 Handle<v8::Integer> HasOwnPropertyNamedPropertyQuery2(
16589     Local<String> property, const AccessorInfo& info) {
16590   if (property->Equals(v8_str("bar"))) return v8_num(1).As<v8::Integer>();
16591   return Handle<v8::Integer>();
16592 }
16593
16594
16595 Handle<Value> HasOwnPropertyAccessorGetter(Local<String> property,
16596                                            const AccessorInfo& info) {
16597   return v8_str("yes");
16598 }
16599
16600
16601 TEST(HasOwnProperty) {
16602   v8::HandleScope scope;
16603   LocalContext env;
16604   { // Check normal properties and defined getters.
16605     Handle<Value> value = CompileRun(
16606         "function Foo() {"
16607         "    this.foo = 11;"
16608         "    this.__defineGetter__('baz', function() { return 1; });"
16609         "};"
16610         "function Bar() { "
16611         "    this.bar = 13;"
16612         "    this.__defineGetter__('bla', function() { return 2; });"
16613         "};"
16614         "Bar.prototype = new Foo();"
16615         "new Bar();");
16616     CHECK(value->IsObject());
16617     Handle<Object> object = value->ToObject();
16618     CHECK(object->Has(v8_str("foo")));
16619     CHECK(!object->HasOwnProperty(v8_str("foo")));
16620     CHECK(object->HasOwnProperty(v8_str("bar")));
16621     CHECK(object->Has(v8_str("baz")));
16622     CHECK(!object->HasOwnProperty(v8_str("baz")));
16623     CHECK(object->HasOwnProperty(v8_str("bla")));
16624   }
16625   { // Check named getter interceptors.
16626     Handle<ObjectTemplate> templ = ObjectTemplate::New();
16627     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
16628     Handle<Object> instance = templ->NewInstance();
16629     CHECK(!instance->HasOwnProperty(v8_str("42")));
16630     CHECK(instance->HasOwnProperty(v8_str("foo")));
16631     CHECK(!instance->HasOwnProperty(v8_str("bar")));
16632   }
16633   { // Check indexed getter interceptors.
16634     Handle<ObjectTemplate> templ = ObjectTemplate::New();
16635     templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
16636     Handle<Object> instance = templ->NewInstance();
16637     CHECK(instance->HasOwnProperty(v8_str("42")));
16638     CHECK(!instance->HasOwnProperty(v8_str("43")));
16639     CHECK(!instance->HasOwnProperty(v8_str("foo")));
16640   }
16641   { // Check named query interceptors.
16642     Handle<ObjectTemplate> templ = ObjectTemplate::New();
16643     templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
16644     Handle<Object> instance = templ->NewInstance();
16645     CHECK(instance->HasOwnProperty(v8_str("foo")));
16646     CHECK(!instance->HasOwnProperty(v8_str("bar")));
16647   }
16648   { // Check indexed query interceptors.
16649     Handle<ObjectTemplate> templ = ObjectTemplate::New();
16650     templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
16651     Handle<Object> instance = templ->NewInstance();
16652     CHECK(instance->HasOwnProperty(v8_str("42")));
16653     CHECK(!instance->HasOwnProperty(v8_str("41")));
16654   }
16655   { // Check callbacks.
16656     Handle<ObjectTemplate> templ = ObjectTemplate::New();
16657     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
16658     Handle<Object> instance = templ->NewInstance();
16659     CHECK(instance->HasOwnProperty(v8_str("foo")));
16660     CHECK(!instance->HasOwnProperty(v8_str("bar")));
16661   }
16662   { // Check that query wins on disagreement.
16663     Handle<ObjectTemplate> templ = ObjectTemplate::New();
16664     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
16665                                    0,
16666                                    HasOwnPropertyNamedPropertyQuery2);
16667     Handle<Object> instance = templ->NewInstance();
16668     CHECK(!instance->HasOwnProperty(v8_str("foo")));
16669     CHECK(instance->HasOwnProperty(v8_str("bar")));
16670   }
16671 }
16672
16673
16674 void CheckCodeGenerationAllowed() {
16675   Handle<Value> result = CompileRun("eval('42')");
16676   CHECK_EQ(42, result->Int32Value());
16677   result = CompileRun("(function(e) { return e('42'); })(eval)");
16678   CHECK_EQ(42, result->Int32Value());
16679   result = CompileRun("var f = new Function('return 42'); f()");
16680   CHECK_EQ(42, result->Int32Value());
16681 }
16682
16683
16684 void CheckCodeGenerationDisallowed() {
16685   TryCatch try_catch;
16686
16687   Handle<Value> result = CompileRun("eval('42')");
16688   CHECK(result.IsEmpty());
16689   CHECK(try_catch.HasCaught());
16690   try_catch.Reset();
16691
16692   result = CompileRun("(function(e) { return e('42'); })(eval)");
16693   CHECK(result.IsEmpty());
16694   CHECK(try_catch.HasCaught());
16695   try_catch.Reset();
16696
16697   result = CompileRun("var f = new Function('return 42'); f()");
16698   CHECK(result.IsEmpty());
16699   CHECK(try_catch.HasCaught());
16700 }
16701
16702
16703 bool CodeGenerationAllowed(Local<Context> context) {
16704   ApiTestFuzzer::Fuzz();
16705   return true;
16706 }
16707
16708
16709 bool CodeGenerationDisallowed(Local<Context> context) {
16710   ApiTestFuzzer::Fuzz();
16711   return false;
16712 }
16713
16714
16715 THREADED_TEST(AllowCodeGenFromStrings) {
16716   v8::HandleScope scope;
16717   LocalContext context;
16718
16719   // eval and the Function constructor allowed by default.
16720   CHECK(context->IsCodeGenerationFromStringsAllowed());
16721   CheckCodeGenerationAllowed();
16722
16723   // Disallow eval and the Function constructor.
16724   context->AllowCodeGenerationFromStrings(false);
16725   CHECK(!context->IsCodeGenerationFromStringsAllowed());
16726   CheckCodeGenerationDisallowed();
16727
16728   // Allow again.
16729   context->AllowCodeGenerationFromStrings(true);
16730   CheckCodeGenerationAllowed();
16731
16732   // Disallow but setting a global callback that will allow the calls.
16733   context->AllowCodeGenerationFromStrings(false);
16734   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
16735   CHECK(!context->IsCodeGenerationFromStringsAllowed());
16736   CheckCodeGenerationAllowed();
16737
16738   // Set a callback that disallows the code generation.
16739   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
16740   CHECK(!context->IsCodeGenerationFromStringsAllowed());
16741   CheckCodeGenerationDisallowed();
16742 }
16743
16744
16745 TEST(SetErrorMessageForCodeGenFromStrings) {
16746   v8::HandleScope scope;
16747   LocalContext context;
16748   TryCatch try_catch;
16749
16750   Handle<String> message = v8_str("Message") ;
16751   Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
16752   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
16753   context->AllowCodeGenerationFromStrings(false);
16754   context->SetErrorMessageForCodeGenerationFromStrings(message);
16755   Handle<Value> result = CompileRun("eval('42')");
16756   CHECK(result.IsEmpty());
16757   CHECK(try_catch.HasCaught());
16758   Handle<String> actual_message = try_catch.Message()->Get();
16759   CHECK(expected_message->Equals(actual_message));
16760 }
16761
16762
16763 static v8::Handle<Value> NonObjectThis(const v8::Arguments& args) {
16764   return v8::Undefined();
16765 }
16766
16767
16768 THREADED_TEST(CallAPIFunctionOnNonObject) {
16769   v8::HandleScope scope;
16770   LocalContext context;
16771   Handle<FunctionTemplate> templ = v8::FunctionTemplate::New(NonObjectThis);
16772   Handle<Function> function = templ->GetFunction();
16773   context->Global()->Set(v8_str("f"), function);
16774   TryCatch try_catch;
16775   CompileRun("f.call(2)");
16776 }
16777
16778
16779 // Regression test for issue 1470.
16780 THREADED_TEST(ReadOnlyIndexedProperties) {
16781   v8::HandleScope scope;
16782   Local<ObjectTemplate> templ = ObjectTemplate::New();
16783
16784   LocalContext context;
16785   Local<v8::Object> obj = templ->NewInstance();
16786   context->Global()->Set(v8_str("obj"), obj);
16787   obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
16788   obj->Set(v8_str("1"), v8_str("foobar"));
16789   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
16790   obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
16791   obj->Set(v8_num(2), v8_str("foobar"));
16792   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
16793
16794   // Test non-smi case.
16795   obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
16796   obj->Set(v8_str("2000000000"), v8_str("foobar"));
16797   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
16798 }
16799
16800
16801 THREADED_TEST(Regress1516) {
16802   v8::HandleScope scope;
16803
16804   LocalContext context;
16805   { v8::HandleScope temp_scope;
16806     CompileRun("({'a': 0})");
16807   }
16808
16809   int elements;
16810   { i::MapCache* map_cache =
16811         i::MapCache::cast(i::Isolate::Current()->context()->map_cache());
16812     elements = map_cache->NumberOfElements();
16813     CHECK_LE(1, elements);
16814   }
16815
16816   i::Isolate::Current()->heap()->CollectAllGarbage(
16817       i::Heap::kAbortIncrementalMarkingMask);
16818   { i::Object* raw_map_cache = i::Isolate::Current()->context()->map_cache();
16819     if (raw_map_cache != i::Isolate::Current()->heap()->undefined_value()) {
16820       i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
16821       CHECK_GT(elements, map_cache->NumberOfElements());
16822     }
16823   }
16824 }
16825
16826
16827 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
16828                                                 Local<Value> name,
16829                                                 v8::AccessType type,
16830                                                 Local<Value> data) {
16831   // Only block read access to __proto__.
16832   if (type == v8::ACCESS_GET &&
16833       name->IsString() &&
16834       name->ToString()->Length() == 9 &&
16835       name->ToString()->Utf8Length() == 9) {
16836     char buffer[10];
16837     CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
16838     return strncmp(buffer, "__proto__", 9) != 0;
16839   }
16840
16841   return true;
16842 }
16843
16844
16845 THREADED_TEST(Regress93759) {
16846   HandleScope scope;
16847
16848   // Template for object with security check.
16849   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New();
16850   // We don't do indexing, so any callback can be used for that.
16851   no_proto_template->SetAccessCheckCallbacks(
16852       BlockProtoNamedSecurityTestCallback,
16853       IndexedSecurityTestCallback);
16854
16855   // Templates for objects with hidden prototypes and possibly security check.
16856   Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New();
16857   hidden_proto_template->SetHiddenPrototype(true);
16858
16859   Local<FunctionTemplate> protected_hidden_proto_template =
16860       v8::FunctionTemplate::New();
16861   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
16862       BlockProtoNamedSecurityTestCallback,
16863       IndexedSecurityTestCallback);
16864   protected_hidden_proto_template->SetHiddenPrototype(true);
16865
16866   // Context for "foreign" objects used in test.
16867   Persistent<Context> context = v8::Context::New();
16868   context->Enter();
16869
16870   // Plain object, no security check.
16871   Local<Object> simple_object = Object::New();
16872
16873   // Object with explicit security check.
16874   Local<Object> protected_object =
16875       no_proto_template->NewInstance();
16876
16877   // JSGlobalProxy object, always have security check.
16878   Local<Object> proxy_object =
16879       context->Global();
16880
16881   // Global object, the  prototype of proxy_object. No security checks.
16882   Local<Object> global_object =
16883       proxy_object->GetPrototype()->ToObject();
16884
16885   // Hidden prototype without security check.
16886   Local<Object> hidden_prototype =
16887       hidden_proto_template->GetFunction()->NewInstance();
16888   Local<Object> object_with_hidden =
16889     Object::New();
16890   object_with_hidden->SetPrototype(hidden_prototype);
16891
16892   // Hidden prototype with security check on the hidden prototype.
16893   Local<Object> protected_hidden_prototype =
16894       protected_hidden_proto_template->GetFunction()->NewInstance();
16895   Local<Object> object_with_protected_hidden =
16896     Object::New();
16897   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
16898
16899   context->Exit();
16900
16901   // Template for object for second context. Values to test are put on it as
16902   // properties.
16903   Local<ObjectTemplate> global_template = ObjectTemplate::New();
16904   global_template->Set(v8_str("simple"), simple_object);
16905   global_template->Set(v8_str("protected"), protected_object);
16906   global_template->Set(v8_str("global"), global_object);
16907   global_template->Set(v8_str("proxy"), proxy_object);
16908   global_template->Set(v8_str("hidden"), object_with_hidden);
16909   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
16910
16911   LocalContext context2(NULL, global_template);
16912
16913   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
16914   CHECK(result1->Equals(simple_object->GetPrototype()));
16915
16916   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
16917   CHECK(result2->Equals(Undefined()));
16918
16919   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
16920   CHECK(result3->Equals(global_object->GetPrototype()));
16921
16922   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
16923   CHECK(result4->Equals(Undefined()));
16924
16925   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
16926   CHECK(result5->Equals(
16927       object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
16928
16929   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
16930   CHECK(result6->Equals(Undefined()));
16931
16932   context.Dispose();
16933 }
16934
16935
16936 THREADED_TEST(Regress125988) {
16937   v8::HandleScope scope;
16938   Handle<FunctionTemplate> intercept = FunctionTemplate::New();
16939   AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
16940   LocalContext env;
16941   env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
16942   CompileRun("var a = new Object();"
16943              "var b = new Intercept();"
16944              "var c = new Object();"
16945              "c.__proto__ = b;"
16946              "b.__proto__ = a;"
16947              "a.x = 23;"
16948              "for (var i = 0; i < 3; i++) c.x;");
16949   ExpectBoolean("c.hasOwnProperty('x')", false);
16950   ExpectInt32("c.x", 23);
16951   CompileRun("a.y = 42;"
16952              "for (var i = 0; i < 3; i++) c.x;");
16953   ExpectBoolean("c.hasOwnProperty('x')", false);
16954   ExpectInt32("c.x", 23);
16955   ExpectBoolean("c.hasOwnProperty('y')", false);
16956   ExpectInt32("c.y", 42);
16957 }
16958
16959
16960 static void TestReceiver(Local<Value> expected_result,
16961                          Local<Value> expected_receiver,
16962                          const char* code) {
16963   Local<Value> result = CompileRun(code);
16964   CHECK(result->IsObject());
16965   CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
16966   CHECK(expected_result->Equals(result->ToObject()->Get(0)));
16967 }
16968
16969
16970 THREADED_TEST(ForeignFunctionReceiver) {
16971   HandleScope scope;
16972
16973   // Create two contexts with different "id" properties ('i' and 'o').
16974   // Call a function both from its own context and from a the foreign
16975   // context, and see what "this" is bound to (returning both "this"
16976   // and "this.id" for comparison).
16977
16978   Persistent<Context> foreign_context = v8::Context::New();
16979   foreign_context->Enter();
16980   Local<Value> foreign_function =
16981     CompileRun("function func() { return { 0: this.id, "
16982                "                           1: this, "
16983                "                           toString: function() { "
16984                "                               return this[0];"
16985                "                           }"
16986                "                         };"
16987                "}"
16988                "var id = 'i';"
16989                "func;");
16990   CHECK(foreign_function->IsFunction());
16991   foreign_context->Exit();
16992
16993   LocalContext context;
16994
16995   Local<String> password = v8_str("Password");
16996   // Don't get hit by security checks when accessing foreign_context's
16997   // global receiver (aka. global proxy).
16998   context->SetSecurityToken(password);
16999   foreign_context->SetSecurityToken(password);
17000
17001   Local<String> i = v8_str("i");
17002   Local<String> o = v8_str("o");
17003   Local<String> id = v8_str("id");
17004
17005   CompileRun("function ownfunc() { return { 0: this.id, "
17006              "                              1: this, "
17007              "                              toString: function() { "
17008              "                                  return this[0];"
17009              "                              }"
17010              "                             };"
17011              "}"
17012              "var id = 'o';"
17013              "ownfunc");
17014   context->Global()->Set(v8_str("func"), foreign_function);
17015
17016   // Sanity check the contexts.
17017   CHECK(i->Equals(foreign_context->Global()->Get(id)));
17018   CHECK(o->Equals(context->Global()->Get(id)));
17019
17020   // Checking local function's receiver.
17021   // Calling function using its call/apply methods.
17022   TestReceiver(o, context->Global(), "ownfunc.call()");
17023   TestReceiver(o, context->Global(), "ownfunc.apply()");
17024   // Making calls through built-in functions.
17025   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
17026   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
17027   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
17028   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
17029   // Calling with environment record as base.
17030   TestReceiver(o, context->Global(), "ownfunc()");
17031   // Calling with no base.
17032   TestReceiver(o, context->Global(), "(1,ownfunc)()");
17033
17034   // Checking foreign function return value.
17035   // Calling function using its call/apply methods.
17036   TestReceiver(i, foreign_context->Global(), "func.call()");
17037   TestReceiver(i, foreign_context->Global(), "func.apply()");
17038   // Calling function using another context's call/apply methods.
17039   TestReceiver(i, foreign_context->Global(),
17040                "Function.prototype.call.call(func)");
17041   TestReceiver(i, foreign_context->Global(),
17042                "Function.prototype.call.apply(func)");
17043   TestReceiver(i, foreign_context->Global(),
17044                "Function.prototype.apply.call(func)");
17045   TestReceiver(i, foreign_context->Global(),
17046                "Function.prototype.apply.apply(func)");
17047   // Making calls through built-in functions.
17048   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
17049   // ToString(func()) is func()[0], i.e., the returned this.id.
17050   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
17051   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
17052   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
17053
17054   // TODO(1547): Make the following also return "i".
17055   // Calling with environment record as base.
17056   TestReceiver(o, context->Global(), "func()");
17057   // Calling with no base.
17058   TestReceiver(o, context->Global(), "(1,func)()");
17059
17060   foreign_context.Dispose();
17061 }
17062
17063
17064 uint8_t callback_fired = 0;
17065
17066
17067 void CallCompletedCallback1() {
17068   i::OS::Print("Firing callback 1.\n");
17069   callback_fired ^= 1;  // Toggle first bit.
17070 }
17071
17072
17073 void CallCompletedCallback2() {
17074   i::OS::Print("Firing callback 2.\n");
17075   callback_fired ^= 2;  // Toggle second bit.
17076 }
17077
17078
17079 Handle<Value> RecursiveCall(const Arguments& args) {
17080   int32_t level = args[0]->Int32Value();
17081   if (level < 3) {
17082     level++;
17083     i::OS::Print("Entering recursion level %d.\n", level);
17084     char script[64];
17085     i::Vector<char> script_vector(script, sizeof(script));
17086     i::OS::SNPrintF(script_vector, "recursion(%d)", level);
17087     CompileRun(script_vector.start());
17088     i::OS::Print("Leaving recursion level %d.\n", level);
17089     CHECK_EQ(0, callback_fired);
17090   } else {
17091     i::OS::Print("Recursion ends.\n");
17092     CHECK_EQ(0, callback_fired);
17093   }
17094   return Undefined();
17095 }
17096
17097
17098 TEST(CallCompletedCallback) {
17099   v8::HandleScope scope;
17100   LocalContext env;
17101   v8::Handle<v8::FunctionTemplate> recursive_runtime =
17102       v8::FunctionTemplate::New(RecursiveCall);
17103   env->Global()->Set(v8_str("recursion"),
17104                      recursive_runtime->GetFunction());
17105   // Adding the same callback a second time has no effect.
17106   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
17107   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
17108   v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
17109   i::OS::Print("--- Script (1) ---\n");
17110   Local<Script> script =
17111       v8::Script::Compile(v8::String::New("recursion(0)"));
17112   script->Run();
17113   CHECK_EQ(3, callback_fired);
17114
17115   i::OS::Print("\n--- Script (2) ---\n");
17116   callback_fired = 0;
17117   v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
17118   script->Run();
17119   CHECK_EQ(2, callback_fired);
17120
17121   i::OS::Print("\n--- Function ---\n");
17122   callback_fired = 0;
17123   Local<Function> recursive_function =
17124       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
17125   v8::Handle<Value> args[] = { v8_num(0) };
17126   recursive_function->Call(env->Global(), 1, args);
17127   CHECK_EQ(2, callback_fired);
17128 }
17129
17130
17131 void CallCompletedCallbackNoException() {
17132   v8::HandleScope scope;
17133   CompileRun("1+1;");
17134 }
17135
17136
17137 void CallCompletedCallbackException() {
17138   v8::HandleScope scope;
17139   CompileRun("throw 'second exception';");
17140 }
17141
17142
17143 TEST(CallCompletedCallbackOneException) {
17144   v8::HandleScope scope;
17145   LocalContext env;
17146   v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
17147   CompileRun("throw 'exception';");
17148 }
17149
17150
17151 TEST(CallCompletedCallbackTwoExceptions) {
17152   v8::HandleScope scope;
17153   LocalContext env;
17154   v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
17155   CompileRun("throw 'first exception';");
17156 }
17157
17158
17159 static int probes_counter = 0;
17160 static int misses_counter = 0;
17161 static int updates_counter = 0;
17162
17163
17164 static int* LookupCounter(const char* name) {
17165   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
17166     return &probes_counter;
17167   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
17168     return &misses_counter;
17169   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
17170     return &updates_counter;
17171   }
17172   return NULL;
17173 }
17174
17175
17176 static const char* kMegamorphicTestProgram =
17177     "function ClassA() { };"
17178     "function ClassB() { };"
17179     "ClassA.prototype.foo = function() { };"
17180     "ClassB.prototype.foo = function() { };"
17181     "function fooify(obj) { obj.foo(); };"
17182     "var a = new ClassA();"
17183     "var b = new ClassB();"
17184     "for (var i = 0; i < 10000; i++) {"
17185     "  fooify(a);"
17186     "  fooify(b);"
17187     "}";
17188
17189
17190 static void StubCacheHelper(bool primary) {
17191   V8::SetCounterFunction(LookupCounter);
17192   USE(kMegamorphicTestProgram);
17193 #ifdef DEBUG
17194   i::FLAG_native_code_counters = true;
17195   if (primary) {
17196     i::FLAG_test_primary_stub_cache = true;
17197   } else {
17198     i::FLAG_test_secondary_stub_cache = true;
17199   }
17200   i::FLAG_crankshaft = false;
17201   v8::HandleScope scope;
17202   LocalContext env;
17203   int initial_probes = probes_counter;
17204   int initial_misses = misses_counter;
17205   int initial_updates = updates_counter;
17206   CompileRun(kMegamorphicTestProgram);
17207   int probes = probes_counter - initial_probes;
17208   int misses = misses_counter - initial_misses;
17209   int updates = updates_counter - initial_updates;
17210   CHECK_LT(updates, 10);
17211   CHECK_LT(misses, 10);
17212   CHECK_GE(probes, 10000);
17213 #endif
17214 }
17215
17216
17217 TEST(SecondaryStubCache) {
17218   StubCacheHelper(true);
17219 }
17220
17221
17222 TEST(PrimaryStubCache) {
17223   StubCacheHelper(false);
17224 }
17225
17226
17227 static int fatal_error_callback_counter = 0;
17228 static void CountingErrorCallback(const char* location, const char* message) {
17229   printf("CountingErrorCallback(\"%s\", \"%s\")\n", location, message);
17230   fatal_error_callback_counter++;
17231 }
17232
17233
17234 TEST(StaticGetters) {
17235   v8::HandleScope scope;
17236   LocalContext context;
17237   v8::Isolate* isolate = v8::Isolate::GetCurrent();
17238   i::Handle<i::Object> undefined_value = FACTORY->undefined_value();
17239   CHECK(*v8::Utils::OpenHandle(*v8::Undefined()) == *undefined_value);
17240   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
17241   i::Handle<i::Object> null_value = FACTORY->null_value();
17242   CHECK(*v8::Utils::OpenHandle(*v8::Null()) == *null_value);
17243   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
17244   i::Handle<i::Object> true_value = FACTORY->true_value();
17245   CHECK(*v8::Utils::OpenHandle(*v8::True()) == *true_value);
17246   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
17247   i::Handle<i::Object> false_value = FACTORY->false_value();
17248   CHECK(*v8::Utils::OpenHandle(*v8::False()) == *false_value);
17249   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
17250
17251   // Test after-death behavior.
17252   CHECK(i::Internals::IsInitialized(isolate));
17253   CHECK_EQ(0, fatal_error_callback_counter);
17254   v8::V8::SetFatalErrorHandler(CountingErrorCallback);
17255   v8::Utils::ReportApiFailure("StaticGetters()", "Kill V8");
17256   i::Isolate::Current()->TearDown();
17257   CHECK(!i::Internals::IsInitialized(isolate));
17258   CHECK_EQ(1, fatal_error_callback_counter);
17259   CHECK(v8::Undefined().IsEmpty());
17260   CHECK_EQ(2, fatal_error_callback_counter);
17261   CHECK(v8::Undefined(isolate).IsEmpty());
17262   CHECK_EQ(3, fatal_error_callback_counter);
17263   CHECK(v8::Null().IsEmpty());
17264   CHECK_EQ(4, fatal_error_callback_counter);
17265   CHECK(v8::Null(isolate).IsEmpty());
17266   CHECK_EQ(5, fatal_error_callback_counter);
17267   CHECK(v8::True().IsEmpty());
17268   CHECK_EQ(6, fatal_error_callback_counter);
17269   CHECK(v8::True(isolate).IsEmpty());
17270   CHECK_EQ(7, fatal_error_callback_counter);
17271   CHECK(v8::False().IsEmpty());
17272   CHECK_EQ(8, fatal_error_callback_counter);
17273   CHECK(v8::False(isolate).IsEmpty());
17274   CHECK_EQ(9, fatal_error_callback_counter);
17275 }
17276
17277
17278 TEST(IsolateEmbedderData) {
17279   v8::Isolate* isolate = v8::Isolate::GetCurrent();
17280   CHECK_EQ(NULL, isolate->GetData());
17281   CHECK_EQ(NULL, ISOLATE->GetData());
17282   static void* data1 = reinterpret_cast<void*>(0xacce55ed);
17283   isolate->SetData(data1);
17284   CHECK_EQ(data1, isolate->GetData());
17285   CHECK_EQ(data1, ISOLATE->GetData());
17286   static void* data2 = reinterpret_cast<void*>(0xdecea5ed);
17287   ISOLATE->SetData(data2);
17288   CHECK_EQ(data2, isolate->GetData());
17289   CHECK_EQ(data2, ISOLATE->GetData());
17290   ISOLATE->TearDown();
17291   CHECK_EQ(data2, isolate->GetData());
17292   CHECK_EQ(data2, ISOLATE->GetData());
17293 }
17294
17295
17296 TEST(StringEmpty) {
17297   v8::HandleScope scope;
17298   LocalContext context;
17299   v8::Isolate* isolate = v8::Isolate::GetCurrent();
17300   i::Handle<i::Object> empty_string = FACTORY->empty_symbol();
17301   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty()) == *empty_string);
17302   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
17303
17304   // Test after-death behavior.
17305   CHECK(i::Internals::IsInitialized(isolate));
17306   CHECK_EQ(0, fatal_error_callback_counter);
17307   v8::V8::SetFatalErrorHandler(CountingErrorCallback);
17308   v8::Utils::ReportApiFailure("StringEmpty()", "Kill V8");
17309   i::Isolate::Current()->TearDown();
17310   CHECK(!i::Internals::IsInitialized(isolate));
17311   CHECK_EQ(1, fatal_error_callback_counter);
17312   CHECK(v8::String::Empty().IsEmpty());
17313   CHECK_EQ(2, fatal_error_callback_counter);
17314   CHECK(v8::String::Empty(isolate).IsEmpty());
17315   CHECK_EQ(3, fatal_error_callback_counter);
17316 }
17317
17318
17319 static int instance_checked_getter_count = 0;
17320 static Handle<Value> InstanceCheckedGetter(Local<String> name,
17321                                            const AccessorInfo& info) {
17322   CHECK_EQ(name, v8_str("foo"));
17323   instance_checked_getter_count++;
17324   return v8_num(11);
17325 }
17326
17327
17328 static int instance_checked_setter_count = 0;
17329 static void InstanceCheckedSetter(Local<String> name,
17330                       Local<Value> value,
17331                       const AccessorInfo& info) {
17332   CHECK_EQ(name, v8_str("foo"));
17333   CHECK_EQ(value, v8_num(23));
17334   instance_checked_setter_count++;
17335 }
17336
17337
17338 static void CheckInstanceCheckedResult(int getters,
17339                                        int setters,
17340                                        bool expects_callbacks,
17341                                        TryCatch* try_catch) {
17342   if (expects_callbacks) {
17343     CHECK(!try_catch->HasCaught());
17344     CHECK_EQ(getters, instance_checked_getter_count);
17345     CHECK_EQ(setters, instance_checked_setter_count);
17346   } else {
17347     CHECK(try_catch->HasCaught());
17348     CHECK_EQ(0, instance_checked_getter_count);
17349     CHECK_EQ(0, instance_checked_setter_count);
17350   }
17351   try_catch->Reset();
17352 }
17353
17354
17355 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
17356   instance_checked_getter_count = 0;
17357   instance_checked_setter_count = 0;
17358   TryCatch try_catch;
17359
17360   // Test path through generic runtime code.
17361   CompileRun("obj.foo");
17362   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
17363   CompileRun("obj.foo = 23");
17364   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
17365
17366   // Test path through generated LoadIC and StoredIC.
17367   CompileRun("function test_get(o) { o.foo; }"
17368              "test_get(obj);");
17369   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
17370   CompileRun("test_get(obj);");
17371   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
17372   CompileRun("test_get(obj);");
17373   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
17374   CompileRun("function test_set(o) { o.foo = 23; }"
17375              "test_set(obj);");
17376   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
17377   CompileRun("test_set(obj);");
17378   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
17379   CompileRun("test_set(obj);");
17380   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
17381
17382   // Test path through optimized code.
17383   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
17384              "test_get(obj);");
17385   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
17386   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
17387              "test_set(obj);");
17388   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
17389
17390   // Cleanup so that closures start out fresh in next check.
17391   CompileRun("%DeoptimizeFunction(test_get);"
17392              "%ClearFunctionTypeFeedback(test_get);"
17393              "%DeoptimizeFunction(test_set);"
17394              "%ClearFunctionTypeFeedback(test_set);");
17395 }
17396
17397
17398 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
17399   v8::internal::FLAG_allow_natives_syntax = true;
17400   v8::HandleScope scope;
17401   LocalContext context;
17402
17403   Local<FunctionTemplate> templ = FunctionTemplate::New();
17404   Local<ObjectTemplate> inst = templ->InstanceTemplate();
17405   inst->SetAccessor(v8_str("foo"),
17406                     InstanceCheckedGetter, InstanceCheckedSetter,
17407                     Handle<Value>(),
17408                     v8::DEFAULT,
17409                     v8::None,
17410                     v8::AccessorSignature::New(templ));
17411   context->Global()->Set(v8_str("f"), templ->GetFunction());
17412
17413   printf("Testing positive ...\n");
17414   CompileRun("var obj = new f();");
17415   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
17416   CheckInstanceCheckedAccessors(true);
17417
17418   printf("Testing negative ...\n");
17419   CompileRun("var obj = {};"
17420              "obj.__proto__ = new f();");
17421   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
17422   CheckInstanceCheckedAccessors(false);
17423 }
17424
17425
17426 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
17427   v8::internal::FLAG_allow_natives_syntax = true;
17428   v8::HandleScope scope;
17429   LocalContext context;
17430
17431   Local<FunctionTemplate> templ = FunctionTemplate::New();
17432   Local<ObjectTemplate> inst = templ->InstanceTemplate();
17433   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
17434   inst->SetAccessor(v8_str("foo"),
17435                     InstanceCheckedGetter, InstanceCheckedSetter,
17436                     Handle<Value>(),
17437                     v8::DEFAULT,
17438                     v8::None,
17439                     v8::AccessorSignature::New(templ));
17440   context->Global()->Set(v8_str("f"), templ->GetFunction());
17441
17442   printf("Testing positive ...\n");
17443   CompileRun("var obj = new f();");
17444   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
17445   CheckInstanceCheckedAccessors(true);
17446
17447   printf("Testing negative ...\n");
17448   CompileRun("var obj = {};"
17449              "obj.__proto__ = new f();");
17450   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
17451   CheckInstanceCheckedAccessors(false);
17452 }
17453
17454
17455 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
17456   v8::internal::FLAG_allow_natives_syntax = true;
17457   v8::HandleScope scope;
17458   LocalContext context;
17459
17460   Local<FunctionTemplate> templ = FunctionTemplate::New();
17461   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
17462   proto->SetAccessor(v8_str("foo"),
17463                      InstanceCheckedGetter, InstanceCheckedSetter,
17464                      Handle<Value>(),
17465                      v8::DEFAULT,
17466                      v8::None,
17467                      v8::AccessorSignature::New(templ));
17468   context->Global()->Set(v8_str("f"), templ->GetFunction());
17469
17470   printf("Testing positive ...\n");
17471   CompileRun("var obj = new f();");
17472   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
17473   CheckInstanceCheckedAccessors(true);
17474
17475   printf("Testing negative ...\n");
17476   CompileRun("var obj = {};"
17477              "obj.__proto__ = new f();");
17478   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
17479   CheckInstanceCheckedAccessors(false);
17480
17481   printf("Testing positive with modified prototype chain ...\n");
17482   CompileRun("var obj = new f();"
17483              "var pro = {};"
17484              "pro.__proto__ = obj.__proto__;"
17485              "obj.__proto__ = pro;");
17486   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
17487   CheckInstanceCheckedAccessors(true);
17488 }
17489
17490
17491 TEST(TryFinallyMessage) {
17492   v8::HandleScope scope;
17493   LocalContext context;
17494   {
17495     // Test that the original error message is not lost if there is a
17496     // recursive call into Javascript is done in the finally block, e.g. to
17497     // initialize an IC. (crbug.com/129171)
17498     TryCatch try_catch;
17499     const char* trigger_ic =
17500         "try {                      \n"
17501         "  throw new Error('test'); \n"
17502         "} finally {                \n"
17503         "  var x = 0;               \n"
17504         "  x++;                     \n"  // Trigger an IC initialization here.
17505         "}                          \n";
17506     CompileRun(trigger_ic);
17507     CHECK(try_catch.HasCaught());
17508     Local<Message> message = try_catch.Message();
17509     CHECK(!message.IsEmpty());
17510     CHECK_EQ(2, message->GetLineNumber());
17511   }
17512
17513   {
17514     // Test that the original exception message is indeed overwritten if
17515     // a new error is thrown in the finally block.
17516     TryCatch try_catch;
17517     const char* throw_again =
17518         "try {                       \n"
17519         "  throw new Error('test');  \n"
17520         "} finally {                 \n"
17521         "  var x = 0;                \n"
17522         "  x++;                      \n"
17523         "  throw new Error('again'); \n"  // This is the new uncaught error.
17524         "}                           \n";
17525     CompileRun(throw_again);
17526     CHECK(try_catch.HasCaught());
17527     Local<Message> message = try_catch.Message();
17528     CHECK(!message.IsEmpty());
17529     CHECK_EQ(6, message->GetLineNumber());
17530   }
17531 }
17532
17533
17534 static void Helper137002(bool do_store,
17535                          bool polymorphic,
17536                          bool remove_accessor,
17537                          bool interceptor) {
17538   LocalContext context;
17539   Local<ObjectTemplate> templ = ObjectTemplate::New();
17540   if (interceptor) {
17541     templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
17542   } else {
17543     templ->SetAccessor(v8_str("foo"),
17544                        GetterWhichReturns42,
17545                        SetterWhichSetsYOnThisTo23);
17546   }
17547   context->Global()->Set(v8_str("obj"), templ->NewInstance());
17548
17549   // Turn monomorphic on slow object with native accessor, then turn
17550   // polymorphic, finally optimize to create negative lookup and fail.
17551   CompileRun(do_store ?
17552              "function f(x) { x.foo = void 0; }" :
17553              "function f(x) { return x.foo; }");
17554   CompileRun("obj.y = void 0;");
17555   if (!interceptor) {
17556     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
17557   }
17558   CompileRun("obj.__proto__ = null;"
17559              "f(obj); f(obj); f(obj);");
17560   if (polymorphic) {
17561     CompileRun("f({});");
17562   }
17563   CompileRun("obj.y = void 0;"
17564              "%OptimizeFunctionOnNextCall(f);");
17565   if (remove_accessor) {
17566     CompileRun("delete obj.foo;");
17567   }
17568   CompileRun("var result = f(obj);");
17569   if (do_store) {
17570     CompileRun("result = obj.y;");
17571   }
17572   if (remove_accessor && !interceptor) {
17573     CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
17574   } else {
17575     CHECK_EQ(do_store ? 23 : 42,
17576              context->Global()->Get(v8_str("result"))->Int32Value());
17577   }
17578 }
17579
17580
17581 THREADED_TEST(Regress137002a) {
17582   i::FLAG_allow_natives_syntax = true;
17583   i::FLAG_compilation_cache = false;
17584   v8::HandleScope scope;
17585   for (int i = 0; i < 16; i++) {
17586     Helper137002(i & 8, i & 4, i & 2, i & 1);
17587   }
17588 }
17589
17590
17591 THREADED_TEST(Regress137002b) {
17592   i::FLAG_allow_natives_syntax = true;
17593   v8::HandleScope scope;
17594   LocalContext context;
17595   Local<ObjectTemplate> templ = ObjectTemplate::New();
17596   templ->SetAccessor(v8_str("foo"),
17597                      GetterWhichReturns42,
17598                      SetterWhichSetsYOnThisTo23);
17599   context->Global()->Set(v8_str("obj"), templ->NewInstance());
17600
17601   // Turn monomorphic on slow object with native accessor, then just
17602   // delete the property and fail.
17603   CompileRun("function load(x) { return x.foo; }"
17604              "function store(x) { x.foo = void 0; }"
17605              "function keyed_load(x, key) { return x[key]; }"
17606              // Second version of function has a different source (add void 0)
17607              // so that it does not share code with the first version.  This
17608              // ensures that the ICs are monomorphic.
17609              "function load2(x) { void 0; return x.foo; }"
17610              "function store2(x) { void 0; x.foo = void 0; }"
17611              "function keyed_load2(x, key) { void 0; return x[key]; }"
17612
17613              "obj.y = void 0;"
17614              "obj.__proto__ = null;"
17615              "var subobj = {};"
17616              "subobj.y = void 0;"
17617              "subobj.__proto__ = obj;"
17618              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
17619
17620              // Make the ICs monomorphic.
17621              "load(obj); load(obj);"
17622              "load2(subobj); load2(subobj);"
17623              "store(obj); store(obj);"
17624              "store2(subobj); store2(subobj);"
17625              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
17626              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
17627
17628              // Actually test the shiny new ICs and better not crash. This
17629              // serves as a regression test for issue 142088 as well.
17630              "load(obj);"
17631              "load2(subobj);"
17632              "store(obj);"
17633              "store2(subobj);"
17634              "keyed_load(obj, 'foo');"
17635              "keyed_load2(subobj, 'foo');"
17636
17637              // Delete the accessor.  It better not be called any more now.
17638              "delete obj.foo;"
17639              "obj.y = void 0;"
17640              "subobj.y = void 0;"
17641
17642              "var load_result = load(obj);"
17643              "var load_result2 = load2(subobj);"
17644              "var keyed_load_result = keyed_load(obj, 'foo');"
17645              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
17646              "store(obj);"
17647              "store2(subobj);"
17648              "var y_from_obj = obj.y;"
17649              "var y_from_subobj = subobj.y;");
17650   CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
17651   CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
17652   CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
17653   CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
17654   CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
17655   CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
17656 }
17657
17658
17659 THREADED_TEST(Regress142088) {
17660   i::FLAG_allow_natives_syntax = true;
17661   v8::HandleScope scope;
17662   LocalContext context;
17663   Local<ObjectTemplate> templ = ObjectTemplate::New();
17664   templ->SetAccessor(v8_str("foo"),
17665                      GetterWhichReturns42,
17666                      SetterWhichSetsYOnThisTo23);
17667   context->Global()->Set(v8_str("obj"), templ->NewInstance());
17668
17669   CompileRun("function load(x) { return x.foo; }"
17670              "var o = Object.create(obj);"
17671              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
17672              "load(o); load(o); load(o); load(o);");
17673 }
17674
17675
17676 THREADED_TEST(Regress137496) {
17677   i::FLAG_expose_gc = true;
17678   v8::HandleScope scope;
17679   LocalContext context;
17680
17681   // Compile a try-finally clause where the finally block causes a GC
17682   // while there still is a message pending for external reporting.
17683   TryCatch try_catch;
17684   try_catch.SetVerbose(true);
17685   CompileRun("try { throw new Error(); } finally { gc(); }");
17686   CHECK(try_catch.HasCaught());
17687 }
17688
17689
17690 THREADED_TEST(Regress149912) {
17691   v8::HandleScope scope;
17692   LocalContext context;
17693   Handle<FunctionTemplate> templ = FunctionTemplate::New();
17694   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
17695   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
17696   CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
17697 }
17698
17699
17700 THREADED_TEST(Regress157124) {
17701   v8::HandleScope scope;
17702   LocalContext context;
17703   Local<ObjectTemplate> templ = ObjectTemplate::New();
17704   Local<Object> obj = templ->NewInstance();
17705   obj->GetIdentityHash();
17706   obj->DeleteHiddenValue(v8_str("Bug"));
17707 }
17708
17709
17710 THREADED_TEST(Regress260106) {
17711   LocalContext context;
17712   v8::HandleScope scope(context->GetIsolate());
17713   Local<FunctionTemplate> templ = FunctionTemplate::New(DummyCallHandler);
17714   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
17715   Local<Function> function = templ->GetFunction();
17716   CHECK(!function.IsEmpty());
17717   CHECK(function->IsFunction());
17718 }
17719
17720
17721 #ifndef WIN32
17722 class ThreadInterruptTest {
17723  public:
17724   ThreadInterruptTest() : sem_(NULL), sem_value_(0) { }
17725   ~ThreadInterruptTest() { delete sem_; }
17726
17727   void RunTest() {
17728     sem_ = i::OS::CreateSemaphore(0);
17729
17730     InterruptThread i_thread(this);
17731     i_thread.Start();
17732
17733     sem_->Wait();
17734     CHECK_EQ(kExpectedValue, sem_value_);
17735   }
17736
17737  private:
17738   static const int kExpectedValue = 1;
17739
17740   class InterruptThread : public i::Thread {
17741    public:
17742     explicit InterruptThread(ThreadInterruptTest* test)
17743         : Thread("InterruptThread"), test_(test) {}
17744
17745     virtual void Run() {
17746       struct sigaction action;
17747
17748       // Ensure that we'll enter waiting condition
17749       i::OS::Sleep(100);
17750
17751       // Setup signal handler
17752       memset(&action, 0, sizeof(action));
17753       action.sa_handler = SignalHandler;
17754       sigaction(SIGCHLD, &action, NULL);
17755
17756       // Send signal
17757       kill(getpid(), SIGCHLD);
17758
17759       // Ensure that if wait has returned because of error
17760       i::OS::Sleep(100);
17761
17762       // Set value and signal semaphore
17763       test_->sem_value_ = 1;
17764       test_->sem_->Signal();
17765     }
17766
17767     static void SignalHandler(int signal) {
17768     }
17769
17770    private:
17771      ThreadInterruptTest* test_;
17772      struct sigaction sa_;
17773   };
17774
17775   i::Semaphore* sem_;
17776   volatile int sem_value_;
17777 };
17778
17779
17780 THREADED_TEST(SemaphoreInterruption) {
17781   ThreadInterruptTest().RunTest();
17782 }
17783 #endif  // WIN32