Merge remote-tracking branch 'upstream/v0.10'
[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 <climits>
29 #include <csignal>
30 #include <string>
31 #include <map>
32
33 #include "v8.h"
34
35 #if V8_OS_POSIX
36 #include <unistd.h>  // NOLINT
37 #endif
38
39 #include "api.h"
40 #include "arguments.h"
41 #include "cctest.h"
42 #include "compilation-cache.h"
43 #include "cpu-profiler.h"
44 #include "execution.h"
45 #include "isolate.h"
46 #include "objects.h"
47 #include "parser.h"
48 #include "platform.h"
49 #include "snapshot.h"
50 #include "unicode-inl.h"
51 #include "utils.h"
52 #include "vm-state.h"
53
54 static const bool kLogThreading = false;
55
56 using ::v8::Boolean;
57 using ::v8::BooleanObject;
58 using ::v8::Context;
59 using ::v8::Extension;
60 using ::v8::Function;
61 using ::v8::FunctionTemplate;
62 using ::v8::Handle;
63 using ::v8::HandleScope;
64 using ::v8::Local;
65 using ::v8::Message;
66 using ::v8::MessageCallback;
67 using ::v8::Object;
68 using ::v8::ObjectTemplate;
69 using ::v8::Persistent;
70 using ::v8::Script;
71 using ::v8::StackTrace;
72 using ::v8::String;
73 using ::v8::TryCatch;
74 using ::v8::Undefined;
75 using ::v8::UniqueId;
76 using ::v8::V8;
77 using ::v8::Value;
78
79
80 #define THREADED_PROFILED_TEST(Name)                                 \
81   static void Test##Name();                                          \
82   TEST(Name##WithProfiler) {                                         \
83     RunWithProfiler(&Test##Name);                                    \
84   }                                                                  \
85   THREADED_TEST(Name)
86
87 void RunWithProfiler(void (*test)()) {
88   LocalContext env;
89   v8::HandleScope scope(env->GetIsolate());
90   v8::Local<v8::String> profile_name = v8::String::New("my_profile1");
91   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
92
93   cpu_profiler->StartCpuProfiling(profile_name);
94   (*test)();
95   cpu_profiler->DeleteAllCpuProfiles();
96 }
97
98
99 static void ExpectString(const char* code, const char* expected) {
100   Local<Value> result = CompileRun(code);
101   CHECK(result->IsString());
102   String::Utf8Value utf8(result);
103   CHECK_EQ(expected, *utf8);
104 }
105
106
107 static void ExpectInt32(const char* code, int expected) {
108   Local<Value> result = CompileRun(code);
109   CHECK(result->IsInt32());
110   CHECK_EQ(expected, result->Int32Value());
111 }
112
113
114 static void ExpectBoolean(const char* code, bool expected) {
115   Local<Value> result = CompileRun(code);
116   CHECK(result->IsBoolean());
117   CHECK_EQ(expected, result->BooleanValue());
118 }
119
120
121 static void ExpectTrue(const char* code) {
122   ExpectBoolean(code, true);
123 }
124
125
126 static void ExpectFalse(const char* code) {
127   ExpectBoolean(code, false);
128 }
129
130
131 static void ExpectObject(const char* code, Local<Value> expected) {
132   Local<Value> result = CompileRun(code);
133   CHECK(result->Equals(expected));
134 }
135
136
137 static void ExpectUndefined(const char* code) {
138   Local<Value> result = CompileRun(code);
139   CHECK(result->IsUndefined());
140 }
141
142
143 static int signature_callback_count;
144 static Local<Value> signature_expected_receiver;
145 static void IncrementingSignatureCallback(
146     const v8::FunctionCallbackInfo<v8::Value>& args) {
147   ApiTestFuzzer::Fuzz();
148   signature_callback_count++;
149   CHECK_EQ(signature_expected_receiver, args.Holder());
150   CHECK_EQ(signature_expected_receiver, args.This());
151   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
152   for (int i = 0; i < args.Length(); i++)
153     result->Set(v8::Integer::New(i), args[i]);
154   args.GetReturnValue().Set(result);
155 }
156
157
158 static void SignatureCallback(
159     const v8::FunctionCallbackInfo<v8::Value>& args) {
160   ApiTestFuzzer::Fuzz();
161   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
162   for (int i = 0; i < args.Length(); i++) {
163     result->Set(v8::Integer::New(i), args[i]);
164   }
165   args.GetReturnValue().Set(result);
166 }
167
168
169 // Tests that call v8::V8::Dispose() cannot be threaded.
170 TEST(InitializeAndDisposeOnce) {
171   CHECK(v8::V8::Initialize());
172   CHECK(v8::V8::Dispose());
173 }
174
175
176 // Tests that call v8::V8::Dispose() cannot be threaded.
177 TEST(InitializeAndDisposeMultiple) {
178   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
179   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
180   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
181   // TODO(mstarzinger): This should fail gracefully instead of asserting.
182   // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
183   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
184 }
185
186
187 THREADED_TEST(Handles) {
188   v8::HandleScope scope(v8::Isolate::GetCurrent());
189   Local<Context> local_env;
190   {
191     LocalContext env;
192     local_env = env.local();
193   }
194
195   // Local context should still be live.
196   CHECK(!local_env.IsEmpty());
197   local_env->Enter();
198
199   v8::Handle<v8::Primitive> undef = v8::Undefined();
200   CHECK(!undef.IsEmpty());
201   CHECK(undef->IsUndefined());
202
203   const char* c_source = "1 + 2 + 3";
204   Local<String> source = String::New(c_source);
205   Local<Script> script = Script::Compile(source);
206   CHECK_EQ(6, script->Run()->Int32Value());
207
208   local_env->Exit();
209 }
210
211
212 THREADED_TEST(IsolateOfContext) {
213   v8::HandleScope scope(v8::Isolate::GetCurrent());
214   v8::Handle<Context> env = Context::New(v8::Isolate::GetCurrent());
215
216   CHECK(!env->InContext());
217   CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
218   env->Enter();
219   CHECK(env->InContext());
220   CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
221   env->Exit();
222   CHECK(!env->InContext());
223   CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
224 }
225
226
227 static void TestSignature(const char* loop_js, Local<Value> receiver) {
228   i::ScopedVector<char> source(200);
229   i::OS::SNPrintF(source,
230                   "for (var i = 0; i < 10; i++) {"
231                   "  %s"
232                   "}",
233                   loop_js);
234   signature_callback_count = 0;
235   signature_expected_receiver = receiver;
236   bool expected_to_throw = receiver.IsEmpty();
237   v8::TryCatch try_catch;
238   CompileRun(source.start());
239   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
240   if (!expected_to_throw) {
241     CHECK_EQ(10, signature_callback_count);
242   } else {
243     CHECK_EQ(v8_str("TypeError: Illegal invocation"),
244              try_catch.Exception()->ToString());
245   }
246 }
247
248
249 THREADED_TEST(ReceiverSignature) {
250   LocalContext env;
251   v8::HandleScope scope(env->GetIsolate());
252   // Setup templates.
253   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
254   v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
255   v8::Handle<v8::FunctionTemplate> callback_sig =
256       v8::FunctionTemplate::New(
257           IncrementingSignatureCallback, Local<Value>(), sig);
258   v8::Handle<v8::FunctionTemplate> callback =
259       v8::FunctionTemplate::New(IncrementingSignatureCallback);
260   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
261   sub_fun->Inherit(fun);
262   v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
263   // Install properties.
264   v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
265   fun_proto->Set(v8_str("prop_sig"), callback_sig);
266   fun_proto->Set(v8_str("prop"), callback);
267   fun_proto->SetAccessorProperty(
268       v8_str("accessor_sig"), callback_sig, callback_sig);
269   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
270   // Instantiate templates.
271   Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
272   Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
273   // Setup global variables.
274   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
275   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
276   env->Global()->Set(v8_str("fun_instance"), fun_instance);
277   env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
278   CompileRun(
279       "var accessor_sig_key = 'accessor_sig';"
280       "var accessor_key = 'accessor';"
281       "var prop_sig_key = 'prop_sig';"
282       "var prop_key = 'prop';"
283       ""
284       "function copy_props(obj) {"
285       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
286       "  var source = Fun.prototype;"
287       "  for (var i in keys) {"
288       "    var key = keys[i];"
289       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
290       "    Object.defineProperty(obj, key, desc);"
291       "  }"
292       "}"
293       ""
294       "var obj = {};"
295       "copy_props(obj);"
296       "var unrel = new UnrelFun();"
297       "copy_props(unrel);");
298   // Test with and without ICs
299   const char* test_objects[] = {
300       "fun_instance", "sub_fun_instance", "obj", "unrel" };
301   unsigned bad_signature_start_offset = 2;
302   for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
303     i::ScopedVector<char> source(200);
304     i::OS::SNPrintF(
305         source, "var test_object = %s; test_object", test_objects[i]);
306     Local<Value> test_object = CompileRun(source.start());
307     TestSignature("test_object.prop();", test_object);
308     TestSignature("test_object.accessor;", test_object);
309     TestSignature("test_object[accessor_key];", test_object);
310     TestSignature("test_object.accessor = 1;", test_object);
311     TestSignature("test_object[accessor_key] = 1;", test_object);
312     if (i >= bad_signature_start_offset) test_object = Local<Value>();
313     TestSignature("test_object.prop_sig();", test_object);
314     TestSignature("test_object.accessor_sig;", test_object);
315     TestSignature("test_object[accessor_sig_key];", test_object);
316     TestSignature("test_object.accessor_sig = 1;", test_object);
317     TestSignature("test_object[accessor_sig_key] = 1;", test_object);
318   }
319 }
320
321
322 THREADED_TEST(ArgumentSignature) {
323   LocalContext env;
324   v8::HandleScope scope(env->GetIsolate());
325   v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
326   cons->SetClassName(v8_str("Cons"));
327   v8::Handle<v8::Signature> sig =
328       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
329   v8::Handle<v8::FunctionTemplate> fun =
330       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
331   env->Global()->Set(v8_str("Cons"), cons->GetFunction());
332   env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
333
334   v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
335   CHECK(value1->IsTrue());
336
337   v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
338   CHECK(value2->IsTrue());
339
340   v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
341   CHECK(value3->IsTrue());
342
343   v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
344   cons1->SetClassName(v8_str("Cons1"));
345   v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
346   cons2->SetClassName(v8_str("Cons2"));
347   v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
348   cons3->SetClassName(v8_str("Cons3"));
349
350   v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
351   v8::Handle<v8::Signature> wsig =
352       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
353   v8::Handle<v8::FunctionTemplate> fun2 =
354       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
355
356   env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
357   env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
358   env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
359   env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
360   v8::Handle<Value> value4 = CompileRun(
361       "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
362       "'[object Cons1],[object Cons2],[object Cons3]'");
363   CHECK(value4->IsTrue());
364
365   v8::Handle<Value> value5 = CompileRun(
366       "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
367   CHECK(value5->IsTrue());
368
369   v8::Handle<Value> value6 = CompileRun(
370       "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
371   CHECK(value6->IsTrue());
372
373   v8::Handle<Value> value7 = CompileRun(
374       "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
375       "'[object Cons1],[object Cons2],[object Cons3],d';");
376   CHECK(value7->IsTrue());
377
378   v8::Handle<Value> value8 = CompileRun(
379       "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
380   CHECK(value8->IsTrue());
381 }
382
383
384 THREADED_TEST(HulIgennem) {
385   LocalContext env;
386   v8::HandleScope scope(env->GetIsolate());
387   v8::Handle<v8::Primitive> undef = v8::Undefined();
388   Local<String> undef_str = undef->ToString();
389   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
390   undef_str->WriteUtf8(value);
391   CHECK_EQ(0, strcmp(value, "undefined"));
392   i::DeleteArray(value);
393 }
394
395
396 THREADED_TEST(Access) {
397   LocalContext env;
398   v8::HandleScope scope(env->GetIsolate());
399   Local<v8::Object> obj = v8::Object::New();
400   Local<Value> foo_before = obj->Get(v8_str("foo"));
401   CHECK(foo_before->IsUndefined());
402   Local<String> bar_str = v8_str("bar");
403   obj->Set(v8_str("foo"), bar_str);
404   Local<Value> foo_after = obj->Get(v8_str("foo"));
405   CHECK(!foo_after->IsUndefined());
406   CHECK(foo_after->IsString());
407   CHECK_EQ(bar_str, foo_after);
408 }
409
410
411 THREADED_TEST(AccessElement) {
412   LocalContext env;
413   v8::HandleScope scope(env->GetIsolate());
414   Local<v8::Object> obj = v8::Object::New();
415   Local<Value> before = obj->Get(1);
416   CHECK(before->IsUndefined());
417   Local<String> bar_str = v8_str("bar");
418   obj->Set(1, bar_str);
419   Local<Value> after = obj->Get(1);
420   CHECK(!after->IsUndefined());
421   CHECK(after->IsString());
422   CHECK_EQ(bar_str, after);
423
424   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
425   CHECK_EQ(v8_str("a"), value->Get(0));
426   CHECK_EQ(v8_str("b"), value->Get(1));
427 }
428
429
430 THREADED_TEST(Script) {
431   LocalContext env;
432   v8::HandleScope scope(env->GetIsolate());
433   const char* c_source = "1 + 2 + 3";
434   Local<String> source = String::New(c_source);
435   Local<Script> script = Script::Compile(source);
436   CHECK_EQ(6, script->Run()->Int32Value());
437 }
438
439
440 static uint16_t* AsciiToTwoByteString(const char* source) {
441   int array_length = i::StrLength(source) + 1;
442   uint16_t* converted = i::NewArray<uint16_t>(array_length);
443   for (int i = 0; i < array_length; i++) converted[i] = source[i];
444   return converted;
445 }
446
447
448 class TestResource: public String::ExternalStringResource {
449  public:
450   explicit TestResource(uint16_t* data, int* counter = NULL)
451     : data_(data), length_(0), counter_(counter) {
452     while (data[length_]) ++length_;
453   }
454
455   ~TestResource() {
456     i::DeleteArray(data_);
457     if (counter_ != NULL) ++*counter_;
458   }
459
460   const uint16_t* data() const {
461     return data_;
462   }
463
464   size_t length() const {
465     return length_;
466   }
467  private:
468   uint16_t* data_;
469   size_t length_;
470   int* counter_;
471 };
472
473
474 class TestAsciiResource: public String::ExternalAsciiStringResource {
475  public:
476   explicit TestAsciiResource(const char* data, int* counter = NULL)
477     : data_(data), length_(strlen(data)), counter_(counter) { }
478
479   ~TestAsciiResource() {
480     i::DeleteArray(data_);
481     if (counter_ != NULL) ++*counter_;
482   }
483
484   const char* data() const {
485     return data_;
486   }
487
488   size_t length() const {
489     return length_;
490   }
491  private:
492   const char* data_;
493   size_t length_;
494   int* counter_;
495 };
496
497
498 THREADED_TEST(ScriptUsingStringResource) {
499   int dispose_count = 0;
500   const char* c_source = "1 + 2 * 3";
501   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
502   {
503     LocalContext env;
504     v8::HandleScope scope(env->GetIsolate());
505     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
506     Local<String> source = String::NewExternal(resource);
507     Local<Script> script = Script::Compile(source);
508     Local<Value> value = script->Run();
509     CHECK(value->IsNumber());
510     CHECK_EQ(7, value->Int32Value());
511     CHECK(source->IsExternal());
512     CHECK_EQ(resource,
513              static_cast<TestResource*>(source->GetExternalStringResource()));
514     String::Encoding encoding = String::UNKNOWN_ENCODING;
515     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
516              source->GetExternalStringResourceBase(&encoding));
517     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
518     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
519     CHECK_EQ(0, dispose_count);
520   }
521   v8::internal::Isolate::Current()->compilation_cache()->Clear();
522   HEAP->CollectAllAvailableGarbage();
523   CHECK_EQ(1, dispose_count);
524 }
525
526
527 THREADED_TEST(ScriptUsingAsciiStringResource) {
528   int dispose_count = 0;
529   const char* c_source = "1 + 2 * 3";
530   {
531     LocalContext env;
532     v8::HandleScope scope(env->GetIsolate());
533     TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
534                                                         &dispose_count);
535     Local<String> source = String::NewExternal(resource);
536     CHECK(source->IsExternalAscii());
537     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
538              source->GetExternalAsciiStringResource());
539     String::Encoding encoding = String::UNKNOWN_ENCODING;
540     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
541              source->GetExternalStringResourceBase(&encoding));
542     CHECK_EQ(String::ASCII_ENCODING, encoding);
543     Local<Script> script = Script::Compile(source);
544     Local<Value> value = script->Run();
545     CHECK(value->IsNumber());
546     CHECK_EQ(7, value->Int32Value());
547     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
548     CHECK_EQ(0, dispose_count);
549   }
550   i::Isolate::Current()->compilation_cache()->Clear();
551   HEAP->CollectAllAvailableGarbage();
552   CHECK_EQ(1, dispose_count);
553 }
554
555
556 THREADED_TEST(ScriptMakingExternalString) {
557   int dispose_count = 0;
558   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
559   {
560     LocalContext env;
561     v8::HandleScope scope(env->GetIsolate());
562     Local<String> source = String::New(two_byte_source);
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     CHECK_EQ(source->IsExternal(), false);
567     CHECK_EQ(source->IsExternalAscii(), false);
568     String::Encoding encoding = String::UNKNOWN_ENCODING;
569     CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
570     CHECK_EQ(String::ASCII_ENCODING, encoding);
571     bool success = source->MakeExternal(new TestResource(two_byte_source,
572                                                          &dispose_count));
573     CHECK(success);
574     Local<Script> script = Script::Compile(source);
575     Local<Value> value = script->Run();
576     CHECK(value->IsNumber());
577     CHECK_EQ(7, value->Int32Value());
578     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
579     CHECK_EQ(0, dispose_count);
580   }
581   i::Isolate::Current()->compilation_cache()->Clear();
582   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
583   CHECK_EQ(1, dispose_count);
584 }
585
586
587 THREADED_TEST(ScriptMakingExternalAsciiString) {
588   int dispose_count = 0;
589   const char* c_source = "1 + 2 * 3";
590   {
591     LocalContext env;
592     v8::HandleScope scope(env->GetIsolate());
593     Local<String> source = v8_str(c_source);
594     // Trigger GCs so that the newly allocated string moves to old gen.
595     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
596     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
597     bool success = source->MakeExternal(
598         new TestAsciiResource(i::StrDup(c_source), &dispose_count));
599     CHECK(success);
600     Local<Script> script = Script::Compile(source);
601     Local<Value> value = script->Run();
602     CHECK(value->IsNumber());
603     CHECK_EQ(7, value->Int32Value());
604     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
605     CHECK_EQ(0, dispose_count);
606   }
607   i::Isolate::Current()->compilation_cache()->Clear();
608   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
609   CHECK_EQ(1, dispose_count);
610 }
611
612
613 TEST(MakingExternalStringConditions) {
614   LocalContext env;
615   v8::HandleScope scope(env->GetIsolate());
616
617   // Free some space in the new space so that we can check freshness.
618   HEAP->CollectGarbage(i::NEW_SPACE);
619   HEAP->CollectGarbage(i::NEW_SPACE);
620
621   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
622   Local<String> small_string = String::New(two_byte_string);
623   i::DeleteArray(two_byte_string);
624
625   // We should refuse to externalize newly created small string.
626   CHECK(!small_string->CanMakeExternal());
627   // Trigger GCs so that the newly allocated string moves to old gen.
628   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
629   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
630   // Old space strings should be accepted.
631   CHECK(small_string->CanMakeExternal());
632
633   two_byte_string = AsciiToTwoByteString("small string 2");
634   small_string = String::New(two_byte_string);
635   i::DeleteArray(two_byte_string);
636
637   // We should refuse externalizing newly created small string.
638   CHECK(!small_string->CanMakeExternal());
639   for (int i = 0; i < 100; i++) {
640     String::Value value(small_string);
641   }
642   // Frequently used strings should be accepted.
643   CHECK(small_string->CanMakeExternal());
644
645   const int buf_size = 10 * 1024;
646   char* buf = i::NewArray<char>(buf_size);
647   memset(buf, 'a', buf_size);
648   buf[buf_size - 1] = '\0';
649
650   two_byte_string = AsciiToTwoByteString(buf);
651   Local<String> large_string = String::New(two_byte_string);
652   i::DeleteArray(buf);
653   i::DeleteArray(two_byte_string);
654   // Large strings should be immediately accepted.
655   CHECK(large_string->CanMakeExternal());
656 }
657
658
659 TEST(MakingExternalAsciiStringConditions) {
660   LocalContext env;
661   v8::HandleScope scope(env->GetIsolate());
662
663   // Free some space in the new space so that we can check freshness.
664   HEAP->CollectGarbage(i::NEW_SPACE);
665   HEAP->CollectGarbage(i::NEW_SPACE);
666
667   Local<String> small_string = String::New("s1");
668   // We should refuse to externalize newly created small string.
669   CHECK(!small_string->CanMakeExternal());
670   // Trigger GCs so that the newly allocated string moves to old gen.
671   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
672   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
673   // Old space strings should be accepted.
674   CHECK(small_string->CanMakeExternal());
675
676   small_string = String::New("small string 2");
677   // We should refuse externalizing newly created small string.
678   CHECK(!small_string->CanMakeExternal());
679   for (int i = 0; i < 100; i++) {
680     String::Value value(small_string);
681   }
682   // Frequently used strings should be accepted.
683   CHECK(small_string->CanMakeExternal());
684
685   const int buf_size = 10 * 1024;
686   char* buf = i::NewArray<char>(buf_size);
687   memset(buf, 'a', buf_size);
688   buf[buf_size - 1] = '\0';
689   Local<String> large_string = String::New(buf);
690   i::DeleteArray(buf);
691   // Large strings should be immediately accepted.
692   CHECK(large_string->CanMakeExternal());
693 }
694
695
696 TEST(MakingExternalUnalignedAsciiString) {
697   LocalContext env;
698   v8::HandleScope scope(env->GetIsolate());
699
700   CompileRun("function cons(a, b) { return a + b; }"
701              "function slice(a) { return a.substring(1); }");
702   // Create a cons string that will land in old pointer space.
703   Local<String> cons = Local<String>::Cast(CompileRun(
704       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
705   // Create a sliced string that will land in old pointer space.
706   Local<String> slice = Local<String>::Cast(CompileRun(
707       "slice('abcdefghijklmnopqrstuvwxyz');"));
708
709   // Trigger GCs so that the newly allocated string moves to old gen.
710   SimulateFullSpace(HEAP->old_pointer_space());
711   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
712   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
713
714   // Turn into external string with unaligned resource data.
715   int dispose_count = 0;
716   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
717   bool success = cons->MakeExternal(
718       new TestAsciiResource(i::StrDup(c_cons) + 1, &dispose_count));
719   CHECK(success);
720   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
721   success = slice->MakeExternal(
722       new TestAsciiResource(i::StrDup(c_slice) + 1, &dispose_count));
723   CHECK(success);
724
725   // Trigger GCs and force evacuation.
726   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
727   HEAP->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
728 }
729
730
731 THREADED_TEST(UsingExternalString) {
732   i::Factory* factory = i::Isolate::Current()->factory();
733   {
734     v8::HandleScope scope(v8::Isolate::GetCurrent());
735     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
736     Local<String> string =
737         String::NewExternal(new TestResource(two_byte_string));
738     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
739     // Trigger GCs so that the newly allocated string moves to old gen.
740     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
741     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
742     i::Handle<i::String> isymbol =
743         factory->InternalizedStringFromString(istring);
744     CHECK(isymbol->IsInternalizedString());
745   }
746   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
747   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
748 }
749
750
751 THREADED_TEST(UsingExternalAsciiString) {
752   i::Factory* factory = i::Isolate::Current()->factory();
753   {
754     v8::HandleScope scope(v8::Isolate::GetCurrent());
755     const char* one_byte_string = "test string";
756     Local<String> string = String::NewExternal(
757         new TestAsciiResource(i::StrDup(one_byte_string)));
758     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
759     // Trigger GCs so that the newly allocated string moves to old gen.
760     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
761     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
762     i::Handle<i::String> isymbol =
763         factory->InternalizedStringFromString(istring);
764     CHECK(isymbol->IsInternalizedString());
765   }
766   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
767   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
768 }
769
770
771 THREADED_TEST(ScavengeExternalString) {
772   i::FLAG_stress_compaction = false;
773   i::FLAG_gc_global = false;
774   int dispose_count = 0;
775   bool in_new_space = false;
776   {
777     v8::HandleScope scope(v8::Isolate::GetCurrent());
778     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
779     Local<String> string =
780       String::NewExternal(new TestResource(two_byte_string,
781                                            &dispose_count));
782     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
783     HEAP->CollectGarbage(i::NEW_SPACE);
784     in_new_space = HEAP->InNewSpace(*istring);
785     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
786     CHECK_EQ(0, dispose_count);
787   }
788   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
789   CHECK_EQ(1, dispose_count);
790 }
791
792
793 THREADED_TEST(ScavengeExternalAsciiString) {
794   i::FLAG_stress_compaction = false;
795   i::FLAG_gc_global = false;
796   int dispose_count = 0;
797   bool in_new_space = false;
798   {
799     v8::HandleScope scope(v8::Isolate::GetCurrent());
800     const char* one_byte_string = "test string";
801     Local<String> string = String::NewExternal(
802         new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
803     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
804     HEAP->CollectGarbage(i::NEW_SPACE);
805     in_new_space = HEAP->InNewSpace(*istring);
806     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
807     CHECK_EQ(0, dispose_count);
808   }
809   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
810   CHECK_EQ(1, dispose_count);
811 }
812
813
814 class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
815  public:
816   // Only used by non-threaded tests, so it can use static fields.
817   static int dispose_calls;
818   static int dispose_count;
819
820   TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
821       : TestAsciiResource(data, &dispose_count),
822         dispose_(dispose) { }
823
824   void Dispose() {
825     ++dispose_calls;
826     if (dispose_) delete this;
827   }
828  private:
829   bool dispose_;
830 };
831
832
833 int TestAsciiResourceWithDisposeControl::dispose_count = 0;
834 int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
835
836
837 TEST(ExternalStringWithDisposeHandling) {
838   const char* c_source = "1 + 2 * 3";
839
840   // Use a stack allocated external string resource allocated object.
841   TestAsciiResourceWithDisposeControl::dispose_count = 0;
842   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
843   TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
844   {
845     LocalContext env;
846     v8::HandleScope scope(env->GetIsolate());
847     Local<String> source =  String::NewExternal(&res_stack);
848     Local<Script> script = Script::Compile(source);
849     Local<Value> value = script->Run();
850     CHECK(value->IsNumber());
851     CHECK_EQ(7, value->Int32Value());
852     HEAP->CollectAllAvailableGarbage();
853     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
854   }
855   i::Isolate::Current()->compilation_cache()->Clear();
856   HEAP->CollectAllAvailableGarbage();
857   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
858   CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
859
860   // Use a heap allocated external string resource allocated object.
861   TestAsciiResourceWithDisposeControl::dispose_count = 0;
862   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
863   TestAsciiResource* res_heap =
864       new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
865   {
866     LocalContext env;
867     v8::HandleScope scope(env->GetIsolate());
868     Local<String> source =  String::NewExternal(res_heap);
869     Local<Script> script = Script::Compile(source);
870     Local<Value> value = script->Run();
871     CHECK(value->IsNumber());
872     CHECK_EQ(7, value->Int32Value());
873     HEAP->CollectAllAvailableGarbage();
874     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
875   }
876   i::Isolate::Current()->compilation_cache()->Clear();
877   HEAP->CollectAllAvailableGarbage();
878   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
879   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
880 }
881
882
883 THREADED_TEST(StringConcat) {
884   {
885     LocalContext env;
886     v8::HandleScope scope(env->GetIsolate());
887     const char* one_byte_string_1 = "function a_times_t";
888     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
889     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
890     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
891     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
892     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
893     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
894     Local<String> left = v8_str(one_byte_string_1);
895
896     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
897     Local<String> right = String::New(two_byte_source);
898     i::DeleteArray(two_byte_source);
899
900     Local<String> source = String::Concat(left, right);
901     right = String::NewExternal(
902         new TestAsciiResource(i::StrDup(one_byte_extern_1)));
903     source = String::Concat(source, right);
904     right = String::NewExternal(
905         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
906     source = String::Concat(source, right);
907     right = v8_str(one_byte_string_2);
908     source = String::Concat(source, right);
909
910     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
911     right = String::New(two_byte_source);
912     i::DeleteArray(two_byte_source);
913
914     source = String::Concat(source, right);
915     right = String::NewExternal(
916         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
917     source = String::Concat(source, right);
918     Local<Script> script = Script::Compile(source);
919     Local<Value> value = script->Run();
920     CHECK(value->IsNumber());
921     CHECK_EQ(68, value->Int32Value());
922   }
923   i::Isolate::Current()->compilation_cache()->Clear();
924   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
925   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
926 }
927
928
929 THREADED_TEST(GlobalProperties) {
930   LocalContext env;
931   v8::HandleScope scope(env->GetIsolate());
932   v8::Handle<v8::Object> global = env->Global();
933   global->Set(v8_str("pi"), v8_num(3.1415926));
934   Local<Value> pi = global->Get(v8_str("pi"));
935   CHECK_EQ(3.1415926, pi->NumberValue());
936 }
937
938
939 template<typename T>
940 static void CheckReturnValue(const T& t, i::Address callback) {
941   v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
942   i::Object** o = *reinterpret_cast<i::Object***>(&rv);
943   CHECK_EQ(v8::Isolate::GetCurrent(), t.GetIsolate());
944   CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
945   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
946   // Verify reset
947   bool is_runtime = (*o)->IsTheHole();
948   rv.Set(true);
949   CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
950   rv.Set(v8::Handle<v8::Object>());
951   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
952   CHECK_EQ(is_runtime, (*o)->IsTheHole());
953
954   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
955   // If CPU profiler is active check that when API callback is invoked
956   // VMState is set to EXTERNAL.
957   if (isolate->cpu_profiler()->is_profiling()) {
958     CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
959     CHECK(isolate->external_callback_scope());
960     CHECK_EQ(callback, isolate->external_callback_scope()->callback());
961   }
962 }
963
964
965 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
966                                  i::Address callback) {
967   ApiTestFuzzer::Fuzz();
968   CheckReturnValue(info, callback);
969   info.GetReturnValue().Set(v8_str("bad value"));
970   info.GetReturnValue().Set(v8_num(102));
971 }
972
973
974 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
975   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
976 }
977
978
979 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
980   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
981 }
982
983 static void construct_callback(
984     const v8::FunctionCallbackInfo<Value>& info) {
985   ApiTestFuzzer::Fuzz();
986   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
987   info.This()->Set(v8_str("x"), v8_num(1));
988   info.This()->Set(v8_str("y"), v8_num(2));
989   info.GetReturnValue().Set(v8_str("bad value"));
990   info.GetReturnValue().Set(info.This());
991 }
992
993
994 static void Return239Callback(
995     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
996   ApiTestFuzzer::Fuzz();
997   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
998   info.GetReturnValue().Set(v8_str("bad value"));
999   info.GetReturnValue().Set(v8_num(239));
1000 }
1001
1002
1003 template<typename Handler>
1004 static void TestFunctionTemplateInitializer(Handler handler,
1005                                             Handler handler_2) {
1006   // Test constructor calls.
1007   {
1008     LocalContext env;
1009     v8::HandleScope scope(env->GetIsolate());
1010
1011     Local<v8::FunctionTemplate> fun_templ =
1012         v8::FunctionTemplate::New(handler);
1013     Local<Function> fun = fun_templ->GetFunction();
1014     env->Global()->Set(v8_str("obj"), fun);
1015     Local<Script> script = v8_compile("obj()");
1016     for (int i = 0; i < 30; i++) {
1017       CHECK_EQ(102, script->Run()->Int32Value());
1018     }
1019   }
1020   // Use SetCallHandler to initialize a function template, should work like
1021   // the previous one.
1022   {
1023     LocalContext env;
1024     v8::HandleScope scope(env->GetIsolate());
1025
1026     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
1027     fun_templ->SetCallHandler(handler_2);
1028     Local<Function> fun = fun_templ->GetFunction();
1029     env->Global()->Set(v8_str("obj"), fun);
1030     Local<Script> script = v8_compile("obj()");
1031     for (int i = 0; i < 30; i++) {
1032       CHECK_EQ(102, script->Run()->Int32Value());
1033     }
1034   }
1035 }
1036
1037
1038 template<typename Constructor, typename Accessor>
1039 static void TestFunctionTemplateAccessor(Constructor constructor,
1040                                          Accessor accessor) {
1041   LocalContext env;
1042   v8::HandleScope scope(env->GetIsolate());
1043
1044   Local<v8::FunctionTemplate> fun_templ =
1045       v8::FunctionTemplate::New(constructor);
1046   fun_templ->SetClassName(v8_str("funky"));
1047   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
1048   Local<Function> fun = fun_templ->GetFunction();
1049   env->Global()->Set(v8_str("obj"), fun);
1050   Local<Value> result = v8_compile("(new obj()).toString()")->Run();
1051   CHECK_EQ(v8_str("[object funky]"), result);
1052   CompileRun("var obj_instance = new obj();");
1053   Local<Script> script;
1054   script = v8_compile("obj_instance.x");
1055   for (int i = 0; i < 30; i++) {
1056     CHECK_EQ(1, script->Run()->Int32Value());
1057   }
1058   script = v8_compile("obj_instance.m");
1059   for (int i = 0; i < 30; i++) {
1060     CHECK_EQ(239, script->Run()->Int32Value());
1061   }
1062 }
1063
1064
1065 THREADED_PROFILED_TEST(FunctionTemplate) {
1066   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
1067   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1068 }
1069
1070
1071 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1072   ApiTestFuzzer::Fuzz();
1073   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
1074   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1075 }
1076
1077
1078 template<typename Callback>
1079 static void TestSimpleCallback(Callback callback) {
1080   LocalContext env;
1081   v8::HandleScope scope(env->GetIsolate());
1082
1083   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
1084   object_template->Set("callback", v8::FunctionTemplate::New(callback));
1085   v8::Local<v8::Object> object = object_template->NewInstance();
1086   (*env)->Global()->Set(v8_str("callback_object"), object);
1087   v8::Handle<v8::Script> script;
1088   script = v8_compile("callback_object.callback(17)");
1089   for (int i = 0; i < 30; i++) {
1090     CHECK_EQ(51424, script->Run()->Int32Value());
1091   }
1092   script = v8_compile("callback_object.callback(17, 24)");
1093   for (int i = 0; i < 30; i++) {
1094     CHECK_EQ(51425, script->Run()->Int32Value());
1095   }
1096 }
1097
1098
1099 THREADED_PROFILED_TEST(SimpleCallback) {
1100   TestSimpleCallback(SimpleCallback);
1101 }
1102
1103
1104 template<typename T>
1105 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1106
1107 // constant return values
1108 static int32_t fast_return_value_int32 = 471;
1109 static uint32_t fast_return_value_uint32 = 571;
1110 static const double kFastReturnValueDouble = 2.7;
1111 // variable return values
1112 static bool fast_return_value_bool = false;
1113 enum ReturnValueOddball {
1114   kNullReturnValue,
1115   kUndefinedReturnValue,
1116   kEmptyStringReturnValue
1117 };
1118 static ReturnValueOddball fast_return_value_void;
1119 static bool fast_return_value_object_is_empty = false;
1120
1121 // Helper function to avoid compiler error: insufficient contextual information
1122 // to determine type when applying FUNCTION_ADDR to a template function.
1123 static i::Address address_of(v8::FunctionCallback callback) {
1124   return FUNCTION_ADDR(callback);
1125 }
1126
1127 template<>
1128 void FastReturnValueCallback<int32_t>(
1129     const v8::FunctionCallbackInfo<v8::Value>& info) {
1130   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1131   info.GetReturnValue().Set(fast_return_value_int32);
1132 }
1133
1134 template<>
1135 void FastReturnValueCallback<uint32_t>(
1136     const v8::FunctionCallbackInfo<v8::Value>& info) {
1137   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1138   info.GetReturnValue().Set(fast_return_value_uint32);
1139 }
1140
1141 template<>
1142 void FastReturnValueCallback<double>(
1143     const v8::FunctionCallbackInfo<v8::Value>& info) {
1144   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1145   info.GetReturnValue().Set(kFastReturnValueDouble);
1146 }
1147
1148 template<>
1149 void FastReturnValueCallback<bool>(
1150     const v8::FunctionCallbackInfo<v8::Value>& info) {
1151   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1152   info.GetReturnValue().Set(fast_return_value_bool);
1153 }
1154
1155 template<>
1156 void FastReturnValueCallback<void>(
1157     const v8::FunctionCallbackInfo<v8::Value>& info) {
1158   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1159   switch (fast_return_value_void) {
1160     case kNullReturnValue:
1161       info.GetReturnValue().SetNull();
1162       break;
1163     case kUndefinedReturnValue:
1164       info.GetReturnValue().SetUndefined();
1165       break;
1166     case kEmptyStringReturnValue:
1167       info.GetReturnValue().SetEmptyString();
1168       break;
1169   }
1170 }
1171
1172 template<>
1173 void FastReturnValueCallback<Object>(
1174     const v8::FunctionCallbackInfo<v8::Value>& info) {
1175   v8::Handle<v8::Object> object;
1176   if (!fast_return_value_object_is_empty) object = Object::New();
1177   info.GetReturnValue().Set(object);
1178 }
1179
1180 template<typename T>
1181 Handle<Value> TestFastReturnValues() {
1182   LocalContext env;
1183   v8::HandleScope scope(env->GetIsolate());
1184   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
1185   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1186   object_template->Set("callback", v8::FunctionTemplate::New(callback));
1187   v8::Local<v8::Object> object = object_template->NewInstance();
1188   (*env)->Global()->Set(v8_str("callback_object"), object);
1189   return scope.Close(CompileRun("callback_object.callback()"));
1190 }
1191
1192
1193 THREADED_PROFILED_TEST(FastReturnValues) {
1194   LocalContext env;
1195   v8::HandleScope scope(v8::Isolate::GetCurrent());
1196   v8::Handle<v8::Value> value;
1197   // check int32_t and uint32_t
1198   int32_t int_values[] = {
1199       0, 234, -723,
1200       i::Smi::kMinValue, i::Smi::kMaxValue
1201   };
1202   for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
1203     for (int modifier = -1; modifier <= 1; modifier++) {
1204       int int_value = int_values[i] + modifier;
1205       // check int32_t
1206       fast_return_value_int32 = int_value;
1207       value = TestFastReturnValues<int32_t>();
1208       CHECK(value->IsInt32());
1209       CHECK(fast_return_value_int32 == value->Int32Value());
1210       // check uint32_t
1211       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1212       value = TestFastReturnValues<uint32_t>();
1213       CHECK(value->IsUint32());
1214       CHECK(fast_return_value_uint32 == value->Uint32Value());
1215     }
1216   }
1217   // check double
1218   value = TestFastReturnValues<double>();
1219   CHECK(value->IsNumber());
1220   CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
1221   // check bool values
1222   for (int i = 0; i < 2; i++) {
1223     fast_return_value_bool = i == 0;
1224     value = TestFastReturnValues<bool>();
1225     CHECK(value->IsBoolean());
1226     CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
1227   }
1228   // check oddballs
1229   ReturnValueOddball oddballs[] = {
1230       kNullReturnValue,
1231       kUndefinedReturnValue,
1232       kEmptyStringReturnValue
1233   };
1234   for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
1235     fast_return_value_void = oddballs[i];
1236     value = TestFastReturnValues<void>();
1237     switch (fast_return_value_void) {
1238       case kNullReturnValue:
1239         CHECK(value->IsNull());
1240         break;
1241       case kUndefinedReturnValue:
1242         CHECK(value->IsUndefined());
1243         break;
1244       case kEmptyStringReturnValue:
1245         CHECK(value->IsString());
1246         CHECK_EQ(0, v8::String::Cast(*value)->Length());
1247         break;
1248     }
1249   }
1250   // check handles
1251   fast_return_value_object_is_empty = false;
1252   value = TestFastReturnValues<Object>();
1253   CHECK(value->IsObject());
1254   fast_return_value_object_is_empty = true;
1255   value = TestFastReturnValues<Object>();
1256   CHECK(value->IsUndefined());
1257 }
1258
1259
1260 THREADED_TEST(FunctionTemplateSetLength) {
1261   LocalContext env;
1262   v8::HandleScope scope(env->GetIsolate());
1263   {
1264     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(
1265         handle_callback, Handle<v8::Value>(), Handle<v8::Signature>(), 23);
1266     Local<Function> fun = fun_templ->GetFunction();
1267     env->Global()->Set(v8_str("obj"), fun);
1268     Local<Script> script = v8_compile("obj.length");
1269     CHECK_EQ(23, script->Run()->Int32Value());
1270   }
1271   {
1272     Local<v8::FunctionTemplate> fun_templ =
1273         v8::FunctionTemplate::New(handle_callback);
1274     fun_templ->SetLength(22);
1275     Local<Function> fun = fun_templ->GetFunction();
1276     env->Global()->Set(v8_str("obj"), fun);
1277     Local<Script> script = v8_compile("obj.length");
1278     CHECK_EQ(22, script->Run()->Int32Value());
1279   }
1280   {
1281     // Without setting length it defaults to 0.
1282     Local<v8::FunctionTemplate> fun_templ =
1283         v8::FunctionTemplate::New(handle_callback);
1284     Local<Function> fun = fun_templ->GetFunction();
1285     env->Global()->Set(v8_str("obj"), fun);
1286     Local<Script> script = v8_compile("obj.length");
1287     CHECK_EQ(0, script->Run()->Int32Value());
1288   }
1289 }
1290
1291
1292 static void* expected_ptr;
1293 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1294   void* ptr = v8::External::Cast(*args.Data())->Value();
1295   CHECK_EQ(expected_ptr, ptr);
1296   args.GetReturnValue().Set(true);
1297 }
1298
1299
1300 static void TestExternalPointerWrapping() {
1301   LocalContext env;
1302   v8::HandleScope scope(env->GetIsolate());
1303
1304   v8::Handle<v8::Value> data = v8::External::New(expected_ptr);
1305
1306   v8::Handle<v8::Object> obj = v8::Object::New();
1307   obj->Set(v8_str("func"),
1308            v8::FunctionTemplate::New(callback, data)->GetFunction());
1309   env->Global()->Set(v8_str("obj"), obj);
1310
1311   CHECK(CompileRun(
1312         "function foo() {\n"
1313         "  for (var i = 0; i < 13; i++) obj.func();\n"
1314         "}\n"
1315         "foo(), true")->BooleanValue());
1316 }
1317
1318
1319 THREADED_TEST(ExternalWrap) {
1320   // Check heap allocated object.
1321   int* ptr = new int;
1322   expected_ptr = ptr;
1323   TestExternalPointerWrapping();
1324   delete ptr;
1325
1326   // Check stack allocated object.
1327   int foo;
1328   expected_ptr = &foo;
1329   TestExternalPointerWrapping();
1330
1331   // Check not aligned addresses.
1332   const int n = 100;
1333   char* s = new char[n];
1334   for (int i = 0; i < n; i++) {
1335     expected_ptr = s + i;
1336     TestExternalPointerWrapping();
1337   }
1338
1339   delete[] s;
1340
1341   // Check several invalid addresses.
1342   expected_ptr = reinterpret_cast<void*>(1);
1343   TestExternalPointerWrapping();
1344
1345   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1346   TestExternalPointerWrapping();
1347
1348   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1349   TestExternalPointerWrapping();
1350
1351 #if defined(V8_HOST_ARCH_X64)
1352   // Check a value with a leading 1 bit in x64 Smi encoding.
1353   expected_ptr = reinterpret_cast<void*>(0x400000000);
1354   TestExternalPointerWrapping();
1355
1356   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1357   TestExternalPointerWrapping();
1358
1359   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1360   TestExternalPointerWrapping();
1361 #endif
1362 }
1363
1364
1365 THREADED_TEST(FindInstanceInPrototypeChain) {
1366   LocalContext env;
1367   v8::HandleScope scope(env->GetIsolate());
1368
1369   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
1370   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
1371   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
1372   derived->Inherit(base);
1373
1374   Local<v8::Function> base_function = base->GetFunction();
1375   Local<v8::Function> derived_function = derived->GetFunction();
1376   Local<v8::Function> other_function = other->GetFunction();
1377
1378   Local<v8::Object> base_instance = base_function->NewInstance();
1379   Local<v8::Object> derived_instance = derived_function->NewInstance();
1380   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1381   Local<v8::Object> other_instance = other_function->NewInstance();
1382   derived_instance2->Set(v8_str("__proto__"), derived_instance);
1383   other_instance->Set(v8_str("__proto__"), derived_instance2);
1384
1385   // base_instance is only an instance of base.
1386   CHECK_EQ(base_instance,
1387            base_instance->FindInstanceInPrototypeChain(base));
1388   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1389   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1390
1391   // derived_instance is an instance of base and derived.
1392   CHECK_EQ(derived_instance,
1393            derived_instance->FindInstanceInPrototypeChain(base));
1394   CHECK_EQ(derived_instance,
1395            derived_instance->FindInstanceInPrototypeChain(derived));
1396   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1397
1398   // other_instance is an instance of other and its immediate
1399   // prototype derived_instance2 is an instance of base and derived.
1400   // Note, derived_instance is an instance of base and derived too,
1401   // but it comes after derived_instance2 in the prototype chain of
1402   // other_instance.
1403   CHECK_EQ(derived_instance2,
1404            other_instance->FindInstanceInPrototypeChain(base));
1405   CHECK_EQ(derived_instance2,
1406            other_instance->FindInstanceInPrototypeChain(derived));
1407   CHECK_EQ(other_instance,
1408            other_instance->FindInstanceInPrototypeChain(other));
1409 }
1410
1411
1412 THREADED_TEST(TinyInteger) {
1413   LocalContext env;
1414   v8::HandleScope scope(env->GetIsolate());
1415   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1416
1417   int32_t value = 239;
1418   Local<v8::Integer> value_obj = v8::Integer::New(value);
1419   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1420
1421   value_obj = v8::Integer::New(value, isolate);
1422   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1423 }
1424
1425
1426 THREADED_TEST(BigSmiInteger) {
1427   LocalContext env;
1428   v8::HandleScope scope(env->GetIsolate());
1429   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1430
1431   int32_t value = i::Smi::kMaxValue;
1432   // We cannot add one to a Smi::kMaxValue without wrapping.
1433   if (i::SmiValuesAre31Bits()) {
1434     CHECK(i::Smi::IsValid(value));
1435     CHECK(!i::Smi::IsValid(value + 1));
1436
1437     Local<v8::Integer> value_obj = v8::Integer::New(value);
1438     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1439
1440     value_obj = v8::Integer::New(value, isolate);
1441     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1442   }
1443 }
1444
1445
1446 THREADED_TEST(BigInteger) {
1447   LocalContext env;
1448   v8::HandleScope scope(env->GetIsolate());
1449   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1450
1451   // We cannot add one to a Smi::kMaxValue without wrapping.
1452   if (i::SmiValuesAre31Bits()) {
1453     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1454     // The code will not be run in that case, due to the "if" guard.
1455     int32_t value =
1456         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1457     CHECK(value > i::Smi::kMaxValue);
1458     CHECK(!i::Smi::IsValid(value));
1459
1460     Local<v8::Integer> value_obj = v8::Integer::New(value);
1461     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1462
1463     value_obj = v8::Integer::New(value, isolate);
1464     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1465   }
1466 }
1467
1468
1469 THREADED_TEST(TinyUnsignedInteger) {
1470   LocalContext env;
1471   v8::HandleScope scope(env->GetIsolate());
1472   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1473
1474   uint32_t value = 239;
1475
1476   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1477   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1478
1479   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1480   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1481 }
1482
1483
1484 THREADED_TEST(BigUnsignedSmiInteger) {
1485   LocalContext env;
1486   v8::HandleScope scope(env->GetIsolate());
1487   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1488
1489   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1490   CHECK(i::Smi::IsValid(value));
1491   CHECK(!i::Smi::IsValid(value + 1));
1492
1493   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1494   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1495
1496   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1497   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1498 }
1499
1500
1501 THREADED_TEST(BigUnsignedInteger) {
1502   LocalContext env;
1503   v8::HandleScope scope(env->GetIsolate());
1504   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1505
1506   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1507   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1508   CHECK(!i::Smi::IsValid(value));
1509
1510   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1511   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1512
1513   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1514   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1515 }
1516
1517
1518 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
1519   LocalContext env;
1520   v8::HandleScope scope(env->GetIsolate());
1521   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1522
1523   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1524   uint32_t value = INT32_MAX_AS_UINT + 1;
1525   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
1526
1527   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1528   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1529
1530   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1531   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1532 }
1533
1534
1535 THREADED_TEST(IsNativeError) {
1536   LocalContext env;
1537   v8::HandleScope scope(env->GetIsolate());
1538   v8::Handle<Value> syntax_error = CompileRun(
1539       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1540   CHECK(syntax_error->IsNativeError());
1541   v8::Handle<Value> not_error = CompileRun("{a:42}");
1542   CHECK(!not_error->IsNativeError());
1543   v8::Handle<Value> not_object = CompileRun("42");
1544   CHECK(!not_object->IsNativeError());
1545 }
1546
1547
1548 THREADED_TEST(StringObject) {
1549   LocalContext env;
1550   v8::HandleScope scope(env->GetIsolate());
1551   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1552   CHECK(boxed_string->IsStringObject());
1553   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1554   CHECK(!unboxed_string->IsStringObject());
1555   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1556   CHECK(!boxed_not_string->IsStringObject());
1557   v8::Handle<Value> not_object = CompileRun("0");
1558   CHECK(!not_object->IsStringObject());
1559   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1560   CHECK(!as_boxed.IsEmpty());
1561   Local<v8::String> the_string = as_boxed->ValueOf();
1562   CHECK(!the_string.IsEmpty());
1563   ExpectObject("\"test\"", the_string);
1564   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1565   CHECK(new_boxed_string->IsStringObject());
1566   as_boxed = new_boxed_string.As<v8::StringObject>();
1567   the_string = as_boxed->ValueOf();
1568   CHECK(!the_string.IsEmpty());
1569   ExpectObject("\"test\"", the_string);
1570 }
1571
1572
1573 THREADED_TEST(NumberObject) {
1574   LocalContext env;
1575   v8::HandleScope scope(env->GetIsolate());
1576   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1577   CHECK(boxed_number->IsNumberObject());
1578   v8::Handle<Value> unboxed_number = CompileRun("42");
1579   CHECK(!unboxed_number->IsNumberObject());
1580   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1581   CHECK(!boxed_not_number->IsNumberObject());
1582   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1583   CHECK(!as_boxed.IsEmpty());
1584   double the_number = as_boxed->ValueOf();
1585   CHECK_EQ(42.0, the_number);
1586   v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
1587   CHECK(new_boxed_number->IsNumberObject());
1588   as_boxed = new_boxed_number.As<v8::NumberObject>();
1589   the_number = as_boxed->ValueOf();
1590   CHECK_EQ(43.0, the_number);
1591 }
1592
1593
1594 THREADED_TEST(BooleanObject) {
1595   LocalContext env;
1596   v8::HandleScope scope(env->GetIsolate());
1597   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1598   CHECK(boxed_boolean->IsBooleanObject());
1599   v8::Handle<Value> unboxed_boolean = CompileRun("true");
1600   CHECK(!unboxed_boolean->IsBooleanObject());
1601   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1602   CHECK(!boxed_not_boolean->IsBooleanObject());
1603   v8::Handle<v8::BooleanObject> as_boxed =
1604       boxed_boolean.As<v8::BooleanObject>();
1605   CHECK(!as_boxed.IsEmpty());
1606   bool the_boolean = as_boxed->ValueOf();
1607   CHECK_EQ(true, the_boolean);
1608   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1609   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1610   CHECK(boxed_true->IsBooleanObject());
1611   CHECK(boxed_false->IsBooleanObject());
1612   as_boxed = boxed_true.As<v8::BooleanObject>();
1613   CHECK_EQ(true, as_boxed->ValueOf());
1614   as_boxed = boxed_false.As<v8::BooleanObject>();
1615   CHECK_EQ(false, as_boxed->ValueOf());
1616 }
1617
1618
1619 THREADED_TEST(PrimitiveAndWrappedBooleans) {
1620   LocalContext env;
1621   v8::HandleScope scope(env->GetIsolate());
1622
1623   Local<Value> primitive_false = Boolean::New(false);
1624   CHECK(primitive_false->IsBoolean());
1625   CHECK(!primitive_false->IsBooleanObject());
1626   CHECK(!primitive_false->BooleanValue());
1627   CHECK(!primitive_false->IsTrue());
1628   CHECK(primitive_false->IsFalse());
1629
1630   Local<Value> false_value = BooleanObject::New(false);
1631   CHECK(!false_value->IsBoolean());
1632   CHECK(false_value->IsBooleanObject());
1633   CHECK(false_value->BooleanValue());
1634   CHECK(!false_value->IsTrue());
1635   CHECK(!false_value->IsFalse());
1636
1637   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1638   CHECK(!false_boolean_object->IsBoolean());
1639   CHECK(false_boolean_object->IsBooleanObject());
1640   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1641   // CHECK(false_boolean_object->BooleanValue());
1642   CHECK(!false_boolean_object->ValueOf());
1643   CHECK(!false_boolean_object->IsTrue());
1644   CHECK(!false_boolean_object->IsFalse());
1645
1646   Local<Value> primitive_true = Boolean::New(true);
1647   CHECK(primitive_true->IsBoolean());
1648   CHECK(!primitive_true->IsBooleanObject());
1649   CHECK(primitive_true->BooleanValue());
1650   CHECK(primitive_true->IsTrue());
1651   CHECK(!primitive_true->IsFalse());
1652
1653   Local<Value> true_value = BooleanObject::New(true);
1654   CHECK(!true_value->IsBoolean());
1655   CHECK(true_value->IsBooleanObject());
1656   CHECK(true_value->BooleanValue());
1657   CHECK(!true_value->IsTrue());
1658   CHECK(!true_value->IsFalse());
1659
1660   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1661   CHECK(!true_boolean_object->IsBoolean());
1662   CHECK(true_boolean_object->IsBooleanObject());
1663   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1664   // CHECK(true_boolean_object->BooleanValue());
1665   CHECK(true_boolean_object->ValueOf());
1666   CHECK(!true_boolean_object->IsTrue());
1667   CHECK(!true_boolean_object->IsFalse());
1668 }
1669
1670
1671 THREADED_TEST(Number) {
1672   LocalContext env;
1673   v8::HandleScope scope(env->GetIsolate());
1674   double PI = 3.1415926;
1675   Local<v8::Number> pi_obj = v8::Number::New(PI);
1676   CHECK_EQ(PI, pi_obj->NumberValue());
1677 }
1678
1679
1680 THREADED_TEST(ToNumber) {
1681   LocalContext env;
1682   v8::HandleScope scope(env->GetIsolate());
1683   Local<String> str = v8_str("3.1415926");
1684   CHECK_EQ(3.1415926, str->NumberValue());
1685   v8::Handle<v8::Boolean> t = v8::True();
1686   CHECK_EQ(1.0, t->NumberValue());
1687   v8::Handle<v8::Boolean> f = v8::False();
1688   CHECK_EQ(0.0, f->NumberValue());
1689 }
1690
1691
1692 THREADED_TEST(Date) {
1693   LocalContext env;
1694   v8::HandleScope scope(env->GetIsolate());
1695   double PI = 3.1415926;
1696   Local<Value> date = v8::Date::New(PI);
1697   CHECK_EQ(3.0, date->NumberValue());
1698   date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42));
1699   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
1700 }
1701
1702
1703 THREADED_TEST(Boolean) {
1704   LocalContext env;
1705   v8::HandleScope scope(env->GetIsolate());
1706   v8::Handle<v8::Boolean> t = v8::True();
1707   CHECK(t->Value());
1708   v8::Handle<v8::Boolean> f = v8::False();
1709   CHECK(!f->Value());
1710   v8::Handle<v8::Primitive> u = v8::Undefined();
1711   CHECK(!u->BooleanValue());
1712   v8::Handle<v8::Primitive> n = v8::Null();
1713   CHECK(!n->BooleanValue());
1714   v8::Handle<String> str1 = v8_str("");
1715   CHECK(!str1->BooleanValue());
1716   v8::Handle<String> str2 = v8_str("x");
1717   CHECK(str2->BooleanValue());
1718   CHECK(!v8::Number::New(0)->BooleanValue());
1719   CHECK(v8::Number::New(-1)->BooleanValue());
1720   CHECK(v8::Number::New(1)->BooleanValue());
1721   CHECK(v8::Number::New(42)->BooleanValue());
1722   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1723 }
1724
1725
1726 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
1727   ApiTestFuzzer::Fuzz();
1728   args.GetReturnValue().Set(v8_num(13.4));
1729 }
1730
1731
1732 static void GetM(Local<String> name,
1733                  const v8::PropertyCallbackInfo<v8::Value>& info) {
1734   ApiTestFuzzer::Fuzz();
1735   info.GetReturnValue().Set(v8_num(876));
1736 }
1737
1738
1739 THREADED_TEST(GlobalPrototype) {
1740   v8::HandleScope scope(v8::Isolate::GetCurrent());
1741   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
1742   func_templ->PrototypeTemplate()->Set(
1743       "dummy",
1744       v8::FunctionTemplate::New(DummyCallHandler));
1745   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1746   templ->Set("x", v8_num(200));
1747   templ->SetAccessor(v8_str("m"), GetM);
1748   LocalContext env(0, templ);
1749   v8::Handle<Script> script(v8_compile("dummy()"));
1750   v8::Handle<Value> result(script->Run());
1751   CHECK_EQ(13.4, result->NumberValue());
1752   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1753   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1754 }
1755
1756
1757 THREADED_TEST(ObjectTemplate) {
1758   v8::HandleScope scope(v8::Isolate::GetCurrent());
1759   Local<ObjectTemplate> templ1 = ObjectTemplate::New();
1760   templ1->Set("x", v8_num(10));
1761   templ1->Set("y", v8_num(13));
1762   LocalContext env;
1763   Local<v8::Object> instance1 = templ1->NewInstance();
1764   env->Global()->Set(v8_str("p"), instance1);
1765   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1766   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1767   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
1768   fun->PrototypeTemplate()->Set("nirk", v8_num(123));
1769   Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
1770   templ2->Set("a", v8_num(12));
1771   templ2->Set("b", templ1);
1772   Local<v8::Object> instance2 = templ2->NewInstance();
1773   env->Global()->Set(v8_str("q"), instance2);
1774   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1775   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1776   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1777   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1778 }
1779
1780
1781 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
1782   ApiTestFuzzer::Fuzz();
1783   args.GetReturnValue().Set(v8_num(17.2));
1784 }
1785
1786
1787 static void GetKnurd(Local<String> property,
1788                      const v8::PropertyCallbackInfo<v8::Value>& info) {
1789   ApiTestFuzzer::Fuzz();
1790   info.GetReturnValue().Set(v8_num(15.2));
1791 }
1792
1793
1794 THREADED_TEST(DescriptorInheritance) {
1795   v8::HandleScope scope(v8::Isolate::GetCurrent());
1796   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
1797   super->PrototypeTemplate()->Set("flabby",
1798                                   v8::FunctionTemplate::New(GetFlabby));
1799   super->PrototypeTemplate()->Set("PI", v8_num(3.14));
1800
1801   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1802
1803   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
1804   base1->Inherit(super);
1805   base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
1806
1807   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
1808   base2->Inherit(super);
1809   base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
1810
1811   LocalContext env;
1812
1813   env->Global()->Set(v8_str("s"), super->GetFunction());
1814   env->Global()->Set(v8_str("base1"), base1->GetFunction());
1815   env->Global()->Set(v8_str("base2"), base2->GetFunction());
1816
1817   // Checks right __proto__ chain.
1818   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1819   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1820
1821   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1822
1823   // Instance accessor should not be visible on function object or its prototype
1824   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1825   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1826   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1827
1828   env->Global()->Set(v8_str("obj"),
1829                      base1->GetFunction()->NewInstance());
1830   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1831   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1832   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1833   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1834   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1835
1836   env->Global()->Set(v8_str("obj2"),
1837                      base2->GetFunction()->NewInstance());
1838   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1839   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1840   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1841   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1842   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1843
1844   // base1 and base2 cannot cross reference to each's prototype
1845   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1846   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1847 }
1848
1849
1850 int echo_named_call_count;
1851
1852
1853 static void EchoNamedProperty(Local<String> name,
1854                               const v8::PropertyCallbackInfo<v8::Value>& info) {
1855   ApiTestFuzzer::Fuzz();
1856   CHECK_EQ(v8_str("data"), info.Data());
1857   echo_named_call_count++;
1858   info.GetReturnValue().Set(name);
1859 }
1860
1861
1862 // Helper functions for Interceptor/Accessor interaction tests
1863
1864 void SimpleAccessorGetter(Local<String> name,
1865                           const v8::PropertyCallbackInfo<v8::Value>& info) {
1866   Handle<Object> self = info.This();
1867   info.GetReturnValue().Set(
1868       self->Get(String::Concat(v8_str("accessor_"), name)));
1869 }
1870
1871 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1872                           const v8::PropertyCallbackInfo<void>& info) {
1873   Handle<Object> self = info.This();
1874   self->Set(String::Concat(v8_str("accessor_"), name), value);
1875 }
1876
1877 void EmptyInterceptorGetter(Local<String> name,
1878                             const v8::PropertyCallbackInfo<v8::Value>& info) {
1879 }
1880
1881 void EmptyInterceptorSetter(Local<String> name,
1882                             Local<Value> value,
1883                             const v8::PropertyCallbackInfo<v8::Value>& info) {
1884 }
1885
1886 void InterceptorGetter(Local<String> name,
1887                        const v8::PropertyCallbackInfo<v8::Value>& info) {
1888   // Intercept names that start with 'interceptor_'.
1889   String::Utf8Value utf8(name);
1890   char* name_str = *utf8;
1891   char prefix[] = "interceptor_";
1892   int i;
1893   for (i = 0; name_str[i] && prefix[i]; ++i) {
1894     if (name_str[i] != prefix[i]) return;
1895   }
1896   Handle<Object> self = info.This();
1897   info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
1898 }
1899
1900 void InterceptorSetter(Local<String> name,
1901                        Local<Value> value,
1902                        const v8::PropertyCallbackInfo<v8::Value>& info) {
1903   // Intercept accesses that set certain integer values, for which the name does
1904   // not start with 'accessor_'.
1905   String::Utf8Value utf8(name);
1906   char* name_str = *utf8;
1907   char prefix[] = "accessor_";
1908   int i;
1909   for (i = 0; name_str[i] && prefix[i]; ++i) {
1910     if (name_str[i] != prefix[i]) break;
1911   }
1912   if (!prefix[i]) return;
1913
1914   if (value->IsInt32() && value->Int32Value() < 10000) {
1915     Handle<Object> self = info.This();
1916     self->SetHiddenValue(name, value);
1917     info.GetReturnValue().Set(value);
1918   }
1919 }
1920
1921 void AddAccessor(Handle<FunctionTemplate> templ,
1922                  Handle<String> name,
1923                  v8::AccessorGetterCallback getter,
1924                  v8::AccessorSetterCallback setter) {
1925   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1926 }
1927
1928 void AddInterceptor(Handle<FunctionTemplate> templ,
1929                     v8::NamedPropertyGetterCallback getter,
1930                     v8::NamedPropertySetterCallback setter) {
1931   templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1932 }
1933
1934
1935 THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
1936   v8::HandleScope scope(v8::Isolate::GetCurrent());
1937   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1938   Handle<FunctionTemplate> child = FunctionTemplate::New();
1939   child->Inherit(parent);
1940   AddAccessor(parent, v8_str("age"),
1941               SimpleAccessorGetter, SimpleAccessorSetter);
1942   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1943   LocalContext env;
1944   env->Global()->Set(v8_str("Child"), child->GetFunction());
1945   CompileRun("var child = new Child;"
1946              "child.age = 10;");
1947   ExpectBoolean("child.hasOwnProperty('age')", false);
1948   ExpectInt32("child.age", 10);
1949   ExpectInt32("child.accessor_age", 10);
1950 }
1951
1952
1953 THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
1954   v8::HandleScope scope(v8::Isolate::GetCurrent());
1955   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1956   Handle<FunctionTemplate> child = FunctionTemplate::New();
1957   child->Inherit(parent);
1958   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1959   LocalContext env;
1960   env->Global()->Set(v8_str("Child"), child->GetFunction());
1961   CompileRun("var child = new Child;"
1962              "var parent = child.__proto__;"
1963              "Object.defineProperty(parent, 'age', "
1964              "  {get: function(){ return this.accessor_age; }, "
1965              "   set: function(v){ this.accessor_age = v; }, "
1966              "   enumerable: true, configurable: true});"
1967              "child.age = 10;");
1968   ExpectBoolean("child.hasOwnProperty('age')", false);
1969   ExpectInt32("child.age", 10);
1970   ExpectInt32("child.accessor_age", 10);
1971 }
1972
1973
1974 THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
1975   v8::HandleScope scope(v8::Isolate::GetCurrent());
1976   Handle<FunctionTemplate> parent = FunctionTemplate::New();
1977   Handle<FunctionTemplate> child = FunctionTemplate::New();
1978   child->Inherit(parent);
1979   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1980   LocalContext env;
1981   env->Global()->Set(v8_str("Child"), child->GetFunction());
1982   CompileRun("var child = new Child;"
1983              "var parent = child.__proto__;"
1984              "parent.name = 'Alice';");
1985   ExpectBoolean("child.hasOwnProperty('name')", false);
1986   ExpectString("child.name", "Alice");
1987   CompileRun("child.name = 'Bob';");
1988   ExpectString("child.name", "Bob");
1989   ExpectBoolean("child.hasOwnProperty('name')", true);
1990   ExpectString("parent.name", "Alice");
1991 }
1992
1993
1994 THREADED_TEST(SwitchFromInterceptorToAccessor) {
1995   v8::HandleScope scope(v8::Isolate::GetCurrent());
1996   Handle<FunctionTemplate> templ = FunctionTemplate::New();
1997   AddAccessor(templ, v8_str("age"),
1998               SimpleAccessorGetter, SimpleAccessorSetter);
1999   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2000   LocalContext env;
2001   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2002   CompileRun("var obj = new Obj;"
2003              "function setAge(i){ obj.age = i; };"
2004              "for(var i = 0; i <= 10000; i++) setAge(i);");
2005   // All i < 10000 go to the interceptor.
2006   ExpectInt32("obj.interceptor_age", 9999);
2007   // The last i goes to the accessor.
2008   ExpectInt32("obj.accessor_age", 10000);
2009 }
2010
2011
2012 THREADED_TEST(SwitchFromAccessorToInterceptor) {
2013   v8::HandleScope scope(v8::Isolate::GetCurrent());
2014   Handle<FunctionTemplate> templ = FunctionTemplate::New();
2015   AddAccessor(templ, v8_str("age"),
2016               SimpleAccessorGetter, SimpleAccessorSetter);
2017   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2018   LocalContext env;
2019   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2020   CompileRun("var obj = new Obj;"
2021              "function setAge(i){ obj.age = i; };"
2022              "for(var i = 20000; i >= 9999; i--) setAge(i);");
2023   // All i >= 10000 go to the accessor.
2024   ExpectInt32("obj.accessor_age", 10000);
2025   // The last i goes to the interceptor.
2026   ExpectInt32("obj.interceptor_age", 9999);
2027 }
2028
2029
2030 THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
2031   v8::HandleScope scope(v8::Isolate::GetCurrent());
2032   Handle<FunctionTemplate> parent = FunctionTemplate::New();
2033   Handle<FunctionTemplate> child = FunctionTemplate::New();
2034   child->Inherit(parent);
2035   AddAccessor(parent, v8_str("age"),
2036               SimpleAccessorGetter, SimpleAccessorSetter);
2037   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2038   LocalContext env;
2039   env->Global()->Set(v8_str("Child"), child->GetFunction());
2040   CompileRun("var child = new Child;"
2041              "function setAge(i){ child.age = i; };"
2042              "for(var i = 0; i <= 10000; i++) setAge(i);");
2043   // All i < 10000 go to the interceptor.
2044   ExpectInt32("child.interceptor_age", 9999);
2045   // The last i goes to the accessor.
2046   ExpectInt32("child.accessor_age", 10000);
2047 }
2048
2049
2050 THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
2051   v8::HandleScope scope(v8::Isolate::GetCurrent());
2052   Handle<FunctionTemplate> parent = FunctionTemplate::New();
2053   Handle<FunctionTemplate> child = FunctionTemplate::New();
2054   child->Inherit(parent);
2055   AddAccessor(parent, v8_str("age"),
2056               SimpleAccessorGetter, SimpleAccessorSetter);
2057   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2058   LocalContext env;
2059   env->Global()->Set(v8_str("Child"), child->GetFunction());
2060   CompileRun("var child = new Child;"
2061              "function setAge(i){ child.age = i; };"
2062              "for(var i = 20000; i >= 9999; i--) setAge(i);");
2063   // All i >= 10000 go to the accessor.
2064   ExpectInt32("child.accessor_age", 10000);
2065   // The last i goes to the interceptor.
2066   ExpectInt32("child.interceptor_age", 9999);
2067 }
2068
2069
2070 THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
2071   v8::HandleScope scope(v8::Isolate::GetCurrent());
2072   Handle<FunctionTemplate> templ = FunctionTemplate::New();
2073   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2074   LocalContext env;
2075   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2076   CompileRun("var obj = new Obj;"
2077              "function setter(i) { this.accessor_age = i; };"
2078              "function getter() { return this.accessor_age; };"
2079              "function setAge(i) { obj.age = i; };"
2080              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2081              "for(var i = 0; i <= 10000; i++) setAge(i);");
2082   // All i < 10000 go to the interceptor.
2083   ExpectInt32("obj.interceptor_age", 9999);
2084   // The last i goes to the JavaScript accessor.
2085   ExpectInt32("obj.accessor_age", 10000);
2086   // The installed JavaScript getter is still intact.
2087   // This last part is a regression test for issue 1651 and relies on the fact
2088   // that both interceptor and accessor are being installed on the same object.
2089   ExpectInt32("obj.age", 10000);
2090   ExpectBoolean("obj.hasOwnProperty('age')", true);
2091   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2092 }
2093
2094
2095 THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
2096   v8::HandleScope scope(v8::Isolate::GetCurrent());
2097   Handle<FunctionTemplate> templ = FunctionTemplate::New();
2098   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2099   LocalContext env;
2100   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2101   CompileRun("var obj = new Obj;"
2102              "function setter(i) { this.accessor_age = i; };"
2103              "function getter() { return this.accessor_age; };"
2104              "function setAge(i) { obj.age = i; };"
2105              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2106              "for(var i = 20000; i >= 9999; i--) setAge(i);");
2107   // All i >= 10000 go to the accessor.
2108   ExpectInt32("obj.accessor_age", 10000);
2109   // The last i goes to the interceptor.
2110   ExpectInt32("obj.interceptor_age", 9999);
2111   // The installed JavaScript getter is still intact.
2112   // This last part is a regression test for issue 1651 and relies on the fact
2113   // that both interceptor and accessor are being installed on the same object.
2114   ExpectInt32("obj.age", 10000);
2115   ExpectBoolean("obj.hasOwnProperty('age')", true);
2116   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2117 }
2118
2119
2120 THREADED_TEST(SwitchFromInterceptorToProperty) {
2121   v8::HandleScope scope(v8::Isolate::GetCurrent());
2122   Handle<FunctionTemplate> parent = FunctionTemplate::New();
2123   Handle<FunctionTemplate> child = FunctionTemplate::New();
2124   child->Inherit(parent);
2125   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2126   LocalContext env;
2127   env->Global()->Set(v8_str("Child"), child->GetFunction());
2128   CompileRun("var child = new Child;"
2129              "function setAge(i){ child.age = i; };"
2130              "for(var i = 0; i <= 10000; i++) setAge(i);");
2131   // All i < 10000 go to the interceptor.
2132   ExpectInt32("child.interceptor_age", 9999);
2133   // The last i goes to child's own property.
2134   ExpectInt32("child.age", 10000);
2135 }
2136
2137
2138 THREADED_TEST(SwitchFromPropertyToInterceptor) {
2139   v8::HandleScope scope(v8::Isolate::GetCurrent());
2140   Handle<FunctionTemplate> parent = FunctionTemplate::New();
2141   Handle<FunctionTemplate> child = FunctionTemplate::New();
2142   child->Inherit(parent);
2143   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2144   LocalContext env;
2145   env->Global()->Set(v8_str("Child"), child->GetFunction());
2146   CompileRun("var child = new Child;"
2147              "function setAge(i){ child.age = i; };"
2148              "for(var i = 20000; i >= 9999; i--) setAge(i);");
2149   // All i >= 10000 go to child's own property.
2150   ExpectInt32("child.age", 10000);
2151   // The last i goes to the interceptor.
2152   ExpectInt32("child.interceptor_age", 9999);
2153 }
2154
2155
2156 THREADED_TEST(NamedPropertyHandlerGetter) {
2157   echo_named_call_count = 0;
2158   v8::HandleScope scope(v8::Isolate::GetCurrent());
2159   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2160   templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
2161                                                      0, 0, 0, 0,
2162                                                      v8_str("data"));
2163   LocalContext env;
2164   env->Global()->Set(v8_str("obj"),
2165                      templ->GetFunction()->NewInstance());
2166   CHECK_EQ(echo_named_call_count, 0);
2167   v8_compile("obj.x")->Run();
2168   CHECK_EQ(echo_named_call_count, 1);
2169   const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
2170   v8::Handle<Value> str = CompileRun(code);
2171   String::Utf8Value value(str);
2172   CHECK_EQ(*value, "oddlepoddle");
2173   // Check default behavior
2174   CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
2175   CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
2176   CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
2177 }
2178
2179
2180 int echo_indexed_call_count = 0;
2181
2182
2183 static void EchoIndexedProperty(
2184     uint32_t index,
2185     const v8::PropertyCallbackInfo<v8::Value>& info) {
2186   ApiTestFuzzer::Fuzz();
2187   CHECK_EQ(v8_num(637), info.Data());
2188   echo_indexed_call_count++;
2189   info.GetReturnValue().Set(v8_num(index));
2190 }
2191
2192
2193 THREADED_TEST(IndexedPropertyHandlerGetter) {
2194   v8::HandleScope scope(v8::Isolate::GetCurrent());
2195   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2196   templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
2197                                                        0, 0, 0, 0,
2198                                                        v8_num(637));
2199   LocalContext env;
2200   env->Global()->Set(v8_str("obj"),
2201                      templ->GetFunction()->NewInstance());
2202   Local<Script> script = v8_compile("obj[900]");
2203   CHECK_EQ(script->Run()->Int32Value(), 900);
2204 }
2205
2206
2207 v8::Handle<v8::Object> bottom;
2208
2209 static void CheckThisIndexedPropertyHandler(
2210     uint32_t index,
2211     const v8::PropertyCallbackInfo<v8::Value>& info) {
2212   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
2213   ApiTestFuzzer::Fuzz();
2214   CHECK(info.This()->Equals(bottom));
2215 }
2216
2217 static void CheckThisNamedPropertyHandler(
2218     Local<String> name,
2219     const v8::PropertyCallbackInfo<v8::Value>& info) {
2220   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
2221   ApiTestFuzzer::Fuzz();
2222   CHECK(info.This()->Equals(bottom));
2223 }
2224
2225 void CheckThisIndexedPropertySetter(
2226     uint32_t index,
2227     Local<Value> value,
2228     const v8::PropertyCallbackInfo<v8::Value>& info) {
2229   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
2230   ApiTestFuzzer::Fuzz();
2231   CHECK(info.This()->Equals(bottom));
2232 }
2233
2234
2235 void CheckThisNamedPropertySetter(
2236     Local<String> property,
2237     Local<Value> value,
2238     const v8::PropertyCallbackInfo<v8::Value>& info) {
2239   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
2240   ApiTestFuzzer::Fuzz();
2241   CHECK(info.This()->Equals(bottom));
2242 }
2243
2244 void CheckThisIndexedPropertyQuery(
2245     uint32_t index,
2246     const v8::PropertyCallbackInfo<v8::Integer>& info) {
2247   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
2248   ApiTestFuzzer::Fuzz();
2249   CHECK(info.This()->Equals(bottom));
2250 }
2251
2252
2253 void CheckThisNamedPropertyQuery(
2254     Local<String> property,
2255     const v8::PropertyCallbackInfo<v8::Integer>& info) {
2256   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
2257   ApiTestFuzzer::Fuzz();
2258   CHECK(info.This()->Equals(bottom));
2259 }
2260
2261
2262 void CheckThisIndexedPropertyDeleter(
2263     uint32_t index,
2264     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
2265   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
2266   ApiTestFuzzer::Fuzz();
2267   CHECK(info.This()->Equals(bottom));
2268 }
2269
2270
2271 void CheckThisNamedPropertyDeleter(
2272     Local<String> property,
2273     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
2274   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
2275   ApiTestFuzzer::Fuzz();
2276   CHECK(info.This()->Equals(bottom));
2277 }
2278
2279
2280 void CheckThisIndexedPropertyEnumerator(
2281     const v8::PropertyCallbackInfo<v8::Array>& info) {
2282   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
2283   ApiTestFuzzer::Fuzz();
2284   CHECK(info.This()->Equals(bottom));
2285 }
2286
2287
2288 void CheckThisNamedPropertyEnumerator(
2289     const v8::PropertyCallbackInfo<v8::Array>& info) {
2290   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
2291   ApiTestFuzzer::Fuzz();
2292   CHECK(info.This()->Equals(bottom));
2293 }
2294
2295
2296 THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
2297   LocalContext env;
2298   v8::HandleScope scope(env->GetIsolate());
2299
2300   // Set up a prototype chain with three interceptors.
2301   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2302   templ->InstanceTemplate()->SetIndexedPropertyHandler(
2303       CheckThisIndexedPropertyHandler,
2304       CheckThisIndexedPropertySetter,
2305       CheckThisIndexedPropertyQuery,
2306       CheckThisIndexedPropertyDeleter,
2307       CheckThisIndexedPropertyEnumerator);
2308
2309   templ->InstanceTemplate()->SetNamedPropertyHandler(
2310       CheckThisNamedPropertyHandler,
2311       CheckThisNamedPropertySetter,
2312       CheckThisNamedPropertyQuery,
2313       CheckThisNamedPropertyDeleter,
2314       CheckThisNamedPropertyEnumerator);
2315
2316   bottom = templ->GetFunction()->NewInstance();
2317   Local<v8::Object> top = templ->GetFunction()->NewInstance();
2318   Local<v8::Object> middle = templ->GetFunction()->NewInstance();
2319
2320   bottom->SetPrototype(middle);
2321   middle->SetPrototype(top);
2322   env->Global()->Set(v8_str("obj"), bottom);
2323
2324   // Indexed and named get.
2325   Script::Compile(v8_str("obj[0]"))->Run();
2326   Script::Compile(v8_str("obj.x"))->Run();
2327
2328   // Indexed and named set.
2329   Script::Compile(v8_str("obj[1] = 42"))->Run();
2330   Script::Compile(v8_str("obj.y = 42"))->Run();
2331
2332   // Indexed and named query.
2333   Script::Compile(v8_str("0 in obj"))->Run();
2334   Script::Compile(v8_str("'x' in obj"))->Run();
2335
2336   // Indexed and named deleter.
2337   Script::Compile(v8_str("delete obj[0]"))->Run();
2338   Script::Compile(v8_str("delete obj.x"))->Run();
2339
2340   // Enumerators.
2341   Script::Compile(v8_str("for (var p in obj) ;"))->Run();
2342 }
2343
2344
2345 static void PrePropertyHandlerGet(
2346     Local<String> key,
2347     const v8::PropertyCallbackInfo<v8::Value>& info) {
2348   ApiTestFuzzer::Fuzz();
2349   if (v8_str("pre")->Equals(key)) {
2350     info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
2351   }
2352 }
2353
2354
2355 static void PrePropertyHandlerQuery(
2356     Local<String> key,
2357     const v8::PropertyCallbackInfo<v8::Integer>& info) {
2358   if (v8_str("pre")->Equals(key)) {
2359     info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
2360   }
2361 }
2362
2363
2364 THREADED_TEST(PrePropertyHandler) {
2365   v8::HandleScope scope(v8::Isolate::GetCurrent());
2366   v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
2367   desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
2368                                                     0,
2369                                                     PrePropertyHandlerQuery);
2370   LocalContext env(NULL, desc->InstanceTemplate());
2371   Script::Compile(v8_str(
2372       "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
2373   v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
2374   CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
2375   v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
2376   CHECK_EQ(v8_str("Object: on"), result_on);
2377   v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
2378   CHECK(result_post.IsEmpty());
2379 }
2380
2381
2382 THREADED_TEST(UndefinedIsNotEnumerable) {
2383   LocalContext env;
2384   v8::HandleScope scope(env->GetIsolate());
2385   v8::Handle<Value> result = Script::Compile(v8_str(
2386       "this.propertyIsEnumerable(undefined)"))->Run();
2387   CHECK(result->IsFalse());
2388 }
2389
2390
2391 v8::Handle<Script> call_recursively_script;
2392 static const int kTargetRecursionDepth = 200;  // near maximum
2393
2394
2395 static void CallScriptRecursivelyCall(
2396     const v8::FunctionCallbackInfo<v8::Value>& args) {
2397   ApiTestFuzzer::Fuzz();
2398   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2399   if (depth == kTargetRecursionDepth) return;
2400   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
2401   args.GetReturnValue().Set(call_recursively_script->Run());
2402 }
2403
2404
2405 static void CallFunctionRecursivelyCall(
2406     const v8::FunctionCallbackInfo<v8::Value>& args) {
2407   ApiTestFuzzer::Fuzz();
2408   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2409   if (depth == kTargetRecursionDepth) {
2410     printf("[depth = %d]\n", depth);
2411     return;
2412   }
2413   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
2414   v8::Handle<Value> function =
2415       args.This()->Get(v8_str("callFunctionRecursively"));
2416   args.GetReturnValue().Set(
2417       function.As<Function>()->Call(args.This(), 0, NULL));
2418 }
2419
2420
2421 THREADED_TEST(DeepCrossLanguageRecursion) {
2422   v8::HandleScope scope(v8::Isolate::GetCurrent());
2423   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
2424   global->Set(v8_str("callScriptRecursively"),
2425               v8::FunctionTemplate::New(CallScriptRecursivelyCall));
2426   global->Set(v8_str("callFunctionRecursively"),
2427               v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
2428   LocalContext env(NULL, global);
2429
2430   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
2431   call_recursively_script = v8_compile("callScriptRecursively()");
2432   call_recursively_script->Run();
2433   call_recursively_script = v8::Handle<Script>();
2434
2435   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
2436   Script::Compile(v8_str("callFunctionRecursively()"))->Run();
2437 }
2438
2439
2440 static void ThrowingPropertyHandlerGet(
2441     Local<String> key,
2442     const v8::PropertyCallbackInfo<v8::Value>& info) {
2443   ApiTestFuzzer::Fuzz();
2444   info.GetReturnValue().Set(v8::ThrowException(key));
2445 }
2446
2447
2448 static void ThrowingPropertyHandlerSet(
2449     Local<String> key,
2450     Local<Value>,
2451     const v8::PropertyCallbackInfo<v8::Value>& info) {
2452   v8::ThrowException(key);
2453   info.GetReturnValue().SetUndefined();  // not the same as empty handle
2454 }
2455
2456
2457 THREADED_TEST(CallbackExceptionRegression) {
2458   v8::HandleScope scope(v8::Isolate::GetCurrent());
2459   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
2460   obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
2461                                ThrowingPropertyHandlerSet);
2462   LocalContext env;
2463   env->Global()->Set(v8_str("obj"), obj->NewInstance());
2464   v8::Handle<Value> otto = Script::Compile(v8_str(
2465       "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
2466   CHECK_EQ(v8_str("otto"), otto);
2467   v8::Handle<Value> netto = Script::Compile(v8_str(
2468       "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
2469   CHECK_EQ(v8_str("netto"), netto);
2470 }
2471
2472
2473 THREADED_TEST(FunctionPrototype) {
2474   v8::HandleScope scope(v8::Isolate::GetCurrent());
2475   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
2476   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2477   LocalContext env;
2478   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2479   Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
2480   CHECK_EQ(script->Run()->Int32Value(), 321);
2481 }
2482
2483
2484 THREADED_TEST(InternalFields) {
2485   LocalContext env;
2486   v8::HandleScope scope(env->GetIsolate());
2487
2488   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2489   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2490   instance_templ->SetInternalFieldCount(1);
2491   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2492   CHECK_EQ(1, obj->InternalFieldCount());
2493   CHECK(obj->GetInternalField(0)->IsUndefined());
2494   obj->SetInternalField(0, v8_num(17));
2495   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2496 }
2497
2498
2499 THREADED_TEST(GlobalObjectInternalFields) {
2500   v8::HandleScope scope(v8::Isolate::GetCurrent());
2501   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
2502   global_template->SetInternalFieldCount(1);
2503   LocalContext env(NULL, global_template);
2504   v8::Handle<v8::Object> global_proxy = env->Global();
2505   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2506   CHECK_EQ(1, global->InternalFieldCount());
2507   CHECK(global->GetInternalField(0)->IsUndefined());
2508   global->SetInternalField(0, v8_num(17));
2509   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2510 }
2511
2512
2513 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2514   LocalContext env;
2515   v8::HandleScope scope(v8::Isolate::GetCurrent());
2516
2517   v8::Local<v8::Object> global = env->Global();
2518   global->Set(0, v8::String::New("value"));
2519   CHECK(global->HasRealIndexedProperty(0));
2520 }
2521
2522
2523 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2524                                                void* value) {
2525   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2526   obj->SetAlignedPointerInInternalField(0, value);
2527   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2528   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2529 }
2530
2531
2532 THREADED_TEST(InternalFieldsAlignedPointers) {
2533   LocalContext env;
2534   v8::HandleScope scope(env->GetIsolate());
2535
2536   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2537   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2538   instance_templ->SetInternalFieldCount(1);
2539   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2540   CHECK_EQ(1, obj->InternalFieldCount());
2541
2542   CheckAlignedPointerInInternalField(obj, NULL);
2543
2544   int* heap_allocated = new int[100];
2545   CheckAlignedPointerInInternalField(obj, heap_allocated);
2546   delete[] heap_allocated;
2547
2548   int stack_allocated[100];
2549   CheckAlignedPointerInInternalField(obj, stack_allocated);
2550
2551   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2552   CheckAlignedPointerInInternalField(obj, huge);
2553 }
2554
2555
2556 static void CheckAlignedPointerInEmbedderData(LocalContext* env,
2557                                               int index,
2558                                               void* value) {
2559   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2560   (*env)->SetAlignedPointerInEmbedderData(index, value);
2561   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2562   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2563 }
2564
2565
2566 static void* AlignedTestPointer(int i) {
2567   return reinterpret_cast<void*>(i * 1234);
2568 }
2569
2570
2571 THREADED_TEST(EmbedderDataAlignedPointers) {
2572   LocalContext env;
2573   v8::HandleScope scope(env->GetIsolate());
2574
2575   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2576
2577   int* heap_allocated = new int[100];
2578   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2579   delete[] heap_allocated;
2580
2581   int stack_allocated[100];
2582   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2583
2584   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2585   CheckAlignedPointerInEmbedderData(&env, 3, huge);
2586
2587   // Test growing of the embedder data's backing store.
2588   for (int i = 0; i < 100; i++) {
2589     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2590   }
2591   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2592   for (int i = 0; i < 100; i++) {
2593     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2594   }
2595 }
2596
2597
2598 static void CheckEmbedderData(LocalContext* env,
2599                               int index,
2600                               v8::Handle<Value> data) {
2601   (*env)->SetEmbedderData(index, data);
2602   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2603 }
2604
2605
2606 THREADED_TEST(EmbedderData) {
2607   LocalContext env;
2608   v8::HandleScope scope(env->GetIsolate());
2609
2610   CheckEmbedderData(&env, 3, v8::String::New("The quick brown fox jumps"));
2611   CheckEmbedderData(&env, 2, v8::String::New("over the lazy dog."));
2612   CheckEmbedderData(&env, 1, v8::Number::New(1.2345));
2613   CheckEmbedderData(&env, 0, v8::Boolean::New(true));
2614 }
2615
2616
2617 THREADED_TEST(IdentityHash) {
2618   LocalContext env;
2619   v8::HandleScope scope(env->GetIsolate());
2620
2621   // Ensure that the test starts with an fresh heap to test whether the hash
2622   // code is based on the address.
2623   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2624   Local<v8::Object> obj = v8::Object::New();
2625   int hash = obj->GetIdentityHash();
2626   int hash1 = obj->GetIdentityHash();
2627   CHECK_EQ(hash, hash1);
2628   int hash2 = v8::Object::New()->GetIdentityHash();
2629   // Since the identity hash is essentially a random number two consecutive
2630   // objects should not be assigned the same hash code. If the test below fails
2631   // the random number generator should be evaluated.
2632   CHECK_NE(hash, hash2);
2633   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2634   int hash3 = v8::Object::New()->GetIdentityHash();
2635   // Make sure that the identity hash is not based on the initial address of
2636   // the object alone. If the test below fails the random number generator
2637   // should be evaluated.
2638   CHECK_NE(hash, hash3);
2639   int hash4 = obj->GetIdentityHash();
2640   CHECK_EQ(hash, hash4);
2641
2642   // Check identity hashes behaviour in the presence of JS accessors.
2643   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2644   {
2645     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2646     Local<v8::Object> o1 = v8::Object::New();
2647     Local<v8::Object> o2 = v8::Object::New();
2648     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2649   }
2650   {
2651     CompileRun(
2652         "function cnst() { return 42; };\n"
2653         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2654     Local<v8::Object> o1 = v8::Object::New();
2655     Local<v8::Object> o2 = v8::Object::New();
2656     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2657   }
2658 }
2659
2660
2661 THREADED_TEST(SymbolProperties) {
2662   i::FLAG_harmony_symbols = true;
2663
2664   LocalContext env;
2665   v8::Isolate* isolate = env->GetIsolate();
2666   v8::HandleScope scope(isolate);
2667
2668   v8::Local<v8::Object> obj = v8::Object::New();
2669   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2670   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
2671
2672   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2673
2674   // Check basic symbol functionality.
2675   CHECK(sym1->IsSymbol());
2676   CHECK(sym2->IsSymbol());
2677   CHECK(!obj->IsSymbol());
2678
2679   CHECK(sym1->Equals(sym1));
2680   CHECK(sym2->Equals(sym2));
2681   CHECK(!sym1->Equals(sym2));
2682   CHECK(!sym2->Equals(sym1));
2683   CHECK(sym1->StrictEquals(sym1));
2684   CHECK(sym2->StrictEquals(sym2));
2685   CHECK(!sym1->StrictEquals(sym2));
2686   CHECK(!sym2->StrictEquals(sym1));
2687
2688   CHECK(sym2->Name()->Equals(v8::String::New("my-symbol")));
2689
2690   v8::Local<v8::Value> sym_val = sym2;
2691   CHECK(sym_val->IsSymbol());
2692   CHECK(sym_val->Equals(sym2));
2693   CHECK(sym_val->StrictEquals(sym2));
2694   CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2695
2696   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2697   CHECK(sym_obj->IsSymbolObject());
2698   CHECK(!sym2->IsSymbolObject());
2699   CHECK(!obj->IsSymbolObject());
2700   CHECK(sym_obj->Equals(sym2));
2701   CHECK(!sym_obj->StrictEquals(sym2));
2702   CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
2703   CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
2704
2705   // Make sure delete of a non-existent symbol property works.
2706   CHECK(obj->Delete(sym1));
2707   CHECK(!obj->Has(sym1));
2708
2709   CHECK(obj->Set(sym1, v8::Integer::New(1503)));
2710   CHECK(obj->Has(sym1));
2711   CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2712   CHECK(obj->Set(sym1, v8::Integer::New(2002)));
2713   CHECK(obj->Has(sym1));
2714   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2715   CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2716
2717   CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2718   int num_props = obj->GetPropertyNames()->Length();
2719   CHECK(obj->Set(v8::String::New("bla"), v8::Integer::New(20)));
2720   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2721   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2722
2723   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2724
2725   // Add another property and delete it afterwards to force the object in
2726   // slow case.
2727   CHECK(obj->Set(sym2, v8::Integer::New(2008)));
2728   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2729   CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2730   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2731   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2732
2733   CHECK(obj->Has(sym1));
2734   CHECK(obj->Has(sym2));
2735   CHECK(obj->Delete(sym2));
2736   CHECK(obj->Has(sym1));
2737   CHECK(!obj->Has(sym2));
2738   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2739   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2740 }
2741
2742
2743 class ScopedArrayBufferContents {
2744  public:
2745   explicit ScopedArrayBufferContents(
2746       const v8::ArrayBuffer::Contents& contents)
2747     : contents_(contents) {}
2748   ~ScopedArrayBufferContents() { free(contents_.Data()); }
2749   void* Data() const { return contents_.Data(); }
2750   size_t ByteLength() const { return contents_.ByteLength(); }
2751  private:
2752   const v8::ArrayBuffer::Contents contents_;
2753 };
2754
2755 template <typename T>
2756 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2757   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2758   for (int i = 0; i < value->InternalFieldCount(); i++) {
2759     CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2760   }
2761 }
2762
2763
2764 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
2765   LocalContext env;
2766   v8::Isolate* isolate = env->GetIsolate();
2767   v8::HandleScope handle_scope(isolate);
2768
2769   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(1024);
2770   CheckInternalFieldsAreZero(ab);
2771   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2772   CHECK(!ab->IsExternal());
2773   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2774
2775   ScopedArrayBufferContents ab_contents(ab->Externalize());
2776   CHECK(ab->IsExternal());
2777
2778   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2779   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2780   ASSERT(data != NULL);
2781   env->Global()->Set(v8_str("ab"), ab);
2782
2783   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2784   CHECK_EQ(1024, result->Int32Value());
2785
2786   result = CompileRun("var u8 = new Uint8Array(ab);"
2787                       "u8[0] = 0xFF;"
2788                       "u8[1] = 0xAA;"
2789                       "u8.length");
2790   CHECK_EQ(1024, result->Int32Value());
2791   CHECK_EQ(0xFF, data[0]);
2792   CHECK_EQ(0xAA, data[1]);
2793   data[0] = 0xCC;
2794   data[1] = 0x11;
2795   result = CompileRun("u8[0] + u8[1]");
2796   CHECK_EQ(0xDD, result->Int32Value());
2797 }
2798
2799
2800 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
2801   LocalContext env;
2802   v8::Isolate* isolate = env->GetIsolate();
2803   v8::HandleScope handle_scope(isolate);
2804
2805
2806   v8::Local<v8::Value> result =
2807       CompileRun("var ab1 = new ArrayBuffer(2);"
2808                  "var u8_a = new Uint8Array(ab1);"
2809                  "u8_a[0] = 0xAA;"
2810                  "u8_a[1] = 0xFF; u8_a.buffer");
2811   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
2812   CheckInternalFieldsAreZero(ab1);
2813   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
2814   CHECK(!ab1->IsExternal());
2815   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
2816   CHECK(ab1->IsExternal());
2817
2818   result = CompileRun("ab1.byteLength");
2819   CHECK_EQ(2, result->Int32Value());
2820   result = CompileRun("u8_a[0]");
2821   CHECK_EQ(0xAA, result->Int32Value());
2822   result = CompileRun("u8_a[1]");
2823   CHECK_EQ(0xFF, result->Int32Value());
2824   result = CompileRun("var u8_b = new Uint8Array(ab1);"
2825                       "u8_b[0] = 0xBB;"
2826                       "u8_a[0]");
2827   CHECK_EQ(0xBB, result->Int32Value());
2828   result = CompileRun("u8_b[1]");
2829   CHECK_EQ(0xFF, result->Int32Value());
2830
2831   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2832   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2833   CHECK_EQ(0xBB, ab1_data[0]);
2834   CHECK_EQ(0xFF, ab1_data[1]);
2835   ab1_data[0] = 0xCC;
2836   ab1_data[1] = 0x11;
2837   result = CompileRun("u8_a[0] + u8_a[1]");
2838   CHECK_EQ(0xDD, result->Int32Value());
2839 }
2840
2841
2842 THREADED_TEST(ArrayBuffer_External) {
2843   LocalContext env;
2844   v8::Isolate* isolate = env->GetIsolate();
2845   v8::HandleScope handle_scope(isolate);
2846
2847   i::ScopedVector<uint8_t> my_data(100);
2848   memset(my_data.start(), 0, 100);
2849   Local<v8::ArrayBuffer> ab3 = v8::ArrayBuffer::New(my_data.start(), 100);
2850   CheckInternalFieldsAreZero(ab3);
2851   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
2852   CHECK(ab3->IsExternal());
2853
2854   env->Global()->Set(v8_str("ab3"), ab3);
2855
2856   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2857   CHECK_EQ(100, result->Int32Value());
2858
2859   result = CompileRun("var u8_b = new Uint8Array(ab3);"
2860                       "u8_b[0] = 0xBB;"
2861                       "u8_b[1] = 0xCC;"
2862                       "u8_b.length");
2863   CHECK_EQ(100, result->Int32Value());
2864   CHECK_EQ(0xBB, my_data[0]);
2865   CHECK_EQ(0xCC, my_data[1]);
2866   my_data[0] = 0xCC;
2867   my_data[1] = 0x11;
2868   result = CompileRun("u8_b[0] + u8_b[1]");
2869   CHECK_EQ(0xDD, result->Int32Value());
2870 }
2871
2872
2873 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
2874   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
2875   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
2876 }
2877
2878
2879 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
2880   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
2881   CHECK_EQ(0, static_cast<int>(ta->Length()));
2882   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
2883 }
2884
2885
2886 static void CheckIsTypedArrayVarNeutered(const char* name) {
2887   i::ScopedVector<char> source(1024);
2888   i::OS::SNPrintF(source,
2889       "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
2890       name, name, name);
2891   CHECK(CompileRun(source.start())->IsTrue());
2892   v8::Handle<v8::TypedArray> ta =
2893     v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
2894   CheckIsNeutered(ta);
2895 }
2896
2897
2898 template <typename TypedArray, int kElementSize>
2899 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
2900                                          int byteOffset,
2901                                          int length) {
2902   v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
2903   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
2904   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
2905   CHECK_EQ(length, static_cast<int>(ta->Length()));
2906   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
2907   return ta;
2908 }
2909
2910
2911 THREADED_TEST(ArrayBuffer_NeuteringApi) {
2912   LocalContext env;
2913   v8::Isolate* isolate = env->GetIsolate();
2914   v8::HandleScope handle_scope(isolate);
2915
2916   v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(1024);
2917
2918   v8::Handle<v8::Uint8Array> u8a =
2919     CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
2920   v8::Handle<v8::Uint8ClampedArray> u8c =
2921     CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
2922   v8::Handle<v8::Int8Array> i8a =
2923     CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
2924
2925   v8::Handle<v8::Uint16Array> u16a =
2926     CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
2927   v8::Handle<v8::Int16Array> i16a =
2928     CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
2929
2930   v8::Handle<v8::Uint32Array> u32a =
2931     CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
2932   v8::Handle<v8::Int32Array> i32a =
2933     CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
2934
2935   v8::Handle<v8::Float32Array> f32a =
2936     CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
2937   v8::Handle<v8::Float64Array> f64a =
2938     CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
2939
2940   v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
2941   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
2942   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
2943   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
2944
2945   ScopedArrayBufferContents contents(buffer->Externalize());
2946   buffer->Neuter();
2947   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
2948   CheckIsNeutered(u8a);
2949   CheckIsNeutered(u8c);
2950   CheckIsNeutered(i8a);
2951   CheckIsNeutered(u16a);
2952   CheckIsNeutered(i16a);
2953   CheckIsNeutered(u32a);
2954   CheckIsNeutered(i32a);
2955   CheckIsNeutered(f32a);
2956   CheckIsNeutered(f64a);
2957   CheckDataViewIsNeutered(dv);
2958 }
2959
2960
2961 THREADED_TEST(ArrayBuffer_NeuteringScript) {
2962   LocalContext env;
2963   v8::Isolate* isolate = env->GetIsolate();
2964   v8::HandleScope handle_scope(isolate);
2965
2966   CompileRun(
2967       "var ab = new ArrayBuffer(1024);"
2968       "var u8a = new Uint8Array(ab, 1, 1023);"
2969       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
2970       "var i8a = new Int8Array(ab, 1, 1023);"
2971       "var u16a = new Uint16Array(ab, 2, 511);"
2972       "var i16a = new Int16Array(ab, 2, 511);"
2973       "var u32a = new Uint32Array(ab, 4, 255);"
2974       "var i32a = new Int32Array(ab, 4, 255);"
2975       "var f32a = new Float32Array(ab, 4, 255);"
2976       "var f64a = new Float64Array(ab, 8, 127);"
2977       "var dv = new DataView(ab, 1, 1023);");
2978
2979   v8::Handle<v8::ArrayBuffer> ab =
2980       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
2981
2982   v8::Handle<v8::DataView> dv =
2983     v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
2984
2985   ScopedArrayBufferContents contents(ab->Externalize());
2986   ab->Neuter();
2987   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
2988   CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
2989
2990   CheckIsTypedArrayVarNeutered("u8a");
2991   CheckIsTypedArrayVarNeutered("u8c");
2992   CheckIsTypedArrayVarNeutered("i8a");
2993   CheckIsTypedArrayVarNeutered("u16a");
2994   CheckIsTypedArrayVarNeutered("i16a");
2995   CheckIsTypedArrayVarNeutered("u32a");
2996   CheckIsTypedArrayVarNeutered("i32a");
2997   CheckIsTypedArrayVarNeutered("f32a");
2998   CheckIsTypedArrayVarNeutered("f64a");
2999
3000   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3001   CheckDataViewIsNeutered(dv);
3002 }
3003
3004
3005
3006 THREADED_TEST(HiddenProperties) {
3007   LocalContext env;
3008   v8::HandleScope scope(env->GetIsolate());
3009
3010   v8::Local<v8::Object> obj = v8::Object::New();
3011   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3012   v8::Local<v8::String> empty = v8_str("");
3013   v8::Local<v8::String> prop_name = v8_str("prop_name");
3014
3015   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
3016
3017   // Make sure delete of a non-existent hidden value works
3018   CHECK(obj->DeleteHiddenValue(key));
3019
3020   CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
3021   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
3022   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
3023   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3024
3025   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
3026
3027   // Make sure we do not find the hidden property.
3028   CHECK(!obj->Has(empty));
3029   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3030   CHECK(obj->Get(empty)->IsUndefined());
3031   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3032   CHECK(obj->Set(empty, v8::Integer::New(2003)));
3033   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3034   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
3035
3036   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
3037
3038   // Add another property and delete it afterwards to force the object in
3039   // slow case.
3040   CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
3041   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3042   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
3043   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3044   CHECK(obj->Delete(prop_name));
3045   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3046
3047   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
3048
3049   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
3050   CHECK(obj->GetHiddenValue(key).IsEmpty());
3051
3052   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
3053   CHECK(obj->DeleteHiddenValue(key));
3054   CHECK(obj->GetHiddenValue(key).IsEmpty());
3055 }
3056
3057
3058 THREADED_TEST(Regress97784) {
3059   // Regression test for crbug.com/97784
3060   // Messing with the Object.prototype should not have effect on
3061   // hidden properties.
3062   LocalContext env;
3063   v8::HandleScope scope(env->GetIsolate());
3064
3065   v8::Local<v8::Object> obj = v8::Object::New();
3066   v8::Local<v8::String> key = v8_str("hidden");
3067
3068   CompileRun(
3069       "set_called = false;"
3070       "Object.defineProperty("
3071       "    Object.prototype,"
3072       "    'hidden',"
3073       "    {get: function() { return 45; },"
3074       "     set: function() { set_called = true; }})");
3075
3076   CHECK(obj->GetHiddenValue(key).IsEmpty());
3077   // Make sure that the getter and setter from Object.prototype is not invoked.
3078   // If it did we would have full access to the hidden properties in
3079   // the accessor.
3080   CHECK(obj->SetHiddenValue(key, v8::Integer::New(42)));
3081   ExpectFalse("set_called");
3082   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
3083 }
3084
3085
3086 static bool interceptor_for_hidden_properties_called;
3087 static void InterceptorForHiddenProperties(
3088     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
3089   interceptor_for_hidden_properties_called = true;
3090 }
3091
3092
3093 THREADED_TEST(HiddenPropertiesWithInterceptors) {
3094   LocalContext context;
3095   v8::HandleScope scope(context->GetIsolate());
3096
3097   interceptor_for_hidden_properties_called = false;
3098
3099   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3100
3101   // Associate an interceptor with an object and start setting hidden values.
3102   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
3103   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
3104   instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
3105   Local<v8::Function> function = fun_templ->GetFunction();
3106   Local<v8::Object> obj = function->NewInstance();
3107   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
3108   CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
3109   CHECK(!interceptor_for_hidden_properties_called);
3110 }
3111
3112
3113 THREADED_TEST(External) {
3114   v8::HandleScope scope(v8::Isolate::GetCurrent());
3115   int x = 3;
3116   Local<v8::External> ext = v8::External::New(&x);
3117   LocalContext env;
3118   env->Global()->Set(v8_str("ext"), ext);
3119   Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
3120   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
3121   int* ptr = static_cast<int*>(reext->Value());
3122   CHECK_EQ(x, 3);
3123   *ptr = 10;
3124   CHECK_EQ(x, 10);
3125
3126   // Make sure unaligned pointers are wrapped properly.
3127   char* data = i::StrDup("0123456789");
3128   Local<v8::Value> zero = v8::External::New(&data[0]);
3129   Local<v8::Value> one = v8::External::New(&data[1]);
3130   Local<v8::Value> two = v8::External::New(&data[2]);
3131   Local<v8::Value> three = v8::External::New(&data[3]);
3132
3133   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
3134   CHECK_EQ('0', *char_ptr);
3135   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
3136   CHECK_EQ('1', *char_ptr);
3137   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
3138   CHECK_EQ('2', *char_ptr);
3139   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
3140   CHECK_EQ('3', *char_ptr);
3141   i::DeleteArray(data);
3142 }
3143
3144
3145 THREADED_TEST(GlobalHandle) {
3146   v8::Isolate* isolate = v8::Isolate::GetCurrent();
3147   v8::Persistent<String> global;
3148   {
3149     v8::HandleScope scope(isolate);
3150     global.Reset(isolate, v8_str("str"));
3151   }
3152   {
3153     v8::HandleScope scope(isolate);
3154     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3155   }
3156   global.Dispose();
3157   global.Clear();
3158   {
3159     v8::HandleScope scope(isolate);
3160     global.Reset(isolate, v8_str("str"));
3161   }
3162   {
3163     v8::HandleScope scope(isolate);
3164     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3165   }
3166   global.Dispose();
3167 }
3168
3169
3170 THREADED_TEST(ResettingGlobalHandle) {
3171   v8::Isolate* isolate = v8::Isolate::GetCurrent();
3172   v8::Persistent<String> global;
3173   {
3174     v8::HandleScope scope(isolate);
3175     global.Reset(isolate, v8_str("str"));
3176   }
3177   v8::internal::GlobalHandles* global_handles =
3178       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3179   int initial_handle_count = global_handles->global_handles_count();
3180   {
3181     v8::HandleScope scope(isolate);
3182     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3183   }
3184   {
3185     v8::HandleScope scope(isolate);
3186     global.Reset(isolate, v8_str("longer"));
3187   }
3188   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3189   {
3190     v8::HandleScope scope(isolate);
3191     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3192   }
3193   global.Dispose();
3194   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3195 }
3196
3197
3198 THREADED_TEST(ResettingGlobalHandleToEmpty) {
3199   v8::Isolate* isolate = v8::Isolate::GetCurrent();
3200   v8::Persistent<String> global;
3201   {
3202     v8::HandleScope scope(isolate);
3203     global.Reset(isolate, v8_str("str"));
3204   }
3205   v8::internal::GlobalHandles* global_handles =
3206       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3207   int initial_handle_count = global_handles->global_handles_count();
3208   {
3209     v8::HandleScope scope(isolate);
3210     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3211   }
3212   {
3213     v8::HandleScope scope(isolate);
3214     Local<String> empty;
3215     global.Reset(isolate, empty);
3216   }
3217   CHECK(global.IsEmpty());
3218   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3219 }
3220
3221
3222 THREADED_TEST(ClearAndLeakGlobal) {
3223   v8::Isolate* isolate = v8::Isolate::GetCurrent();
3224   v8::internal::GlobalHandles* global_handles = NULL;
3225   int initial_handle_count = 0;
3226   v8::Persistent<String> global;
3227   {
3228     v8::HandleScope scope(isolate);
3229     Local<String> str = v8_str("str");
3230     global_handles =
3231         reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3232     initial_handle_count = global_handles->global_handles_count();
3233     global.Reset(isolate, str);
3234   }
3235   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count + 1);
3236   String* str = global.ClearAndLeak();
3237   CHECK(global.IsEmpty());
3238   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count + 1);
3239   global_handles->Destroy(reinterpret_cast<i::Object**>(str));
3240   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3241 }
3242
3243
3244 THREADED_TEST(GlobalHandleUpcast) {
3245   v8::Isolate* isolate = v8::Isolate::GetCurrent();
3246   v8::HandleScope scope(isolate);
3247   v8::Local<String> local = v8::Local<String>::New(v8_str("str"));
3248   v8::Persistent<String> global_string(isolate, local);
3249   v8::Persistent<Value>& global_value =
3250       v8::Persistent<Value>::Cast(global_string);
3251   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3252   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
3253   global_string.Dispose();
3254 }
3255
3256
3257 THREADED_TEST(HandleEquality) {
3258   v8::Isolate* isolate = v8::Isolate::GetCurrent();
3259   v8::Persistent<String> global1;
3260   v8::Persistent<String> global2;
3261   {
3262     v8::HandleScope scope(isolate);
3263     global1.Reset(isolate, v8_str("str"));
3264     global2.Reset(isolate, v8_str("str2"));
3265   }
3266   CHECK_EQ(global1 == global1, true);
3267   CHECK_EQ(global1 != global1, false);
3268   {
3269     v8::HandleScope scope(isolate);
3270     Local<String> local1 = Local<String>::New(isolate, global1);
3271     Local<String> local2 = Local<String>::New(isolate, global2);
3272
3273     CHECK_EQ(global1 == local1, true);
3274     CHECK_EQ(global1 != local1, false);
3275     CHECK_EQ(local1 == global1, true);
3276     CHECK_EQ(local1 != global1, false);
3277
3278     CHECK_EQ(global1 == local2, false);
3279     CHECK_EQ(global1 != local2, true);
3280     CHECK_EQ(local2 == global1, false);
3281     CHECK_EQ(local2 != global1, true);
3282
3283     CHECK_EQ(local1 == local2, false);
3284     CHECK_EQ(local1 != local2, true);
3285
3286     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3287     CHECK_EQ(local1 == anotherLocal1, true);
3288     CHECK_EQ(local1 != anotherLocal1, false);
3289   }
3290   global1.Dispose();
3291   global2.Dispose();
3292 }
3293
3294
3295 THREADED_TEST(LocalHandle) {
3296   v8::HandleScope scope(v8::Isolate::GetCurrent());
3297   v8::Local<String> local = v8::Local<String>::New(v8_str("str"));
3298   CHECK_EQ(local->Length(), 3);
3299
3300   local = v8::Local<String>::New(v8::Isolate::GetCurrent(), v8_str("str"));
3301   CHECK_EQ(local->Length(), 3);
3302 }
3303
3304
3305 class WeakCallCounter {
3306  public:
3307   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
3308   int id() { return id_; }
3309   void increment() { number_of_weak_calls_++; }
3310   int NumberOfWeakCalls() { return number_of_weak_calls_; }
3311  private:
3312   int id_;
3313   int number_of_weak_calls_;
3314 };
3315
3316
3317 static void WeakPointerCallback(v8::Isolate* isolate,
3318                                 Persistent<Value>* handle,
3319                                 WeakCallCounter* counter) {
3320   CHECK_EQ(1234, counter->id());
3321   counter->increment();
3322   handle->Dispose();
3323 }
3324
3325
3326 static UniqueId MakeUniqueId(const Persistent<Value>& p) {
3327   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3328 }
3329
3330
3331 THREADED_TEST(ApiObjectGroups) {
3332   LocalContext env;
3333   v8::Isolate* iso = env->GetIsolate();
3334   HandleScope scope(iso);
3335
3336   Persistent<Value> g1s1;
3337   Persistent<Value> g1s2;
3338   Persistent<Value> g1c1;
3339   Persistent<Value> g2s1;
3340   Persistent<Value> g2s2;
3341   Persistent<Value> g2c1;
3342
3343   WeakCallCounter counter(1234);
3344
3345   {
3346     HandleScope scope(iso);
3347     g1s1.Reset(iso, Object::New());
3348     g1s2.Reset(iso, Object::New());
3349     g1c1.Reset(iso, Object::New());
3350     g1s1.MakeWeak(&counter, &WeakPointerCallback);
3351     g1s2.MakeWeak(&counter, &WeakPointerCallback);
3352     g1c1.MakeWeak(&counter, &WeakPointerCallback);
3353
3354     g2s1.Reset(iso, Object::New());
3355     g2s2.Reset(iso, Object::New());
3356     g2c1.Reset(iso, Object::New());
3357     g2s1.MakeWeak(&counter, &WeakPointerCallback);
3358     g2s2.MakeWeak(&counter, &WeakPointerCallback);
3359     g2c1.MakeWeak(&counter, &WeakPointerCallback);
3360   }
3361
3362   Persistent<Value> root(iso, g1s1);  // make a root.
3363
3364   // Connect group 1 and 2, make a cycle.
3365   {
3366     HandleScope scope(iso);
3367     CHECK(Local<Object>::New(iso, g1s2.As<Object>())->
3368             Set(0, Local<Value>::New(iso, g2s2)));
3369     CHECK(Local<Object>::New(iso, g2s1.As<Object>())->
3370             Set(0, Local<Value>::New(iso, g1s1)));
3371   }
3372
3373   {
3374     UniqueId id1 = MakeUniqueId(g1s1);
3375     UniqueId id2 = MakeUniqueId(g2s2);
3376     iso->SetObjectGroupId(g1s1, id1);
3377     iso->SetObjectGroupId(g1s2, id1);
3378     iso->SetReferenceFromGroup(id1, g1c1);
3379     iso->SetObjectGroupId(g2s1, id2);
3380     iso->SetObjectGroupId(g2s2, id2);
3381     iso->SetReferenceFromGroup(id2, g2c1);
3382   }
3383   // Do a single full GC, ensure incremental marking is stopped.
3384   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3385       iso)->heap();
3386   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3387
3388   // All object should be alive.
3389   CHECK_EQ(0, counter.NumberOfWeakCalls());
3390
3391   // Weaken the root.
3392   root.MakeWeak(&counter, &WeakPointerCallback);
3393   // But make children strong roots---all the objects (except for children)
3394   // should be collectable now.
3395   g1c1.ClearWeak();
3396   g2c1.ClearWeak();
3397
3398   // Groups are deleted, rebuild groups.
3399   {
3400     UniqueId id1 = MakeUniqueId(g1s1);
3401     UniqueId id2 = MakeUniqueId(g2s2);
3402     iso->SetObjectGroupId(g1s1, id1);
3403     iso->SetObjectGroupId(g1s2, id1);
3404     iso->SetReferenceFromGroup(id1, g1c1);
3405     iso->SetObjectGroupId(g2s1, id2);
3406     iso->SetObjectGroupId(g2s2, id2);
3407     iso->SetReferenceFromGroup(id2, g2c1);
3408   }
3409
3410   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3411
3412   // All objects should be gone. 5 global handles in total.
3413   CHECK_EQ(5, counter.NumberOfWeakCalls());
3414
3415   // And now make children weak again and collect them.
3416   g1c1.MakeWeak(&counter, &WeakPointerCallback);
3417   g2c1.MakeWeak(&counter, &WeakPointerCallback);
3418
3419   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3420   CHECK_EQ(7, counter.NumberOfWeakCalls());
3421 }
3422
3423
3424 THREADED_TEST(ApiObjectGroupsCycle) {
3425   LocalContext env;
3426   v8::Isolate* iso = env->GetIsolate();
3427   HandleScope scope(iso);
3428
3429   WeakCallCounter counter(1234);
3430
3431   Persistent<Value> g1s1;
3432   Persistent<Value> g1s2;
3433   Persistent<Value> g2s1;
3434   Persistent<Value> g2s2;
3435   Persistent<Value> g3s1;
3436   Persistent<Value> g3s2;
3437   Persistent<Value> g4s1;
3438   Persistent<Value> g4s2;
3439
3440   {
3441     HandleScope scope(iso);
3442     g1s1.Reset(iso, Object::New());
3443     g1s2.Reset(iso, Object::New());
3444     g1s1.MakeWeak(&counter, &WeakPointerCallback);
3445     g1s2.MakeWeak(&counter, &WeakPointerCallback);
3446     CHECK(g1s1.IsWeak());
3447     CHECK(g1s2.IsWeak());
3448
3449     g2s1.Reset(iso, Object::New());
3450     g2s2.Reset(iso, Object::New());
3451     g2s1.MakeWeak(&counter, &WeakPointerCallback);
3452     g2s2.MakeWeak(&counter, &WeakPointerCallback);
3453     CHECK(g2s1.IsWeak());
3454     CHECK(g2s2.IsWeak());
3455
3456     g3s1.Reset(iso, Object::New());
3457     g3s2.Reset(iso, Object::New());
3458     g3s1.MakeWeak(&counter, &WeakPointerCallback);
3459     g3s2.MakeWeak(&counter, &WeakPointerCallback);
3460     CHECK(g3s1.IsWeak());
3461     CHECK(g3s2.IsWeak());
3462
3463     g4s1.Reset(iso, Object::New());
3464     g4s2.Reset(iso, Object::New());
3465     g4s1.MakeWeak(&counter, &WeakPointerCallback);
3466     g4s2.MakeWeak(&counter, &WeakPointerCallback);
3467     CHECK(g4s1.IsWeak());
3468     CHECK(g4s2.IsWeak());
3469   }
3470
3471   Persistent<Value> root(iso, g1s1);  // make a root.
3472
3473   // Connect groups.  We're building the following cycle:
3474   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3475   // groups.
3476   {
3477     UniqueId id1 = MakeUniqueId(g1s1);
3478     UniqueId id2 = MakeUniqueId(g2s1);
3479     UniqueId id3 = MakeUniqueId(g3s1);
3480     UniqueId id4 = MakeUniqueId(g4s1);
3481     iso->SetObjectGroupId(g1s1, id1);
3482     iso->SetObjectGroupId(g1s2, id1);
3483     iso->SetReferenceFromGroup(id1, g2s1);
3484     iso->SetObjectGroupId(g2s1, id2);
3485     iso->SetObjectGroupId(g2s2, id2);
3486     iso->SetReferenceFromGroup(id2, g3s1);
3487     iso->SetObjectGroupId(g3s1, id3);
3488     iso->SetObjectGroupId(g3s2, id3);
3489     iso->SetReferenceFromGroup(id3, g4s1);
3490     iso->SetObjectGroupId(g4s1, id4);
3491     iso->SetObjectGroupId(g4s2, id4);
3492     iso->SetReferenceFromGroup(id4, g1s1);
3493   }
3494   // Do a single full GC
3495   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3496       iso)->heap();
3497   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3498
3499   // All object should be alive.
3500   CHECK_EQ(0, counter.NumberOfWeakCalls());
3501
3502   // Weaken the root.
3503   root.MakeWeak(&counter, &WeakPointerCallback);
3504
3505   // Groups are deleted, rebuild groups.
3506   {
3507     UniqueId id1 = MakeUniqueId(g1s1);
3508     UniqueId id2 = MakeUniqueId(g2s1);
3509     UniqueId id3 = MakeUniqueId(g3s1);
3510     UniqueId id4 = MakeUniqueId(g4s1);
3511     iso->SetObjectGroupId(g1s1, id1);
3512     iso->SetObjectGroupId(g1s2, id1);
3513     iso->SetReferenceFromGroup(id1, g2s1);
3514     iso->SetObjectGroupId(g2s1, id2);
3515     iso->SetObjectGroupId(g2s2, id2);
3516     iso->SetReferenceFromGroup(id2, g3s1);
3517     iso->SetObjectGroupId(g3s1, id3);
3518     iso->SetObjectGroupId(g3s2, id3);
3519     iso->SetReferenceFromGroup(id3, g4s1);
3520     iso->SetObjectGroupId(g4s1, id4);
3521     iso->SetObjectGroupId(g4s2, id4);
3522     iso->SetReferenceFromGroup(id4, g1s1);
3523   }
3524
3525   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3526
3527   // All objects should be gone. 9 global handles in total.
3528   CHECK_EQ(9, counter.NumberOfWeakCalls());
3529 }
3530
3531
3532 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3533 // on the buildbots, so was made non-threaded for the time being.
3534 TEST(ApiObjectGroupsCycleForScavenger) {
3535   i::FLAG_stress_compaction = false;
3536   i::FLAG_gc_global = false;
3537   LocalContext env;
3538   v8::Isolate* iso = env->GetIsolate();
3539   HandleScope scope(iso);
3540
3541   WeakCallCounter counter(1234);
3542
3543   Persistent<Value> g1s1;
3544   Persistent<Value> g1s2;
3545   Persistent<Value> g2s1;
3546   Persistent<Value> g2s2;
3547   Persistent<Value> g3s1;
3548   Persistent<Value> g3s2;
3549
3550   {
3551     HandleScope scope(iso);
3552     g1s1.Reset(iso, Object::New());
3553     g1s2.Reset(iso, Object::New());
3554     g1s1.MakeWeak(&counter, &WeakPointerCallback);
3555     g1s2.MakeWeak(&counter, &WeakPointerCallback);
3556
3557     g2s1.Reset(iso, Object::New());
3558     g2s2.Reset(iso, Object::New());
3559     g2s1.MakeWeak(&counter, &WeakPointerCallback);
3560     g2s2.MakeWeak(&counter, &WeakPointerCallback);
3561
3562     g3s1.Reset(iso, Object::New());
3563     g3s2.Reset(iso, Object::New());
3564     g3s1.MakeWeak(&counter, &WeakPointerCallback);
3565     g3s2.MakeWeak(&counter, &WeakPointerCallback);
3566   }
3567
3568   // Make a root.
3569   Persistent<Value> root(iso, g1s1);
3570   root.MarkPartiallyDependent();
3571
3572   // Connect groups.  We're building the following cycle:
3573   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3574   // groups.
3575   {
3576     HandleScope handle_scope(iso);
3577     g1s1.MarkPartiallyDependent();
3578     g1s2.MarkPartiallyDependent();
3579     g2s1.MarkPartiallyDependent();
3580     g2s2.MarkPartiallyDependent();
3581     g3s1.MarkPartiallyDependent();
3582     g3s2.MarkPartiallyDependent();
3583     iso->SetObjectGroupId(g1s1, UniqueId(1));
3584     iso->SetObjectGroupId(g1s2, UniqueId(1));
3585     Local<Object>::New(iso, g1s1.As<Object>())->Set(
3586         v8_str("x"), Local<Value>::New(iso, g2s1));
3587     iso->SetObjectGroupId(g2s1, UniqueId(2));
3588     iso->SetObjectGroupId(g2s2, UniqueId(2));
3589     Local<Object>::New(iso, g2s1.As<Object>())->Set(
3590         v8_str("x"), Local<Value>::New(iso, g3s1));
3591     iso->SetObjectGroupId(g3s1, UniqueId(3));
3592     iso->SetObjectGroupId(g3s2, UniqueId(3));
3593     Local<Object>::New(iso, g3s1.As<Object>())->Set(
3594         v8_str("x"), Local<Value>::New(iso, g1s1));
3595   }
3596
3597   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3598       iso)->heap();
3599   heap->CollectGarbage(i::NEW_SPACE);
3600
3601   // All objects should be alive.
3602   CHECK_EQ(0, counter.NumberOfWeakCalls());
3603
3604   // Weaken the root.
3605   root.MakeWeak(&counter, &WeakPointerCallback);
3606   root.MarkPartiallyDependent();
3607
3608   // Groups are deleted, rebuild groups.
3609   {
3610     HandleScope handle_scope(iso);
3611     g1s1.MarkPartiallyDependent();
3612     g1s2.MarkPartiallyDependent();
3613     g2s1.MarkPartiallyDependent();
3614     g2s2.MarkPartiallyDependent();
3615     g3s1.MarkPartiallyDependent();
3616     g3s2.MarkPartiallyDependent();
3617     iso->SetObjectGroupId(g1s1, UniqueId(1));
3618     iso->SetObjectGroupId(g1s2, UniqueId(1));
3619     Local<Object>::New(iso, g1s1.As<Object>())->Set(
3620         v8_str("x"), Local<Value>::New(iso, g2s1));
3621     iso->SetObjectGroupId(g2s1, UniqueId(2));
3622     iso->SetObjectGroupId(g2s2, UniqueId(2));
3623     Local<Object>::New(iso, g2s1.As<Object>())->Set(
3624         v8_str("x"), Local<Value>::New(iso, g3s1));
3625     iso->SetObjectGroupId(g3s1, UniqueId(3));
3626     iso->SetObjectGroupId(g3s2, UniqueId(3));
3627     Local<Object>::New(iso, g3s1.As<Object>())->Set(
3628         v8_str("x"), Local<Value>::New(iso, g1s1));
3629   }
3630
3631   heap->CollectGarbage(i::NEW_SPACE);
3632
3633   // All objects should be gone. 7 global handles in total.
3634   CHECK_EQ(7, counter.NumberOfWeakCalls());
3635 }
3636
3637
3638 THREADED_TEST(ScriptException) {
3639   LocalContext env;
3640   v8::HandleScope scope(env->GetIsolate());
3641   Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
3642   v8::TryCatch try_catch;
3643   Local<Value> result = script->Run();
3644   CHECK(result.IsEmpty());
3645   CHECK(try_catch.HasCaught());
3646   String::Utf8Value exception_value(try_catch.Exception());
3647   CHECK_EQ(*exception_value, "panama!");
3648 }
3649
3650
3651 TEST(TryCatchCustomException) {
3652   LocalContext env;
3653   v8::HandleScope scope(env->GetIsolate());
3654   v8::TryCatch try_catch;
3655   CompileRun("function CustomError() { this.a = 'b'; }"
3656              "(function f() { throw new CustomError(); })();");
3657   CHECK(try_catch.HasCaught());
3658   CHECK(try_catch.Exception()->ToObject()->
3659             Get(v8_str("a"))->Equals(v8_str("b")));
3660 }
3661
3662
3663 bool message_received;
3664
3665
3666 static void check_message_0(v8::Handle<v8::Message> message,
3667                             v8::Handle<Value> data) {
3668   CHECK_EQ(5.76, data->NumberValue());
3669   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3670   CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
3671   CHECK(!message->IsSharedCrossOrigin());
3672   message_received = true;
3673 }
3674
3675
3676 THREADED_TEST(MessageHandler0) {
3677   message_received = false;
3678   v8::HandleScope scope(v8::Isolate::GetCurrent());
3679   CHECK(!message_received);
3680   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
3681   LocalContext context;
3682   v8::ScriptOrigin origin =
3683       v8::ScriptOrigin(v8_str("6.75"));
3684   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3685                                                   &origin);
3686   script->SetData(v8_str("7.56"));
3687   script->Run();
3688   CHECK(message_received);
3689   // clear out the message listener
3690   v8::V8::RemoveMessageListeners(check_message_0);
3691 }
3692
3693
3694 static void check_message_1(v8::Handle<v8::Message> message,
3695                             v8::Handle<Value> data) {
3696   CHECK(data->IsNumber());
3697   CHECK_EQ(1337, data->Int32Value());
3698   CHECK(!message->IsSharedCrossOrigin());
3699   message_received = true;
3700 }
3701
3702
3703 TEST(MessageHandler1) {
3704   message_received = false;
3705   v8::HandleScope scope(v8::Isolate::GetCurrent());
3706   CHECK(!message_received);
3707   v8::V8::AddMessageListener(check_message_1);
3708   LocalContext context;
3709   CompileRun("throw 1337;");
3710   CHECK(message_received);
3711   // clear out the message listener
3712   v8::V8::RemoveMessageListeners(check_message_1);
3713 }
3714
3715
3716 static void check_message_2(v8::Handle<v8::Message> message,
3717                             v8::Handle<Value> data) {
3718   LocalContext context;
3719   CHECK(data->IsObject());
3720   v8::Local<v8::Value> hidden_property =
3721       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
3722   CHECK(v8_str("hidden value")->Equals(hidden_property));
3723   CHECK(!message->IsSharedCrossOrigin());
3724   message_received = true;
3725 }
3726
3727
3728 TEST(MessageHandler2) {
3729   message_received = false;
3730   v8::HandleScope scope(v8::Isolate::GetCurrent());
3731   CHECK(!message_received);
3732   v8::V8::AddMessageListener(check_message_2);
3733   LocalContext context;
3734   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
3735   v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
3736                                            v8_str("hidden value"));
3737   context->Global()->Set(v8_str("error"), error);
3738   CompileRun("throw error;");
3739   CHECK(message_received);
3740   // clear out the message listener
3741   v8::V8::RemoveMessageListeners(check_message_2);
3742 }
3743
3744
3745 static void check_message_3(v8::Handle<v8::Message> message,
3746                             v8::Handle<Value> data) {
3747   CHECK(message->IsSharedCrossOrigin());
3748   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3749   message_received = true;
3750 }
3751
3752
3753 TEST(MessageHandler3) {
3754   message_received = false;
3755   v8::HandleScope scope(v8::Isolate::GetCurrent());
3756   CHECK(!message_received);
3757   v8::V8::AddMessageListener(check_message_3);
3758   LocalContext context;
3759   v8::ScriptOrigin origin =
3760       v8::ScriptOrigin(v8_str("6.75"),
3761                        v8::Integer::New(1),
3762                        v8::Integer::New(2),
3763                        v8::True());
3764   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3765                                                   &origin);
3766   script->Run();
3767   CHECK(message_received);
3768   // clear out the message listener
3769   v8::V8::RemoveMessageListeners(check_message_3);
3770 }
3771
3772
3773 static void check_message_4(v8::Handle<v8::Message> message,
3774                             v8::Handle<Value> data) {
3775   CHECK(!message->IsSharedCrossOrigin());
3776   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3777   message_received = true;
3778 }
3779
3780
3781 TEST(MessageHandler4) {
3782   message_received = false;
3783   v8::HandleScope scope(v8::Isolate::GetCurrent());
3784   CHECK(!message_received);
3785   v8::V8::AddMessageListener(check_message_4);
3786   LocalContext context;
3787   v8::ScriptOrigin origin =
3788       v8::ScriptOrigin(v8_str("6.75"),
3789                        v8::Integer::New(1),
3790                        v8::Integer::New(2),
3791                        v8::False());
3792   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3793                                                   &origin);
3794   script->Run();
3795   CHECK(message_received);
3796   // clear out the message listener
3797   v8::V8::RemoveMessageListeners(check_message_4);
3798 }
3799
3800
3801 static void check_message_5a(v8::Handle<v8::Message> message,
3802                             v8::Handle<Value> data) {
3803   CHECK(message->IsSharedCrossOrigin());
3804   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3805   message_received = true;
3806 }
3807
3808
3809 static void check_message_5b(v8::Handle<v8::Message> message,
3810                             v8::Handle<Value> data) {
3811   CHECK(!message->IsSharedCrossOrigin());
3812   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3813   message_received = true;
3814 }
3815
3816
3817 TEST(MessageHandler5) {
3818   message_received = false;
3819   v8::HandleScope scope(v8::Isolate::GetCurrent());
3820   CHECK(!message_received);
3821   v8::V8::AddMessageListener(check_message_5a);
3822   LocalContext context;
3823   v8::ScriptOrigin origin =
3824       v8::ScriptOrigin(v8_str("6.75"),
3825                        v8::Integer::New(1),
3826                        v8::Integer::New(2),
3827                        v8::True());
3828   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3829                                                   &origin);
3830   script->Run();
3831   CHECK(message_received);
3832   // clear out the message listener
3833   v8::V8::RemoveMessageListeners(check_message_5a);
3834
3835   message_received = false;
3836   v8::V8::AddMessageListener(check_message_5b);
3837   origin =
3838       v8::ScriptOrigin(v8_str("6.75"),
3839                        v8::Integer::New(1),
3840                        v8::Integer::New(2),
3841                        v8::False());
3842   script = Script::Compile(v8_str("throw 'error'"),
3843                            &origin);
3844   script->Run();
3845   CHECK(message_received);
3846   // clear out the message listener
3847   v8::V8::RemoveMessageListeners(check_message_5b);
3848 }
3849
3850
3851 THREADED_TEST(GetSetProperty) {
3852   LocalContext context;
3853   v8::HandleScope scope(context->GetIsolate());
3854   context->Global()->Set(v8_str("foo"), v8_num(14));
3855   context->Global()->Set(v8_str("12"), v8_num(92));
3856   context->Global()->Set(v8::Integer::New(16), v8_num(32));
3857   context->Global()->Set(v8_num(13), v8_num(56));
3858   Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
3859   CHECK_EQ(14, foo->Int32Value());
3860   Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
3861   CHECK_EQ(92, twelve->Int32Value());
3862   Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
3863   CHECK_EQ(32, sixteen->Int32Value());
3864   Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
3865   CHECK_EQ(56, thirteen->Int32Value());
3866   CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
3867   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
3868   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
3869   CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
3870   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
3871   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
3872   CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
3873   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
3874   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
3875 }
3876
3877
3878 THREADED_TEST(PropertyAttributes) {
3879   LocalContext context;
3880   v8::HandleScope scope(context->GetIsolate());
3881   // none
3882   Local<String> prop = v8_str("none");
3883   context->Global()->Set(prop, v8_num(7));
3884   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
3885   // read-only
3886   prop = v8_str("read_only");
3887   context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
3888   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
3889   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
3890   Script::Compile(v8_str("read_only = 9"))->Run();
3891   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
3892   context->Global()->Set(prop, v8_num(10));
3893   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
3894   // dont-delete
3895   prop = v8_str("dont_delete");
3896   context->Global()->Set(prop, v8_num(13), v8::DontDelete);
3897   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
3898   Script::Compile(v8_str("delete dont_delete"))->Run();
3899   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
3900   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
3901   // dont-enum
3902   prop = v8_str("dont_enum");
3903   context->Global()->Set(prop, v8_num(28), v8::DontEnum);
3904   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
3905   // absent
3906   prop = v8_str("absent");
3907   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
3908   Local<Value> fake_prop = v8_num(1);
3909   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
3910   // exception
3911   TryCatch try_catch;
3912   Local<Value> exception =
3913       CompileRun("({ toString: function() { throw 'exception';} })");
3914   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
3915   CHECK(try_catch.HasCaught());
3916   String::Utf8Value exception_value(try_catch.Exception());
3917   CHECK_EQ("exception", *exception_value);
3918   try_catch.Reset();
3919 }
3920
3921
3922 THREADED_TEST(Array) {
3923   LocalContext context;
3924   v8::HandleScope scope(context->GetIsolate());
3925   Local<v8::Array> array = v8::Array::New();
3926   CHECK_EQ(0, array->Length());
3927   CHECK(array->Get(0)->IsUndefined());
3928   CHECK(!array->Has(0));
3929   CHECK(array->Get(100)->IsUndefined());
3930   CHECK(!array->Has(100));
3931   array->Set(2, v8_num(7));
3932   CHECK_EQ(3, array->Length());
3933   CHECK(!array->Has(0));
3934   CHECK(!array->Has(1));
3935   CHECK(array->Has(2));
3936   CHECK_EQ(7, array->Get(2)->Int32Value());
3937   Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
3938   Local<v8::Array> arr = obj.As<v8::Array>();
3939   CHECK_EQ(3, arr->Length());
3940   CHECK_EQ(1, arr->Get(0)->Int32Value());
3941   CHECK_EQ(2, arr->Get(1)->Int32Value());
3942   CHECK_EQ(3, arr->Get(2)->Int32Value());
3943   array = v8::Array::New(27);
3944   CHECK_EQ(27, array->Length());
3945   array = v8::Array::New(-27);
3946   CHECK_EQ(0, array->Length());
3947 }
3948
3949
3950 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
3951   v8::HandleScope scope(args.GetIsolate());
3952   ApiTestFuzzer::Fuzz();
3953   Local<v8::Array> result = v8::Array::New(args.Length());
3954   for (int i = 0; i < args.Length(); i++)
3955     result->Set(i, args[i]);
3956   args.GetReturnValue().Set(scope.Close(result));
3957 }
3958
3959
3960 THREADED_TEST(Vector) {
3961   v8::HandleScope scope(v8::Isolate::GetCurrent());
3962   Local<ObjectTemplate> global = ObjectTemplate::New();
3963   global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
3964   LocalContext context(0, global);
3965
3966   const char* fun = "f()";
3967   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
3968   CHECK_EQ(0, a0->Length());
3969
3970   const char* fun2 = "f(11)";
3971   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
3972   CHECK_EQ(1, a1->Length());
3973   CHECK_EQ(11, a1->Get(0)->Int32Value());
3974
3975   const char* fun3 = "f(12, 13)";
3976   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
3977   CHECK_EQ(2, a2->Length());
3978   CHECK_EQ(12, a2->Get(0)->Int32Value());
3979   CHECK_EQ(13, a2->Get(1)->Int32Value());
3980
3981   const char* fun4 = "f(14, 15, 16)";
3982   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
3983   CHECK_EQ(3, a3->Length());
3984   CHECK_EQ(14, a3->Get(0)->Int32Value());
3985   CHECK_EQ(15, a3->Get(1)->Int32Value());
3986   CHECK_EQ(16, a3->Get(2)->Int32Value());
3987
3988   const char* fun5 = "f(17, 18, 19, 20)";
3989   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
3990   CHECK_EQ(4, a4->Length());
3991   CHECK_EQ(17, a4->Get(0)->Int32Value());
3992   CHECK_EQ(18, a4->Get(1)->Int32Value());
3993   CHECK_EQ(19, a4->Get(2)->Int32Value());
3994   CHECK_EQ(20, a4->Get(3)->Int32Value());
3995 }
3996
3997
3998 THREADED_TEST(FunctionCall) {
3999   LocalContext context;
4000   v8::HandleScope scope(context->GetIsolate());
4001   CompileRun(
4002     "function Foo() {"
4003     "  var result = [];"
4004     "  for (var i = 0; i < arguments.length; i++) {"
4005     "    result.push(arguments[i]);"
4006     "  }"
4007     "  return result;"
4008     "}");
4009   Local<Function> Foo =
4010       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4011
4012   v8::Handle<Value>* args0 = NULL;
4013   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4014   CHECK_EQ(0, a0->Length());
4015
4016   v8::Handle<Value> args1[] = { v8_num(1.1) };
4017   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4018   CHECK_EQ(1, a1->Length());
4019   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
4020
4021   v8::Handle<Value> args2[] = { v8_num(2.2),
4022                                 v8_num(3.3) };
4023   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4024   CHECK_EQ(2, a2->Length());
4025   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
4026   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
4027
4028   v8::Handle<Value> args3[] = { v8_num(4.4),
4029                                 v8_num(5.5),
4030                                 v8_num(6.6) };
4031   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4032   CHECK_EQ(3, a3->Length());
4033   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
4034   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
4035   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
4036
4037   v8::Handle<Value> args4[] = { v8_num(7.7),
4038                                 v8_num(8.8),
4039                                 v8_num(9.9),
4040                                 v8_num(10.11) };
4041   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4042   CHECK_EQ(4, a4->Length());
4043   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
4044   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
4045   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
4046   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
4047 }
4048
4049
4050 static const char* js_code_causing_out_of_memory =
4051     "var a = new Array(); while(true) a.push(a);";
4052
4053
4054 // These tests run for a long time and prevent us from running tests
4055 // that come after them so they cannot run in parallel.
4056 TEST(OutOfMemory) {
4057   // It's not possible to read a snapshot into a heap with different dimensions.
4058   if (i::Snapshot::IsEnabled()) return;
4059   // Set heap limits.
4060   static const int K = 1024;
4061   v8::ResourceConstraints constraints;
4062   constraints.set_max_young_space_size(256 * K);
4063   constraints.set_max_old_space_size(5 * K * K);
4064   v8::SetResourceConstraints(&constraints);
4065
4066   // Execute a script that causes out of memory.
4067   LocalContext context;
4068   v8::HandleScope scope(context->GetIsolate());
4069   v8::V8::IgnoreOutOfMemoryException();
4070   Local<Script> script =
4071       Script::Compile(String::New(js_code_causing_out_of_memory));
4072   Local<Value> result = script->Run();
4073
4074   // Check for out of memory state.
4075   CHECK(result.IsEmpty());
4076   CHECK(context->HasOutOfMemoryException());
4077 }
4078
4079
4080 void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
4081   ApiTestFuzzer::Fuzz();
4082
4083   LocalContext context;
4084   v8::HandleScope scope(context->GetIsolate());
4085   Local<Script> script =
4086       Script::Compile(String::New(js_code_causing_out_of_memory));
4087   Local<Value> result = script->Run();
4088
4089   // Check for out of memory state.
4090   CHECK(result.IsEmpty());
4091   CHECK(context->HasOutOfMemoryException());
4092
4093   args.GetReturnValue().Set(result);
4094 }
4095
4096
4097 TEST(OutOfMemoryNested) {
4098   // It's not possible to read a snapshot into a heap with different dimensions.
4099   if (i::Snapshot::IsEnabled()) return;
4100   // Set heap limits.
4101   static const int K = 1024;
4102   v8::ResourceConstraints constraints;
4103   constraints.set_max_young_space_size(256 * K);
4104   constraints.set_max_old_space_size(5 * K * K);
4105   v8::SetResourceConstraints(&constraints);
4106
4107   v8::HandleScope scope(v8::Isolate::GetCurrent());
4108   Local<ObjectTemplate> templ = ObjectTemplate::New();
4109   templ->Set(v8_str("ProvokeOutOfMemory"),
4110              v8::FunctionTemplate::New(ProvokeOutOfMemory));
4111   LocalContext context(0, templ);
4112   v8::V8::IgnoreOutOfMemoryException();
4113   Local<Value> result = CompileRun(
4114     "var thrown = false;"
4115     "try {"
4116     "  ProvokeOutOfMemory();"
4117     "} catch (e) {"
4118     "  thrown = true;"
4119     "}");
4120   // Check for out of memory state.
4121   CHECK(result.IsEmpty());
4122   CHECK(context->HasOutOfMemoryException());
4123 }
4124
4125
4126 TEST(HugeConsStringOutOfMemory) {
4127   // It's not possible to read a snapshot into a heap with different dimensions.
4128   if (i::Snapshot::IsEnabled()) return;
4129   // Set heap limits.
4130   static const int K = 1024;
4131   v8::ResourceConstraints constraints;
4132   constraints.set_max_young_space_size(256 * K);
4133   constraints.set_max_old_space_size(4 * K * K);
4134   v8::SetResourceConstraints(&constraints);
4135
4136   // Execute a script that causes out of memory.
4137   v8::V8::IgnoreOutOfMemoryException();
4138
4139   LocalContext context;
4140   v8::HandleScope scope(context->GetIsolate());
4141
4142   // Build huge string. This should fail with out of memory exception.
4143   Local<Value> result = CompileRun(
4144     "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
4145     "for (var i = 0; i < 22; i++) { str = str + str; }");
4146
4147   // Check for out of memory state.
4148   CHECK(result.IsEmpty());
4149   CHECK(context->HasOutOfMemoryException());
4150 }
4151
4152
4153 THREADED_TEST(ConstructCall) {
4154   LocalContext context;
4155   v8::HandleScope scope(context->GetIsolate());
4156   CompileRun(
4157     "function Foo() {"
4158     "  var result = [];"
4159     "  for (var i = 0; i < arguments.length; i++) {"
4160     "    result.push(arguments[i]);"
4161     "  }"
4162     "  return result;"
4163     "}");
4164   Local<Function> Foo =
4165       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4166
4167   v8::Handle<Value>* args0 = NULL;
4168   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4169   CHECK_EQ(0, a0->Length());
4170
4171   v8::Handle<Value> args1[] = { v8_num(1.1) };
4172   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4173   CHECK_EQ(1, a1->Length());
4174   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
4175
4176   v8::Handle<Value> args2[] = { v8_num(2.2),
4177                                 v8_num(3.3) };
4178   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4179   CHECK_EQ(2, a2->Length());
4180   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
4181   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
4182
4183   v8::Handle<Value> args3[] = { v8_num(4.4),
4184                                 v8_num(5.5),
4185                                 v8_num(6.6) };
4186   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4187   CHECK_EQ(3, a3->Length());
4188   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
4189   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
4190   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
4191
4192   v8::Handle<Value> args4[] = { v8_num(7.7),
4193                                 v8_num(8.8),
4194                                 v8_num(9.9),
4195                                 v8_num(10.11) };
4196   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4197   CHECK_EQ(4, a4->Length());
4198   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
4199   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
4200   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
4201   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
4202 }
4203
4204
4205 static void CheckUncle(v8::TryCatch* try_catch) {
4206   CHECK(try_catch->HasCaught());
4207   String::Utf8Value str_value(try_catch->Exception());
4208   CHECK_EQ(*str_value, "uncle?");
4209   try_catch->Reset();
4210 }
4211
4212
4213 THREADED_TEST(ConversionNumber) {
4214   LocalContext env;
4215   v8::HandleScope scope(env->GetIsolate());
4216   // Very large number.
4217   CompileRun("var obj = Math.pow(2,32) * 1237;");
4218   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4219   CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
4220   CHECK_EQ(0, obj->ToInt32()->Value());
4221   CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
4222   // Large number.
4223   CompileRun("var obj = -1234567890123;");
4224   obj = env->Global()->Get(v8_str("obj"));
4225   CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
4226   CHECK_EQ(-1912276171, obj->ToInt32()->Value());
4227   CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
4228   // Small positive integer.
4229   CompileRun("var obj = 42;");
4230   obj = env->Global()->Get(v8_str("obj"));
4231   CHECK_EQ(42.0, obj->ToNumber()->Value());
4232   CHECK_EQ(42, obj->ToInt32()->Value());
4233   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
4234   // Negative integer.
4235   CompileRun("var obj = -37;");
4236   obj = env->Global()->Get(v8_str("obj"));
4237   CHECK_EQ(-37.0, obj->ToNumber()->Value());
4238   CHECK_EQ(-37, obj->ToInt32()->Value());
4239   CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
4240   // Positive non-int32 integer.
4241   CompileRun("var obj = 0x81234567;");
4242   obj = env->Global()->Get(v8_str("obj"));
4243   CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
4244   CHECK_EQ(-2128394905, obj->ToInt32()->Value());
4245   CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
4246   // Fraction.
4247   CompileRun("var obj = 42.3;");
4248   obj = env->Global()->Get(v8_str("obj"));
4249   CHECK_EQ(42.3, obj->ToNumber()->Value());
4250   CHECK_EQ(42, obj->ToInt32()->Value());
4251   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
4252   // Large negative fraction.
4253   CompileRun("var obj = -5726623061.75;");
4254   obj = env->Global()->Get(v8_str("obj"));
4255   CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
4256   CHECK_EQ(-1431655765, obj->ToInt32()->Value());
4257   CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
4258 }
4259
4260
4261 THREADED_TEST(isNumberType) {
4262   LocalContext env;
4263   v8::HandleScope scope(env->GetIsolate());
4264   // Very large number.
4265   CompileRun("var obj = Math.pow(2,32) * 1237;");
4266   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4267   CHECK(!obj->IsInt32());
4268   CHECK(!obj->IsUint32());
4269   // Large negative number.
4270   CompileRun("var obj = -1234567890123;");
4271   obj = env->Global()->Get(v8_str("obj"));
4272   CHECK(!obj->IsInt32());
4273   CHECK(!obj->IsUint32());
4274   // Small positive integer.
4275   CompileRun("var obj = 42;");
4276   obj = env->Global()->Get(v8_str("obj"));
4277   CHECK(obj->IsInt32());
4278   CHECK(obj->IsUint32());
4279   // Negative integer.
4280   CompileRun("var obj = -37;");
4281   obj = env->Global()->Get(v8_str("obj"));
4282   CHECK(obj->IsInt32());
4283   CHECK(!obj->IsUint32());
4284   // Positive non-int32 integer.
4285   CompileRun("var obj = 0x81234567;");
4286   obj = env->Global()->Get(v8_str("obj"));
4287   CHECK(!obj->IsInt32());
4288   CHECK(obj->IsUint32());
4289   // Fraction.
4290   CompileRun("var obj = 42.3;");
4291   obj = env->Global()->Get(v8_str("obj"));
4292   CHECK(!obj->IsInt32());
4293   CHECK(!obj->IsUint32());
4294   // Large negative fraction.
4295   CompileRun("var obj = -5726623061.75;");
4296   obj = env->Global()->Get(v8_str("obj"));
4297   CHECK(!obj->IsInt32());
4298   CHECK(!obj->IsUint32());
4299   // Positive zero
4300   CompileRun("var obj = 0.0;");
4301   obj = env->Global()->Get(v8_str("obj"));
4302   CHECK(obj->IsInt32());
4303   CHECK(obj->IsUint32());
4304   // Positive zero
4305   CompileRun("var obj = -0.0;");
4306   obj = env->Global()->Get(v8_str("obj"));
4307   CHECK(!obj->IsInt32());
4308   CHECK(!obj->IsUint32());
4309 }
4310
4311
4312 THREADED_TEST(ConversionException) {
4313   LocalContext env;
4314   v8::HandleScope scope(env->GetIsolate());
4315   CompileRun(
4316     "function TestClass() { };"
4317     "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4318     "var obj = new TestClass();");
4319   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4320
4321   v8::TryCatch try_catch;
4322
4323   Local<Value> to_string_result = obj->ToString();
4324   CHECK(to_string_result.IsEmpty());
4325   CheckUncle(&try_catch);
4326
4327   Local<Value> to_number_result = obj->ToNumber();
4328   CHECK(to_number_result.IsEmpty());
4329   CheckUncle(&try_catch);
4330
4331   Local<Value> to_integer_result = obj->ToInteger();
4332   CHECK(to_integer_result.IsEmpty());
4333   CheckUncle(&try_catch);
4334
4335   Local<Value> to_uint32_result = obj->ToUint32();
4336   CHECK(to_uint32_result.IsEmpty());
4337   CheckUncle(&try_catch);
4338
4339   Local<Value> to_int32_result = obj->ToInt32();
4340   CHECK(to_int32_result.IsEmpty());
4341   CheckUncle(&try_catch);
4342
4343   Local<Value> to_object_result = v8::Undefined()->ToObject();
4344   CHECK(to_object_result.IsEmpty());
4345   CHECK(try_catch.HasCaught());
4346   try_catch.Reset();
4347
4348   int32_t int32_value = obj->Int32Value();
4349   CHECK_EQ(0, int32_value);
4350   CheckUncle(&try_catch);
4351
4352   uint32_t uint32_value = obj->Uint32Value();
4353   CHECK_EQ(0, uint32_value);
4354   CheckUncle(&try_catch);
4355
4356   double number_value = obj->NumberValue();
4357   CHECK_NE(0, std::isnan(number_value));
4358   CheckUncle(&try_catch);
4359
4360   int64_t integer_value = obj->IntegerValue();
4361   CHECK_EQ(0.0, static_cast<double>(integer_value));
4362   CheckUncle(&try_catch);
4363 }
4364
4365
4366 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
4367   ApiTestFuzzer::Fuzz();
4368   v8::ThrowException(v8_str("konto"));
4369 }
4370
4371
4372 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4373   if (args.Length() < 1) {
4374     args.GetReturnValue().Set(false);
4375     return;
4376   }
4377   v8::HandleScope scope(args.GetIsolate());
4378   v8::TryCatch try_catch;
4379   Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
4380   CHECK(!try_catch.HasCaught() || result.IsEmpty());
4381   args.GetReturnValue().Set(try_catch.HasCaught());
4382 }
4383
4384
4385 THREADED_TEST(APICatch) {
4386   v8::HandleScope scope(v8::Isolate::GetCurrent());
4387   Local<ObjectTemplate> templ = ObjectTemplate::New();
4388   templ->Set(v8_str("ThrowFromC"),
4389              v8::FunctionTemplate::New(ThrowFromC));
4390   LocalContext context(0, templ);
4391   CompileRun(
4392     "var thrown = false;"
4393     "try {"
4394     "  ThrowFromC();"
4395     "} catch (e) {"
4396     "  thrown = true;"
4397     "}");
4398   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4399   CHECK(thrown->BooleanValue());
4400 }
4401
4402
4403 THREADED_TEST(APIThrowTryCatch) {
4404   v8::HandleScope scope(v8::Isolate::GetCurrent());
4405   Local<ObjectTemplate> templ = ObjectTemplate::New();
4406   templ->Set(v8_str("ThrowFromC"),
4407              v8::FunctionTemplate::New(ThrowFromC));
4408   LocalContext context(0, templ);
4409   v8::TryCatch try_catch;
4410   CompileRun("ThrowFromC();");
4411   CHECK(try_catch.HasCaught());
4412 }
4413
4414
4415 // Test that a try-finally block doesn't shadow a try-catch block
4416 // when setting up an external handler.
4417 //
4418 // BUG(271): Some of the exception propagation does not work on the
4419 // ARM simulator because the simulator separates the C++ stack and the
4420 // JS stack.  This test therefore fails on the simulator.  The test is
4421 // not threaded to allow the threading tests to run on the simulator.
4422 TEST(TryCatchInTryFinally) {
4423   v8::HandleScope scope(v8::Isolate::GetCurrent());
4424   Local<ObjectTemplate> templ = ObjectTemplate::New();
4425   templ->Set(v8_str("CCatcher"),
4426              v8::FunctionTemplate::New(CCatcher));
4427   LocalContext context(0, templ);
4428   Local<Value> result = CompileRun("try {"
4429                                    "  try {"
4430                                    "    CCatcher('throw 7;');"
4431                                    "  } finally {"
4432                                    "  }"
4433                                    "} catch (e) {"
4434                                    "}");
4435   CHECK(result->IsTrue());
4436 }
4437
4438
4439 static void check_reference_error_message(
4440     v8::Handle<v8::Message> message,
4441     v8::Handle<v8::Value> data) {
4442   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4443   CHECK(message->Get()->Equals(v8_str(reference_error)));
4444 }
4445
4446
4447 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
4448   ApiTestFuzzer::Fuzz();
4449   CHECK(false);
4450 }
4451
4452
4453 // Test that overwritten methods are not invoked on uncaught exception
4454 // formatting. However, they are invoked when performing normal error
4455 // string conversions.
4456 TEST(APIThrowMessageOverwrittenToString) {
4457   v8::HandleScope scope(v8::Isolate::GetCurrent());
4458   v8::V8::AddMessageListener(check_reference_error_message);
4459   Local<ObjectTemplate> templ = ObjectTemplate::New();
4460   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
4461   LocalContext context(NULL, templ);
4462   CompileRun("asdf;");
4463   CompileRun("var limit = {};"
4464              "limit.valueOf = fail;"
4465              "Error.stackTraceLimit = limit;");
4466   CompileRun("asdf");
4467   CompileRun("Array.prototype.pop = fail;");
4468   CompileRun("Object.prototype.hasOwnProperty = fail;");
4469   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
4470   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4471   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
4472   CompileRun("ReferenceError.prototype.toString ="
4473              "  function() { return 'Whoops' }");
4474   CompileRun("asdf;");
4475   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4476   CompileRun("asdf;");
4477   CompileRun("ReferenceError.prototype.constructor = void 0;");
4478   CompileRun("asdf;");
4479   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4480   CompileRun("asdf;");
4481   CompileRun("ReferenceError.prototype = new Object();");
4482   CompileRun("asdf;");
4483   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4484   CHECK(string->Equals(v8_str("Whoops")));
4485   CompileRun("ReferenceError.prototype.constructor = new Object();"
4486              "ReferenceError.prototype.constructor.name = 1;"
4487              "Number.prototype.toString = function() { return 'Whoops'; };"
4488              "ReferenceError.prototype.toString = Object.prototype.toString;");
4489   CompileRun("asdf;");
4490   v8::V8::RemoveMessageListeners(check_reference_error_message);
4491 }
4492
4493
4494 static void check_custom_error_tostring(
4495     v8::Handle<v8::Message> message,
4496     v8::Handle<v8::Value> data) {
4497   const char* uncaught_error = "Uncaught MyError toString";
4498   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4499 }
4500
4501
4502 TEST(CustomErrorToString) {
4503   LocalContext context;
4504   v8::HandleScope scope(context->GetIsolate());
4505   v8::V8::AddMessageListener(check_custom_error_tostring);
4506   CompileRun(
4507     "function MyError(name, message) {                   "
4508     "  this.name = name;                                 "
4509     "  this.message = message;                           "
4510     "}                                                   "
4511     "MyError.prototype = Object.create(Error.prototype); "
4512     "MyError.prototype.toString = function() {           "
4513     "  return 'MyError toString';                        "
4514     "};                                                  "
4515     "throw new MyError('my name', 'my message');         ");
4516   v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4517 }
4518
4519
4520 static void check_custom_error_message(
4521     v8::Handle<v8::Message> message,
4522     v8::Handle<v8::Value> data) {
4523   const char* uncaught_error = "Uncaught MyError: my message";
4524   printf("%s\n", *v8::String::Utf8Value(message->Get()));
4525   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4526 }
4527
4528
4529 TEST(CustomErrorMessage) {
4530   LocalContext context;
4531   v8::HandleScope scope(context->GetIsolate());
4532   v8::V8::AddMessageListener(check_custom_error_message);
4533
4534   // Handlebars.
4535   CompileRun(
4536     "function MyError(msg) {                             "
4537     "  this.name = 'MyError';                            "
4538     "  this.message = msg;                               "
4539     "}                                                   "
4540     "MyError.prototype = new Error();                    "
4541     "throw new MyError('my message');                    ");
4542
4543   // Closure.
4544   CompileRun(
4545     "function MyError(msg) {                             "
4546     "  this.name = 'MyError';                            "
4547     "  this.message = msg;                               "
4548     "}                                                   "
4549     "inherits = function(childCtor, parentCtor) {        "
4550     "    function tempCtor() {};                         "
4551     "    tempCtor.prototype = parentCtor.prototype;      "
4552     "    childCtor.superClass_ = parentCtor.prototype;   "
4553     "    childCtor.prototype = new tempCtor();           "
4554     "    childCtor.prototype.constructor = childCtor;    "
4555     "};                                                  "
4556     "inherits(MyError, Error);                           "
4557     "throw new MyError('my message');                    ");
4558
4559   // Object.create.
4560   CompileRun(
4561     "function MyError(msg) {                             "
4562     "  this.name = 'MyError';                            "
4563     "  this.message = msg;                               "
4564     "}                                                   "
4565     "MyError.prototype = Object.create(Error.prototype); "
4566     "throw new MyError('my message');                    ");
4567
4568   v8::V8::RemoveMessageListeners(check_custom_error_message);
4569 }
4570
4571
4572 static void receive_message(v8::Handle<v8::Message> message,
4573                             v8::Handle<v8::Value> data) {
4574   message->Get();
4575   message_received = true;
4576 }
4577
4578
4579 TEST(APIThrowMessage) {
4580   message_received = false;
4581   v8::HandleScope scope(v8::Isolate::GetCurrent());
4582   v8::V8::AddMessageListener(receive_message);
4583   Local<ObjectTemplate> templ = ObjectTemplate::New();
4584   templ->Set(v8_str("ThrowFromC"),
4585              v8::FunctionTemplate::New(ThrowFromC));
4586   LocalContext context(0, templ);
4587   CompileRun("ThrowFromC();");
4588   CHECK(message_received);
4589   v8::V8::RemoveMessageListeners(receive_message);
4590 }
4591
4592
4593 TEST(APIThrowMessageAndVerboseTryCatch) {
4594   message_received = false;
4595   v8::HandleScope scope(v8::Isolate::GetCurrent());
4596   v8::V8::AddMessageListener(receive_message);
4597   Local<ObjectTemplate> templ = ObjectTemplate::New();
4598   templ->Set(v8_str("ThrowFromC"),
4599              v8::FunctionTemplate::New(ThrowFromC));
4600   LocalContext context(0, templ);
4601   v8::TryCatch try_catch;
4602   try_catch.SetVerbose(true);
4603   Local<Value> result = CompileRun("ThrowFromC();");
4604   CHECK(try_catch.HasCaught());
4605   CHECK(result.IsEmpty());
4606   CHECK(message_received);
4607   v8::V8::RemoveMessageListeners(receive_message);
4608 }
4609
4610
4611 TEST(APIStackOverflowAndVerboseTryCatch) {
4612   message_received = false;
4613   LocalContext context;
4614   v8::HandleScope scope(context->GetIsolate());
4615   v8::V8::AddMessageListener(receive_message);
4616   v8::TryCatch try_catch;
4617   try_catch.SetVerbose(true);
4618   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
4619   CHECK(try_catch.HasCaught());
4620   CHECK(result.IsEmpty());
4621   CHECK(message_received);
4622   v8::V8::RemoveMessageListeners(receive_message);
4623 }
4624
4625
4626 THREADED_TEST(ExternalScriptException) {
4627   v8::HandleScope scope(v8::Isolate::GetCurrent());
4628   Local<ObjectTemplate> templ = ObjectTemplate::New();
4629   templ->Set(v8_str("ThrowFromC"),
4630              v8::FunctionTemplate::New(ThrowFromC));
4631   LocalContext context(0, templ);
4632
4633   v8::TryCatch try_catch;
4634   Local<Script> script
4635       = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
4636   Local<Value> result = script->Run();
4637   CHECK(result.IsEmpty());
4638   CHECK(try_catch.HasCaught());
4639   String::Utf8Value exception_value(try_catch.Exception());
4640   CHECK_EQ("konto", *exception_value);
4641 }
4642
4643
4644
4645 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
4646   ApiTestFuzzer::Fuzz();
4647   CHECK_EQ(4, args.Length());
4648   int count = args[0]->Int32Value();
4649   int cInterval = args[2]->Int32Value();
4650   if (count == 0) {
4651     v8::ThrowException(v8_str("FromC"));
4652     return;
4653   } else {
4654     Local<v8::Object> global = Context::GetCurrent()->Global();
4655     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
4656     v8::Handle<Value> argv[] = { v8_num(count - 1),
4657                                  args[1],
4658                                  args[2],
4659                                  args[3] };
4660     if (count % cInterval == 0) {
4661       v8::TryCatch try_catch;
4662       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
4663       int expected = args[3]->Int32Value();
4664       if (try_catch.HasCaught()) {
4665         CHECK_EQ(expected, count);
4666         CHECK(result.IsEmpty());
4667         CHECK(!i::Isolate::Current()->has_scheduled_exception());
4668       } else {
4669         CHECK_NE(expected, count);
4670       }
4671       args.GetReturnValue().Set(result);
4672       return;
4673     } else {
4674       args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
4675       return;
4676     }
4677   }
4678 }
4679
4680
4681 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
4682   ApiTestFuzzer::Fuzz();
4683   CHECK_EQ(3, args.Length());
4684   bool equality = args[0]->BooleanValue();
4685   int count = args[1]->Int32Value();
4686   int expected = args[2]->Int32Value();
4687   if (equality) {
4688     CHECK_EQ(count, expected);
4689   } else {
4690     CHECK_NE(count, expected);
4691   }
4692 }
4693
4694
4695 THREADED_TEST(EvalInTryFinally) {
4696   LocalContext context;
4697   v8::HandleScope scope(context->GetIsolate());
4698   v8::TryCatch try_catch;
4699   CompileRun("(function() {"
4700              "  try {"
4701              "    eval('asldkf (*&^&*^');"
4702              "  } finally {"
4703              "    return;"
4704              "  }"
4705              "})()");
4706   CHECK(!try_catch.HasCaught());
4707 }
4708
4709
4710 // This test works by making a stack of alternating JavaScript and C
4711 // activations.  These activations set up exception handlers with regular
4712 // intervals, one interval for C activations and another for JavaScript
4713 // activations.  When enough activations have been created an exception is
4714 // thrown and we check that the right activation catches the exception and that
4715 // no other activations do.  The right activation is always the topmost one with
4716 // a handler, regardless of whether it is in JavaScript or C.
4717 //
4718 // The notation used to describe a test case looks like this:
4719 //
4720 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
4721 //
4722 // Each entry is an activation, either JS or C.  The index is the count at that
4723 // level.  Stars identify activations with exception handlers, the @ identifies
4724 // the exception handler that should catch the exception.
4725 //
4726 // BUG(271): Some of the exception propagation does not work on the
4727 // ARM simulator because the simulator separates the C++ stack and the
4728 // JS stack.  This test therefore fails on the simulator.  The test is
4729 // not threaded to allow the threading tests to run on the simulator.
4730 TEST(ExceptionOrder) {
4731   v8::HandleScope scope(v8::Isolate::GetCurrent());
4732   Local<ObjectTemplate> templ = ObjectTemplate::New();
4733   templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
4734   templ->Set(v8_str("CThrowCountDown"),
4735              v8::FunctionTemplate::New(CThrowCountDown));
4736   LocalContext context(0, templ);
4737   CompileRun(
4738     "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
4739     "  if (count == 0) throw 'FromJS';"
4740     "  if (count % jsInterval == 0) {"
4741     "    try {"
4742     "      var value = CThrowCountDown(count - 1,"
4743     "                                  jsInterval,"
4744     "                                  cInterval,"
4745     "                                  expected);"
4746     "      check(false, count, expected);"
4747     "      return value;"
4748     "    } catch (e) {"
4749     "      check(true, count, expected);"
4750     "    }"
4751     "  } else {"
4752     "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
4753     "  }"
4754     "}");
4755   Local<Function> fun =
4756       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
4757
4758   const int argc = 4;
4759   //                             count      jsInterval cInterval  expected
4760
4761   // *JS[4] *C[3] @JS[2] C[1] JS[0]
4762   v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
4763   fun->Call(fun, argc, a0);
4764
4765   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
4766   v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
4767   fun->Call(fun, argc, a1);
4768
4769   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
4770   v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
4771   fun->Call(fun, argc, a2);
4772
4773   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
4774   v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
4775   fun->Call(fun, argc, a3);
4776
4777   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
4778   v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
4779   fun->Call(fun, argc, a4);
4780
4781   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
4782   v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
4783   fun->Call(fun, argc, a5);
4784 }
4785
4786
4787 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
4788   ApiTestFuzzer::Fuzz();
4789   CHECK_EQ(1, args.Length());
4790   v8::ThrowException(args[0]);
4791 }
4792
4793
4794 THREADED_TEST(ThrowValues) {
4795   v8::HandleScope scope(v8::Isolate::GetCurrent());
4796   Local<ObjectTemplate> templ = ObjectTemplate::New();
4797   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
4798   LocalContext context(0, templ);
4799   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
4800     "function Run(obj) {"
4801     "  try {"
4802     "    Throw(obj);"
4803     "  } catch (e) {"
4804     "    return e;"
4805     "  }"
4806     "  return 'no exception';"
4807     "}"
4808     "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
4809   CHECK_EQ(5, result->Length());
4810   CHECK(result->Get(v8::Integer::New(0))->IsString());
4811   CHECK(result->Get(v8::Integer::New(1))->IsNumber());
4812   CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
4813   CHECK(result->Get(v8::Integer::New(2))->IsNumber());
4814   CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
4815   CHECK(result->Get(v8::Integer::New(3))->IsNull());
4816   CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
4817 }
4818
4819
4820 THREADED_TEST(CatchZero) {
4821   LocalContext context;
4822   v8::HandleScope scope(context->GetIsolate());
4823   v8::TryCatch try_catch;
4824   CHECK(!try_catch.HasCaught());
4825   Script::Compile(v8_str("throw 10"))->Run();
4826   CHECK(try_catch.HasCaught());
4827   CHECK_EQ(10, try_catch.Exception()->Int32Value());
4828   try_catch.Reset();
4829   CHECK(!try_catch.HasCaught());
4830   Script::Compile(v8_str("throw 0"))->Run();
4831   CHECK(try_catch.HasCaught());
4832   CHECK_EQ(0, try_catch.Exception()->Int32Value());
4833 }
4834
4835
4836 THREADED_TEST(CatchExceptionFromWith) {
4837   LocalContext context;
4838   v8::HandleScope scope(context->GetIsolate());
4839   v8::TryCatch try_catch;
4840   CHECK(!try_catch.HasCaught());
4841   Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
4842   CHECK(try_catch.HasCaught());
4843 }
4844
4845
4846 THREADED_TEST(TryCatchAndFinallyHidingException) {
4847   LocalContext context;
4848   v8::HandleScope scope(context->GetIsolate());
4849   v8::TryCatch try_catch;
4850   CHECK(!try_catch.HasCaught());
4851   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
4852   CompileRun("f({toString: function() { throw 42; }});");
4853   CHECK(!try_catch.HasCaught());
4854 }
4855
4856
4857 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
4858   v8::TryCatch try_catch;
4859 }
4860
4861
4862 THREADED_TEST(TryCatchAndFinally) {
4863   LocalContext context;
4864   v8::HandleScope scope(context->GetIsolate());
4865   context->Global()->Set(
4866       v8_str("native_with_try_catch"),
4867       v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
4868   v8::TryCatch try_catch;
4869   CHECK(!try_catch.HasCaught());
4870   CompileRun(
4871       "try {\n"
4872       "  throw new Error('a');\n"
4873       "} finally {\n"
4874       "  native_with_try_catch();\n"
4875       "}\n");
4876   CHECK(try_catch.HasCaught());
4877 }
4878
4879
4880 static void TryCatchNestedHelper(int depth) {
4881   if (depth > 0) {
4882     v8::TryCatch try_catch;
4883     try_catch.SetVerbose(true);
4884     TryCatchNestedHelper(depth - 1);
4885     CHECK(try_catch.HasCaught());
4886     try_catch.ReThrow();
4887   } else {
4888     v8::ThrowException(v8_str("back"));
4889   }
4890 }
4891
4892
4893 TEST(TryCatchNested) {
4894   v8::V8::Initialize();
4895   LocalContext context;
4896   v8::HandleScope scope(context->GetIsolate());
4897   v8::TryCatch try_catch;
4898   TryCatchNestedHelper(5);
4899   CHECK(try_catch.HasCaught());
4900   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
4901 }
4902
4903
4904 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
4905   CHECK(try_catch->HasCaught());
4906   Handle<Message> message = try_catch->Message();
4907   Handle<Value> resource = message->GetScriptResourceName();
4908   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
4909   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
4910                      "Uncaught Error: a"));
4911   CHECK_EQ(1, message->GetLineNumber());
4912   CHECK_EQ(6, message->GetStartColumn());
4913 }
4914
4915
4916 void TryCatchMixedNestingHelper(
4917     const v8::FunctionCallbackInfo<v8::Value>& args) {
4918   ApiTestFuzzer::Fuzz();
4919   v8::TryCatch try_catch;
4920   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
4921   CHECK(try_catch.HasCaught());
4922   TryCatchMixedNestingCheck(&try_catch);
4923   try_catch.ReThrow();
4924 }
4925
4926
4927 // This test ensures that an outer TryCatch in the following situation:
4928 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
4929 // does not clobber the Message object generated for the inner TryCatch.
4930 // This exercises the ability of TryCatch.ReThrow() to restore the
4931 // inner pending Message before throwing the exception again.
4932 TEST(TryCatchMixedNesting) {
4933   v8::HandleScope scope(v8::Isolate::GetCurrent());
4934   v8::V8::Initialize();
4935   v8::TryCatch try_catch;
4936   Local<ObjectTemplate> templ = ObjectTemplate::New();
4937   templ->Set(v8_str("TryCatchMixedNestingHelper"),
4938              v8::FunctionTemplate::New(TryCatchMixedNestingHelper));
4939   LocalContext context(0, templ);
4940   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
4941   TryCatchMixedNestingCheck(&try_catch);
4942 }
4943
4944
4945 THREADED_TEST(Equality) {
4946   LocalContext context;
4947   v8::Isolate* isolate = context->GetIsolate();
4948   v8::HandleScope scope(context->GetIsolate());
4949   // Check that equality works at all before relying on CHECK_EQ
4950   CHECK(v8_str("a")->Equals(v8_str("a")));
4951   CHECK(!v8_str("a")->Equals(v8_str("b")));
4952
4953   CHECK_EQ(v8_str("a"), v8_str("a"));
4954   CHECK_NE(v8_str("a"), v8_str("b"));
4955   CHECK_EQ(v8_num(1), v8_num(1));
4956   CHECK_EQ(v8_num(1.00), v8_num(1));
4957   CHECK_NE(v8_num(1), v8_num(2));
4958
4959   // Assume String is not internalized.
4960   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
4961   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
4962   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
4963   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
4964   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
4965   CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
4966   Local<Value> not_a_number = v8_num(i::OS::nan_value());
4967   CHECK(!not_a_number->StrictEquals(not_a_number));
4968   CHECK(v8::False()->StrictEquals(v8::False()));
4969   CHECK(!v8::False()->StrictEquals(v8::Undefined()));
4970
4971   v8::Handle<v8::Object> obj = v8::Object::New();
4972   v8::Persistent<v8::Object> alias(isolate, obj);
4973   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
4974   alias.Dispose();
4975 }
4976
4977
4978 THREADED_TEST(MultiRun) {
4979   LocalContext context;
4980   v8::HandleScope scope(context->GetIsolate());
4981   Local<Script> script = Script::Compile(v8_str("x"));
4982   for (int i = 0; i < 10; i++)
4983     script->Run();
4984 }
4985
4986
4987 static void GetXValue(Local<String> name,
4988                       const v8::PropertyCallbackInfo<v8::Value>& info) {
4989   ApiTestFuzzer::Fuzz();
4990   CHECK_EQ(info.Data(), v8_str("donut"));
4991   CHECK_EQ(name, v8_str("x"));
4992   info.GetReturnValue().Set(name);
4993 }
4994
4995
4996 THREADED_TEST(SimplePropertyRead) {
4997   LocalContext context;
4998   v8::HandleScope scope(context->GetIsolate());
4999   Local<ObjectTemplate> templ = ObjectTemplate::New();
5000   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5001   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5002   Local<Script> script = Script::Compile(v8_str("obj.x"));
5003   for (int i = 0; i < 10; i++) {
5004     Local<Value> result = script->Run();
5005     CHECK_EQ(result, v8_str("x"));
5006   }
5007 }
5008
5009
5010 THREADED_TEST(DefinePropertyOnAPIAccessor) {
5011   LocalContext context;
5012   v8::HandleScope scope(context->GetIsolate());
5013   Local<ObjectTemplate> templ = ObjectTemplate::New();
5014   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5015   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5016
5017   // Uses getOwnPropertyDescriptor to check the configurable status
5018   Local<Script> script_desc
5019     = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
5020                              "obj, 'x');"
5021                              "prop.configurable;"));
5022   Local<Value> result = script_desc->Run();
5023   CHECK_EQ(result->BooleanValue(), true);
5024
5025   // Redefine get - but still configurable
5026   Local<Script> script_define
5027     = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
5028                              "            configurable: true };"
5029                              "Object.defineProperty(obj, 'x', desc);"
5030                              "obj.x"));
5031   result = script_define->Run();
5032   CHECK_EQ(result, v8_num(42));
5033
5034   // Check that the accessor is still configurable
5035   result = script_desc->Run();
5036   CHECK_EQ(result->BooleanValue(), true);
5037
5038   // Redefine to a non-configurable
5039   script_define
5040     = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
5041                              "             configurable: false };"
5042                              "Object.defineProperty(obj, 'x', desc);"
5043                              "obj.x"));
5044   result = script_define->Run();
5045   CHECK_EQ(result, v8_num(43));
5046   result = script_desc->Run();
5047   CHECK_EQ(result->BooleanValue(), false);
5048
5049   // Make sure that it is not possible to redefine again
5050   v8::TryCatch try_catch;
5051   result = script_define->Run();
5052   CHECK(try_catch.HasCaught());
5053   String::Utf8Value exception_value(try_catch.Exception());
5054   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5055 }
5056
5057
5058 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
5059   v8::HandleScope scope(v8::Isolate::GetCurrent());
5060   Local<ObjectTemplate> templ = ObjectTemplate::New();
5061   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5062   LocalContext context;
5063   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5064
5065   Local<Script> script_desc = Script::Compile(v8_str("var prop ="
5066                                     "Object.getOwnPropertyDescriptor( "
5067                                     "obj, 'x');"
5068                                     "prop.configurable;"));
5069   Local<Value> result = script_desc->Run();
5070   CHECK_EQ(result->BooleanValue(), true);
5071
5072   Local<Script> script_define =
5073     Script::Compile(v8_str("var desc = {get: function(){return 42; },"
5074                            "            configurable: true };"
5075                            "Object.defineProperty(obj, 'x', desc);"
5076                            "obj.x"));
5077   result = script_define->Run();
5078   CHECK_EQ(result, v8_num(42));
5079
5080
5081   result = script_desc->Run();
5082   CHECK_EQ(result->BooleanValue(), true);
5083
5084
5085   script_define =
5086     Script::Compile(v8_str("var desc = {get: function(){return 43; },"
5087                            "            configurable: false };"
5088                            "Object.defineProperty(obj, 'x', desc);"
5089                            "obj.x"));
5090   result = script_define->Run();
5091   CHECK_EQ(result, v8_num(43));
5092   result = script_desc->Run();
5093
5094   CHECK_EQ(result->BooleanValue(), false);
5095
5096   v8::TryCatch try_catch;
5097   result = script_define->Run();
5098   CHECK(try_catch.HasCaught());
5099   String::Utf8Value exception_value(try_catch.Exception());
5100   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5101 }
5102
5103
5104 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5105                                                 char const* name) {
5106   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5107 }
5108
5109
5110 THREADED_TEST(DefineAPIAccessorOnObject) {
5111   v8::HandleScope scope(v8::Isolate::GetCurrent());
5112   Local<ObjectTemplate> templ = ObjectTemplate::New();
5113   LocalContext context;
5114
5115   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5116   CompileRun("var obj2 = {};");
5117
5118   CHECK(CompileRun("obj1.x")->IsUndefined());
5119   CHECK(CompileRun("obj2.x")->IsUndefined());
5120
5121   CHECK(GetGlobalProperty(&context, "obj1")->
5122       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5123
5124   ExpectString("obj1.x", "x");
5125   CHECK(CompileRun("obj2.x")->IsUndefined());
5126
5127   CHECK(GetGlobalProperty(&context, "obj2")->
5128       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5129
5130   ExpectString("obj1.x", "x");
5131   ExpectString("obj2.x", "x");
5132
5133   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5134   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5135
5136   CompileRun("Object.defineProperty(obj1, 'x',"
5137              "{ get: function() { return 'y'; }, configurable: true })");
5138
5139   ExpectString("obj1.x", "y");
5140   ExpectString("obj2.x", "x");
5141
5142   CompileRun("Object.defineProperty(obj2, 'x',"
5143              "{ get: function() { return 'y'; }, configurable: true })");
5144
5145   ExpectString("obj1.x", "y");
5146   ExpectString("obj2.x", "y");
5147
5148   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5149   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5150
5151   CHECK(GetGlobalProperty(&context, "obj1")->
5152       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5153   CHECK(GetGlobalProperty(&context, "obj2")->
5154       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5155
5156   ExpectString("obj1.x", "x");
5157   ExpectString("obj2.x", "x");
5158
5159   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5160   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5161
5162   // Define getters/setters, but now make them not configurable.
5163   CompileRun("Object.defineProperty(obj1, 'x',"
5164              "{ get: function() { return 'z'; }, configurable: false })");
5165   CompileRun("Object.defineProperty(obj2, 'x',"
5166              "{ get: function() { return 'z'; }, configurable: false })");
5167
5168   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5169   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5170
5171   ExpectString("obj1.x", "z");
5172   ExpectString("obj2.x", "z");
5173
5174   CHECK(!GetGlobalProperty(&context, "obj1")->
5175       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5176   CHECK(!GetGlobalProperty(&context, "obj2")->
5177       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5178
5179   ExpectString("obj1.x", "z");
5180   ExpectString("obj2.x", "z");
5181 }
5182
5183
5184 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
5185   v8::HandleScope scope(v8::Isolate::GetCurrent());
5186   Local<ObjectTemplate> templ = ObjectTemplate::New();
5187   LocalContext context;
5188
5189   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5190   CompileRun("var obj2 = {};");
5191
5192   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5193         v8_str("x"),
5194         GetXValue, NULL,
5195         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5196   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5197         v8_str("x"),
5198         GetXValue, NULL,
5199         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5200
5201   ExpectString("obj1.x", "x");
5202   ExpectString("obj2.x", "x");
5203
5204   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5205   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5206
5207   CHECK(!GetGlobalProperty(&context, "obj1")->
5208       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5209   CHECK(!GetGlobalProperty(&context, "obj2")->
5210       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5211
5212   {
5213     v8::TryCatch try_catch;
5214     CompileRun("Object.defineProperty(obj1, 'x',"
5215         "{get: function() { return 'func'; }})");
5216     CHECK(try_catch.HasCaught());
5217     String::Utf8Value exception_value(try_catch.Exception());
5218     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5219   }
5220   {
5221     v8::TryCatch try_catch;
5222     CompileRun("Object.defineProperty(obj2, 'x',"
5223         "{get: function() { return 'func'; }})");
5224     CHECK(try_catch.HasCaught());
5225     String::Utf8Value exception_value(try_catch.Exception());
5226     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5227   }
5228 }
5229
5230
5231 static void Get239Value(Local<String> name,
5232                         const v8::PropertyCallbackInfo<v8::Value>& info) {
5233   ApiTestFuzzer::Fuzz();
5234   CHECK_EQ(info.Data(), v8_str("donut"));
5235   CHECK_EQ(name, v8_str("239"));
5236   info.GetReturnValue().Set(name);
5237 }
5238
5239
5240 THREADED_TEST(ElementAPIAccessor) {
5241   v8::HandleScope scope(v8::Isolate::GetCurrent());
5242   Local<ObjectTemplate> templ = ObjectTemplate::New();
5243   LocalContext context;
5244
5245   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5246   CompileRun("var obj2 = {};");
5247
5248   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5249         v8_str("239"),
5250         Get239Value, NULL,
5251         v8_str("donut")));
5252   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5253         v8_str("239"),
5254         Get239Value, NULL,
5255         v8_str("donut")));
5256
5257   ExpectString("obj1[239]", "239");
5258   ExpectString("obj2[239]", "239");
5259   ExpectString("obj1['239']", "239");
5260   ExpectString("obj2['239']", "239");
5261 }
5262
5263
5264 v8::Persistent<Value> xValue;
5265
5266
5267 static void SetXValue(Local<String> name,
5268                       Local<Value> value,
5269                       const v8::PropertyCallbackInfo<void>& info) {
5270   CHECK_EQ(value, v8_num(4));
5271   CHECK_EQ(info.Data(), v8_str("donut"));
5272   CHECK_EQ(name, v8_str("x"));
5273   CHECK(xValue.IsEmpty());
5274   xValue.Reset(info.GetIsolate(), value);
5275 }
5276
5277
5278 THREADED_TEST(SimplePropertyWrite) {
5279   v8::HandleScope scope(v8::Isolate::GetCurrent());
5280   Local<ObjectTemplate> templ = ObjectTemplate::New();
5281   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5282   LocalContext context;
5283   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5284   Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
5285   for (int i = 0; i < 10; i++) {
5286     CHECK(xValue.IsEmpty());
5287     script->Run();
5288     CHECK_EQ(v8_num(4), Local<Value>::New(v8::Isolate::GetCurrent(), xValue));
5289     xValue.Dispose();
5290     xValue.Clear();
5291   }
5292 }
5293
5294
5295 THREADED_TEST(SetterOnly) {
5296   v8::HandleScope scope(v8::Isolate::GetCurrent());
5297   Local<ObjectTemplate> templ = ObjectTemplate::New();
5298   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5299   LocalContext context;
5300   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5301   Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5302   for (int i = 0; i < 10; i++) {
5303     CHECK(xValue.IsEmpty());
5304     script->Run();
5305     CHECK_EQ(v8_num(4), Local<Value>::New(v8::Isolate::GetCurrent(), xValue));
5306     xValue.Dispose();
5307     xValue.Clear();
5308   }
5309 }
5310
5311
5312 THREADED_TEST(NoAccessors) {
5313   v8::HandleScope scope(v8::Isolate::GetCurrent());
5314   Local<ObjectTemplate> templ = ObjectTemplate::New();
5315   templ->SetAccessor(v8_str("x"),
5316                      static_cast<v8::AccessorGetterCallback>(NULL),
5317                      NULL,
5318                      v8_str("donut"));
5319   LocalContext context;
5320   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5321   Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5322   for (int i = 0; i < 10; i++) {
5323     script->Run();
5324   }
5325 }
5326
5327
5328 static void XPropertyGetter(Local<String> property,
5329                             const v8::PropertyCallbackInfo<v8::Value>& info) {
5330   ApiTestFuzzer::Fuzz();
5331   CHECK(info.Data()->IsUndefined());
5332   info.GetReturnValue().Set(property);
5333 }
5334
5335
5336 THREADED_TEST(NamedInterceptorPropertyRead) {
5337   v8::HandleScope scope(v8::Isolate::GetCurrent());
5338   Local<ObjectTemplate> templ = ObjectTemplate::New();
5339   templ->SetNamedPropertyHandler(XPropertyGetter);
5340   LocalContext context;
5341   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5342   Local<Script> script = Script::Compile(v8_str("obj.x"));
5343   for (int i = 0; i < 10; i++) {
5344     Local<Value> result = script->Run();
5345     CHECK_EQ(result, v8_str("x"));
5346   }
5347 }
5348
5349
5350 THREADED_TEST(NamedInterceptorDictionaryIC) {
5351   v8::HandleScope scope(v8::Isolate::GetCurrent());
5352   Local<ObjectTemplate> templ = ObjectTemplate::New();
5353   templ->SetNamedPropertyHandler(XPropertyGetter);
5354   LocalContext context;
5355   // Create an object with a named interceptor.
5356   context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
5357   Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
5358   for (int i = 0; i < 10; i++) {
5359     Local<Value> result = script->Run();
5360     CHECK_EQ(result, v8_str("x"));
5361   }
5362   // Create a slow case object and a function accessing a property in
5363   // that slow case object (with dictionary probing in generated
5364   // code). Then force object with a named interceptor into slow-case,
5365   // pass it to the function, and check that the interceptor is called
5366   // instead of accessing the local property.
5367   Local<Value> result =
5368       CompileRun("function get_x(o) { return o.x; };"
5369                  "var obj = { x : 42, y : 0 };"
5370                  "delete obj.y;"
5371                  "for (var i = 0; i < 10; i++) get_x(obj);"
5372                  "interceptor_obj.x = 42;"
5373                  "interceptor_obj.y = 10;"
5374                  "delete interceptor_obj.y;"
5375                  "get_x(interceptor_obj)");
5376   CHECK_EQ(result, v8_str("x"));
5377 }
5378
5379
5380 THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
5381   v8::Isolate* isolate = v8::Isolate::GetCurrent();
5382   v8::HandleScope scope(isolate);
5383   v8::Local<Context> context1 = Context::New(isolate);
5384
5385   context1->Enter();
5386   Local<ObjectTemplate> templ = ObjectTemplate::New();
5387   templ->SetNamedPropertyHandler(XPropertyGetter);
5388   // Create an object with a named interceptor.
5389   v8::Local<v8::Object> object = templ->NewInstance();
5390   context1->Global()->Set(v8_str("interceptor_obj"), object);
5391
5392   // Force the object into the slow case.
5393   CompileRun("interceptor_obj.y = 0;"
5394              "delete interceptor_obj.y;");
5395   context1->Exit();
5396
5397   {
5398     // Introduce the object into a different context.
5399     // Repeat named loads to exercise ICs.
5400     LocalContext context2;
5401     context2->Global()->Set(v8_str("interceptor_obj"), object);
5402     Local<Value> result =
5403       CompileRun("function get_x(o) { return o.x; }"
5404                  "interceptor_obj.x = 42;"
5405                  "for (var i=0; i != 10; i++) {"
5406                  "  get_x(interceptor_obj);"
5407                  "}"
5408                  "get_x(interceptor_obj)");
5409     // Check that the interceptor was actually invoked.
5410     CHECK_EQ(result, v8_str("x"));
5411   }
5412
5413   // Return to the original context and force some object to the slow case
5414   // to cause the NormalizedMapCache to verify.
5415   context1->Enter();
5416   CompileRun("var obj = { x : 0 }; delete obj.x;");
5417   context1->Exit();
5418 }
5419
5420
5421 static void SetXOnPrototypeGetter(
5422     Local<String> property,
5423     const v8::PropertyCallbackInfo<v8::Value>& info) {
5424   // Set x on the prototype object and do not handle the get request.
5425   v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
5426   proto.As<v8::Object>()->Set(v8_str("x"), v8::Integer::New(23));
5427 }
5428
5429
5430 // This is a regression test for http://crbug.com/20104. Map
5431 // transitions should not interfere with post interceptor lookup.
5432 THREADED_TEST(NamedInterceptorMapTransitionRead) {
5433   v8::HandleScope scope(v8::Isolate::GetCurrent());
5434   Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
5435   Local<v8::ObjectTemplate> instance_template
5436       = function_template->InstanceTemplate();
5437   instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
5438   LocalContext context;
5439   context->Global()->Set(v8_str("F"), function_template->GetFunction());
5440   // Create an instance of F and introduce a map transition for x.
5441   CompileRun("var o = new F(); o.x = 23;");
5442   // Create an instance of F and invoke the getter. The result should be 23.
5443   Local<Value> result = CompileRun("o = new F(); o.x");
5444   CHECK_EQ(result->Int32Value(), 23);
5445 }
5446
5447
5448 static void IndexedPropertyGetter(
5449     uint32_t index,
5450     const v8::PropertyCallbackInfo<v8::Value>& info) {
5451   ApiTestFuzzer::Fuzz();
5452   if (index == 37) {
5453     info.GetReturnValue().Set(v8_num(625));
5454   }
5455 }
5456
5457
5458 static void IndexedPropertySetter(
5459     uint32_t index,
5460     Local<Value> value,
5461     const v8::PropertyCallbackInfo<v8::Value>& info) {
5462   ApiTestFuzzer::Fuzz();
5463   if (index == 39) {
5464     info.GetReturnValue().Set(value);
5465   }
5466 }
5467
5468
5469 THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
5470   v8::HandleScope scope(v8::Isolate::GetCurrent());
5471   Local<ObjectTemplate> templ = ObjectTemplate::New();
5472   templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
5473                                    IndexedPropertySetter);
5474   LocalContext context;
5475   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5476   Local<Script> getter_script = Script::Compile(v8_str(
5477       "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
5478   Local<Script> setter_script = Script::Compile(v8_str(
5479       "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
5480       "obj[17] = 23;"
5481       "obj.foo;"));
5482   Local<Script> interceptor_setter_script = Script::Compile(v8_str(
5483       "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
5484       "obj[39] = 47;"
5485       "obj.foo;"));  // This setter should not run, due to the interceptor.
5486   Local<Script> interceptor_getter_script = Script::Compile(v8_str(
5487       "obj[37];"));
5488   Local<Value> result = getter_script->Run();
5489   CHECK_EQ(v8_num(5), result);
5490   result = setter_script->Run();
5491   CHECK_EQ(v8_num(23), result);
5492   result = interceptor_setter_script->Run();
5493   CHECK_EQ(v8_num(23), result);
5494   result = interceptor_getter_script->Run();
5495   CHECK_EQ(v8_num(625), result);
5496 }
5497
5498
5499 static void UnboxedDoubleIndexedPropertyGetter(
5500     uint32_t index,
5501     const v8::PropertyCallbackInfo<v8::Value>& info) {
5502   ApiTestFuzzer::Fuzz();
5503   if (index < 25) {
5504     info.GetReturnValue().Set(v8_num(index));
5505   }
5506 }
5507
5508
5509 static void UnboxedDoubleIndexedPropertySetter(
5510     uint32_t index,
5511     Local<Value> value,
5512     const v8::PropertyCallbackInfo<v8::Value>& info) {
5513   ApiTestFuzzer::Fuzz();
5514   if (index < 25) {
5515     info.GetReturnValue().Set(v8_num(index));
5516   }
5517 }
5518
5519
5520 void UnboxedDoubleIndexedPropertyEnumerator(
5521     const v8::PropertyCallbackInfo<v8::Array>& info) {
5522   // Force the list of returned keys to be stored in a FastDoubleArray.
5523   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5524       "keys = new Array(); keys[125000] = 1;"
5525       "for(i = 0; i < 80000; i++) { keys[i] = i; };"
5526       "keys.length = 25; keys;"));
5527   Local<Value> result = indexed_property_names_script->Run();
5528   info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
5529 }
5530
5531
5532 // Make sure that the the interceptor code in the runtime properly handles
5533 // merging property name lists for double-array-backed arrays.
5534 THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
5535   v8::HandleScope scope(v8::Isolate::GetCurrent());
5536   Local<ObjectTemplate> templ = ObjectTemplate::New();
5537   templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
5538                                    UnboxedDoubleIndexedPropertySetter,
5539                                    0,
5540                                    0,
5541                                    UnboxedDoubleIndexedPropertyEnumerator);
5542   LocalContext context;
5543   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5544   // When obj is created, force it to be Stored in a FastDoubleArray.
5545   Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
5546       "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
5547       "key_count = 0; "
5548       "for (x in obj) {key_count++;};"
5549       "obj;"));
5550   Local<Value> result = create_unboxed_double_script->Run();
5551   CHECK(result->ToObject()->HasRealIndexedProperty(2000));
5552   Local<Script> key_count_check = Script::Compile(v8_str(
5553       "key_count;"));
5554   result = key_count_check->Run();
5555   CHECK_EQ(v8_num(40013), result);
5556 }
5557
5558
5559 void NonStrictArgsIndexedPropertyEnumerator(
5560     const v8::PropertyCallbackInfo<v8::Array>& info) {
5561   // Force the list of returned keys to be stored in a Arguments object.
5562   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5563       "function f(w,x) {"
5564       " return arguments;"
5565       "}"
5566       "keys = f(0, 1, 2, 3);"
5567       "keys;"));
5568   Local<Object> result =
5569       Local<Object>::Cast(indexed_property_names_script->Run());
5570   // Have to populate the handle manually, as it's not Cast-able.
5571   i::Handle<i::JSObject> o =
5572       v8::Utils::OpenHandle<Object, i::JSObject>(result);
5573   i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
5574   info.GetReturnValue().Set(v8::Utils::ToLocal(array));
5575 }
5576
5577
5578 static void NonStrictIndexedPropertyGetter(
5579     uint32_t index,
5580     const v8::PropertyCallbackInfo<v8::Value>& info) {
5581   ApiTestFuzzer::Fuzz();
5582   if (index < 4) {
5583     info.GetReturnValue().Set(v8_num(index));
5584   }
5585 }
5586
5587
5588 // Make sure that the the interceptor code in the runtime properly handles
5589 // merging property name lists for non-string arguments arrays.
5590 THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
5591   v8::HandleScope scope(v8::Isolate::GetCurrent());
5592   Local<ObjectTemplate> templ = ObjectTemplate::New();
5593   templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
5594                                    0,
5595                                    0,
5596                                    0,
5597                                    NonStrictArgsIndexedPropertyEnumerator);
5598   LocalContext context;
5599   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5600   Local<Script> create_args_script =
5601       Script::Compile(v8_str(
5602           "var key_count = 0;"
5603           "for (x in obj) {key_count++;} key_count;"));
5604   Local<Value> result = create_args_script->Run();
5605   CHECK_EQ(v8_num(4), result);
5606 }
5607
5608
5609 static void IdentityIndexedPropertyGetter(
5610     uint32_t index,
5611     const v8::PropertyCallbackInfo<v8::Value>& info) {
5612   info.GetReturnValue().Set(index);
5613 }
5614
5615
5616 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
5617   v8::HandleScope scope(v8::Isolate::GetCurrent());
5618   Local<ObjectTemplate> templ = ObjectTemplate::New();
5619   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5620
5621   LocalContext context;
5622   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5623
5624   // Check fast object case.
5625   const char* fast_case_code =
5626       "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
5627   ExpectString(fast_case_code, "0");
5628
5629   // Check slow case.
5630   const char* slow_case_code =
5631       "obj.x = 1; delete obj.x;"
5632       "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
5633   ExpectString(slow_case_code, "1");
5634 }
5635
5636
5637 THREADED_TEST(IndexedInterceptorWithNoSetter) {
5638   v8::HandleScope scope(v8::Isolate::GetCurrent());
5639   Local<ObjectTemplate> templ = ObjectTemplate::New();
5640   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5641
5642   LocalContext context;
5643   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5644
5645   const char* code =
5646       "try {"
5647       "  obj[0] = 239;"
5648       "  for (var i = 0; i < 100; i++) {"
5649       "    var v = obj[0];"
5650       "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
5651       "  }"
5652       "  'PASSED'"
5653       "} catch(e) {"
5654       "  e"
5655       "}";
5656   ExpectString(code, "PASSED");
5657 }
5658
5659
5660 THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
5661   v8::HandleScope scope(v8::Isolate::GetCurrent());
5662   Local<ObjectTemplate> templ = ObjectTemplate::New();
5663   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5664
5665   LocalContext context;
5666   Local<v8::Object> obj = templ->NewInstance();
5667   obj->TurnOnAccessCheck();
5668   context->Global()->Set(v8_str("obj"), obj);
5669
5670   const char* code =
5671       "try {"
5672       "  for (var i = 0; i < 100; i++) {"
5673       "    var v = obj[0];"
5674       "    if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
5675       "  }"
5676       "  'PASSED'"
5677       "} catch(e) {"
5678       "  e"
5679       "}";
5680   ExpectString(code, "PASSED");
5681 }
5682
5683
5684 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
5685   i::FLAG_allow_natives_syntax = true;
5686   v8::HandleScope scope(v8::Isolate::GetCurrent());
5687   Local<ObjectTemplate> templ = ObjectTemplate::New();
5688   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5689
5690   LocalContext context;
5691   Local<v8::Object> obj = templ->NewInstance();
5692   context->Global()->Set(v8_str("obj"), obj);
5693
5694   const char* code =
5695       "try {"
5696       "  for (var i = 0; i < 100; i++) {"
5697       "    var expected = i;"
5698       "    if (i == 5) {"
5699       "      %EnableAccessChecks(obj);"
5700       "      expected = undefined;"
5701       "    }"
5702       "    var v = obj[i];"
5703       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5704       "    if (i == 5) %DisableAccessChecks(obj);"
5705       "  }"
5706       "  'PASSED'"
5707       "} catch(e) {"
5708       "  e"
5709       "}";
5710   ExpectString(code, "PASSED");
5711 }
5712
5713
5714 THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
5715   v8::HandleScope scope(v8::Isolate::GetCurrent());
5716   Local<ObjectTemplate> templ = ObjectTemplate::New();
5717   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5718
5719   LocalContext context;
5720   Local<v8::Object> obj = templ->NewInstance();
5721   context->Global()->Set(v8_str("obj"), obj);
5722
5723   const char* code =
5724       "try {"
5725       "  for (var i = 0; i < 100; i++) {"
5726       "    var v = obj[i];"
5727       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
5728       "  }"
5729       "  'PASSED'"
5730       "} catch(e) {"
5731       "  e"
5732       "}";
5733   ExpectString(code, "PASSED");
5734 }
5735
5736
5737 THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
5738   v8::HandleScope scope(v8::Isolate::GetCurrent());
5739   Local<ObjectTemplate> templ = ObjectTemplate::New();
5740   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5741
5742   LocalContext context;
5743   Local<v8::Object> obj = templ->NewInstance();
5744   context->Global()->Set(v8_str("obj"), obj);
5745
5746   const char* code =
5747       "try {"
5748       "  for (var i = 0; i < 100; i++) {"
5749       "    var expected = i;"
5750       "    var key = i;"
5751       "    if (i == 25) {"
5752       "       key = -1;"
5753       "       expected = undefined;"
5754       "    }"
5755       "    if (i == 50) {"
5756       "       /* probe minimal Smi number on 32-bit platforms */"
5757       "       key = -(1 << 30);"
5758       "       expected = undefined;"
5759       "    }"
5760       "    if (i == 75) {"
5761       "       /* probe minimal Smi number on 64-bit platforms */"
5762       "       key = 1 << 31;"
5763       "       expected = undefined;"
5764       "    }"
5765       "    var v = obj[key];"
5766       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5767       "  }"
5768       "  'PASSED'"
5769       "} catch(e) {"
5770       "  e"
5771       "}";
5772   ExpectString(code, "PASSED");
5773 }
5774
5775
5776 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
5777   v8::HandleScope scope(v8::Isolate::GetCurrent());
5778   Local<ObjectTemplate> templ = ObjectTemplate::New();
5779   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5780
5781   LocalContext context;
5782   Local<v8::Object> obj = templ->NewInstance();
5783   context->Global()->Set(v8_str("obj"), obj);
5784
5785   const char* code =
5786       "try {"
5787       "  for (var i = 0; i < 100; i++) {"
5788       "    var expected = i;"
5789       "    var key = i;"
5790       "    if (i == 50) {"
5791       "       key = 'foobar';"
5792       "       expected = undefined;"
5793       "    }"
5794       "    var v = obj[key];"
5795       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5796       "  }"
5797       "  'PASSED'"
5798       "} catch(e) {"
5799       "  e"
5800       "}";
5801   ExpectString(code, "PASSED");
5802 }
5803
5804
5805 THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
5806   v8::HandleScope scope(v8::Isolate::GetCurrent());
5807   Local<ObjectTemplate> templ = ObjectTemplate::New();
5808   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5809
5810   LocalContext context;
5811   Local<v8::Object> obj = templ->NewInstance();
5812   context->Global()->Set(v8_str("obj"), obj);
5813
5814   const char* code =
5815       "var original = obj;"
5816       "try {"
5817       "  for (var i = 0; i < 100; i++) {"
5818       "    var expected = i;"
5819       "    if (i == 50) {"
5820       "       obj = {50: 'foobar'};"
5821       "       expected = 'foobar';"
5822       "    }"
5823       "    var v = obj[i];"
5824       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5825       "    if (i == 50) obj = original;"
5826       "  }"
5827       "  'PASSED'"
5828       "} catch(e) {"
5829       "  e"
5830       "}";
5831   ExpectString(code, "PASSED");
5832 }
5833
5834
5835 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
5836   v8::HandleScope scope(v8::Isolate::GetCurrent());
5837   Local<ObjectTemplate> templ = ObjectTemplate::New();
5838   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5839
5840   LocalContext context;
5841   Local<v8::Object> obj = templ->NewInstance();
5842   context->Global()->Set(v8_str("obj"), obj);
5843
5844   const char* code =
5845       "var original = obj;"
5846       "try {"
5847       "  for (var i = 0; i < 100; i++) {"
5848       "    var expected = i;"
5849       "    if (i == 5) {"
5850       "       obj = 239;"
5851       "       expected = undefined;"
5852       "    }"
5853       "    var v = obj[i];"
5854       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5855       "    if (i == 5) obj = original;"
5856       "  }"
5857       "  'PASSED'"
5858       "} catch(e) {"
5859       "  e"
5860       "}";
5861   ExpectString(code, "PASSED");
5862 }
5863
5864
5865 THREADED_TEST(IndexedInterceptorOnProto) {
5866   v8::HandleScope scope(v8::Isolate::GetCurrent());
5867   Local<ObjectTemplate> templ = ObjectTemplate::New();
5868   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5869
5870   LocalContext context;
5871   Local<v8::Object> obj = templ->NewInstance();
5872   context->Global()->Set(v8_str("obj"), obj);
5873
5874   const char* code =
5875       "var o = {__proto__: obj};"
5876       "try {"
5877       "  for (var i = 0; i < 100; i++) {"
5878       "    var v = o[i];"
5879       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
5880       "  }"
5881       "  'PASSED'"
5882       "} catch(e) {"
5883       "  e"
5884       "}";
5885   ExpectString(code, "PASSED");
5886 }
5887
5888
5889 THREADED_TEST(MultiContexts) {
5890   v8::HandleScope scope(v8::Isolate::GetCurrent());
5891   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
5892   templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
5893
5894   Local<String> password = v8_str("Password");
5895
5896   // Create an environment
5897   LocalContext context0(0, templ);
5898   context0->SetSecurityToken(password);
5899   v8::Handle<v8::Object> global0 = context0->Global();
5900   global0->Set(v8_str("custom"), v8_num(1234));
5901   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5902
5903   // Create an independent environment
5904   LocalContext context1(0, templ);
5905   context1->SetSecurityToken(password);
5906   v8::Handle<v8::Object> global1 = context1->Global();
5907   global1->Set(v8_str("custom"), v8_num(1234));
5908   CHECK_NE(global0, global1);
5909   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5910   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
5911
5912   // Now create a new context with the old global
5913   LocalContext context2(0, templ, global1);
5914   context2->SetSecurityToken(password);
5915   v8::Handle<v8::Object> global2 = context2->Global();
5916   CHECK_EQ(global1, global2);
5917   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
5918   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
5919 }
5920
5921
5922 THREADED_TEST(FunctionPrototypeAcrossContexts) {
5923   // Make sure that functions created by cloning boilerplates cannot
5924   // communicate through their __proto__ field.
5925
5926   v8::HandleScope scope(v8::Isolate::GetCurrent());
5927
5928   LocalContext env0;
5929   v8::Handle<v8::Object> global0 =
5930       env0->Global();
5931   v8::Handle<v8::Object> object0 =
5932       global0->Get(v8_str("Object")).As<v8::Object>();
5933   v8::Handle<v8::Object> tostring0 =
5934       object0->Get(v8_str("toString")).As<v8::Object>();
5935   v8::Handle<v8::Object> proto0 =
5936       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
5937   proto0->Set(v8_str("custom"), v8_num(1234));
5938
5939   LocalContext env1;
5940   v8::Handle<v8::Object> global1 =
5941       env1->Global();
5942   v8::Handle<v8::Object> object1 =
5943       global1->Get(v8_str("Object")).As<v8::Object>();
5944   v8::Handle<v8::Object> tostring1 =
5945       object1->Get(v8_str("toString")).As<v8::Object>();
5946   v8::Handle<v8::Object> proto1 =
5947       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
5948   CHECK(!proto1->Has(v8_str("custom")));
5949 }
5950
5951
5952 THREADED_TEST(Regress892105) {
5953   // Make sure that object and array literals created by cloning
5954   // boilerplates cannot communicate through their __proto__
5955   // field. This is rather difficult to check, but we try to add stuff
5956   // to Object.prototype and Array.prototype and create a new
5957   // environment. This should succeed.
5958
5959   v8::HandleScope scope(v8::Isolate::GetCurrent());
5960
5961   Local<String> source = v8_str("Object.prototype.obj = 1234;"
5962                                 "Array.prototype.arr = 4567;"
5963                                 "8901");
5964
5965   LocalContext env0;
5966   Local<Script> script0 = Script::Compile(source);
5967   CHECK_EQ(8901.0, script0->Run()->NumberValue());
5968
5969   LocalContext env1;
5970   Local<Script> script1 = Script::Compile(source);
5971   CHECK_EQ(8901.0, script1->Run()->NumberValue());
5972 }
5973
5974
5975 THREADED_TEST(UndetectableObject) {
5976   LocalContext env;
5977   v8::HandleScope scope(env->GetIsolate());
5978
5979   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
5980   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5981
5982   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5983   env->Global()->Set(v8_str("undetectable"), obj);
5984
5985   ExpectString("undetectable.toString()", "[object Object]");
5986   ExpectString("typeof undetectable", "undefined");
5987   ExpectString("typeof(undetectable)", "undefined");
5988   ExpectBoolean("typeof undetectable == 'undefined'", true);
5989   ExpectBoolean("typeof undetectable == 'object'", false);
5990   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
5991   ExpectBoolean("!undetectable", true);
5992
5993   ExpectObject("true&&undetectable", obj);
5994   ExpectBoolean("false&&undetectable", false);
5995   ExpectBoolean("true||undetectable", true);
5996   ExpectObject("false||undetectable", obj);
5997
5998   ExpectObject("undetectable&&true", obj);
5999   ExpectObject("undetectable&&false", obj);
6000   ExpectBoolean("undetectable||true", true);
6001   ExpectBoolean("undetectable||false", false);
6002
6003   ExpectBoolean("undetectable==null", true);
6004   ExpectBoolean("null==undetectable", true);
6005   ExpectBoolean("undetectable==undefined", true);
6006   ExpectBoolean("undefined==undetectable", true);
6007   ExpectBoolean("undetectable==undetectable", true);
6008
6009
6010   ExpectBoolean("undetectable===null", false);
6011   ExpectBoolean("null===undetectable", false);
6012   ExpectBoolean("undetectable===undefined", false);
6013   ExpectBoolean("undefined===undetectable", false);
6014   ExpectBoolean("undetectable===undetectable", true);
6015 }
6016
6017
6018 THREADED_TEST(VoidLiteral) {
6019   LocalContext env;
6020   v8::HandleScope scope(env->GetIsolate());
6021
6022   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
6023   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
6024
6025   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6026   env->Global()->Set(v8_str("undetectable"), obj);
6027
6028   ExpectBoolean("undefined == void 0", true);
6029   ExpectBoolean("undetectable == void 0", true);
6030   ExpectBoolean("null == void 0", true);
6031   ExpectBoolean("undefined === void 0", true);
6032   ExpectBoolean("undetectable === void 0", false);
6033   ExpectBoolean("null === void 0", false);
6034
6035   ExpectBoolean("void 0 == undefined", true);
6036   ExpectBoolean("void 0 == undetectable", true);
6037   ExpectBoolean("void 0 == null", true);
6038   ExpectBoolean("void 0 === undefined", true);
6039   ExpectBoolean("void 0 === undetectable", false);
6040   ExpectBoolean("void 0 === null", false);
6041
6042   ExpectString("(function() {"
6043                "  try {"
6044                "    return x === void 0;"
6045                "  } catch(e) {"
6046                "    return e.toString();"
6047                "  }"
6048                "})()",
6049                "ReferenceError: x is not defined");
6050   ExpectString("(function() {"
6051                "  try {"
6052                "    return void 0 === x;"
6053                "  } catch(e) {"
6054                "    return e.toString();"
6055                "  }"
6056                "})()",
6057                "ReferenceError: x is not defined");
6058 }
6059
6060
6061 THREADED_TEST(ExtensibleOnUndetectable) {
6062   LocalContext env;
6063   v8::HandleScope scope(env->GetIsolate());
6064
6065   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
6066   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
6067
6068   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6069   env->Global()->Set(v8_str("undetectable"), obj);
6070
6071   Local<String> source = v8_str("undetectable.x = 42;"
6072                                 "undetectable.x");
6073
6074   Local<Script> script = Script::Compile(source);
6075
6076   CHECK_EQ(v8::Integer::New(42), script->Run());
6077
6078   ExpectBoolean("Object.isExtensible(undetectable)", true);
6079
6080   source = v8_str("Object.preventExtensions(undetectable);");
6081   script = Script::Compile(source);
6082   script->Run();
6083   ExpectBoolean("Object.isExtensible(undetectable)", false);
6084
6085   source = v8_str("undetectable.y = 2000;");
6086   script = Script::Compile(source);
6087   script->Run();
6088   ExpectBoolean("undetectable.y == undefined", true);
6089 }
6090
6091
6092
6093 THREADED_TEST(UndetectableString) {
6094   LocalContext env;
6095   v8::HandleScope scope(env->GetIsolate());
6096
6097   Local<String> obj = String::NewUndetectable("foo");
6098   env->Global()->Set(v8_str("undetectable"), obj);
6099
6100   ExpectString("undetectable", "foo");
6101   ExpectString("typeof undetectable", "undefined");
6102   ExpectString("typeof(undetectable)", "undefined");
6103   ExpectBoolean("typeof undetectable == 'undefined'", true);
6104   ExpectBoolean("typeof undetectable == 'string'", false);
6105   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6106   ExpectBoolean("!undetectable", true);
6107
6108   ExpectObject("true&&undetectable", obj);
6109   ExpectBoolean("false&&undetectable", false);
6110   ExpectBoolean("true||undetectable", true);
6111   ExpectObject("false||undetectable", obj);
6112
6113   ExpectObject("undetectable&&true", obj);
6114   ExpectObject("undetectable&&false", obj);
6115   ExpectBoolean("undetectable||true", true);
6116   ExpectBoolean("undetectable||false", false);
6117
6118   ExpectBoolean("undetectable==null", true);
6119   ExpectBoolean("null==undetectable", true);
6120   ExpectBoolean("undetectable==undefined", true);
6121   ExpectBoolean("undefined==undetectable", true);
6122   ExpectBoolean("undetectable==undetectable", true);
6123
6124
6125   ExpectBoolean("undetectable===null", false);
6126   ExpectBoolean("null===undetectable", false);
6127   ExpectBoolean("undetectable===undefined", false);
6128   ExpectBoolean("undefined===undetectable", false);
6129   ExpectBoolean("undetectable===undetectable", true);
6130 }
6131
6132
6133 TEST(UndetectableOptimized) {
6134   i::FLAG_allow_natives_syntax = true;
6135   LocalContext env;
6136   v8::HandleScope scope(env->GetIsolate());
6137
6138   Local<String> obj = String::NewUndetectable("foo");
6139   env->Global()->Set(v8_str("undetectable"), obj);
6140   env->Global()->Set(v8_str("detectable"), v8_str("bar"));
6141
6142   ExpectString(
6143       "function testBranch() {"
6144       "  if (!%_IsUndetectableObject(undetectable)) throw 1;"
6145       "  if (%_IsUndetectableObject(detectable)) throw 2;"
6146       "}\n"
6147       "function testBool() {"
6148       "  var b1 = !%_IsUndetectableObject(undetectable);"
6149       "  var b2 = %_IsUndetectableObject(detectable);"
6150       "  if (b1) throw 3;"
6151       "  if (b2) throw 4;"
6152       "  return b1 == b2;"
6153       "}\n"
6154       "%OptimizeFunctionOnNextCall(testBranch);"
6155       "%OptimizeFunctionOnNextCall(testBool);"
6156       "for (var i = 0; i < 10; i++) {"
6157       "  testBranch();"
6158       "  testBool();"
6159       "}\n"
6160       "\"PASS\"",
6161       "PASS");
6162 }
6163
6164
6165 template <typename T> static void USE(T) { }
6166
6167
6168 // This test is not intended to be run, just type checked.
6169 static inline void PersistentHandles(v8::Isolate* isolate) {
6170   USE(PersistentHandles);
6171   Local<String> str = v8_str("foo");
6172   v8::Persistent<String> p_str(isolate, str);
6173   p_str.Dispose();
6174   Local<Script> scr = Script::Compile(v8_str(""));
6175   v8::Persistent<Script> p_scr(isolate, scr);
6176   p_scr.Dispose();
6177   Local<ObjectTemplate> templ = ObjectTemplate::New();
6178   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
6179   p_templ.Dispose();
6180 }
6181
6182
6183 static void HandleLogDelegator(
6184     const v8::FunctionCallbackInfo<v8::Value>& args) {
6185   ApiTestFuzzer::Fuzz();
6186 }
6187
6188
6189 THREADED_TEST(GlobalObjectTemplate) {
6190   v8::Isolate* isolate = v8::Isolate::GetCurrent();
6191   v8::HandleScope handle_scope(isolate);
6192   Local<ObjectTemplate> global_template = ObjectTemplate::New();
6193   global_template->Set(v8_str("JSNI_Log"),
6194                        v8::FunctionTemplate::New(HandleLogDelegator));
6195   v8::Local<Context> context = Context::New(isolate, 0, global_template);
6196   Context::Scope context_scope(context);
6197   Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
6198 }
6199
6200
6201 static const char* kSimpleExtensionSource =
6202   "function Foo() {"
6203   "  return 4;"
6204   "}";
6205
6206
6207 THREADED_TEST(SimpleExtensions) {
6208   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6209   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6210   const char* extension_names[] = { "simpletest" };
6211   v8::ExtensionConfiguration extensions(1, extension_names);
6212   v8::Handle<Context> context =
6213       Context::New(v8::Isolate::GetCurrent(), &extensions);
6214   Context::Scope lock(context);
6215   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
6216   CHECK_EQ(result, v8::Integer::New(4));
6217 }
6218
6219
6220 THREADED_TEST(NullExtensions) {
6221   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6222   v8::RegisterExtension(new Extension("nulltest", NULL));
6223   const char* extension_names[] = { "nulltest" };
6224   v8::ExtensionConfiguration extensions(1, extension_names);
6225   v8::Handle<Context> context =
6226       Context::New(v8::Isolate::GetCurrent(), &extensions);
6227   Context::Scope lock(context);
6228   v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
6229   CHECK_EQ(result, v8::Integer::New(4));
6230 }
6231
6232
6233 static const char* kEmbeddedExtensionSource =
6234     "function Ret54321(){return 54321;}~~@@$"
6235     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6236 static const int kEmbeddedExtensionSourceValidLen = 34;
6237
6238
6239 THREADED_TEST(ExtensionMissingSourceLength) {
6240   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6241   v8::RegisterExtension(new Extension("srclentest_fail",
6242                                       kEmbeddedExtensionSource));
6243   const char* extension_names[] = { "srclentest_fail" };
6244   v8::ExtensionConfiguration extensions(1, extension_names);
6245   v8::Handle<Context> context =
6246       Context::New(v8::Isolate::GetCurrent(), &extensions);
6247   CHECK_EQ(0, *context);
6248 }
6249
6250
6251 THREADED_TEST(ExtensionWithSourceLength) {
6252   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6253        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
6254     v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6255     i::ScopedVector<char> extension_name(32);
6256     i::OS::SNPrintF(extension_name, "ext #%d", source_len);
6257     v8::RegisterExtension(new Extension(extension_name.start(),
6258                                         kEmbeddedExtensionSource, 0, 0,
6259                                         source_len));
6260     const char* extension_names[1] = { extension_name.start() };
6261     v8::ExtensionConfiguration extensions(1, extension_names);
6262     v8::Handle<Context> context =
6263       Context::New(v8::Isolate::GetCurrent(), &extensions);
6264     if (source_len == kEmbeddedExtensionSourceValidLen) {
6265       Context::Scope lock(context);
6266       v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
6267       CHECK_EQ(v8::Integer::New(54321), result);
6268     } else {
6269       // Anything but exactly the right length should fail to compile.
6270       CHECK_EQ(0, *context);
6271     }
6272   }
6273 }
6274
6275
6276 static const char* kEvalExtensionSource1 =
6277   "function UseEval1() {"
6278   "  var x = 42;"
6279   "  return eval('x');"
6280   "}";
6281
6282
6283 static const char* kEvalExtensionSource2 =
6284   "(function() {"
6285   "  var x = 42;"
6286   "  function e() {"
6287   "    return eval('x');"
6288   "  }"
6289   "  this.UseEval2 = e;"
6290   "})()";
6291
6292
6293 THREADED_TEST(UseEvalFromExtension) {
6294   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6295   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6296   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6297   const char* extension_names[] = { "evaltest1", "evaltest2" };
6298   v8::ExtensionConfiguration extensions(2, extension_names);
6299   v8::Handle<Context> context =
6300       Context::New(v8::Isolate::GetCurrent(), &extensions);
6301   Context::Scope lock(context);
6302   v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
6303   CHECK_EQ(result, v8::Integer::New(42));
6304   result = Script::Compile(v8_str("UseEval2()"))->Run();
6305   CHECK_EQ(result, v8::Integer::New(42));
6306 }
6307
6308
6309 static const char* kWithExtensionSource1 =
6310   "function UseWith1() {"
6311   "  var x = 42;"
6312   "  with({x:87}) { return x; }"
6313   "}";
6314
6315
6316
6317 static const char* kWithExtensionSource2 =
6318   "(function() {"
6319   "  var x = 42;"
6320   "  function e() {"
6321   "    with ({x:87}) { return x; }"
6322   "  }"
6323   "  this.UseWith2 = e;"
6324   "})()";
6325
6326
6327 THREADED_TEST(UseWithFromExtension) {
6328   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6329   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6330   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6331   const char* extension_names[] = { "withtest1", "withtest2" };
6332   v8::ExtensionConfiguration extensions(2, extension_names);
6333   v8::Handle<Context> context =
6334       Context::New(v8::Isolate::GetCurrent(), &extensions);
6335   Context::Scope lock(context);
6336   v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
6337   CHECK_EQ(result, v8::Integer::New(87));
6338   result = Script::Compile(v8_str("UseWith2()"))->Run();
6339   CHECK_EQ(result, v8::Integer::New(87));
6340 }
6341
6342
6343 THREADED_TEST(AutoExtensions) {
6344   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6345   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6346   extension->set_auto_enable(true);
6347   v8::RegisterExtension(extension);
6348   v8::Handle<Context> context =
6349       Context::New(v8::Isolate::GetCurrent());
6350   Context::Scope lock(context);
6351   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
6352   CHECK_EQ(result, v8::Integer::New(4));
6353 }
6354
6355
6356 static const char* kSyntaxErrorInExtensionSource =
6357     "[";
6358
6359
6360 // Test that a syntax error in an extension does not cause a fatal
6361 // error but results in an empty context.
6362 THREADED_TEST(SyntaxErrorExtensions) {
6363   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6364   v8::RegisterExtension(new Extension("syntaxerror",
6365                                       kSyntaxErrorInExtensionSource));
6366   const char* extension_names[] = { "syntaxerror" };
6367   v8::ExtensionConfiguration extensions(1, extension_names);
6368   v8::Handle<Context> context =
6369       Context::New(v8::Isolate::GetCurrent(), &extensions);
6370   CHECK(context.IsEmpty());
6371 }
6372
6373
6374 static const char* kExceptionInExtensionSource =
6375     "throw 42";
6376
6377
6378 // Test that an exception when installing an extension does not cause
6379 // a fatal error but results in an empty context.
6380 THREADED_TEST(ExceptionExtensions) {
6381   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6382   v8::RegisterExtension(new Extension("exception",
6383                                       kExceptionInExtensionSource));
6384   const char* extension_names[] = { "exception" };
6385   v8::ExtensionConfiguration extensions(1, extension_names);
6386   v8::Handle<Context> context =
6387       Context::New(v8::Isolate::GetCurrent(), &extensions);
6388   CHECK(context.IsEmpty());
6389 }
6390
6391
6392 static const char* kNativeCallInExtensionSource =
6393     "function call_runtime_last_index_of(x) {"
6394     "  return %StringLastIndexOf(x, 'bob', 10);"
6395     "}";
6396
6397
6398 static const char* kNativeCallTest =
6399     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6400
6401 // Test that a native runtime calls are supported in extensions.
6402 THREADED_TEST(NativeCallInExtensions) {
6403   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6404   v8::RegisterExtension(new Extension("nativecall",
6405                                       kNativeCallInExtensionSource));
6406   const char* extension_names[] = { "nativecall" };
6407   v8::ExtensionConfiguration extensions(1, extension_names);
6408   v8::Handle<Context> context =
6409       Context::New(v8::Isolate::GetCurrent(), &extensions);
6410   Context::Scope lock(context);
6411   v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
6412   CHECK_EQ(result, v8::Integer::New(3));
6413 }
6414
6415
6416 class NativeFunctionExtension : public Extension {
6417  public:
6418   NativeFunctionExtension(const char* name,
6419                           const char* source,
6420                           v8::FunctionCallback fun = &Echo)
6421       : Extension(name, source),
6422         function_(fun) { }
6423
6424   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
6425       v8::Handle<v8::String> name) {
6426     return v8::FunctionTemplate::New(function_);
6427   }
6428
6429   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6430     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
6431   }
6432  private:
6433   v8::FunctionCallback function_;
6434 };
6435
6436
6437 THREADED_TEST(NativeFunctionDeclaration) {
6438   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6439   const char* name = "nativedecl";
6440   v8::RegisterExtension(new NativeFunctionExtension(name,
6441                                                     "native function foo();"));
6442   const char* extension_names[] = { name };
6443   v8::ExtensionConfiguration extensions(1, extension_names);
6444   v8::Handle<Context> context =
6445       Context::New(v8::Isolate::GetCurrent(), &extensions);
6446   Context::Scope lock(context);
6447   v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
6448   CHECK_EQ(result, v8::Integer::New(42));
6449 }
6450
6451
6452 THREADED_TEST(NativeFunctionDeclarationError) {
6453   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6454   const char* name = "nativedeclerr";
6455   // Syntax error in extension code.
6456   v8::RegisterExtension(new NativeFunctionExtension(name,
6457                                                     "native\nfunction foo();"));
6458   const char* extension_names[] = { name };
6459   v8::ExtensionConfiguration extensions(1, extension_names);
6460   v8::Handle<Context> context =
6461       Context::New(v8::Isolate::GetCurrent(), &extensions);
6462   CHECK(context.IsEmpty());
6463 }
6464
6465
6466 THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
6467   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6468   const char* name = "nativedeclerresc";
6469   // Syntax error in extension code - escape code in "native" means that
6470   // it's not treated as a keyword.
6471   v8::RegisterExtension(new NativeFunctionExtension(
6472       name,
6473       "nativ\\u0065 function foo();"));
6474   const char* extension_names[] = { name };
6475   v8::ExtensionConfiguration extensions(1, extension_names);
6476   v8::Handle<Context> context =
6477       Context::New(v8::Isolate::GetCurrent(), &extensions);
6478   CHECK(context.IsEmpty());
6479 }
6480
6481
6482 static void CheckDependencies(const char* name, const char* expected) {
6483   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6484   v8::ExtensionConfiguration config(1, &name);
6485   LocalContext context(&config);
6486   CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
6487 }
6488
6489
6490 /*
6491  * Configuration:
6492  *
6493  *     /-- B <--\
6494  * A <-          -- D <-- E
6495  *     \-- C <--/
6496  */
6497 THREADED_TEST(ExtensionDependency) {
6498   static const char* kEDeps[] = { "D" };
6499   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6500   static const char* kDDeps[] = { "B", "C" };
6501   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6502   static const char* kBCDeps[] = { "A" };
6503   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6504   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6505   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6506   CheckDependencies("A", "undefinedA");
6507   CheckDependencies("B", "undefinedAB");
6508   CheckDependencies("C", "undefinedAC");
6509   CheckDependencies("D", "undefinedABCD");
6510   CheckDependencies("E", "undefinedABCDE");
6511   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6512   static const char* exts[2] = { "C", "E" };
6513   v8::ExtensionConfiguration config(2, exts);
6514   LocalContext context(&config);
6515   CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
6516 }
6517
6518
6519 static const char* kExtensionTestScript =
6520   "native function A();"
6521   "native function B();"
6522   "native function C();"
6523   "function Foo(i) {"
6524   "  if (i == 0) return A();"
6525   "  if (i == 1) return B();"
6526   "  if (i == 2) return C();"
6527   "}";
6528
6529
6530 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
6531   ApiTestFuzzer::Fuzz();
6532   if (args.IsConstructCall()) {
6533     args.This()->Set(v8_str("data"), args.Data());
6534     args.GetReturnValue().SetNull();
6535     return;
6536   }
6537   args.GetReturnValue().Set(args.Data());
6538 }
6539
6540
6541 class FunctionExtension : public Extension {
6542  public:
6543   FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
6544   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
6545       v8::Handle<String> name);
6546 };
6547
6548
6549 static int lookup_count = 0;
6550 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
6551       v8::Handle<String> name) {
6552   lookup_count++;
6553   if (name->Equals(v8_str("A"))) {
6554     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
6555   } else if (name->Equals(v8_str("B"))) {
6556     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
6557   } else if (name->Equals(v8_str("C"))) {
6558     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
6559   } else {
6560     return v8::Handle<v8::FunctionTemplate>();
6561   }
6562 }
6563
6564
6565 THREADED_TEST(FunctionLookup) {
6566   v8::RegisterExtension(new FunctionExtension());
6567   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6568   static const char* exts[1] = { "functiontest" };
6569   v8::ExtensionConfiguration config(1, exts);
6570   LocalContext context(&config);
6571   CHECK_EQ(3, lookup_count);
6572   CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
6573   CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
6574   CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
6575 }
6576
6577
6578 THREADED_TEST(NativeFunctionConstructCall) {
6579   v8::RegisterExtension(new FunctionExtension());
6580   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6581   static const char* exts[1] = { "functiontest" };
6582   v8::ExtensionConfiguration config(1, exts);
6583   LocalContext context(&config);
6584   for (int i = 0; i < 10; i++) {
6585     // Run a few times to ensure that allocation of objects doesn't
6586     // change behavior of a constructor function.
6587     CHECK_EQ(v8::Integer::New(8),
6588              Script::Compile(v8_str("(new A()).data"))->Run());
6589     CHECK_EQ(v8::Integer::New(7),
6590              Script::Compile(v8_str("(new B()).data"))->Run());
6591     CHECK_EQ(v8::Integer::New(6),
6592              Script::Compile(v8_str("(new C()).data"))->Run());
6593   }
6594 }
6595
6596
6597 static const char* last_location;
6598 static const char* last_message;
6599 void StoringErrorCallback(const char* location, const char* message) {
6600   if (last_location == NULL) {
6601     last_location = location;
6602     last_message = message;
6603   }
6604 }
6605
6606
6607 // ErrorReporting creates a circular extensions configuration and
6608 // tests that the fatal error handler gets called.  This renders V8
6609 // unusable and therefore this test cannot be run in parallel.
6610 TEST(ErrorReporting) {
6611   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
6612   static const char* aDeps[] = { "B" };
6613   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
6614   static const char* bDeps[] = { "A" };
6615   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
6616   last_location = NULL;
6617   v8::ExtensionConfiguration config(1, bDeps);
6618   v8::Handle<Context> context =
6619       Context::New(v8::Isolate::GetCurrent(), &config);
6620   CHECK(context.IsEmpty());
6621   CHECK_NE(last_location, NULL);
6622 }
6623
6624
6625 static const char* js_code_causing_huge_string_flattening =
6626     "var str = 'X';"
6627     "for (var i = 0; i < 30; i++) {"
6628     "  str = str + str;"
6629     "}"
6630     "str.match(/X/);";
6631
6632
6633 void OOMCallback(const char* location, const char* message) {
6634   exit(0);
6635 }
6636
6637
6638 TEST(RegexpOutOfMemory) {
6639   // Execute a script that causes out of memory when flattening a string.
6640   v8::HandleScope scope(v8::Isolate::GetCurrent());
6641   v8::V8::SetFatalErrorHandler(OOMCallback);
6642   LocalContext context;
6643   Local<Script> script =
6644       Script::Compile(String::New(js_code_causing_huge_string_flattening));
6645   last_location = NULL;
6646   script->Run();
6647
6648   CHECK(false);  // Should not return.
6649 }
6650
6651
6652 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
6653                                              v8::Handle<Value> data) {
6654   CHECK(message->GetScriptResourceName()->IsUndefined());
6655   CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
6656   message->GetLineNumber();
6657   message->GetSourceLine();
6658 }
6659
6660
6661 THREADED_TEST(ErrorWithMissingScriptInfo) {
6662   LocalContext context;
6663   v8::HandleScope scope(context->GetIsolate());
6664   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
6665   Script::Compile(v8_str("throw Error()"))->Run();
6666   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
6667 }
6668
6669
6670 int global_index = 0;
6671
6672 class Snorkel {
6673  public:
6674   Snorkel() { index_ = global_index++; }
6675   int index_;
6676 };
6677
6678 class Whammy {
6679  public:
6680   explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
6681   ~Whammy() { script_.Dispose(); }
6682   v8::Handle<Script> getScript() {
6683     if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
6684     return Local<Script>::New(isolate_, script_);
6685   }
6686
6687  public:
6688   static const int kObjectCount = 256;
6689   int cursor_;
6690   v8::Isolate* isolate_;
6691   v8::Persistent<v8::Object> objects_[kObjectCount];
6692   v8::Persistent<Script> script_;
6693 };
6694
6695 static void HandleWeakReference(v8::Isolate* isolate,
6696                                 v8::Persistent<v8::Value>* obj,
6697                                 Snorkel* snorkel) {
6698   delete snorkel;
6699   obj->ClearWeak();
6700 }
6701
6702 void WhammyPropertyGetter(Local<String> name,
6703                           const v8::PropertyCallbackInfo<v8::Value>& info) {
6704   Whammy* whammy =
6705     static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
6706
6707   v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_];
6708
6709   v8::Handle<v8::Object> obj = v8::Object::New();
6710   if (!prev.IsEmpty()) {
6711     v8::Local<v8::Object>::New(info.GetIsolate(), prev)
6712         ->Set(v8_str("next"), obj);
6713     prev.MakeWeak<Value, Snorkel>(new Snorkel(), &HandleWeakReference);
6714     whammy->objects_[whammy->cursor_].Clear();
6715   }
6716   whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj);
6717   whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
6718   info.GetReturnValue().Set(whammy->getScript()->Run());
6719 }
6720
6721
6722 THREADED_TEST(WeakReference) {
6723   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
6724   v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
6725   Whammy* whammy = new Whammy(v8::Isolate::GetCurrent());
6726   templ->SetNamedPropertyHandler(WhammyPropertyGetter,
6727                                  0, 0, 0, 0,
6728                                  v8::External::New(whammy));
6729   const char* extension_list[] = { "v8/gc" };
6730   v8::ExtensionConfiguration extensions(1, extension_list);
6731   v8::Handle<Context> context =
6732       Context::New(v8::Isolate::GetCurrent(), &extensions);
6733   Context::Scope context_scope(context);
6734
6735   v8::Handle<v8::Object> interceptor = templ->NewInstance();
6736   context->Global()->Set(v8_str("whammy"), interceptor);
6737   const char* code =
6738       "var last;"
6739       "for (var i = 0; i < 10000; i++) {"
6740       "  var obj = whammy.length;"
6741       "  if (last) last.next = obj;"
6742       "  last = obj;"
6743       "}"
6744       "gc();"
6745       "4";
6746   v8::Handle<Value> result = CompileRun(code);
6747   CHECK_EQ(4.0, result->NumberValue());
6748   delete whammy;
6749 }
6750
6751
6752 static void DisposeAndSetFlag(v8::Isolate* isolate,
6753                               v8::Persistent<v8::Object>* obj,
6754                               bool* data) {
6755   obj->Dispose();
6756   *(data) = true;
6757 }
6758
6759
6760 THREADED_TEST(IndependentWeakHandle) {
6761   v8::Isolate* iso = v8::Isolate::GetCurrent();
6762   v8::HandleScope scope(iso);
6763   v8::Handle<Context> context = Context::New(iso);
6764   Context::Scope context_scope(context);
6765
6766   v8::Persistent<v8::Object> object_a, object_b;
6767
6768   {
6769     v8::HandleScope handle_scope(iso);
6770     object_a.Reset(iso, v8::Object::New());
6771     object_b.Reset(iso, v8::Object::New());
6772   }
6773
6774   bool object_a_disposed = false;
6775   bool object_b_disposed = false;
6776   object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag);
6777   object_b.MakeWeak(&object_b_disposed, &DisposeAndSetFlag);
6778   CHECK(!object_b.IsIndependent());
6779   object_a.MarkIndependent();
6780   object_b.MarkIndependent();
6781   CHECK(object_b.IsIndependent());
6782   HEAP->PerformScavenge();
6783   CHECK(object_a_disposed);
6784   CHECK(object_b_disposed);
6785 }
6786
6787
6788 static void InvokeScavenge() {
6789   HEAP->PerformScavenge();
6790 }
6791
6792
6793 static void InvokeMarkSweep() {
6794   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
6795 }
6796
6797
6798 static void ForceScavenge(v8::Isolate* isolate,
6799                           v8::Persistent<v8::Object>* obj,
6800                           bool* data) {
6801   obj->Dispose();
6802   *(data) = true;
6803   InvokeScavenge();
6804 }
6805
6806
6807 static void ForceMarkSweep(v8::Isolate* isolate,
6808                            v8::Persistent<v8::Object>* obj,
6809                            bool* data) {
6810   obj->Dispose();
6811   *(data) = true;
6812   InvokeMarkSweep();
6813 }
6814
6815
6816 THREADED_TEST(GCFromWeakCallbacks) {
6817   v8::Isolate* isolate = v8::Isolate::GetCurrent();
6818   v8::HandleScope scope(isolate);
6819   v8::Handle<Context> context = Context::New(isolate);
6820   Context::Scope context_scope(context);
6821
6822   static const int kNumberOfGCTypes = 2;
6823   typedef v8::WeakReferenceCallbacks<v8::Object, bool>::Revivable Callback;
6824   Callback gc_forcing_callback[kNumberOfGCTypes] =
6825       {&ForceScavenge, &ForceMarkSweep};
6826
6827   typedef void (*GCInvoker)();
6828   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
6829
6830   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
6831     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
6832       v8::Persistent<v8::Object> object;
6833       {
6834         v8::HandleScope handle_scope(isolate);
6835         object.Reset(isolate, v8::Object::New());
6836       }
6837       bool disposed = false;
6838       object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]);
6839       object.MarkIndependent();
6840       invoke_gc[outer_gc]();
6841       CHECK(disposed);
6842     }
6843   }
6844 }
6845
6846
6847 static void RevivingCallback(v8::Isolate* isolate,
6848                              v8::Persistent<v8::Object>* obj,
6849                              bool* data) {
6850   obj->ClearWeak();
6851   *(data) = true;
6852 }
6853
6854
6855 THREADED_TEST(IndependentHandleRevival) {
6856   v8::Isolate* isolate = v8::Isolate::GetCurrent();
6857   v8::HandleScope scope(isolate);
6858   v8::Handle<Context> context = Context::New(isolate);
6859   Context::Scope context_scope(context);
6860
6861   v8::Persistent<v8::Object> object;
6862   {
6863     v8::HandleScope handle_scope(isolate);
6864     v8::Local<v8::Object> o = v8::Object::New();
6865     object.Reset(isolate, o);
6866     o->Set(v8_str("x"), v8::Integer::New(1));
6867     v8::Local<String> y_str = v8_str("y");
6868     o->Set(y_str, y_str);
6869   }
6870   bool revived = false;
6871   object.MakeWeak(&revived, &RevivingCallback);
6872   object.MarkIndependent();
6873   HEAP->PerformScavenge();
6874   CHECK(revived);
6875   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
6876   {
6877     v8::HandleScope handle_scope(isolate);
6878     v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, object);
6879     v8::Local<String> y_str = v8_str("y");
6880     CHECK_EQ(v8::Integer::New(1), o->Get(v8_str("x")));
6881     CHECK(o->Get(y_str)->Equals(y_str));
6882   }
6883 }
6884
6885
6886 v8::Handle<Function> args_fun;
6887
6888
6889 static void ArgumentsTestCallback(
6890     const v8::FunctionCallbackInfo<v8::Value>& args) {
6891   ApiTestFuzzer::Fuzz();
6892   CHECK_EQ(args_fun, args.Callee());
6893   CHECK_EQ(3, args.Length());
6894   CHECK_EQ(v8::Integer::New(1), args[0]);
6895   CHECK_EQ(v8::Integer::New(2), args[1]);
6896   CHECK_EQ(v8::Integer::New(3), args[2]);
6897   CHECK_EQ(v8::Undefined(), args[3]);
6898   v8::HandleScope scope(args.GetIsolate());
6899   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
6900 }
6901
6902
6903 THREADED_TEST(Arguments) {
6904   v8::HandleScope scope(v8::Isolate::GetCurrent());
6905   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
6906   global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
6907   LocalContext context(NULL, global);
6908   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
6909   v8_compile("f(1, 2, 3)")->Run();
6910 }
6911
6912
6913 static void NoBlockGetterX(Local<String> name,
6914                            const v8::PropertyCallbackInfo<v8::Value>&) {
6915 }
6916
6917
6918 static void NoBlockGetterI(uint32_t index,
6919                            const v8::PropertyCallbackInfo<v8::Value>&) {
6920 }
6921
6922
6923 static void PDeleter(Local<String> name,
6924                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
6925   if (!name->Equals(v8_str("foo"))) {
6926     return;  // not intercepted
6927   }
6928
6929   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
6930 }
6931
6932
6933 static void IDeleter(uint32_t index,
6934                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
6935   if (index != 2) {
6936     return;  // not intercepted
6937   }
6938
6939   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
6940 }
6941
6942
6943 THREADED_TEST(Deleter) {
6944   v8::HandleScope scope(v8::Isolate::GetCurrent());
6945   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
6946   obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
6947   obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
6948   LocalContext context;
6949   context->Global()->Set(v8_str("k"), obj->NewInstance());
6950   CompileRun(
6951     "k.foo = 'foo';"
6952     "k.bar = 'bar';"
6953     "k[2] = 2;"
6954     "k[4] = 4;");
6955   CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
6956   CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
6957
6958   CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
6959   CHECK(v8_compile("k.bar")->Run()->IsUndefined());
6960
6961   CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
6962   CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
6963
6964   CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
6965   CHECK(v8_compile("k[4]")->Run()->IsUndefined());
6966 }
6967
6968
6969 static void GetK(Local<String> name,
6970                  const v8::PropertyCallbackInfo<v8::Value>& info) {
6971   ApiTestFuzzer::Fuzz();
6972   if (name->Equals(v8_str("foo")) ||
6973       name->Equals(v8_str("bar")) ||
6974       name->Equals(v8_str("baz"))) {
6975     info.GetReturnValue().SetUndefined();
6976   }
6977 }
6978
6979
6980 static void IndexedGetK(uint32_t index,
6981                         const v8::PropertyCallbackInfo<v8::Value>& info) {
6982   ApiTestFuzzer::Fuzz();
6983   if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
6984 }
6985
6986
6987 static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
6988   ApiTestFuzzer::Fuzz();
6989   v8::Handle<v8::Array> result = v8::Array::New(3);
6990   result->Set(v8::Integer::New(0), v8_str("foo"));
6991   result->Set(v8::Integer::New(1), v8_str("bar"));
6992   result->Set(v8::Integer::New(2), v8_str("baz"));
6993   info.GetReturnValue().Set(result);
6994 }
6995
6996
6997 static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
6998   ApiTestFuzzer::Fuzz();
6999   v8::Handle<v8::Array> result = v8::Array::New(2);
7000   result->Set(v8::Integer::New(0), v8_str("0"));
7001   result->Set(v8::Integer::New(1), v8_str("1"));
7002   info.GetReturnValue().Set(result);
7003 }
7004
7005
7006 THREADED_TEST(Enumerators) {
7007   v8::HandleScope scope(v8::Isolate::GetCurrent());
7008   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7009   obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
7010   obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
7011   LocalContext context;
7012   context->Global()->Set(v8_str("k"), obj->NewInstance());
7013   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
7014     "k[10] = 0;"
7015     "k.a = 0;"
7016     "k[5] = 0;"
7017     "k.b = 0;"
7018     "k[4294967295] = 0;"
7019     "k.c = 0;"
7020     "k[4294967296] = 0;"
7021     "k.d = 0;"
7022     "k[140000] = 0;"
7023     "k.e = 0;"
7024     "k[30000000000] = 0;"
7025     "k.f = 0;"
7026     "var result = [];"
7027     "for (var prop in k) {"
7028     "  result.push(prop);"
7029     "}"
7030     "result"));
7031   // Check that we get all the property names returned including the
7032   // ones from the enumerators in the right order: indexed properties
7033   // in numerical order, indexed interceptor properties, named
7034   // properties in insertion order, named interceptor properties.
7035   // This order is not mandated by the spec, so this test is just
7036   // documenting our behavior.
7037   CHECK_EQ(17, result->Length());
7038   // Indexed properties in numerical order.
7039   CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
7040   CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
7041   CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
7042   CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
7043   // Indexed interceptor properties in the order they are returned
7044   // from the enumerator interceptor.
7045   CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
7046   CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
7047   // Named properties in insertion order.
7048   CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
7049   CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
7050   CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
7051   CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
7052   CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
7053   CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
7054   CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
7055   CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
7056   // Named interceptor properties.
7057   CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
7058   CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
7059   CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
7060 }
7061
7062
7063 int p_getter_count;
7064 int p_getter_count2;
7065
7066
7067 static void PGetter(Local<String> name,
7068                     const v8::PropertyCallbackInfo<v8::Value>& info) {
7069   ApiTestFuzzer::Fuzz();
7070   p_getter_count++;
7071   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
7072   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7073   if (name->Equals(v8_str("p1"))) {
7074     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7075   } else if (name->Equals(v8_str("p2"))) {
7076     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7077   } else if (name->Equals(v8_str("p3"))) {
7078     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7079   } else if (name->Equals(v8_str("p4"))) {
7080     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7081   }
7082 }
7083
7084
7085 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
7086   ApiTestFuzzer::Fuzz();
7087   LocalContext context;
7088   context->Global()->Set(v8_str("o1"), obj->NewInstance());
7089   CompileRun(
7090     "o1.__proto__ = { };"
7091     "var o2 = { __proto__: o1 };"
7092     "var o3 = { __proto__: o2 };"
7093     "var o4 = { __proto__: o3 };"
7094     "for (var i = 0; i < 10; i++) o4.p4;"
7095     "for (var i = 0; i < 10; i++) o3.p3;"
7096     "for (var i = 0; i < 10; i++) o2.p2;"
7097     "for (var i = 0; i < 10; i++) o1.p1;");
7098 }
7099
7100
7101 static void PGetter2(Local<String> name,
7102                      const v8::PropertyCallbackInfo<v8::Value>& info) {
7103   ApiTestFuzzer::Fuzz();
7104   p_getter_count2++;
7105   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
7106   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7107   if (name->Equals(v8_str("p1"))) {
7108     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7109   } else if (name->Equals(v8_str("p2"))) {
7110     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7111   } else if (name->Equals(v8_str("p3"))) {
7112     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7113   } else if (name->Equals(v8_str("p4"))) {
7114     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7115   }
7116 }
7117
7118
7119 THREADED_TEST(GetterHolders) {
7120   v8::HandleScope scope(v8::Isolate::GetCurrent());
7121   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7122   obj->SetAccessor(v8_str("p1"), PGetter);
7123   obj->SetAccessor(v8_str("p2"), PGetter);
7124   obj->SetAccessor(v8_str("p3"), PGetter);
7125   obj->SetAccessor(v8_str("p4"), PGetter);
7126   p_getter_count = 0;
7127   RunHolderTest(obj);
7128   CHECK_EQ(40, p_getter_count);
7129 }
7130
7131
7132 THREADED_TEST(PreInterceptorHolders) {
7133   v8::HandleScope scope(v8::Isolate::GetCurrent());
7134   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7135   obj->SetNamedPropertyHandler(PGetter2);
7136   p_getter_count2 = 0;
7137   RunHolderTest(obj);
7138   CHECK_EQ(40, p_getter_count2);
7139 }
7140
7141
7142 THREADED_TEST(ObjectInstantiation) {
7143   v8::HandleScope scope(v8::Isolate::GetCurrent());
7144   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
7145   templ->SetAccessor(v8_str("t"), PGetter2);
7146   LocalContext context;
7147   context->Global()->Set(v8_str("o"), templ->NewInstance());
7148   for (int i = 0; i < 100; i++) {
7149     v8::HandleScope inner_scope(v8::Isolate::GetCurrent());
7150     v8::Handle<v8::Object> obj = templ->NewInstance();
7151     CHECK_NE(obj, context->Global()->Get(v8_str("o")));
7152     context->Global()->Set(v8_str("o2"), obj);
7153     v8::Handle<Value> value =
7154         Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
7155     CHECK_EQ(v8::True(), value);
7156     context->Global()->Set(v8_str("o"), obj);
7157   }
7158 }
7159
7160
7161 static int StrCmp16(uint16_t* a, uint16_t* b) {
7162   while (true) {
7163     if (*a == 0 && *b == 0) return 0;
7164     if (*a != *b) return 0 + *a - *b;
7165     a++;
7166     b++;
7167   }
7168 }
7169
7170
7171 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7172   while (true) {
7173     if (n-- == 0) return 0;
7174     if (*a == 0 && *b == 0) return 0;
7175     if (*a != *b) return 0 + *a - *b;
7176     a++;
7177     b++;
7178   }
7179 }
7180
7181
7182 int GetUtf8Length(Handle<String> str) {
7183   int len = str->Utf8Length();
7184   if (len < 0) {
7185     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
7186     i::FlattenString(istr);
7187     len = str->Utf8Length();
7188   }
7189   return len;
7190 }
7191
7192
7193 THREADED_TEST(StringWrite) {
7194   LocalContext context;
7195   v8::HandleScope scope(context->GetIsolate());
7196   v8::Handle<String> str = v8_str("abcde");
7197   // abc<Icelandic eth><Unicode snowman>.
7198   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
7199   v8::Handle<String> str3 = v8::String::New("abc\0def", 7);
7200   const int kStride = 4;  // Must match stride in for loops in JS below.
7201   CompileRun(
7202       "var left = '';"
7203       "for (var i = 0; i < 0xd800; i += 4) {"
7204       "  left = left + String.fromCharCode(i);"
7205       "}");
7206   CompileRun(
7207       "var right = '';"
7208       "for (var i = 0; i < 0xd800; i += 4) {"
7209       "  right = String.fromCharCode(i) + right;"
7210       "}");
7211   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
7212   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7213   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
7214
7215   CHECK_EQ(5, str2->Length());
7216   CHECK_EQ(0xd800 / kStride, left_tree->Length());
7217   CHECK_EQ(0xd800 / kStride, right_tree->Length());
7218
7219   char buf[100];
7220   char utf8buf[0xd800 * 3];
7221   uint16_t wbuf[100];
7222   int len;
7223   int charlen;
7224
7225   memset(utf8buf, 0x1, 1000);
7226   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7227   CHECK_EQ(9, len);
7228   CHECK_EQ(5, charlen);
7229   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7230
7231   memset(utf8buf, 0x1, 1000);
7232   len = str2->WriteUtf8(utf8buf, 8, &charlen);
7233   CHECK_EQ(8, len);
7234   CHECK_EQ(5, charlen);
7235   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
7236
7237   memset(utf8buf, 0x1, 1000);
7238   len = str2->WriteUtf8(utf8buf, 7, &charlen);
7239   CHECK_EQ(5, len);
7240   CHECK_EQ(4, charlen);
7241   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7242
7243   memset(utf8buf, 0x1, 1000);
7244   len = str2->WriteUtf8(utf8buf, 6, &charlen);
7245   CHECK_EQ(5, len);
7246   CHECK_EQ(4, charlen);
7247   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7248
7249   memset(utf8buf, 0x1, 1000);
7250   len = str2->WriteUtf8(utf8buf, 5, &charlen);
7251   CHECK_EQ(5, len);
7252   CHECK_EQ(4, charlen);
7253   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7254
7255   memset(utf8buf, 0x1, 1000);
7256   len = str2->WriteUtf8(utf8buf, 4, &charlen);
7257   CHECK_EQ(3, len);
7258   CHECK_EQ(3, charlen);
7259   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7260
7261   memset(utf8buf, 0x1, 1000);
7262   len = str2->WriteUtf8(utf8buf, 3, &charlen);
7263   CHECK_EQ(3, len);
7264   CHECK_EQ(3, charlen);
7265   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7266
7267   memset(utf8buf, 0x1, 1000);
7268   len = str2->WriteUtf8(utf8buf, 2, &charlen);
7269   CHECK_EQ(2, len);
7270   CHECK_EQ(2, charlen);
7271   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
7272
7273   memset(utf8buf, 0x1, sizeof(utf8buf));
7274   len = GetUtf8Length(left_tree);
7275   int utf8_expected =
7276       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7277   CHECK_EQ(utf8_expected, len);
7278   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7279   CHECK_EQ(utf8_expected, len);
7280   CHECK_EQ(0xd800 / kStride, charlen);
7281   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7282   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7283   CHECK_EQ(0xc0 - kStride,
7284            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7285   CHECK_EQ(1, utf8buf[utf8_expected]);
7286
7287   memset(utf8buf, 0x1, sizeof(utf8buf));
7288   len = GetUtf8Length(right_tree);
7289   CHECK_EQ(utf8_expected, len);
7290   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7291   CHECK_EQ(utf8_expected, len);
7292   CHECK_EQ(0xd800 / kStride, charlen);
7293   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7294   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7295   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7296   CHECK_EQ(1, utf8buf[utf8_expected]);
7297
7298   memset(buf, 0x1, sizeof(buf));
7299   memset(wbuf, 0x1, sizeof(wbuf));
7300   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7301   CHECK_EQ(5, len);
7302   len = str->Write(wbuf);
7303   CHECK_EQ(5, len);
7304   CHECK_EQ(0, strcmp("abcde", buf));
7305   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7306   CHECK_EQ(0, StrCmp16(answer1, wbuf));
7307
7308   memset(buf, 0x1, sizeof(buf));
7309   memset(wbuf, 0x1, sizeof(wbuf));
7310   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
7311   CHECK_EQ(4, len);
7312   len = str->Write(wbuf, 0, 4);
7313   CHECK_EQ(4, len);
7314   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
7315   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
7316   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
7317
7318   memset(buf, 0x1, sizeof(buf));
7319   memset(wbuf, 0x1, sizeof(wbuf));
7320   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
7321   CHECK_EQ(5, len);
7322   len = str->Write(wbuf, 0, 5);
7323   CHECK_EQ(5, len);
7324   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
7325   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
7326   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
7327
7328   memset(buf, 0x1, sizeof(buf));
7329   memset(wbuf, 0x1, sizeof(wbuf));
7330   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
7331   CHECK_EQ(5, len);
7332   len = str->Write(wbuf, 0, 6);
7333   CHECK_EQ(5, len);
7334   CHECK_EQ(0, strcmp("abcde", buf));
7335   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7336   CHECK_EQ(0, StrCmp16(answer4, wbuf));
7337
7338   memset(buf, 0x1, sizeof(buf));
7339   memset(wbuf, 0x1, sizeof(wbuf));
7340   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
7341   CHECK_EQ(1, len);
7342   len = str->Write(wbuf, 4, -1);
7343   CHECK_EQ(1, len);
7344   CHECK_EQ(0, strcmp("e", buf));
7345   uint16_t answer5[] = {'e', '\0'};
7346   CHECK_EQ(0, StrCmp16(answer5, wbuf));
7347
7348   memset(buf, 0x1, sizeof(buf));
7349   memset(wbuf, 0x1, sizeof(wbuf));
7350   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
7351   CHECK_EQ(1, len);
7352   len = str->Write(wbuf, 4, 6);
7353   CHECK_EQ(1, len);
7354   CHECK_EQ(0, strcmp("e", buf));
7355   CHECK_EQ(0, StrCmp16(answer5, wbuf));
7356
7357   memset(buf, 0x1, sizeof(buf));
7358   memset(wbuf, 0x1, sizeof(wbuf));
7359   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
7360   CHECK_EQ(1, len);
7361   len = str->Write(wbuf, 4, 1);
7362   CHECK_EQ(1, len);
7363   CHECK_EQ(0, strncmp("e\1", buf, 2));
7364   uint16_t answer6[] = {'e', 0x101};
7365   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
7366
7367   memset(buf, 0x1, sizeof(buf));
7368   memset(wbuf, 0x1, sizeof(wbuf));
7369   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
7370   CHECK_EQ(1, len);
7371   len = str->Write(wbuf, 3, 1);
7372   CHECK_EQ(1, len);
7373   CHECK_EQ(0, strncmp("d\1", buf, 2));
7374   uint16_t answer7[] = {'d', 0x101};
7375   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
7376
7377   memset(wbuf, 0x1, sizeof(wbuf));
7378   wbuf[5] = 'X';
7379   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7380   CHECK_EQ(5, len);
7381   CHECK_EQ('X', wbuf[5]);
7382   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7383   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7384   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7385   CHECK_NE(0, StrCmp16(answer8b, wbuf));
7386   wbuf[5] = '\0';
7387   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7388
7389   memset(buf, 0x1, sizeof(buf));
7390   buf[5] = 'X';
7391   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7392                           0,
7393                           6,
7394                           String::NO_NULL_TERMINATION);
7395   CHECK_EQ(5, len);
7396   CHECK_EQ('X', buf[5]);
7397   CHECK_EQ(0, strncmp("abcde", buf, 5));
7398   CHECK_NE(0, strcmp("abcde", buf));
7399   buf[5] = '\0';
7400   CHECK_EQ(0, strcmp("abcde", buf));
7401
7402   memset(utf8buf, 0x1, sizeof(utf8buf));
7403   utf8buf[8] = 'X';
7404   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7405                         String::NO_NULL_TERMINATION);
7406   CHECK_EQ(8, len);
7407   CHECK_EQ('X', utf8buf[8]);
7408   CHECK_EQ(5, charlen);
7409   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7410   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7411   utf8buf[8] = '\0';
7412   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7413
7414   memset(utf8buf, 0x1, sizeof(utf8buf));
7415   utf8buf[5] = 'X';
7416   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7417                         String::NO_NULL_TERMINATION);
7418   CHECK_EQ(5, len);
7419   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
7420   CHECK_EQ(5, charlen);
7421   utf8buf[5] = '\0';
7422   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7423
7424   memset(buf, 0x1, sizeof(buf));
7425   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7426   CHECK_EQ(7, len);
7427   CHECK_EQ(0, strcmp("abc", buf));
7428   CHECK_EQ(0, buf[3]);
7429   CHECK_EQ(0, strcmp("def", buf + 4));
7430
7431   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
7432   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7433   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
7434 }
7435
7436
7437 static void Utf16Helper(
7438     LocalContext& context,
7439     const char* name,
7440     const char* lengths_name,
7441     int len) {
7442   Local<v8::Array> a =
7443       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7444   Local<v8::Array> alens =
7445       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7446   for (int i = 0; i < len; i++) {
7447     Local<v8::String> string =
7448       Local<v8::String>::Cast(a->Get(i));
7449     Local<v8::Number> expected_len =
7450       Local<v8::Number>::Cast(alens->Get(i));
7451     int length = GetUtf8Length(string);
7452     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7453   }
7454 }
7455
7456
7457 static uint16_t StringGet(Handle<String> str, int index) {
7458   i::Handle<i::String> istring =
7459       v8::Utils::OpenHandle(String::Cast(*str));
7460   return istring->Get(index);
7461 }
7462
7463
7464 static void WriteUtf8Helper(
7465     LocalContext& context,
7466     const char* name,
7467     const char* lengths_name,
7468     int len) {
7469   Local<v8::Array> b =
7470       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7471   Local<v8::Array> alens =
7472       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7473   char buffer[1000];
7474   char buffer2[1000];
7475   for (int i = 0; i < len; i++) {
7476     Local<v8::String> string =
7477       Local<v8::String>::Cast(b->Get(i));
7478     Local<v8::Number> expected_len =
7479       Local<v8::Number>::Cast(alens->Get(i));
7480     int utf8_length = static_cast<int>(expected_len->Value());
7481     for (int j = utf8_length + 1; j >= 0; j--) {
7482       memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
7483       memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
7484       int nchars;
7485       int utf8_written =
7486           string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
7487       int utf8_written2 =
7488           string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
7489       CHECK_GE(utf8_length + 1, utf8_written);
7490       CHECK_GE(utf8_length, utf8_written2);
7491       for (int k = 0; k < utf8_written2; k++) {
7492         CHECK_EQ(buffer[k], buffer2[k]);
7493       }
7494       CHECK(nchars * 3 >= utf8_written - 1);
7495       CHECK(nchars <= utf8_written);
7496       if (j == utf8_length + 1) {
7497         CHECK_EQ(utf8_written2, utf8_length);
7498         CHECK_EQ(utf8_written2 + 1, utf8_written);
7499       }
7500       CHECK_EQ(buffer[utf8_written], 42);
7501       if (j > utf8_length) {
7502         if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
7503         if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
7504         Handle<String> roundtrip = v8_str(buffer);
7505         CHECK(roundtrip->Equals(string));
7506       } else {
7507         if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7508       }
7509       if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7510       if (nchars >= 2) {
7511         uint16_t trail = StringGet(string, nchars - 1);
7512         uint16_t lead = StringGet(string, nchars - 2);
7513         if (((lead & 0xfc00) == 0xd800) &&
7514             ((trail & 0xfc00) == 0xdc00)) {
7515           unsigned char u1 = buffer2[utf8_written2 - 4];
7516           unsigned char u2 = buffer2[utf8_written2 - 3];
7517           unsigned char u3 = buffer2[utf8_written2 - 2];
7518           unsigned char u4 = buffer2[utf8_written2 - 1];
7519           CHECK_EQ((u1 & 0xf8), 0xf0);
7520           CHECK_EQ((u2 & 0xc0), 0x80);
7521           CHECK_EQ((u3 & 0xc0), 0x80);
7522           CHECK_EQ((u4 & 0xc0), 0x80);
7523           uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
7524           CHECK_EQ((u4 & 0x3f), (c & 0x3f));
7525           CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
7526           CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
7527           CHECK_EQ((u1 & 0x3), c >> 18);
7528         }
7529       }
7530     }
7531   }
7532 }
7533
7534
7535 THREADED_TEST(Utf16) {
7536   LocalContext context;
7537   v8::HandleScope scope(context->GetIsolate());
7538   CompileRun(
7539       "var pad = '01234567890123456789';"
7540       "var p = [];"
7541       "var plens = [20, 3, 3];"
7542       "p.push('01234567890123456789');"
7543       "var lead = 0xd800;"
7544       "var trail = 0xdc00;"
7545       "p.push(String.fromCharCode(0xd800));"
7546       "p.push(String.fromCharCode(0xdc00));"
7547       "var a = [];"
7548       "var b = [];"
7549       "var c = [];"
7550       "var alens = [];"
7551       "for (var i = 0; i < 3; i++) {"
7552       "  p[1] = String.fromCharCode(lead++);"
7553       "  for (var j = 0; j < 3; j++) {"
7554       "    p[2] = String.fromCharCode(trail++);"
7555       "    a.push(p[i] + p[j]);"
7556       "    b.push(p[i] + p[j]);"
7557       "    c.push(p[i] + p[j]);"
7558       "    alens.push(plens[i] + plens[j]);"
7559       "  }"
7560       "}"
7561       "alens[5] -= 2;"  // Here the surrogate pairs match up.
7562       "var a2 = [];"
7563       "var b2 = [];"
7564       "var c2 = [];"
7565       "var a2lens = [];"
7566       "for (var m = 0; m < 9; m++) {"
7567       "  for (var n = 0; n < 9; n++) {"
7568       "    a2.push(a[m] + a[n]);"
7569       "    b2.push(b[m] + b[n]);"
7570       "    var newc = 'x' + c[m] + c[n] + 'y';"
7571       "    c2.push(newc.substring(1, newc.length - 1));"
7572       "    var utf = alens[m] + alens[n];"  // And here.
7573            // The 'n's that start with 0xdc.. are 6-8
7574            // The 'm's that end with 0xd8.. are 1, 4 and 7
7575       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
7576       "    a2lens.push(utf);"
7577       "  }"
7578       "}");
7579   Utf16Helper(context, "a", "alens", 9);
7580   Utf16Helper(context, "a2", "a2lens", 81);
7581   WriteUtf8Helper(context, "b", "alens", 9);
7582   WriteUtf8Helper(context, "b2", "a2lens", 81);
7583   WriteUtf8Helper(context, "c2", "a2lens", 81);
7584 }
7585
7586
7587 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
7588   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
7589   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
7590   return *is1 == *is2;
7591 }
7592
7593
7594 static void SameSymbolHelper(const char* a, const char* b) {
7595   Handle<String> symbol1 = v8::String::NewSymbol(a);
7596   Handle<String> symbol2 = v8::String::NewSymbol(b);
7597   CHECK(SameSymbol(symbol1, symbol2));
7598 }
7599
7600
7601 THREADED_TEST(Utf16Symbol) {
7602   LocalContext context;
7603   v8::HandleScope scope(context->GetIsolate());
7604
7605   Handle<String> symbol1 = v8::String::NewSymbol("abc");
7606   Handle<String> symbol2 = v8::String::NewSymbol("abc");
7607   CHECK(SameSymbol(symbol1, symbol2));
7608
7609   SameSymbolHelper("\360\220\220\205",  // 4 byte encoding.
7610                    "\355\240\201\355\260\205");  // 2 3-byte surrogates.
7611   SameSymbolHelper("\355\240\201\355\260\206",  // 2 3-byte surrogates.
7612                    "\360\220\220\206");  // 4 byte encoding.
7613   SameSymbolHelper("x\360\220\220\205",  // 4 byte encoding.
7614                    "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
7615   SameSymbolHelper("x\355\240\201\355\260\206",  // 2 3-byte surrogates.
7616                    "x\360\220\220\206");  // 4 byte encoding.
7617   CompileRun(
7618       "var sym0 = 'benedictus';"
7619       "var sym0b = 'S\303\270ren';"
7620       "var sym1 = '\355\240\201\355\260\207';"
7621       "var sym2 = '\360\220\220\210';"
7622       "var sym3 = 'x\355\240\201\355\260\207';"
7623       "var sym4 = 'x\360\220\220\210';"
7624       "if (sym1.length != 2) throw sym1;"
7625       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
7626       "if (sym2.length != 2) throw sym2;"
7627       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
7628       "if (sym3.length != 3) throw sym3;"
7629       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
7630       "if (sym4.length != 3) throw sym4;"
7631       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
7632   Handle<String> sym0 = v8::String::NewSymbol("benedictus");
7633   Handle<String> sym0b = v8::String::NewSymbol("S\303\270ren");
7634   Handle<String> sym1 = v8::String::NewSymbol("\355\240\201\355\260\207");
7635   Handle<String> sym2 = v8::String::NewSymbol("\360\220\220\210");
7636   Handle<String> sym3 = v8::String::NewSymbol("x\355\240\201\355\260\207");
7637   Handle<String> sym4 = v8::String::NewSymbol("x\360\220\220\210");
7638   v8::Local<v8::Object> global = context->Global();
7639   Local<Value> s0 = global->Get(v8_str("sym0"));
7640   Local<Value> s0b = global->Get(v8_str("sym0b"));
7641   Local<Value> s1 = global->Get(v8_str("sym1"));
7642   Local<Value> s2 = global->Get(v8_str("sym2"));
7643   Local<Value> s3 = global->Get(v8_str("sym3"));
7644   Local<Value> s4 = global->Get(v8_str("sym4"));
7645   CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
7646   CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
7647   CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
7648   CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
7649   CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
7650   CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
7651 }
7652
7653
7654 THREADED_TEST(ToArrayIndex) {
7655   LocalContext context;
7656   v8::HandleScope scope(context->GetIsolate());
7657
7658   v8::Handle<String> str = v8_str("42");
7659   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
7660   CHECK(!index.IsEmpty());
7661   CHECK_EQ(42.0, index->Uint32Value());
7662   str = v8_str("42asdf");
7663   index = str->ToArrayIndex();
7664   CHECK(index.IsEmpty());
7665   str = v8_str("-42");
7666   index = str->ToArrayIndex();
7667   CHECK(index.IsEmpty());
7668   str = v8_str("4294967295");
7669   index = str->ToArrayIndex();
7670   CHECK(!index.IsEmpty());
7671   CHECK_EQ(4294967295.0, index->Uint32Value());
7672   v8::Handle<v8::Number> num = v8::Number::New(1);
7673   index = num->ToArrayIndex();
7674   CHECK(!index.IsEmpty());
7675   CHECK_EQ(1.0, index->Uint32Value());
7676   num = v8::Number::New(-1);
7677   index = num->ToArrayIndex();
7678   CHECK(index.IsEmpty());
7679   v8::Handle<v8::Object> obj = v8::Object::New();
7680   index = obj->ToArrayIndex();
7681   CHECK(index.IsEmpty());
7682 }
7683
7684
7685 THREADED_TEST(ErrorConstruction) {
7686   LocalContext context;
7687   v8::HandleScope scope(context->GetIsolate());
7688
7689   v8::Handle<String> foo = v8_str("foo");
7690   v8::Handle<String> message = v8_str("message");
7691   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
7692   CHECK(range_error->IsObject());
7693   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
7694   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
7695   CHECK(reference_error->IsObject());
7696   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
7697   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
7698   CHECK(syntax_error->IsObject());
7699   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
7700   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
7701   CHECK(type_error->IsObject());
7702   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
7703   v8::Handle<Value> error = v8::Exception::Error(foo);
7704   CHECK(error->IsObject());
7705   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7706 }
7707
7708
7709 static void YGetter(Local<String> name,
7710                     const v8::PropertyCallbackInfo<v8::Value>& info) {
7711   ApiTestFuzzer::Fuzz();
7712   info.GetReturnValue().Set(v8_num(10));
7713 }
7714
7715
7716 static void YSetter(Local<String> name,
7717                     Local<Value> value,
7718                     const v8::PropertyCallbackInfo<void>& info) {
7719   if (info.This()->Has(name)) {
7720     info.This()->Delete(name);
7721   }
7722   info.This()->Set(name, value);
7723 }
7724
7725
7726 THREADED_TEST(DeleteAccessor) {
7727   v8::HandleScope scope(v8::Isolate::GetCurrent());
7728   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7729   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
7730   LocalContext context;
7731   v8::Handle<v8::Object> holder = obj->NewInstance();
7732   context->Global()->Set(v8_str("holder"), holder);
7733   v8::Handle<Value> result = CompileRun(
7734       "holder.y = 11; holder.y = 12; holder.y");
7735   CHECK_EQ(12, result->Uint32Value());
7736 }
7737
7738
7739 THREADED_TEST(TypeSwitch) {
7740   v8::HandleScope scope(v8::Isolate::GetCurrent());
7741   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
7742   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
7743   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
7744   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
7745   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
7746   LocalContext context;
7747   v8::Handle<v8::Object> obj0 = v8::Object::New();
7748   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
7749   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
7750   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
7751   for (int i = 0; i < 10; i++) {
7752     CHECK_EQ(0, type_switch->match(obj0));
7753     CHECK_EQ(1, type_switch->match(obj1));
7754     CHECK_EQ(2, type_switch->match(obj2));
7755     CHECK_EQ(3, type_switch->match(obj3));
7756     CHECK_EQ(3, type_switch->match(obj3));
7757     CHECK_EQ(2, type_switch->match(obj2));
7758     CHECK_EQ(1, type_switch->match(obj1));
7759     CHECK_EQ(0, type_switch->match(obj0));
7760   }
7761 }
7762
7763
7764 // For use within the TestSecurityHandler() test.
7765 static bool g_security_callback_result = false;
7766 static bool NamedSecurityTestCallback(Local<v8::Object> global,
7767                                       Local<Value> name,
7768                                       v8::AccessType type,
7769                                       Local<Value> data) {
7770   // Always allow read access.
7771   if (type == v8::ACCESS_GET)
7772     return true;
7773
7774   // Sometimes allow other access.
7775   return g_security_callback_result;
7776 }
7777
7778
7779 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
7780                                         uint32_t key,
7781                                         v8::AccessType type,
7782                                         Local<Value> data) {
7783   // Always allow read access.
7784   if (type == v8::ACCESS_GET)
7785     return true;
7786
7787   // Sometimes allow other access.
7788   return g_security_callback_result;
7789 }
7790
7791
7792 static int trouble_nesting = 0;
7793 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
7794   ApiTestFuzzer::Fuzz();
7795   trouble_nesting++;
7796
7797   // Call a JS function that throws an uncaught exception.
7798   Local<v8::Object> arg_this = Context::GetCurrent()->Global();
7799   Local<Value> trouble_callee = (trouble_nesting == 3) ?
7800     arg_this->Get(v8_str("trouble_callee")) :
7801     arg_this->Get(v8_str("trouble_caller"));
7802   CHECK(trouble_callee->IsFunction());
7803   args.GetReturnValue().Set(
7804       Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
7805 }
7806
7807
7808 static int report_count = 0;
7809 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
7810                                              v8::Handle<Value>) {
7811   report_count++;
7812 }
7813
7814
7815 // Counts uncaught exceptions, but other tests running in parallel
7816 // also have uncaught exceptions.
7817 TEST(ApiUncaughtException) {
7818   report_count = 0;
7819   LocalContext env;
7820   v8::HandleScope scope(env->GetIsolate());
7821   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7822
7823   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
7824   v8::Local<v8::Object> global = env->Global();
7825   global->Set(v8_str("trouble"), fun->GetFunction());
7826
7827   Script::Compile(v8_str("function trouble_callee() {"
7828                          "  var x = null;"
7829                          "  return x.foo;"
7830                          "};"
7831                          "function trouble_caller() {"
7832                          "  trouble();"
7833                          "};"))->Run();
7834   Local<Value> trouble = global->Get(v8_str("trouble"));
7835   CHECK(trouble->IsFunction());
7836   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
7837   CHECK(trouble_callee->IsFunction());
7838   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
7839   CHECK(trouble_caller->IsFunction());
7840   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
7841   CHECK_EQ(1, report_count);
7842   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7843 }
7844
7845 static const char* script_resource_name = "ExceptionInNativeScript.js";
7846 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
7847                                                 v8::Handle<Value>) {
7848   v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
7849   CHECK(!name_val.IsEmpty() && name_val->IsString());
7850   v8::String::Utf8Value name(message->GetScriptResourceName());
7851   CHECK_EQ(script_resource_name, *name);
7852   CHECK_EQ(3, message->GetLineNumber());
7853   v8::String::Utf8Value source_line(message->GetSourceLine());
7854   CHECK_EQ("  new o.foo();", *source_line);
7855 }
7856
7857
7858 TEST(ExceptionInNativeScript) {
7859   LocalContext env;
7860   v8::HandleScope scope(env->GetIsolate());
7861   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
7862
7863   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
7864   v8::Local<v8::Object> global = env->Global();
7865   global->Set(v8_str("trouble"), fun->GetFunction());
7866
7867   Script::Compile(v8_str("function trouble() {\n"
7868                          "  var o = {};\n"
7869                          "  new o.foo();\n"
7870                          "};"), v8::String::New(script_resource_name))->Run();
7871   Local<Value> trouble = global->Get(v8_str("trouble"));
7872   CHECK(trouble->IsFunction());
7873   Function::Cast(*trouble)->Call(global, 0, NULL);
7874   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
7875 }
7876
7877
7878 TEST(CompilationErrorUsingTryCatchHandler) {
7879   LocalContext env;
7880   v8::HandleScope scope(env->GetIsolate());
7881   v8::TryCatch try_catch;
7882   Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
7883   CHECK_NE(NULL, *try_catch.Exception());
7884   CHECK(try_catch.HasCaught());
7885 }
7886
7887
7888 TEST(TryCatchFinallyUsingTryCatchHandler) {
7889   LocalContext env;
7890   v8::HandleScope scope(env->GetIsolate());
7891   v8::TryCatch try_catch;
7892   Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
7893   CHECK(!try_catch.HasCaught());
7894   Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
7895   CHECK(try_catch.HasCaught());
7896   try_catch.Reset();
7897   Script::Compile(v8_str("(function() {"
7898                          "try { throw ''; } finally { return; }"
7899                          "})()"))->Run();
7900   CHECK(!try_catch.HasCaught());
7901   Script::Compile(v8_str("(function()"
7902                          "  { try { throw ''; } finally { throw 0; }"
7903                          "})()"))->Run();
7904   CHECK(try_catch.HasCaught());
7905 }
7906
7907
7908 // SecurityHandler can't be run twice
7909 TEST(SecurityHandler) {
7910   v8::HandleScope scope0(v8::Isolate::GetCurrent());
7911   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
7912   global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
7913                                            IndexedSecurityTestCallback);
7914   // Create an environment
7915   v8::Handle<Context> context0 =
7916     Context::New(v8::Isolate::GetCurrent(), NULL, global_template);
7917   context0->Enter();
7918
7919   v8::Handle<v8::Object> global0 = context0->Global();
7920   v8::Handle<Script> script0 = v8_compile("foo = 111");
7921   script0->Run();
7922   global0->Set(v8_str("0"), v8_num(999));
7923   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
7924   CHECK_EQ(111, foo0->Int32Value());
7925   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
7926   CHECK_EQ(999, z0->Int32Value());
7927
7928   // Create another environment, should fail security checks.
7929   v8::HandleScope scope1(v8::Isolate::GetCurrent());
7930
7931   v8::Handle<Context> context1 =
7932     Context::New(v8::Isolate::GetCurrent(), NULL, global_template);
7933   context1->Enter();
7934
7935   v8::Handle<v8::Object> global1 = context1->Global();
7936   global1->Set(v8_str("othercontext"), global0);
7937   // This set will fail the security check.
7938   v8::Handle<Script> script1 =
7939     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
7940   script1->Run();
7941   // This read will pass the security check.
7942   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
7943   CHECK_EQ(111, foo1->Int32Value());
7944   // This read will pass the security check.
7945   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
7946   CHECK_EQ(999, z1->Int32Value());
7947
7948   // Create another environment, should pass security checks.
7949   { g_security_callback_result = true;  // allow security handler to pass.
7950     v8::HandleScope scope2(v8::Isolate::GetCurrent());
7951     LocalContext context2;
7952     v8::Handle<v8::Object> global2 = context2->Global();
7953     global2->Set(v8_str("othercontext"), global0);
7954     v8::Handle<Script> script2 =
7955         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
7956     script2->Run();
7957     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
7958     CHECK_EQ(333, foo2->Int32Value());
7959     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
7960     CHECK_EQ(888, z2->Int32Value());
7961   }
7962
7963   context1->Exit();
7964   context0->Exit();
7965 }
7966
7967
7968 THREADED_TEST(SecurityChecks) {
7969   LocalContext env1;
7970   v8::HandleScope handle_scope(env1->GetIsolate());
7971   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
7972
7973   Local<Value> foo = v8_str("foo");
7974   Local<Value> bar = v8_str("bar");
7975
7976   // Set to the same domain.
7977   env1->SetSecurityToken(foo);
7978
7979   // Create a function in env1.
7980   Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
7981   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
7982   CHECK(spy->IsFunction());
7983
7984   // Create another function accessing global objects.
7985   Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
7986   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
7987   CHECK(spy2->IsFunction());
7988
7989   // Switch to env2 in the same domain and invoke spy on env2.
7990   {
7991     env2->SetSecurityToken(foo);
7992     // Enter env2
7993     Context::Scope scope_env2(env2);
7994     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
7995     CHECK(result->IsFunction());
7996   }
7997
7998   {
7999     env2->SetSecurityToken(bar);
8000     Context::Scope scope_env2(env2);
8001
8002     // Call cross_domain_call, it should throw an exception
8003     v8::TryCatch try_catch;
8004     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
8005     CHECK(try_catch.HasCaught());
8006   }
8007 }
8008
8009
8010 // Regression test case for issue 1183439.
8011 THREADED_TEST(SecurityChecksForPrototypeChain) {
8012   LocalContext current;
8013   v8::HandleScope scope(current->GetIsolate());
8014   v8::Handle<Context> other = Context::New(current->GetIsolate());
8015
8016   // Change context to be able to get to the Object function in the
8017   // other context without hitting the security checks.
8018   v8::Local<Value> other_object;
8019   { Context::Scope scope(other);
8020     other_object = other->Global()->Get(v8_str("Object"));
8021     other->Global()->Set(v8_num(42), v8_num(87));
8022   }
8023
8024   current->Global()->Set(v8_str("other"), other->Global());
8025   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
8026
8027   // Make sure the security check fails here and we get an undefined
8028   // result instead of getting the Object function. Repeat in a loop
8029   // to make sure to exercise the IC code.
8030   v8::Local<Script> access_other0 = v8_compile("other.Object");
8031   v8::Local<Script> access_other1 = v8_compile("other[42]");
8032   for (int i = 0; i < 5; i++) {
8033     CHECK(!access_other0->Run()->Equals(other_object));
8034     CHECK(access_other0->Run()->IsUndefined());
8035     CHECK(!access_other1->Run()->Equals(v8_num(87)));
8036     CHECK(access_other1->Run()->IsUndefined());
8037   }
8038
8039   // Create an object that has 'other' in its prototype chain and make
8040   // sure we cannot access the Object function indirectly through
8041   // that. Repeat in a loop to make sure to exercise the IC code.
8042   v8_compile("function F() { };"
8043              "F.prototype = other;"
8044              "var f = new F();")->Run();
8045   v8::Local<Script> access_f0 = v8_compile("f.Object");
8046   v8::Local<Script> access_f1 = v8_compile("f[42]");
8047   for (int j = 0; j < 5; j++) {
8048     CHECK(!access_f0->Run()->Equals(other_object));
8049     CHECK(access_f0->Run()->IsUndefined());
8050     CHECK(!access_f1->Run()->Equals(v8_num(87)));
8051     CHECK(access_f1->Run()->IsUndefined());
8052   }
8053
8054   // Now it gets hairy: Set the prototype for the other global object
8055   // to be the current global object. The prototype chain for 'f' now
8056   // goes through 'other' but ends up in the current global object.
8057   { Context::Scope scope(other);
8058     other->Global()->Set(v8_str("__proto__"), current->Global());
8059   }
8060   // Set a named and an index property on the current global
8061   // object. To force the lookup to go through the other global object,
8062   // the properties must not exist in the other global object.
8063   current->Global()->Set(v8_str("foo"), v8_num(100));
8064   current->Global()->Set(v8_num(99), v8_num(101));
8065   // Try to read the properties from f and make sure that the access
8066   // gets stopped by the security checks on the other global object.
8067   Local<Script> access_f2 = v8_compile("f.foo");
8068   Local<Script> access_f3 = v8_compile("f[99]");
8069   for (int k = 0; k < 5; k++) {
8070     CHECK(!access_f2->Run()->Equals(v8_num(100)));
8071     CHECK(access_f2->Run()->IsUndefined());
8072     CHECK(!access_f3->Run()->Equals(v8_num(101)));
8073     CHECK(access_f3->Run()->IsUndefined());
8074   }
8075 }
8076
8077
8078 THREADED_TEST(CrossDomainDelete) {
8079   LocalContext env1;
8080   v8::HandleScope handle_scope(env1->GetIsolate());
8081   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8082
8083   Local<Value> foo = v8_str("foo");
8084   Local<Value> bar = v8_str("bar");
8085
8086   // Set to the same domain.
8087   env1->SetSecurityToken(foo);
8088   env2->SetSecurityToken(foo);
8089
8090   env1->Global()->Set(v8_str("prop"), v8_num(3));
8091   env2->Global()->Set(v8_str("env1"), env1->Global());
8092
8093   // Change env2 to a different domain and delete env1.prop.
8094   env2->SetSecurityToken(bar);
8095   {
8096     Context::Scope scope_env2(env2);
8097     Local<Value> result =
8098         Script::Compile(v8_str("delete env1.prop"))->Run();
8099     CHECK(result->IsFalse());
8100   }
8101
8102   // Check that env1.prop still exists.
8103   Local<Value> v = env1->Global()->Get(v8_str("prop"));
8104   CHECK(v->IsNumber());
8105   CHECK_EQ(3, v->Int32Value());
8106 }
8107
8108
8109 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
8110   LocalContext env1;
8111   v8::HandleScope handle_scope(env1->GetIsolate());
8112   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8113
8114   Local<Value> foo = v8_str("foo");
8115   Local<Value> bar = v8_str("bar");
8116
8117   // Set to the same domain.
8118   env1->SetSecurityToken(foo);
8119   env2->SetSecurityToken(foo);
8120
8121   env1->Global()->Set(v8_str("prop"), v8_num(3));
8122   env2->Global()->Set(v8_str("env1"), env1->Global());
8123
8124   // env1.prop is enumerable in env2.
8125   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8126   {
8127     Context::Scope scope_env2(env2);
8128     Local<Value> result = Script::Compile(test)->Run();
8129     CHECK(result->IsTrue());
8130   }
8131
8132   // Change env2 to a different domain and test again.
8133   env2->SetSecurityToken(bar);
8134   {
8135     Context::Scope scope_env2(env2);
8136     Local<Value> result = Script::Compile(test)->Run();
8137     CHECK(result->IsFalse());
8138   }
8139 }
8140
8141
8142 THREADED_TEST(CrossDomainForIn) {
8143   LocalContext env1;
8144   v8::HandleScope handle_scope(env1->GetIsolate());
8145   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8146
8147   Local<Value> foo = v8_str("foo");
8148   Local<Value> bar = v8_str("bar");
8149
8150   // Set to the same domain.
8151   env1->SetSecurityToken(foo);
8152   env2->SetSecurityToken(foo);
8153
8154   env1->Global()->Set(v8_str("prop"), v8_num(3));
8155   env2->Global()->Set(v8_str("env1"), env1->Global());
8156
8157   // Change env2 to a different domain and set env1's global object
8158   // as the __proto__ of an object in env2 and enumerate properties
8159   // in for-in. It shouldn't enumerate properties on env1's global
8160   // object.
8161   env2->SetSecurityToken(bar);
8162   {
8163     Context::Scope scope_env2(env2);
8164     Local<Value> result =
8165         CompileRun("(function(){var obj = {'__proto__':env1};"
8166                    "for (var p in obj)"
8167                    "   if (p == 'prop') return false;"
8168                    "return true;})()");
8169     CHECK(result->IsTrue());
8170   }
8171 }
8172
8173
8174 TEST(ContextDetachGlobal) {
8175   LocalContext env1;
8176   v8::HandleScope handle_scope(env1->GetIsolate());
8177   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8178
8179   Local<v8::Object> global1 = env1->Global();
8180
8181   Local<Value> foo = v8_str("foo");
8182
8183   // Set to the same domain.
8184   env1->SetSecurityToken(foo);
8185   env2->SetSecurityToken(foo);
8186
8187   // Enter env2
8188   env2->Enter();
8189
8190   // Create a function in env2 and add a reference to it in env1.
8191   Local<v8::Object> global2 = env2->Global();
8192   global2->Set(v8_str("prop"), v8::Integer::New(1));
8193   CompileRun("function getProp() {return prop;}");
8194
8195   env1->Global()->Set(v8_str("getProp"),
8196                       global2->Get(v8_str("getProp")));
8197
8198   // Detach env2's global, and reuse the global object of env2
8199   env2->Exit();
8200   env2->DetachGlobal();
8201   // env2 has a new global object.
8202   CHECK(!env2->Global()->Equals(global2));
8203
8204   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8205                                           0,
8206                                           v8::Handle<v8::ObjectTemplate>(),
8207                                           global2);
8208   env3->SetSecurityToken(v8_str("bar"));
8209   env3->Enter();
8210
8211   Local<v8::Object> global3 = env3->Global();
8212   CHECK_EQ(global2, global3);
8213   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8214   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
8215   global3->Set(v8_str("prop"), v8::Integer::New(-1));
8216   global3->Set(v8_str("prop2"), v8::Integer::New(2));
8217   env3->Exit();
8218
8219   // Call getProp in env1, and it should return the value 1
8220   {
8221     Local<Value> get_prop = global1->Get(v8_str("getProp"));
8222     CHECK(get_prop->IsFunction());
8223     v8::TryCatch try_catch;
8224     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8225     CHECK(!try_catch.HasCaught());
8226     CHECK_EQ(1, r->Int32Value());
8227   }
8228
8229   // Check that env3 is not accessible from env1
8230   {
8231     Local<Value> r = global3->Get(v8_str("prop2"));
8232     CHECK(r->IsUndefined());
8233   }
8234 }
8235
8236
8237 TEST(DetachAndReattachGlobal) {
8238   LocalContext env1;
8239   v8::HandleScope scope(env1->GetIsolate());
8240
8241   // Create second environment.
8242   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8243
8244   Local<Value> foo = v8_str("foo");
8245
8246   // Set same security token for env1 and env2.
8247   env1->SetSecurityToken(foo);
8248   env2->SetSecurityToken(foo);
8249
8250   // Create a property on the global object in env2.
8251   {
8252     v8::Context::Scope scope(env2);
8253     env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
8254   }
8255
8256   // Create a reference to env2 global from env1 global.
8257   env1->Global()->Set(v8_str("other"), env2->Global());
8258
8259   // Check that we have access to other.p in env2 from env1.
8260   Local<Value> result = CompileRun("other.p");
8261   CHECK(result->IsInt32());
8262   CHECK_EQ(42, result->Int32Value());
8263
8264   // Hold on to global from env2 and detach global from env2.
8265   Local<v8::Object> global2 = env2->Global();
8266   env2->DetachGlobal();
8267
8268   // Check that the global has been detached. No other.p property can
8269   // be found.
8270   result = CompileRun("other.p");
8271   CHECK(result->IsUndefined());
8272
8273   // Reuse global2 for env3.
8274   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8275                                           0,
8276                                           v8::Handle<v8::ObjectTemplate>(),
8277                                           global2);
8278   CHECK_EQ(global2, env3->Global());
8279
8280   // Start by using the same security token for env3 as for env1 and env2.
8281   env3->SetSecurityToken(foo);
8282
8283   // Create a property on the global object in env3.
8284   {
8285     v8::Context::Scope scope(env3);
8286     env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
8287   }
8288
8289   // Check that other.p is now the property in env3 and that we have access.
8290   result = CompileRun("other.p");
8291   CHECK(result->IsInt32());
8292   CHECK_EQ(24, result->Int32Value());
8293
8294   // Change security token for env3 to something different from env1 and env2.
8295   env3->SetSecurityToken(v8_str("bar"));
8296
8297   // Check that we do not have access to other.p in env1. |other| is now
8298   // the global object for env3 which has a different security token,
8299   // so access should be blocked.
8300   result = CompileRun("other.p");
8301   CHECK(result->IsUndefined());
8302
8303   // Detach the global for env3 and reattach it to env2.
8304   env3->DetachGlobal();
8305   env2->ReattachGlobal(global2);
8306
8307   // Check that we have access to other.p again in env1.  |other| is now
8308   // the global object for env2 which has the same security token as env1.
8309   result = CompileRun("other.p");
8310   CHECK(result->IsInt32());
8311   CHECK_EQ(42, result->Int32Value());
8312 }
8313
8314
8315 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
8316 static bool NamedAccessBlocker(Local<v8::Object> global,
8317                                Local<Value> name,
8318                                v8::AccessType type,
8319                                Local<Value> data) {
8320   return Context::GetCurrent()->Global()->Equals(global) ||
8321       allowed_access_type[type];
8322 }
8323
8324
8325 static bool IndexedAccessBlocker(Local<v8::Object> global,
8326                                  uint32_t key,
8327                                  v8::AccessType type,
8328                                  Local<Value> data) {
8329   return Context::GetCurrent()->Global()->Equals(global) ||
8330       allowed_access_type[type];
8331 }
8332
8333
8334 static int g_echo_value_1 = -1;
8335 static int g_echo_value_2 = -1;
8336
8337
8338 static void EchoGetter(
8339     Local<String> name,
8340     const v8::PropertyCallbackInfo<v8::Value>& info) {
8341   info.GetReturnValue().Set(v8_num(g_echo_value_1));
8342 }
8343
8344
8345 static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8346   info.GetReturnValue().Set(v8_num(g_echo_value_2));
8347 }
8348
8349
8350 static void EchoSetter(Local<String> name,
8351                        Local<Value> value,
8352                        const v8::PropertyCallbackInfo<void>&) {
8353   if (value->IsNumber())
8354     g_echo_value_1 = value->Int32Value();
8355 }
8356
8357
8358 static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8359   v8::Handle<v8::Value> value = info[0];
8360   if (value->IsNumber())
8361     g_echo_value_2 = value->Int32Value();
8362 }
8363
8364
8365 static void UnreachableGetter(
8366     Local<String> name,
8367     const v8::PropertyCallbackInfo<v8::Value>& info) {
8368   CHECK(false);  // This function should not be called..
8369 }
8370
8371
8372 static void UnreachableSetter(Local<String>,
8373                               Local<Value>,
8374                               const v8::PropertyCallbackInfo<void>&) {
8375   CHECK(false);  // This function should nto be called.
8376 }
8377
8378
8379 static void UnreachableFunction(
8380     const v8::FunctionCallbackInfo<v8::Value>& info) {
8381   CHECK(false);  // This function should not be called..
8382 }
8383
8384
8385 TEST(AccessControl) {
8386   v8::Isolate* isolate = v8::Isolate::GetCurrent();
8387   v8::HandleScope handle_scope(isolate);
8388   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
8389
8390   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8391                                            IndexedAccessBlocker);
8392
8393   // Add an accessor accessible by cross-domain JS code.
8394   global_template->SetAccessor(
8395       v8_str("accessible_prop"),
8396       EchoGetter, EchoSetter,
8397       v8::Handle<Value>(),
8398       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8399
8400
8401   global_template->SetAccessorProperty(
8402       v8_str("accessible_js_prop"),
8403       v8::FunctionTemplate::New(EchoGetter),
8404       v8::FunctionTemplate::New(EchoSetter),
8405       v8::None,
8406       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8407
8408   // Add an accessor that is not accessible by cross-domain JS code.
8409   global_template->SetAccessor(v8_str("blocked_prop"),
8410                                UnreachableGetter, UnreachableSetter,
8411                                v8::Handle<Value>(),
8412                                v8::DEFAULT);
8413
8414   global_template->SetAccessorProperty(
8415       v8_str("blocked_js_prop"),
8416       v8::FunctionTemplate::New(UnreachableFunction),
8417       v8::FunctionTemplate::New(UnreachableFunction),
8418       v8::None,
8419       v8::DEFAULT);
8420
8421   // Create an environment
8422   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8423   context0->Enter();
8424
8425   v8::Handle<v8::Object> global0 = context0->Global();
8426
8427   // Define a property with JS getter and setter.
8428   CompileRun(
8429       "function getter() { return 'getter'; };\n"
8430       "function setter() { return 'setter'; }\n"
8431       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8432
8433   Local<Value> getter = global0->Get(v8_str("getter"));
8434   Local<Value> setter = global0->Get(v8_str("setter"));
8435
8436   // And define normal element.
8437   global0->Set(239, v8_str("239"));
8438
8439   // Define an element with JS getter and setter.
8440   CompileRun(
8441       "function el_getter() { return 'el_getter'; };\n"
8442       "function el_setter() { return 'el_setter'; };\n"
8443       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
8444
8445   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
8446   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
8447
8448   v8::HandleScope scope1(isolate);
8449
8450   v8::Local<Context> context1 = Context::New(isolate);
8451   context1->Enter();
8452
8453   v8::Handle<v8::Object> global1 = context1->Global();
8454   global1->Set(v8_str("other"), global0);
8455
8456   // Access blocked property.
8457   CompileRun("other.blocked_prop = 1");
8458
8459   ExpectUndefined("other.blocked_prop");
8460   ExpectUndefined(
8461       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
8462   ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
8463
8464   // Enable ACCESS_HAS
8465   allowed_access_type[v8::ACCESS_HAS] = true;
8466   ExpectUndefined("other.blocked_prop");
8467   // ... and now we can get the descriptor...
8468   ExpectUndefined(
8469       "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
8470   // ... and enumerate the property.
8471   ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
8472   allowed_access_type[v8::ACCESS_HAS] = false;
8473
8474   // Access blocked element.
8475   CompileRun("other[239] = 1");
8476
8477   ExpectUndefined("other[239]");
8478   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
8479   ExpectFalse("propertyIsEnumerable.call(other, '239')");
8480
8481   // Enable ACCESS_HAS
8482   allowed_access_type[v8::ACCESS_HAS] = true;
8483   ExpectUndefined("other[239]");
8484   // ... and now we can get the descriptor...
8485   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
8486   // ... and enumerate the property.
8487   ExpectTrue("propertyIsEnumerable.call(other, '239')");
8488   allowed_access_type[v8::ACCESS_HAS] = false;
8489
8490   // Access a property with JS accessor.
8491   CompileRun("other.js_accessor_p = 2");
8492
8493   ExpectUndefined("other.js_accessor_p");
8494   ExpectUndefined(
8495       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
8496
8497   // Enable ACCESS_HAS.
8498   allowed_access_type[v8::ACCESS_HAS] = true;
8499   ExpectUndefined("other.js_accessor_p");
8500   ExpectUndefined(
8501       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
8502   ExpectUndefined(
8503       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
8504   ExpectUndefined(
8505       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8506   allowed_access_type[v8::ACCESS_HAS] = false;
8507
8508   // Enable both ACCESS_HAS and ACCESS_GET.
8509   allowed_access_type[v8::ACCESS_HAS] = true;
8510   allowed_access_type[v8::ACCESS_GET] = true;
8511
8512   ExpectString("other.js_accessor_p", "getter");
8513   ExpectObject(
8514       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
8515   ExpectUndefined(
8516       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
8517   ExpectUndefined(
8518       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8519
8520   allowed_access_type[v8::ACCESS_GET] = false;
8521   allowed_access_type[v8::ACCESS_HAS] = false;
8522
8523   // Enable both ACCESS_HAS and ACCESS_SET.
8524   allowed_access_type[v8::ACCESS_HAS] = true;
8525   allowed_access_type[v8::ACCESS_SET] = true;
8526
8527   ExpectUndefined("other.js_accessor_p");
8528   ExpectUndefined(
8529       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
8530   ExpectObject(
8531       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
8532   ExpectUndefined(
8533       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8534
8535   allowed_access_type[v8::ACCESS_SET] = false;
8536   allowed_access_type[v8::ACCESS_HAS] = false;
8537
8538   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
8539   allowed_access_type[v8::ACCESS_HAS] = true;
8540   allowed_access_type[v8::ACCESS_GET] = true;
8541   allowed_access_type[v8::ACCESS_SET] = true;
8542
8543   ExpectString("other.js_accessor_p", "getter");
8544   ExpectObject(
8545       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
8546   ExpectObject(
8547       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
8548   ExpectUndefined(
8549       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8550
8551   allowed_access_type[v8::ACCESS_SET] = false;
8552   allowed_access_type[v8::ACCESS_GET] = false;
8553   allowed_access_type[v8::ACCESS_HAS] = false;
8554
8555   // Access an element with JS accessor.
8556   CompileRun("other[42] = 2");
8557
8558   ExpectUndefined("other[42]");
8559   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
8560
8561   // Enable ACCESS_HAS.
8562   allowed_access_type[v8::ACCESS_HAS] = true;
8563   ExpectUndefined("other[42]");
8564   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
8565   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
8566   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8567   allowed_access_type[v8::ACCESS_HAS] = false;
8568
8569   // Enable both ACCESS_HAS and ACCESS_GET.
8570   allowed_access_type[v8::ACCESS_HAS] = true;
8571   allowed_access_type[v8::ACCESS_GET] = true;
8572
8573   ExpectString("other[42]", "el_getter");
8574   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
8575   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
8576   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8577
8578   allowed_access_type[v8::ACCESS_GET] = false;
8579   allowed_access_type[v8::ACCESS_HAS] = false;
8580
8581   // Enable both ACCESS_HAS and ACCESS_SET.
8582   allowed_access_type[v8::ACCESS_HAS] = true;
8583   allowed_access_type[v8::ACCESS_SET] = true;
8584
8585   ExpectUndefined("other[42]");
8586   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
8587   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
8588   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8589
8590   allowed_access_type[v8::ACCESS_SET] = false;
8591   allowed_access_type[v8::ACCESS_HAS] = false;
8592
8593   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
8594   allowed_access_type[v8::ACCESS_HAS] = true;
8595   allowed_access_type[v8::ACCESS_GET] = true;
8596   allowed_access_type[v8::ACCESS_SET] = true;
8597
8598   ExpectString("other[42]", "el_getter");
8599   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
8600   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
8601   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8602
8603   allowed_access_type[v8::ACCESS_SET] = false;
8604   allowed_access_type[v8::ACCESS_GET] = false;
8605   allowed_access_type[v8::ACCESS_HAS] = false;
8606
8607   v8::Handle<Value> value;
8608
8609   // Access accessible property
8610   value = CompileRun("other.accessible_prop = 3");
8611   CHECK(value->IsNumber());
8612   CHECK_EQ(3, value->Int32Value());
8613   CHECK_EQ(3, g_echo_value_1);
8614
8615   // Access accessible js property
8616   value = CompileRun("other.accessible_js_prop = 3");
8617   CHECK(value->IsNumber());
8618   CHECK_EQ(3, value->Int32Value());
8619   CHECK_EQ(3, g_echo_value_2);
8620
8621   value = CompileRun("other.accessible_prop");
8622   CHECK(value->IsNumber());
8623   CHECK_EQ(3, value->Int32Value());
8624
8625   value = CompileRun("other.accessible_js_prop");
8626   CHECK(value->IsNumber());
8627   CHECK_EQ(3, value->Int32Value());
8628
8629   value = CompileRun(
8630       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
8631   CHECK(value->IsNumber());
8632   CHECK_EQ(3, value->Int32Value());
8633
8634   value = CompileRun(
8635       "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
8636   CHECK(value->IsNumber());
8637   CHECK_EQ(3, value->Int32Value());
8638
8639   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
8640   CHECK(value->IsTrue());
8641
8642   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
8643   CHECK(value->IsTrue());
8644
8645   // Enumeration doesn't enumerate accessors from inaccessible objects in
8646   // the prototype chain even if the accessors are in themselves accessible.
8647   value =
8648       CompileRun("(function(){var obj = {'__proto__':other};"
8649                  "for (var p in obj)"
8650                  "   if (p == 'accessible_prop' ||"
8651                  "       p == 'accessible_js_prop' ||"
8652                  "       p == 'blocked_js_prop' ||"
8653                  "       p == 'blocked_js_prop') {"
8654                  "     return false;"
8655                  "   }"
8656                  "return true;})()");
8657   CHECK(value->IsTrue());
8658
8659   context1->Exit();
8660   context0->Exit();
8661 }
8662
8663
8664 TEST(AccessControlES5) {
8665   v8::Isolate* isolate = v8::Isolate::GetCurrent();
8666   v8::HandleScope handle_scope(isolate);
8667   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
8668
8669   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8670                                            IndexedAccessBlocker);
8671
8672   // Add accessible accessor.
8673   global_template->SetAccessor(
8674       v8_str("accessible_prop"),
8675       EchoGetter, EchoSetter,
8676       v8::Handle<Value>(),
8677       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8678
8679
8680   // Add an accessor that is not accessible by cross-domain JS code.
8681   global_template->SetAccessor(v8_str("blocked_prop"),
8682                                UnreachableGetter, UnreachableSetter,
8683                                v8::Handle<Value>(),
8684                                v8::DEFAULT);
8685
8686   // Create an environment
8687   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8688   context0->Enter();
8689
8690   v8::Handle<v8::Object> global0 = context0->Global();
8691
8692   v8::Local<Context> context1 = Context::New(isolate);
8693   context1->Enter();
8694   v8::Handle<v8::Object> global1 = context1->Global();
8695   global1->Set(v8_str("other"), global0);
8696
8697   // Regression test for issue 1154.
8698   ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
8699
8700   ExpectUndefined("other.blocked_prop");
8701
8702   // Regression test for issue 1027.
8703   CompileRun("Object.defineProperty(\n"
8704              "  other, 'blocked_prop', {configurable: false})");
8705   ExpectUndefined("other.blocked_prop");
8706   ExpectUndefined(
8707       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
8708
8709   // Regression test for issue 1171.
8710   ExpectTrue("Object.isExtensible(other)");
8711   CompileRun("Object.preventExtensions(other)");
8712   ExpectTrue("Object.isExtensible(other)");
8713
8714   // Object.seal and Object.freeze.
8715   CompileRun("Object.freeze(other)");
8716   ExpectTrue("Object.isExtensible(other)");
8717
8718   CompileRun("Object.seal(other)");
8719   ExpectTrue("Object.isExtensible(other)");
8720
8721   // Regression test for issue 1250.
8722   // Make sure that we can set the accessible accessors value using normal
8723   // assignment.
8724   CompileRun("other.accessible_prop = 42");
8725   CHECK_EQ(42, g_echo_value_1);
8726
8727   v8::Handle<Value> value;
8728   // We follow Safari in ignoring assignments to host object accessors.
8729   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
8730   value = CompileRun("other.accessible_prop == 42");
8731   CHECK(value->IsTrue());
8732 }
8733
8734
8735 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
8736                                             Local<Value> name,
8737                                             v8::AccessType type,
8738                                             Local<Value> data) {
8739   return false;
8740 }
8741
8742
8743 static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
8744                                               uint32_t key,
8745                                               v8::AccessType type,
8746                                               Local<Value> data) {
8747   return false;
8748 }
8749
8750
8751 THREADED_TEST(AccessControlGetOwnPropertyNames) {
8752   v8::Isolate* isolate = v8::Isolate::GetCurrent();
8753   v8::HandleScope handle_scope(isolate);
8754   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
8755
8756   obj_template->Set(v8_str("x"), v8::Integer::New(42));
8757   obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
8758                                         GetOwnPropertyNamesIndexedBlocker);
8759
8760   // Create an environment
8761   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
8762   context0->Enter();
8763
8764   v8::Handle<v8::Object> global0 = context0->Global();
8765
8766   v8::HandleScope scope1(v8::Isolate::GetCurrent());
8767
8768   v8::Local<Context> context1 = Context::New(isolate);
8769   context1->Enter();
8770
8771   v8::Handle<v8::Object> global1 = context1->Global();
8772   global1->Set(v8_str("other"), global0);
8773   global1->Set(v8_str("object"), obj_template->NewInstance());
8774
8775   v8::Handle<Value> value;
8776
8777   // Attempt to get the property names of the other global object and
8778   // of an object that requires access checks.  Accessing the other
8779   // global object should be blocked by access checks on the global
8780   // proxy object.  Accessing the object that requires access checks
8781   // is blocked by the access checks on the object itself.
8782   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
8783   CHECK(value->IsTrue());
8784
8785   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
8786   CHECK(value->IsTrue());
8787
8788   context1->Exit();
8789   context0->Exit();
8790 }
8791
8792
8793 static void IndexedPropertyEnumerator(
8794     const v8::PropertyCallbackInfo<v8::Array>& info) {
8795   v8::Handle<v8::Array> result = v8::Array::New(2);
8796   result->Set(0, v8::Integer::New(7));
8797   result->Set(1, v8::Object::New());
8798   info.GetReturnValue().Set(result);
8799 }
8800
8801
8802 static void NamedPropertyEnumerator(
8803     const v8::PropertyCallbackInfo<v8::Array>& info) {
8804   v8::Handle<v8::Array> result = v8::Array::New(2);
8805   result->Set(0, v8_str("x"));
8806   result->Set(1, v8::Object::New());
8807   info.GetReturnValue().Set(result);
8808 }
8809
8810
8811 THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
8812   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
8813   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
8814
8815   obj_template->Set(v8_str("7"), v8::Integer::New(7));
8816   obj_template->Set(v8_str("x"), v8::Integer::New(42));
8817   obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
8818                                           IndexedPropertyEnumerator);
8819   obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
8820                                         NamedPropertyEnumerator);
8821
8822   LocalContext context;
8823   v8::Handle<v8::Object> global = context->Global();
8824   global->Set(v8_str("object"), obj_template->NewInstance());
8825
8826   v8::Handle<v8::Value> result =
8827       CompileRun("Object.getOwnPropertyNames(object)");
8828   CHECK(result->IsArray());
8829   v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
8830   CHECK_EQ(3, result_array->Length());
8831   CHECK(result_array->Get(0)->IsString());
8832   CHECK(result_array->Get(1)->IsString());
8833   CHECK(result_array->Get(2)->IsString());
8834   CHECK_EQ(v8_str("7"), result_array->Get(0));
8835   CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
8836   CHECK_EQ(v8_str("x"), result_array->Get(2));
8837 }
8838
8839
8840 static void ConstTenGetter(Local<String> name,
8841                            const v8::PropertyCallbackInfo<v8::Value>& info) {
8842   info.GetReturnValue().Set(v8_num(10));
8843 }
8844
8845
8846 THREADED_TEST(CrossDomainAccessors) {
8847   v8::Isolate* isolate = v8::Isolate::GetCurrent();
8848   v8::HandleScope handle_scope(isolate);
8849
8850   v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
8851
8852   v8::Handle<v8::ObjectTemplate> global_template =
8853       func_template->InstanceTemplate();
8854
8855   v8::Handle<v8::ObjectTemplate> proto_template =
8856       func_template->PrototypeTemplate();
8857
8858   // Add an accessor to proto that's accessible by cross-domain JS code.
8859   proto_template->SetAccessor(v8_str("accessible"),
8860                               ConstTenGetter, 0,
8861                               v8::Handle<Value>(),
8862                               v8::ALL_CAN_READ);
8863
8864   // Add an accessor that is not accessible by cross-domain JS code.
8865   global_template->SetAccessor(v8_str("unreachable"),
8866                                UnreachableGetter, 0,
8867                                v8::Handle<Value>(),
8868                                v8::DEFAULT);
8869
8870   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8871   context0->Enter();
8872
8873   Local<v8::Object> global = context0->Global();
8874   // Add a normal property that shadows 'accessible'
8875   global->Set(v8_str("accessible"), v8_num(11));
8876
8877   // Enter a new context.
8878   v8::HandleScope scope1(v8::Isolate::GetCurrent());
8879   v8::Local<Context> context1 = Context::New(isolate);
8880   context1->Enter();
8881
8882   v8::Handle<v8::Object> global1 = context1->Global();
8883   global1->Set(v8_str("other"), global);
8884
8885   // Should return 10, instead of 11
8886   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
8887   CHECK(value->IsNumber());
8888   CHECK_EQ(10, value->Int32Value());
8889
8890   value = v8_compile("other.unreachable")->Run();
8891   CHECK(value->IsUndefined());
8892
8893   context1->Exit();
8894   context0->Exit();
8895 }
8896
8897
8898 static int named_access_count = 0;
8899 static int indexed_access_count = 0;
8900
8901 static bool NamedAccessCounter(Local<v8::Object> global,
8902                                Local<Value> name,
8903                                v8::AccessType type,
8904                                Local<Value> data) {
8905   named_access_count++;
8906   return true;
8907 }
8908
8909
8910 static bool IndexedAccessCounter(Local<v8::Object> global,
8911                                  uint32_t key,
8912                                  v8::AccessType type,
8913                                  Local<Value> data) {
8914   indexed_access_count++;
8915   return true;
8916 }
8917
8918
8919 // This one is too easily disturbed by other tests.
8920 TEST(AccessControlIC) {
8921   named_access_count = 0;
8922   indexed_access_count = 0;
8923
8924   v8::Isolate* isolate = v8::Isolate::GetCurrent();
8925   v8::HandleScope handle_scope(isolate);
8926
8927   // Create an environment.
8928   v8::Local<Context> context0 = Context::New(isolate);
8929   context0->Enter();
8930
8931   // Create an object that requires access-check functions to be
8932   // called for cross-domain access.
8933   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
8934   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
8935                                            IndexedAccessCounter);
8936   Local<v8::Object> object = object_template->NewInstance();
8937
8938   v8::HandleScope scope1(isolate);
8939
8940   // Create another environment.
8941   v8::Local<Context> context1 = Context::New(isolate);
8942   context1->Enter();
8943
8944   // Make easy access to the object from the other environment.
8945   v8::Handle<v8::Object> global1 = context1->Global();
8946   global1->Set(v8_str("obj"), object);
8947
8948   v8::Handle<Value> value;
8949
8950   // Check that the named access-control function is called every time.
8951   CompileRun("function testProp(obj) {"
8952              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
8953              "  for (var j = 0; j < 10; j++) obj.prop;"
8954              "  return obj.prop"
8955              "}");
8956   value = CompileRun("testProp(obj)");
8957   CHECK(value->IsNumber());
8958   CHECK_EQ(1, value->Int32Value());
8959   CHECK_EQ(21, named_access_count);
8960
8961   // Check that the named access-control function is called every time.
8962   CompileRun("var p = 'prop';"
8963              "function testKeyed(obj) {"
8964              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
8965              "  for (var j = 0; j < 10; j++) obj[p];"
8966              "  return obj[p];"
8967              "}");
8968   // Use obj which requires access checks.  No inline caching is used
8969   // in that case.
8970   value = CompileRun("testKeyed(obj)");
8971   CHECK(value->IsNumber());
8972   CHECK_EQ(1, value->Int32Value());
8973   CHECK_EQ(42, named_access_count);
8974   // Force the inline caches into generic state and try again.
8975   CompileRun("testKeyed({ a: 0 })");
8976   CompileRun("testKeyed({ b: 0 })");
8977   value = CompileRun("testKeyed(obj)");
8978   CHECK(value->IsNumber());
8979   CHECK_EQ(1, value->Int32Value());
8980   CHECK_EQ(63, named_access_count);
8981
8982   // Check that the indexed access-control function is called every time.
8983   CompileRun("function testIndexed(obj) {"
8984              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
8985              "  for (var j = 0; j < 10; j++) obj[0];"
8986              "  return obj[0]"
8987              "}");
8988   value = CompileRun("testIndexed(obj)");
8989   CHECK(value->IsNumber());
8990   CHECK_EQ(1, value->Int32Value());
8991   CHECK_EQ(21, indexed_access_count);
8992   // Force the inline caches into generic state.
8993   CompileRun("testIndexed(new Array(1))");
8994   // Test that the indexed access check is called.
8995   value = CompileRun("testIndexed(obj)");
8996   CHECK(value->IsNumber());
8997   CHECK_EQ(1, value->Int32Value());
8998   CHECK_EQ(42, indexed_access_count);
8999
9000   // Check that the named access check is called when invoking
9001   // functions on an object that requires access checks.
9002   CompileRun("obj.f = function() {}");
9003   CompileRun("function testCallNormal(obj) {"
9004              "  for (var i = 0; i < 10; i++) obj.f();"
9005              "}");
9006   CompileRun("testCallNormal(obj)");
9007   CHECK_EQ(74, named_access_count);
9008
9009   // Force obj into slow case.
9010   value = CompileRun("delete obj.prop");
9011   CHECK(value->BooleanValue());
9012   // Force inline caches into dictionary probing mode.
9013   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9014   // Test that the named access check is called.
9015   value = CompileRun("testProp(obj);");
9016   CHECK(value->IsNumber());
9017   CHECK_EQ(1, value->Int32Value());
9018   CHECK_EQ(96, named_access_count);
9019
9020   // Force the call inline cache into dictionary probing mode.
9021   CompileRun("o.f = function() {}; testCallNormal(o)");
9022   // Test that the named access check is still called for each
9023   // invocation of the function.
9024   value = CompileRun("testCallNormal(obj)");
9025   CHECK_EQ(106, named_access_count);
9026
9027   context1->Exit();
9028   context0->Exit();
9029 }
9030
9031
9032 static bool NamedAccessFlatten(Local<v8::Object> global,
9033                                Local<Value> name,
9034                                v8::AccessType type,
9035                                Local<Value> data) {
9036   char buf[100];
9037   int len;
9038
9039   CHECK(name->IsString());
9040
9041   memset(buf, 0x1, sizeof(buf));
9042   len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
9043   CHECK_EQ(4, len);
9044
9045   uint16_t buf2[100];
9046
9047   memset(buf, 0x1, sizeof(buf));
9048   len = name.As<String>()->Write(buf2);
9049   CHECK_EQ(4, len);
9050
9051   return true;
9052 }
9053
9054
9055 static bool IndexedAccessFlatten(Local<v8::Object> global,
9056                                  uint32_t key,
9057                                  v8::AccessType type,
9058                                  Local<Value> data) {
9059   return true;
9060 }
9061
9062
9063 // Regression test.  In access checks, operations that may cause
9064 // garbage collection are not allowed.  It used to be the case that
9065 // using the Write operation on a string could cause a garbage
9066 // collection due to flattening of the string.  This is no longer the
9067 // case.
9068 THREADED_TEST(AccessControlFlatten) {
9069   named_access_count = 0;
9070   indexed_access_count = 0;
9071
9072   v8::Isolate* isolate = v8::Isolate::GetCurrent();
9073   v8::HandleScope handle_scope(isolate);
9074
9075   // Create an environment.
9076   v8::Local<Context> context0 = Context::New(isolate);
9077   context0->Enter();
9078
9079   // Create an object that requires access-check functions to be
9080   // called for cross-domain access.
9081   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
9082   object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
9083                                            IndexedAccessFlatten);
9084   Local<v8::Object> object = object_template->NewInstance();
9085
9086   v8::HandleScope scope1(isolate);
9087
9088   // Create another environment.
9089   v8::Local<Context> context1 = Context::New(isolate);
9090   context1->Enter();
9091
9092   // Make easy access to the object from the other environment.
9093   v8::Handle<v8::Object> global1 = context1->Global();
9094   global1->Set(v8_str("obj"), object);
9095
9096   v8::Handle<Value> value;
9097
9098   value = v8_compile("var p = 'as' + 'df';")->Run();
9099   value = v8_compile("obj[p];")->Run();
9100
9101   context1->Exit();
9102   context0->Exit();
9103 }
9104
9105
9106 static void AccessControlNamedGetter(
9107     Local<String>,
9108     const v8::PropertyCallbackInfo<v8::Value>& info) {
9109   info.GetReturnValue().Set(42);
9110 }
9111
9112
9113 static void AccessControlNamedSetter(
9114     Local<String>,
9115     Local<Value> value,
9116     const v8::PropertyCallbackInfo<v8::Value>& info) {
9117   info.GetReturnValue().Set(value);
9118 }
9119
9120
9121 static void AccessControlIndexedGetter(
9122       uint32_t index,
9123       const v8::PropertyCallbackInfo<v8::Value>& info) {
9124   info.GetReturnValue().Set(v8_num(42));
9125 }
9126
9127
9128 static void AccessControlIndexedSetter(
9129     uint32_t,
9130     Local<Value> value,
9131     const v8::PropertyCallbackInfo<v8::Value>& info) {
9132   info.GetReturnValue().Set(value);
9133 }
9134
9135
9136 THREADED_TEST(AccessControlInterceptorIC) {
9137   named_access_count = 0;
9138   indexed_access_count = 0;
9139
9140   v8::Isolate* isolate = v8::Isolate::GetCurrent();
9141   v8::HandleScope handle_scope(isolate);
9142
9143   // Create an environment.
9144   v8::Local<Context> context0 = Context::New(isolate);
9145   context0->Enter();
9146
9147   // Create an object that requires access-check functions to be
9148   // called for cross-domain access.  The object also has interceptors
9149   // interceptor.
9150   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
9151   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9152                                            IndexedAccessCounter);
9153   object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
9154                                            AccessControlNamedSetter);
9155   object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
9156                                              AccessControlIndexedSetter);
9157   Local<v8::Object> object = object_template->NewInstance();
9158
9159   v8::HandleScope scope1(isolate);
9160
9161   // Create another environment.
9162   v8::Local<Context> context1 = Context::New(isolate);
9163   context1->Enter();
9164
9165   // Make easy access to the object from the other environment.
9166   v8::Handle<v8::Object> global1 = context1->Global();
9167   global1->Set(v8_str("obj"), object);
9168
9169   v8::Handle<Value> value;
9170
9171   // Check that the named access-control function is called every time
9172   // eventhough there is an interceptor on the object.
9173   value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
9174   value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
9175                      "obj.x")->Run();
9176   CHECK(value->IsNumber());
9177   CHECK_EQ(42, value->Int32Value());
9178   CHECK_EQ(21, named_access_count);
9179
9180   value = v8_compile("var p = 'x';")->Run();
9181   value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
9182   value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
9183                      "obj[p]")->Run();
9184   CHECK(value->IsNumber());
9185   CHECK_EQ(42, value->Int32Value());
9186   CHECK_EQ(42, named_access_count);
9187
9188   // Check that the indexed access-control function is called every
9189   // time eventhough there is an interceptor on the object.
9190   value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
9191   value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
9192                      "obj[0]")->Run();
9193   CHECK(value->IsNumber());
9194   CHECK_EQ(42, value->Int32Value());
9195   CHECK_EQ(21, indexed_access_count);
9196
9197   context1->Exit();
9198   context0->Exit();
9199 }
9200
9201
9202 THREADED_TEST(Version) {
9203   v8::V8::GetVersion();
9204 }
9205
9206
9207 static void InstanceFunctionCallback(
9208     const v8::FunctionCallbackInfo<v8::Value>& args) {
9209   ApiTestFuzzer::Fuzz();
9210   args.GetReturnValue().Set(v8_num(12));
9211 }
9212
9213
9214 THREADED_TEST(InstanceProperties) {
9215   LocalContext context;
9216   v8::HandleScope handle_scope(context->GetIsolate());
9217
9218   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9219   Local<ObjectTemplate> instance = t->InstanceTemplate();
9220
9221   instance->Set(v8_str("x"), v8_num(42));
9222   instance->Set(v8_str("f"),
9223                 v8::FunctionTemplate::New(InstanceFunctionCallback));
9224
9225   Local<Value> o = t->GetFunction()->NewInstance();
9226
9227   context->Global()->Set(v8_str("i"), o);
9228   Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
9229   CHECK_EQ(42, value->Int32Value());
9230
9231   value = Script::Compile(v8_str("i.f()"))->Run();
9232   CHECK_EQ(12, value->Int32Value());
9233 }
9234
9235
9236 static void GlobalObjectInstancePropertiesGet(
9237     Local<String> key,
9238     const v8::PropertyCallbackInfo<v8::Value>&) {
9239   ApiTestFuzzer::Fuzz();
9240 }
9241
9242
9243 THREADED_TEST(GlobalObjectInstanceProperties) {
9244   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
9245
9246   Local<Value> global_object;
9247
9248   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9249   t->InstanceTemplate()->SetNamedPropertyHandler(
9250       GlobalObjectInstancePropertiesGet);
9251   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9252   instance_template->Set(v8_str("x"), v8_num(42));
9253   instance_template->Set(v8_str("f"),
9254                          v8::FunctionTemplate::New(InstanceFunctionCallback));
9255
9256   // The script to check how Crankshaft compiles missing global function
9257   // invocations.  function g is not defined and should throw on call.
9258   const char* script =
9259       "function wrapper(call) {"
9260       "  var x = 0, y = 1;"
9261       "  for (var i = 0; i < 1000; i++) {"
9262       "    x += i * 100;"
9263       "    y += i * 100;"
9264       "  }"
9265       "  if (call) g();"
9266       "}"
9267       "for (var i = 0; i < 17; i++) wrapper(false);"
9268       "var thrown = 0;"
9269       "try { wrapper(true); } catch (e) { thrown = 1; };"
9270       "thrown";
9271
9272   {
9273     LocalContext env(NULL, instance_template);
9274     // Hold on to the global object so it can be used again in another
9275     // environment initialization.
9276     global_object = env->Global();
9277
9278     Local<Value> value = Script::Compile(v8_str("x"))->Run();
9279     CHECK_EQ(42, value->Int32Value());
9280     value = Script::Compile(v8_str("f()"))->Run();
9281     CHECK_EQ(12, value->Int32Value());
9282     value = Script::Compile(v8_str(script))->Run();
9283     CHECK_EQ(1, value->Int32Value());
9284   }
9285
9286   {
9287     // Create new environment reusing the global object.
9288     LocalContext env(NULL, instance_template, global_object);
9289     Local<Value> value = Script::Compile(v8_str("x"))->Run();
9290     CHECK_EQ(42, value->Int32Value());
9291     value = Script::Compile(v8_str("f()"))->Run();
9292     CHECK_EQ(12, value->Int32Value());
9293     value = Script::Compile(v8_str(script))->Run();
9294     CHECK_EQ(1, value->Int32Value());
9295   }
9296 }
9297
9298
9299 THREADED_TEST(CallKnownGlobalReceiver) {
9300   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
9301
9302   Local<Value> global_object;
9303
9304   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9305   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9306
9307   // The script to check that we leave global object not
9308   // global object proxy on stack when we deoptimize from inside
9309   // arguments evaluation.
9310   // To provoke error we need to both force deoptimization
9311   // from arguments evaluation and to force CallIC to take
9312   // CallIC_Miss code path that can't cope with global proxy.
9313   const char* script =
9314       "function bar(x, y) { try { } finally { } }"
9315       "function baz(x) { try { } finally { } }"
9316       "function bom(x) { try { } finally { } }"
9317       "function foo(x) { bar([x], bom(2)); }"
9318       "for (var i = 0; i < 10000; i++) foo(1);"
9319       "foo";
9320
9321   Local<Value> foo;
9322   {
9323     LocalContext env(NULL, instance_template);
9324     // Hold on to the global object so it can be used again in another
9325     // environment initialization.
9326     global_object = env->Global();
9327     foo = Script::Compile(v8_str(script))->Run();
9328   }
9329
9330   {
9331     // Create new environment reusing the global object.
9332     LocalContext env(NULL, instance_template, global_object);
9333     env->Global()->Set(v8_str("foo"), foo);
9334     Script::Compile(v8_str("foo()"))->Run();
9335   }
9336 }
9337
9338
9339 static void ShadowFunctionCallback(
9340     const v8::FunctionCallbackInfo<v8::Value>& args) {
9341   ApiTestFuzzer::Fuzz();
9342   args.GetReturnValue().Set(v8_num(42));
9343 }
9344
9345
9346 static int shadow_y;
9347 static int shadow_y_setter_call_count;
9348 static int shadow_y_getter_call_count;
9349
9350
9351 static void ShadowYSetter(Local<String>,
9352                           Local<Value>,
9353                           const v8::PropertyCallbackInfo<void>&) {
9354   shadow_y_setter_call_count++;
9355   shadow_y = 42;
9356 }
9357
9358
9359 static void ShadowYGetter(Local<String> name,
9360                           const v8::PropertyCallbackInfo<v8::Value>& info) {
9361   ApiTestFuzzer::Fuzz();
9362   shadow_y_getter_call_count++;
9363   info.GetReturnValue().Set(v8_num(shadow_y));
9364 }
9365
9366
9367 static void ShadowIndexedGet(uint32_t index,
9368                              const v8::PropertyCallbackInfo<v8::Value>&) {
9369 }
9370
9371
9372 static void ShadowNamedGet(Local<String> key,
9373                            const v8::PropertyCallbackInfo<v8::Value>&) {
9374 }
9375
9376
9377 THREADED_TEST(ShadowObject) {
9378   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
9379   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
9380
9381   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
9382   LocalContext context(NULL, global_template);
9383
9384   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9385   t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
9386   t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
9387   Local<ObjectTemplate> proto = t->PrototypeTemplate();
9388   Local<ObjectTemplate> instance = t->InstanceTemplate();
9389
9390   proto->Set(v8_str("f"),
9391              v8::FunctionTemplate::New(ShadowFunctionCallback, Local<Value>()));
9392   proto->Set(v8_str("x"), v8_num(12));
9393
9394   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9395
9396   Local<Value> o = t->GetFunction()->NewInstance();
9397   context->Global()->Set(v8_str("__proto__"), o);
9398
9399   Local<Value> value =
9400       Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
9401   CHECK(value->IsBoolean());
9402   CHECK(!value->BooleanValue());
9403
9404   value = Script::Compile(v8_str("x"))->Run();
9405   CHECK_EQ(12, value->Int32Value());
9406
9407   value = Script::Compile(v8_str("f()"))->Run();
9408   CHECK_EQ(42, value->Int32Value());
9409
9410   Script::Compile(v8_str("y = 43"))->Run();
9411   CHECK_EQ(1, shadow_y_setter_call_count);
9412   value = Script::Compile(v8_str("y"))->Run();
9413   CHECK_EQ(1, shadow_y_getter_call_count);
9414   CHECK_EQ(42, value->Int32Value());
9415 }
9416
9417
9418 THREADED_TEST(HiddenPrototype) {
9419   LocalContext context;
9420   v8::HandleScope handle_scope(context->GetIsolate());
9421
9422   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
9423   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9424   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9425   t1->SetHiddenPrototype(true);
9426   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9427   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
9428   t2->SetHiddenPrototype(true);
9429   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9430   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
9431   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9432
9433   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9434   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9435   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9436   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9437
9438   // Setting the prototype on an object skips hidden prototypes.
9439   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9440   o0->Set(v8_str("__proto__"), o1);
9441   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9442   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9443   o0->Set(v8_str("__proto__"), o2);
9444   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9445   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9446   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9447   o0->Set(v8_str("__proto__"), o3);
9448   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9449   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9450   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9451   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9452
9453   // Getting the prototype of o0 should get the first visible one
9454   // which is o3.  Therefore, z should not be defined on the prototype
9455   // object.
9456   Local<Value> proto = o0->Get(v8_str("__proto__"));
9457   CHECK(proto->IsObject());
9458   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
9459 }
9460
9461
9462 THREADED_TEST(HiddenPrototypeSet) {
9463   LocalContext context;
9464   v8::HandleScope handle_scope(context->GetIsolate());
9465
9466   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New();
9467   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New();
9468   ht->SetHiddenPrototype(true);
9469   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New();
9470   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9471
9472   Local<v8::Object> o = ot->GetFunction()->NewInstance();
9473   Local<v8::Object> h = ht->GetFunction()->NewInstance();
9474   Local<v8::Object> p = pt->GetFunction()->NewInstance();
9475   o->Set(v8_str("__proto__"), h);
9476   h->Set(v8_str("__proto__"), p);
9477
9478   // Setting a property that exists on the hidden prototype goes there.
9479   o->Set(v8_str("x"), v8_num(7));
9480   CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
9481   CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
9482   CHECK(p->Get(v8_str("x"))->IsUndefined());
9483
9484   // Setting a new property should not be forwarded to the hidden prototype.
9485   o->Set(v8_str("y"), v8_num(6));
9486   CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
9487   CHECK(h->Get(v8_str("y"))->IsUndefined());
9488   CHECK(p->Get(v8_str("y"))->IsUndefined());
9489
9490   // Setting a property that only exists on a prototype of the hidden prototype
9491   // is treated normally again.
9492   p->Set(v8_str("z"), v8_num(8));
9493   CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
9494   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9495   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9496   o->Set(v8_str("z"), v8_num(9));
9497   CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
9498   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9499   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9500 }
9501
9502
9503 // Regression test for issue 2457.
9504 THREADED_TEST(HiddenPrototypeIdentityHash) {
9505   LocalContext context;
9506   v8::HandleScope handle_scope(context->GetIsolate());
9507
9508   Handle<FunctionTemplate> t = FunctionTemplate::New();
9509   t->SetHiddenPrototype(true);
9510   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
9511   Handle<Object> p = t->GetFunction()->NewInstance();
9512   Handle<Object> o = Object::New();
9513   o->SetPrototype(p);
9514
9515   int hash = o->GetIdentityHash();
9516   USE(hash);
9517   o->Set(v8_str("foo"), v8_num(42));
9518   ASSERT_EQ(hash, o->GetIdentityHash());
9519 }
9520
9521
9522 THREADED_TEST(SetPrototype) {
9523   LocalContext context;
9524   v8::HandleScope handle_scope(context->GetIsolate());
9525
9526   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
9527   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9528   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9529   t1->SetHiddenPrototype(true);
9530   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9531   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
9532   t2->SetHiddenPrototype(true);
9533   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9534   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
9535   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9536
9537   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9538   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9539   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9540   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9541
9542   // Setting the prototype on an object does not skip hidden prototypes.
9543   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9544   CHECK(o0->SetPrototype(o1));
9545   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9546   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9547   CHECK(o1->SetPrototype(o2));
9548   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9549   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9550   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9551   CHECK(o2->SetPrototype(o3));
9552   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9553   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9554   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9555   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9556
9557   // Getting the prototype of o0 should get the first visible one
9558   // which is o3.  Therefore, z should not be defined on the prototype
9559   // object.
9560   Local<Value> proto = o0->Get(v8_str("__proto__"));
9561   CHECK(proto->IsObject());
9562   CHECK_EQ(proto.As<v8::Object>(), o3);
9563
9564   // However, Object::GetPrototype ignores hidden prototype.
9565   Local<Value> proto0 = o0->GetPrototype();
9566   CHECK(proto0->IsObject());
9567   CHECK_EQ(proto0.As<v8::Object>(), o1);
9568
9569   Local<Value> proto1 = o1->GetPrototype();
9570   CHECK(proto1->IsObject());
9571   CHECK_EQ(proto1.As<v8::Object>(), o2);
9572
9573   Local<Value> proto2 = o2->GetPrototype();
9574   CHECK(proto2->IsObject());
9575   CHECK_EQ(proto2.As<v8::Object>(), o3);
9576 }
9577
9578
9579 // Getting property names of an object with a prototype chain that
9580 // triggers dictionary elements in GetLocalPropertyNames() shouldn't
9581 // crash the runtime.
9582 THREADED_TEST(Regress91517) {
9583   i::FLAG_allow_natives_syntax = true;
9584   LocalContext context;
9585   v8::HandleScope handle_scope(context->GetIsolate());
9586
9587   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9588   t1->SetHiddenPrototype(true);
9589   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
9590   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
9591   t2->SetHiddenPrototype(true);
9592   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
9593   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New());
9594   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
9595   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
9596   t3->SetHiddenPrototype(true);
9597   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
9598   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
9599   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
9600
9601   // Force dictionary-based properties.
9602   i::ScopedVector<char> name_buf(1024);
9603   for (int i = 1; i <= 1000; i++) {
9604     i::OS::SNPrintF(name_buf, "sdf%d", i);
9605     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
9606   }
9607
9608   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9609   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9610   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9611   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
9612
9613   // Create prototype chain of hidden prototypes.
9614   CHECK(o4->SetPrototype(o3));
9615   CHECK(o3->SetPrototype(o2));
9616   CHECK(o2->SetPrototype(o1));
9617
9618   // Call the runtime version of GetLocalPropertyNames() on the natively
9619   // created object through JavaScript.
9620   context->Global()->Set(v8_str("obj"), o4);
9621   CompileRun("var names = %GetLocalPropertyNames(obj, true);");
9622
9623   ExpectInt32("names.length", 1006);
9624   ExpectTrue("names.indexOf(\"baz\") >= 0");
9625   ExpectTrue("names.indexOf(\"boo\") >= 0");
9626   ExpectTrue("names.indexOf(\"foo\") >= 0");
9627   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
9628   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
9629   ExpectFalse("names[1005] == undefined");
9630 }
9631
9632
9633 THREADED_TEST(FunctionReadOnlyPrototype) {
9634   LocalContext context;
9635   v8::HandleScope handle_scope(context->GetIsolate());
9636
9637   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9638   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
9639   t1->ReadOnlyPrototype();
9640   context->Global()->Set(v8_str("func1"), t1->GetFunction());
9641   // Configured value of ReadOnly flag.
9642   CHECK(CompileRun(
9643       "(function() {"
9644       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
9645       "  return (descriptor['writable'] == false);"
9646       "})()")->BooleanValue());
9647   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
9648   CHECK_EQ(42,
9649            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
9650
9651   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
9652   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
9653   context->Global()->Set(v8_str("func2"), t2->GetFunction());
9654   // Default value of ReadOnly flag.
9655   CHECK(CompileRun(
9656       "(function() {"
9657       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
9658       "  return (descriptor['writable'] == true);"
9659       "})()")->BooleanValue());
9660   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
9661 }
9662
9663
9664 THREADED_TEST(SetPrototypeThrows) {
9665   LocalContext context;
9666   v8::HandleScope handle_scope(context->GetIsolate());
9667
9668   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9669
9670   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
9671   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
9672
9673   CHECK(o0->SetPrototype(o1));
9674   // If setting the prototype leads to the cycle, SetPrototype should
9675   // return false and keep VM in sane state.
9676   v8::TryCatch try_catch;
9677   CHECK(!o1->SetPrototype(o0));
9678   CHECK(!try_catch.HasCaught());
9679   ASSERT(!i::Isolate::Current()->has_pending_exception());
9680
9681   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
9682 }
9683
9684
9685 THREADED_TEST(FunctionRemovePrototype) {
9686   LocalContext context;
9687   v8::HandleScope handle_scope(context->GetIsolate());
9688
9689   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9690   t1->RemovePrototype();
9691   Local<v8::Function> fun = t1->GetFunction();
9692   context->Global()->Set(v8_str("fun"), fun);
9693   CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
9694
9695   v8::TryCatch try_catch;
9696   CompileRun("new fun()");
9697   CHECK(try_catch.HasCaught());
9698
9699   try_catch.Reset();
9700   fun->NewInstance();
9701   CHECK(try_catch.HasCaught());
9702 }
9703
9704
9705 THREADED_TEST(GetterSetterExceptions) {
9706   LocalContext context;
9707   v8::HandleScope handle_scope(context->GetIsolate());
9708   CompileRun(
9709     "function Foo() { };"
9710     "function Throw() { throw 5; };"
9711     "var x = { };"
9712     "x.__defineSetter__('set', Throw);"
9713     "x.__defineGetter__('get', Throw);");
9714   Local<v8::Object> x =
9715       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
9716   v8::TryCatch try_catch;
9717   x->Set(v8_str("set"), v8::Integer::New(8));
9718   x->Get(v8_str("get"));
9719   x->Set(v8_str("set"), v8::Integer::New(8));
9720   x->Get(v8_str("get"));
9721   x->Set(v8_str("set"), v8::Integer::New(8));
9722   x->Get(v8_str("get"));
9723   x->Set(v8_str("set"), v8::Integer::New(8));
9724   x->Get(v8_str("get"));
9725 }
9726
9727
9728 THREADED_TEST(Constructor) {
9729   LocalContext context;
9730   v8::HandleScope handle_scope(context->GetIsolate());
9731   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
9732   templ->SetClassName(v8_str("Fun"));
9733   Local<Function> cons = templ->GetFunction();
9734   context->Global()->Set(v8_str("Fun"), cons);
9735   Local<v8::Object> inst = cons->NewInstance();
9736   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
9737   CHECK(obj->IsJSObject());
9738   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
9739   CHECK(value->BooleanValue());
9740 }
9741
9742
9743 static void ConstructorCallback(
9744     const v8::FunctionCallbackInfo<v8::Value>& args) {
9745   ApiTestFuzzer::Fuzz();
9746   Local<Object> This;
9747
9748   if (args.IsConstructCall()) {
9749     Local<Object> Holder = args.Holder();
9750     This = Object::New();
9751     Local<Value> proto = Holder->GetPrototype();
9752     if (proto->IsObject()) {
9753       This->SetPrototype(proto);
9754     }
9755   } else {
9756     This = args.This();
9757   }
9758
9759   This->Set(v8_str("a"), args[0]);
9760   args.GetReturnValue().Set(This);
9761 }
9762
9763
9764 static void FakeConstructorCallback(
9765     const v8::FunctionCallbackInfo<v8::Value>& args) {
9766   ApiTestFuzzer::Fuzz();
9767   args.GetReturnValue().Set(args[0]);
9768 }
9769
9770
9771 THREADED_TEST(ConstructorForObject) {
9772   LocalContext context;
9773   v8::HandleScope handle_scope(context->GetIsolate());
9774
9775   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9776     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
9777     Local<Object> instance = instance_template->NewInstance();
9778     context->Global()->Set(v8_str("obj"), instance);
9779     v8::TryCatch try_catch;
9780     Local<Value> value;
9781     CHECK(!try_catch.HasCaught());
9782
9783     // Call the Object's constructor with a 32-bit signed integer.
9784     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
9785     CHECK(!try_catch.HasCaught());
9786     CHECK(value->IsInt32());
9787     CHECK_EQ(28, value->Int32Value());
9788
9789     Local<Value> args1[] = { v8_num(28) };
9790     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
9791     CHECK(value_obj1->IsObject());
9792     Local<Object> object1 = Local<Object>::Cast(value_obj1);
9793     value = object1->Get(v8_str("a"));
9794     CHECK(value->IsInt32());
9795     CHECK(!try_catch.HasCaught());
9796     CHECK_EQ(28, value->Int32Value());
9797
9798     // Call the Object's constructor with a String.
9799     value = CompileRun(
9800         "(function() { var o = new obj('tipli'); return o.a; })()");
9801     CHECK(!try_catch.HasCaught());
9802     CHECK(value->IsString());
9803     String::Utf8Value string_value1(value->ToString());
9804     CHECK_EQ("tipli", *string_value1);
9805
9806     Local<Value> args2[] = { v8_str("tipli") };
9807     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
9808     CHECK(value_obj2->IsObject());
9809     Local<Object> object2 = Local<Object>::Cast(value_obj2);
9810     value = object2->Get(v8_str("a"));
9811     CHECK(!try_catch.HasCaught());
9812     CHECK(value->IsString());
9813     String::Utf8Value string_value2(value->ToString());
9814     CHECK_EQ("tipli", *string_value2);
9815
9816     // Call the Object's constructor with a Boolean.
9817     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
9818     CHECK(!try_catch.HasCaught());
9819     CHECK(value->IsBoolean());
9820     CHECK_EQ(true, value->BooleanValue());
9821
9822     Handle<Value> args3[] = { v8::True() };
9823     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
9824     CHECK(value_obj3->IsObject());
9825     Local<Object> object3 = Local<Object>::Cast(value_obj3);
9826     value = object3->Get(v8_str("a"));
9827     CHECK(!try_catch.HasCaught());
9828     CHECK(value->IsBoolean());
9829     CHECK_EQ(true, value->BooleanValue());
9830
9831     // Call the Object's constructor with undefined.
9832     Handle<Value> args4[] = { v8::Undefined() };
9833     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
9834     CHECK(value_obj4->IsObject());
9835     Local<Object> object4 = Local<Object>::Cast(value_obj4);
9836     value = object4->Get(v8_str("a"));
9837     CHECK(!try_catch.HasCaught());
9838     CHECK(value->IsUndefined());
9839
9840     // Call the Object's constructor with null.
9841     Handle<Value> args5[] = { v8::Null() };
9842     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
9843     CHECK(value_obj5->IsObject());
9844     Local<Object> object5 = Local<Object>::Cast(value_obj5);
9845     value = object5->Get(v8_str("a"));
9846     CHECK(!try_catch.HasCaught());
9847     CHECK(value->IsNull());
9848   }
9849
9850   // Check exception handling when there is no constructor set for the Object.
9851   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9852     Local<Object> instance = instance_template->NewInstance();
9853     context->Global()->Set(v8_str("obj2"), instance);
9854     v8::TryCatch try_catch;
9855     Local<Value> value;
9856     CHECK(!try_catch.HasCaught());
9857
9858     value = CompileRun("new obj2(28)");
9859     CHECK(try_catch.HasCaught());
9860     String::Utf8Value exception_value1(try_catch.Exception());
9861     CHECK_EQ("TypeError: object is not a function", *exception_value1);
9862     try_catch.Reset();
9863
9864     Local<Value> args[] = { v8_num(29) };
9865     value = instance->CallAsConstructor(1, args);
9866     CHECK(try_catch.HasCaught());
9867     String::Utf8Value exception_value2(try_catch.Exception());
9868     CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
9869     try_catch.Reset();
9870   }
9871
9872   // Check the case when constructor throws exception.
9873   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9874     instance_template->SetCallAsFunctionHandler(ThrowValue);
9875     Local<Object> instance = instance_template->NewInstance();
9876     context->Global()->Set(v8_str("obj3"), instance);
9877     v8::TryCatch try_catch;
9878     Local<Value> value;
9879     CHECK(!try_catch.HasCaught());
9880
9881     value = CompileRun("new obj3(22)");
9882     CHECK(try_catch.HasCaught());
9883     String::Utf8Value exception_value1(try_catch.Exception());
9884     CHECK_EQ("22", *exception_value1);
9885     try_catch.Reset();
9886
9887     Local<Value> args[] = { v8_num(23) };
9888     value = instance->CallAsConstructor(1, args);
9889     CHECK(try_catch.HasCaught());
9890     String::Utf8Value exception_value2(try_catch.Exception());
9891     CHECK_EQ("23", *exception_value2);
9892     try_catch.Reset();
9893   }
9894
9895   // Check whether constructor returns with an object or non-object.
9896   { Local<FunctionTemplate> function_template =
9897         FunctionTemplate::New(FakeConstructorCallback);
9898     Local<Function> function = function_template->GetFunction();
9899     Local<Object> instance1 = function;
9900     context->Global()->Set(v8_str("obj4"), instance1);
9901     v8::TryCatch try_catch;
9902     Local<Value> value;
9903     CHECK(!try_catch.HasCaught());
9904
9905     CHECK(instance1->IsObject());
9906     CHECK(instance1->IsFunction());
9907
9908     value = CompileRun("new obj4(28)");
9909     CHECK(!try_catch.HasCaught());
9910     CHECK(value->IsObject());
9911
9912     Local<Value> args1[] = { v8_num(28) };
9913     value = instance1->CallAsConstructor(1, args1);
9914     CHECK(!try_catch.HasCaught());
9915     CHECK(value->IsObject());
9916
9917     Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9918     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
9919     Local<Object> instance2 = instance_template->NewInstance();
9920     context->Global()->Set(v8_str("obj5"), instance2);
9921     CHECK(!try_catch.HasCaught());
9922
9923     CHECK(instance2->IsObject());
9924     CHECK(!instance2->IsFunction());
9925
9926     value = CompileRun("new obj5(28)");
9927     CHECK(!try_catch.HasCaught());
9928     CHECK(!value->IsObject());
9929
9930     Local<Value> args2[] = { v8_num(28) };
9931     value = instance2->CallAsConstructor(1, args2);
9932     CHECK(!try_catch.HasCaught());
9933     CHECK(!value->IsObject());
9934   }
9935 }
9936
9937
9938 THREADED_TEST(FunctionDescriptorException) {
9939   LocalContext context;
9940   v8::HandleScope handle_scope(context->GetIsolate());
9941   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
9942   templ->SetClassName(v8_str("Fun"));
9943   Local<Function> cons = templ->GetFunction();
9944   context->Global()->Set(v8_str("Fun"), cons);
9945   Local<Value> value = CompileRun(
9946     "function test() {"
9947     "  try {"
9948     "    (new Fun()).blah()"
9949     "  } catch (e) {"
9950     "    var str = String(e);"
9951     "    if (str.indexOf('TypeError') == -1) return 1;"
9952     "    if (str.indexOf('[object Fun]') != -1) return 2;"
9953     "    if (str.indexOf('#<Fun>') == -1) return 3;"
9954     "    return 0;"
9955     "  }"
9956     "  return 4;"
9957     "}"
9958     "test();");
9959   CHECK_EQ(0, value->Int32Value());
9960 }
9961
9962
9963 THREADED_TEST(EvalAliasedDynamic) {
9964   LocalContext current;
9965   v8::HandleScope scope(current->GetIsolate());
9966
9967   // Tests where aliased eval can only be resolved dynamically.
9968   Local<Script> script =
9969       Script::Compile(v8_str("function f(x) { "
9970                              "  var foo = 2;"
9971                              "  with (x) { return eval('foo'); }"
9972                              "}"
9973                              "foo = 0;"
9974                              "result1 = f(new Object());"
9975                              "result2 = f(this);"
9976                              "var x = new Object();"
9977                              "x.eval = function(x) { return 1; };"
9978                              "result3 = f(x);"));
9979   script->Run();
9980   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
9981   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
9982   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
9983
9984   v8::TryCatch try_catch;
9985   script =
9986     Script::Compile(v8_str("function f(x) { "
9987                            "  var bar = 2;"
9988                            "  with (x) { return eval('bar'); }"
9989                            "}"
9990                            "result4 = f(this)"));
9991   script->Run();
9992   CHECK(!try_catch.HasCaught());
9993   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
9994
9995   try_catch.Reset();
9996 }
9997
9998
9999 THREADED_TEST(CrossEval) {
10000   v8::HandleScope scope(v8::Isolate::GetCurrent());
10001   LocalContext other;
10002   LocalContext current;
10003
10004   Local<String> token = v8_str("<security token>");
10005   other->SetSecurityToken(token);
10006   current->SetSecurityToken(token);
10007
10008   // Set up reference from current to other.
10009   current->Global()->Set(v8_str("other"), other->Global());
10010
10011   // Check that new variables are introduced in other context.
10012   Local<Script> script =
10013       Script::Compile(v8_str("other.eval('var foo = 1234')"));
10014   script->Run();
10015   Local<Value> foo = other->Global()->Get(v8_str("foo"));
10016   CHECK_EQ(1234, foo->Int32Value());
10017   CHECK(!current->Global()->Has(v8_str("foo")));
10018
10019   // Check that writing to non-existing properties introduces them in
10020   // the other context.
10021   script =
10022       Script::Compile(v8_str("other.eval('na = 1234')"));
10023   script->Run();
10024   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10025   CHECK(!current->Global()->Has(v8_str("na")));
10026
10027   // Check that global variables in current context are not visible in other
10028   // context.
10029   v8::TryCatch try_catch;
10030   script =
10031       Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
10032   Local<Value> result = script->Run();
10033   CHECK(try_catch.HasCaught());
10034   try_catch.Reset();
10035
10036   // Check that local variables in current context are not visible in other
10037   // context.
10038   script =
10039       Script::Compile(v8_str("(function() { "
10040                              "  var baz = 87;"
10041                              "  return other.eval('baz');"
10042                              "})();"));
10043   result = script->Run();
10044   CHECK(try_catch.HasCaught());
10045   try_catch.Reset();
10046
10047   // Check that global variables in the other environment are visible
10048   // when evaluting code.
10049   other->Global()->Set(v8_str("bis"), v8_num(1234));
10050   script = Script::Compile(v8_str("other.eval('bis')"));
10051   CHECK_EQ(1234, script->Run()->Int32Value());
10052   CHECK(!try_catch.HasCaught());
10053
10054   // Check that the 'this' pointer points to the global object evaluating
10055   // code.
10056   other->Global()->Set(v8_str("t"), other->Global());
10057   script = Script::Compile(v8_str("other.eval('this == t')"));
10058   result = script->Run();
10059   CHECK(result->IsTrue());
10060   CHECK(!try_catch.HasCaught());
10061
10062   // Check that variables introduced in with-statement are not visible in
10063   // other context.
10064   script =
10065       Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
10066   result = script->Run();
10067   CHECK(try_catch.HasCaught());
10068   try_catch.Reset();
10069
10070   // Check that you cannot use 'eval.call' with another object than the
10071   // current global object.
10072   script =
10073       Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
10074   result = script->Run();
10075   CHECK(try_catch.HasCaught());
10076 }
10077
10078
10079 // Test that calling eval in a context which has been detached from
10080 // its global throws an exception.  This behavior is consistent with
10081 // other JavaScript implementations.
10082 THREADED_TEST(EvalInDetachedGlobal) {
10083   v8::Isolate* isolate = v8::Isolate::GetCurrent();
10084   v8::HandleScope scope(isolate);
10085
10086   v8::Local<Context> context0 = Context::New(isolate);
10087   v8::Local<Context> context1 = Context::New(isolate);
10088
10089   // Set up function in context0 that uses eval from context0.
10090   context0->Enter();
10091   v8::Handle<v8::Value> fun =
10092       CompileRun("var x = 42;"
10093                  "(function() {"
10094                  "  var e = eval;"
10095                  "  return function(s) { return e(s); }"
10096                  "})()");
10097   context0->Exit();
10098
10099   // Put the function into context1 and call it before and after
10100   // detaching the global.  Before detaching, the call succeeds and
10101   // after detaching and exception is thrown.
10102   context1->Enter();
10103   context1->Global()->Set(v8_str("fun"), fun);
10104   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10105   CHECK_EQ(42, x_value->Int32Value());
10106   context0->DetachGlobal();
10107   v8::TryCatch catcher;
10108   x_value = CompileRun("fun('x')");
10109   CHECK(x_value.IsEmpty());
10110   CHECK(catcher.HasCaught());
10111   context1->Exit();
10112 }
10113
10114
10115 THREADED_TEST(CrossLazyLoad) {
10116   v8::HandleScope scope(v8::Isolate::GetCurrent());
10117   LocalContext other;
10118   LocalContext current;
10119
10120   Local<String> token = v8_str("<security token>");
10121   other->SetSecurityToken(token);
10122   current->SetSecurityToken(token);
10123
10124   // Set up reference from current to other.
10125   current->Global()->Set(v8_str("other"), other->Global());
10126
10127   // Trigger lazy loading in other context.
10128   Local<Script> script =
10129       Script::Compile(v8_str("other.eval('new Date(42)')"));
10130   Local<Value> value = script->Run();
10131   CHECK_EQ(42.0, value->NumberValue());
10132 }
10133
10134
10135 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
10136   ApiTestFuzzer::Fuzz();
10137   if (args.IsConstructCall()) {
10138     if (args[0]->IsInt32()) {
10139       args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10140       return;
10141     }
10142   }
10143
10144   args.GetReturnValue().Set(args[0]);
10145 }
10146
10147
10148 // Test that a call handler can be set for objects which will allow
10149 // non-function objects created through the API to be called as
10150 // functions.
10151 THREADED_TEST(CallAsFunction) {
10152   LocalContext context;
10153   v8::HandleScope scope(context->GetIsolate());
10154
10155   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
10156     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10157     instance_template->SetCallAsFunctionHandler(call_as_function);
10158     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10159     context->Global()->Set(v8_str("obj"), instance);
10160     v8::TryCatch try_catch;
10161     Local<Value> value;
10162     CHECK(!try_catch.HasCaught());
10163
10164     value = CompileRun("obj(42)");
10165     CHECK(!try_catch.HasCaught());
10166     CHECK_EQ(42, value->Int32Value());
10167
10168     value = CompileRun("(function(o){return o(49)})(obj)");
10169     CHECK(!try_catch.HasCaught());
10170     CHECK_EQ(49, value->Int32Value());
10171
10172     // test special case of call as function
10173     value = CompileRun("[obj]['0'](45)");
10174     CHECK(!try_catch.HasCaught());
10175     CHECK_EQ(45, value->Int32Value());
10176
10177     value = CompileRun("obj.call = Function.prototype.call;"
10178                        "obj.call(null, 87)");
10179     CHECK(!try_catch.HasCaught());
10180     CHECK_EQ(87, value->Int32Value());
10181
10182     // Regression tests for bug #1116356: Calling call through call/apply
10183     // must work for non-function receivers.
10184     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10185     value = CompileRun(apply_99);
10186     CHECK(!try_catch.HasCaught());
10187     CHECK_EQ(99, value->Int32Value());
10188
10189     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10190     value = CompileRun(call_17);
10191     CHECK(!try_catch.HasCaught());
10192     CHECK_EQ(17, value->Int32Value());
10193
10194     // Check that the call-as-function handler can be called through
10195     // new.
10196     value = CompileRun("new obj(43)");
10197     CHECK(!try_catch.HasCaught());
10198     CHECK_EQ(-43, value->Int32Value());
10199
10200     // Check that the call-as-function handler can be called through
10201     // the API.
10202     v8::Handle<Value> args[] = { v8_num(28) };
10203     value = instance->CallAsFunction(instance, 1, args);
10204     CHECK(!try_catch.HasCaught());
10205     CHECK_EQ(28, value->Int32Value());
10206   }
10207
10208   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
10209     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
10210     USE(instance_template);
10211     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10212     context->Global()->Set(v8_str("obj2"), instance);
10213     v8::TryCatch try_catch;
10214     Local<Value> value;
10215     CHECK(!try_catch.HasCaught());
10216
10217     // Call an object without call-as-function handler through the JS
10218     value = CompileRun("obj2(28)");
10219     CHECK(value.IsEmpty());
10220     CHECK(try_catch.HasCaught());
10221     String::Utf8Value exception_value1(try_catch.Exception());
10222     CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
10223              *exception_value1);
10224     try_catch.Reset();
10225
10226     // Call an object without call-as-function handler through the API
10227     value = CompileRun("obj2(28)");
10228     v8::Handle<Value> args[] = { v8_num(28) };
10229     value = instance->CallAsFunction(instance, 1, args);
10230     CHECK(value.IsEmpty());
10231     CHECK(try_catch.HasCaught());
10232     String::Utf8Value exception_value2(try_catch.Exception());
10233     CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
10234     try_catch.Reset();
10235   }
10236
10237   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
10238     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10239     instance_template->SetCallAsFunctionHandler(ThrowValue);
10240     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10241     context->Global()->Set(v8_str("obj3"), instance);
10242     v8::TryCatch try_catch;
10243     Local<Value> value;
10244     CHECK(!try_catch.HasCaught());
10245
10246     // Catch the exception which is thrown by call-as-function handler
10247     value = CompileRun("obj3(22)");
10248     CHECK(try_catch.HasCaught());
10249     String::Utf8Value exception_value1(try_catch.Exception());
10250     CHECK_EQ("22", *exception_value1);
10251     try_catch.Reset();
10252
10253     v8::Handle<Value> args[] = { v8_num(23) };
10254     value = instance->CallAsFunction(instance, 1, args);
10255     CHECK(try_catch.HasCaught());
10256     String::Utf8Value exception_value2(try_catch.Exception());
10257     CHECK_EQ("23", *exception_value2);
10258     try_catch.Reset();
10259   }
10260 }
10261
10262
10263 // Check whether a non-function object is callable.
10264 THREADED_TEST(CallableObject) {
10265   LocalContext context;
10266   v8::HandleScope scope(context->GetIsolate());
10267
10268   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
10269     instance_template->SetCallAsFunctionHandler(call_as_function);
10270     Local<Object> instance = instance_template->NewInstance();
10271     v8::TryCatch try_catch;
10272
10273     CHECK(instance->IsCallable());
10274     CHECK(!try_catch.HasCaught());
10275   }
10276
10277   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
10278     Local<Object> instance = instance_template->NewInstance();
10279     v8::TryCatch try_catch;
10280
10281     CHECK(!instance->IsCallable());
10282     CHECK(!try_catch.HasCaught());
10283   }
10284
10285   { Local<FunctionTemplate> function_template =
10286         FunctionTemplate::New(call_as_function);
10287     Local<Function> function = function_template->GetFunction();
10288     Local<Object> instance = function;
10289     v8::TryCatch try_catch;
10290
10291     CHECK(instance->IsCallable());
10292     CHECK(!try_catch.HasCaught());
10293   }
10294
10295   { Local<FunctionTemplate> function_template = FunctionTemplate::New();
10296     Local<Function> function = function_template->GetFunction();
10297     Local<Object> instance = function;
10298     v8::TryCatch try_catch;
10299
10300     CHECK(instance->IsCallable());
10301     CHECK(!try_catch.HasCaught());
10302   }
10303 }
10304
10305
10306 static int CountHandles() {
10307   return v8::HandleScope::NumberOfHandles();
10308 }
10309
10310
10311 static int Recurse(int depth, int iterations) {
10312   v8::HandleScope scope(v8::Isolate::GetCurrent());
10313   if (depth == 0) return CountHandles();
10314   for (int i = 0; i < iterations; i++) {
10315     Local<v8::Number> n(v8::Integer::New(42));
10316   }
10317   return Recurse(depth - 1, iterations);
10318 }
10319
10320
10321 THREADED_TEST(HandleIteration) {
10322   static const int kIterations = 500;
10323   static const int kNesting = 200;
10324   CHECK_EQ(0, CountHandles());
10325   {
10326     v8::HandleScope scope1(v8::Isolate::GetCurrent());
10327     CHECK_EQ(0, CountHandles());
10328     for (int i = 0; i < kIterations; i++) {
10329       Local<v8::Number> n(v8::Integer::New(42));
10330       CHECK_EQ(i + 1, CountHandles());
10331     }
10332
10333     CHECK_EQ(kIterations, CountHandles());
10334     {
10335       v8::HandleScope scope2(v8::Isolate::GetCurrent());
10336       for (int j = 0; j < kIterations; j++) {
10337         Local<v8::Number> n(v8::Integer::New(42));
10338         CHECK_EQ(j + 1 + kIterations, CountHandles());
10339       }
10340     }
10341     CHECK_EQ(kIterations, CountHandles());
10342   }
10343   CHECK_EQ(0, CountHandles());
10344   CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
10345 }
10346
10347
10348 static void InterceptorHasOwnPropertyGetter(
10349     Local<String> name,
10350     const v8::PropertyCallbackInfo<v8::Value>& info) {
10351   ApiTestFuzzer::Fuzz();
10352 }
10353
10354
10355 THREADED_TEST(InterceptorHasOwnProperty) {
10356   LocalContext context;
10357   v8::HandleScope scope(context->GetIsolate());
10358   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10359   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
10360   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
10361   Local<Function> function = fun_templ->GetFunction();
10362   context->Global()->Set(v8_str("constructor"), function);
10363   v8::Handle<Value> value = CompileRun(
10364       "var o = new constructor();"
10365       "o.hasOwnProperty('ostehaps');");
10366   CHECK_EQ(false, value->BooleanValue());
10367   value = CompileRun(
10368       "o.ostehaps = 42;"
10369       "o.hasOwnProperty('ostehaps');");
10370   CHECK_EQ(true, value->BooleanValue());
10371   value = CompileRun(
10372       "var p = new constructor();"
10373       "p.hasOwnProperty('ostehaps');");
10374   CHECK_EQ(false, value->BooleanValue());
10375 }
10376
10377
10378 static void InterceptorHasOwnPropertyGetterGC(
10379     Local<String> name,
10380     const v8::PropertyCallbackInfo<v8::Value>& info) {
10381   ApiTestFuzzer::Fuzz();
10382   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
10383 }
10384
10385
10386 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
10387   LocalContext context;
10388   v8::HandleScope scope(context->GetIsolate());
10389   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10390   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
10391   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
10392   Local<Function> function = fun_templ->GetFunction();
10393   context->Global()->Set(v8_str("constructor"), function);
10394   // Let's first make some stuff so we can be sure to get a good GC.
10395   CompileRun(
10396       "function makestr(size) {"
10397       "  switch (size) {"
10398       "    case 1: return 'f';"
10399       "    case 2: return 'fo';"
10400       "    case 3: return 'foo';"
10401       "  }"
10402       "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
10403       "}"
10404       "var x = makestr(12345);"
10405       "x = makestr(31415);"
10406       "x = makestr(23456);");
10407   v8::Handle<Value> value = CompileRun(
10408       "var o = new constructor();"
10409       "o.__proto__ = new String(x);"
10410       "o.hasOwnProperty('ostehaps');");
10411   CHECK_EQ(false, value->BooleanValue());
10412 }
10413
10414
10415 typedef void (*NamedPropertyGetter)(
10416     Local<String> property,
10417     const v8::PropertyCallbackInfo<v8::Value>& info);
10418
10419
10420 static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
10421                                    const char* source,
10422                                    int expected) {
10423   v8::HandleScope scope(v8::Isolate::GetCurrent());
10424   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10425   templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
10426   LocalContext context;
10427   context->Global()->Set(v8_str("o"), templ->NewInstance());
10428   v8::Handle<Value> value = CompileRun(source);
10429   CHECK_EQ(expected, value->Int32Value());
10430 }
10431
10432
10433 static void InterceptorLoadICGetter(
10434     Local<String> name,
10435     const v8::PropertyCallbackInfo<v8::Value>& info) {
10436   ApiTestFuzzer::Fuzz();
10437   v8::Isolate* isolate = v8::Isolate::GetCurrent();
10438   CHECK_EQ(isolate, info.GetIsolate());
10439   CHECK_EQ(v8_str("data"), info.Data());
10440   CHECK_EQ(v8_str("x"), name);
10441   info.GetReturnValue().Set(v8::Integer::New(42));
10442 }
10443
10444
10445 // This test should hit the load IC for the interceptor case.
10446 THREADED_TEST(InterceptorLoadIC) {
10447   CheckInterceptorLoadIC(InterceptorLoadICGetter,
10448     "var result = 0;"
10449     "for (var i = 0; i < 1000; i++) {"
10450     "  result = o.x;"
10451     "}",
10452     42);
10453 }
10454
10455
10456 // Below go several tests which verify that JITing for various
10457 // configurations of interceptor and explicit fields works fine
10458 // (those cases are special cased to get better performance).
10459
10460 static void InterceptorLoadXICGetter(
10461     Local<String> name,
10462     const v8::PropertyCallbackInfo<v8::Value>& info) {
10463   ApiTestFuzzer::Fuzz();
10464   info.GetReturnValue().Set(
10465       v8_str("x")->Equals(name) ?
10466           v8::Handle<v8::Value>(v8::Integer::New(42)) :
10467           v8::Handle<v8::Value>());
10468 }
10469
10470
10471 THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
10472   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10473     "var result = 0;"
10474     "o.y = 239;"
10475     "for (var i = 0; i < 1000; i++) {"
10476     "  result = o.y;"
10477     "}",
10478     239);
10479 }
10480
10481
10482 THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
10483   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10484     "var result = 0;"
10485     "o.__proto__ = { 'y': 239 };"
10486     "for (var i = 0; i < 1000; i++) {"
10487     "  result = o.y + o.x;"
10488     "}",
10489     239 + 42);
10490 }
10491
10492
10493 THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
10494   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10495     "var result = 0;"
10496     "o.__proto__.y = 239;"
10497     "for (var i = 0; i < 1000; i++) {"
10498     "  result = o.y + o.x;"
10499     "}",
10500     239 + 42);
10501 }
10502
10503
10504 THREADED_TEST(InterceptorLoadICUndefined) {
10505   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10506     "var result = 0;"
10507     "for (var i = 0; i < 1000; i++) {"
10508     "  result = (o.y == undefined) ? 239 : 42;"
10509     "}",
10510     239);
10511 }
10512
10513
10514 THREADED_TEST(InterceptorLoadICWithOverride) {
10515   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10516     "fst = new Object();  fst.__proto__ = o;"
10517     "snd = new Object();  snd.__proto__ = fst;"
10518     "var result1 = 0;"
10519     "for (var i = 0; i < 1000;  i++) {"
10520     "  result1 = snd.x;"
10521     "}"
10522     "fst.x = 239;"
10523     "var result = 0;"
10524     "for (var i = 0; i < 1000; i++) {"
10525     "  result = snd.x;"
10526     "}"
10527     "result + result1",
10528     239 + 42);
10529 }
10530
10531
10532 // Test the case when we stored field into
10533 // a stub, but interceptor produced value on its own.
10534 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
10535   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10536     "proto = new Object();"
10537     "o.__proto__ = proto;"
10538     "proto.x = 239;"
10539     "for (var i = 0; i < 1000; i++) {"
10540     "  o.x;"
10541     // Now it should be ICed and keep a reference to x defined on proto
10542     "}"
10543     "var result = 0;"
10544     "for (var i = 0; i < 1000; i++) {"
10545     "  result += o.x;"
10546     "}"
10547     "result;",
10548     42 * 1000);
10549 }
10550
10551
10552 // Test the case when we stored field into
10553 // a stub, but it got invalidated later on.
10554 THREADED_TEST(InterceptorLoadICInvalidatedField) {
10555   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10556     "proto1 = new Object();"
10557     "proto2 = new Object();"
10558     "o.__proto__ = proto1;"
10559     "proto1.__proto__ = proto2;"
10560     "proto2.y = 239;"
10561     "for (var i = 0; i < 1000; i++) {"
10562     "  o.y;"
10563     // Now it should be ICed and keep a reference to y defined on proto2
10564     "}"
10565     "proto1.y = 42;"
10566     "var result = 0;"
10567     "for (var i = 0; i < 1000; i++) {"
10568     "  result += o.y;"
10569     "}"
10570     "result;",
10571     42 * 1000);
10572 }
10573
10574
10575 static int interceptor_load_not_handled_calls = 0;
10576 static void InterceptorLoadNotHandled(
10577     Local<String> name,
10578     const v8::PropertyCallbackInfo<v8::Value>& info) {
10579   ++interceptor_load_not_handled_calls;
10580 }
10581
10582
10583 // Test how post-interceptor lookups are done in the non-cacheable
10584 // case: the interceptor should not be invoked during this lookup.
10585 THREADED_TEST(InterceptorLoadICPostInterceptor) {
10586   interceptor_load_not_handled_calls = 0;
10587   CheckInterceptorLoadIC(InterceptorLoadNotHandled,
10588     "receiver = new Object();"
10589     "receiver.__proto__ = o;"
10590     "proto = new Object();"
10591     "/* Make proto a slow-case object. */"
10592     "for (var i = 0; i < 1000; i++) {"
10593     "  proto[\"xxxxxxxx\" + i] = [];"
10594     "}"
10595     "proto.x = 17;"
10596     "o.__proto__ = proto;"
10597     "var result = 0;"
10598     "for (var i = 0; i < 1000; i++) {"
10599     "  result += receiver.x;"
10600     "}"
10601     "result;",
10602     17 * 1000);
10603   CHECK_EQ(1000, interceptor_load_not_handled_calls);
10604 }
10605
10606
10607 // Test the case when we stored field into
10608 // a stub, but it got invalidated later on due to override on
10609 // global object which is between interceptor and fields' holders.
10610 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
10611   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10612     "o.__proto__ = this;"  // set a global to be a proto of o.
10613     "this.__proto__.y = 239;"
10614     "for (var i = 0; i < 10; i++) {"
10615     "  if (o.y != 239) throw 'oops: ' + o.y;"
10616     // Now it should be ICed and keep a reference to y defined on field_holder.
10617     "}"
10618     "this.y = 42;"  // Assign on a global.
10619     "var result = 0;"
10620     "for (var i = 0; i < 10; i++) {"
10621     "  result += o.y;"
10622     "}"
10623     "result;",
10624     42 * 10);
10625 }
10626
10627
10628 static void SetOnThis(Local<String> name,
10629                       Local<Value> value,
10630                       const v8::PropertyCallbackInfo<void>& info) {
10631   info.This()->ForceSet(name, value);
10632 }
10633
10634
10635 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
10636   v8::HandleScope scope(v8::Isolate::GetCurrent());
10637   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10638   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10639   templ->SetAccessor(v8_str("y"), Return239Callback);
10640   LocalContext context;
10641   context->Global()->Set(v8_str("o"), templ->NewInstance());
10642
10643   // Check the case when receiver and interceptor's holder
10644   // are the same objects.
10645   v8::Handle<Value> value = CompileRun(
10646       "var result = 0;"
10647       "for (var i = 0; i < 7; i++) {"
10648       "  result = o.y;"
10649       "}");
10650   CHECK_EQ(239, value->Int32Value());
10651
10652   // Check the case when interceptor's holder is in proto chain
10653   // of receiver.
10654   value = CompileRun(
10655       "r = { __proto__: o };"
10656       "var result = 0;"
10657       "for (var i = 0; i < 7; i++) {"
10658       "  result = r.y;"
10659       "}");
10660   CHECK_EQ(239, value->Int32Value());
10661 }
10662
10663
10664 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
10665   v8::HandleScope scope(v8::Isolate::GetCurrent());
10666   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10667   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10668   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
10669   templ_p->SetAccessor(v8_str("y"), Return239Callback);
10670
10671   LocalContext context;
10672   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10673   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
10674
10675   // Check the case when receiver and interceptor's holder
10676   // are the same objects.
10677   v8::Handle<Value> value = CompileRun(
10678       "o.__proto__ = p;"
10679       "var result = 0;"
10680       "for (var i = 0; i < 7; i++) {"
10681       "  result = o.x + o.y;"
10682       "}");
10683   CHECK_EQ(239 + 42, value->Int32Value());
10684
10685   // Check the case when interceptor's holder is in proto chain
10686   // of receiver.
10687   value = CompileRun(
10688       "r = { __proto__: o };"
10689       "var result = 0;"
10690       "for (var i = 0; i < 7; i++) {"
10691       "  result = r.x + r.y;"
10692       "}");
10693   CHECK_EQ(239 + 42, value->Int32Value());
10694 }
10695
10696
10697 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
10698   v8::HandleScope scope(v8::Isolate::GetCurrent());
10699   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10700   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10701   templ->SetAccessor(v8_str("y"), Return239Callback);
10702
10703   LocalContext context;
10704   context->Global()->Set(v8_str("o"), templ->NewInstance());
10705
10706   v8::Handle<Value> value = CompileRun(
10707     "fst = new Object();  fst.__proto__ = o;"
10708     "snd = new Object();  snd.__proto__ = fst;"
10709     "var result1 = 0;"
10710     "for (var i = 0; i < 7;  i++) {"
10711     "  result1 = snd.x;"
10712     "}"
10713     "fst.x = 239;"
10714     "var result = 0;"
10715     "for (var i = 0; i < 7; i++) {"
10716     "  result = snd.x;"
10717     "}"
10718     "result + result1");
10719   CHECK_EQ(239 + 42, value->Int32Value());
10720 }
10721
10722
10723 // Test the case when we stored callback into
10724 // a stub, but interceptor produced value on its own.
10725 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
10726   v8::HandleScope scope(v8::Isolate::GetCurrent());
10727   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10728   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10729   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
10730   templ_p->SetAccessor(v8_str("y"), Return239Callback);
10731
10732   LocalContext context;
10733   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10734   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
10735
10736   v8::Handle<Value> value = CompileRun(
10737     "o.__proto__ = p;"
10738     "for (var i = 0; i < 7; i++) {"
10739     "  o.x;"
10740     // Now it should be ICed and keep a reference to x defined on p
10741     "}"
10742     "var result = 0;"
10743     "for (var i = 0; i < 7; i++) {"
10744     "  result += o.x;"
10745     "}"
10746     "result");
10747   CHECK_EQ(42 * 7, value->Int32Value());
10748 }
10749
10750
10751 // Test the case when we stored callback into
10752 // a stub, but it got invalidated later on.
10753 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
10754   v8::HandleScope scope(v8::Isolate::GetCurrent());
10755   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10756   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10757   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
10758   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
10759
10760   LocalContext context;
10761   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10762   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
10763
10764   v8::Handle<Value> value = CompileRun(
10765     "inbetween = new Object();"
10766     "o.__proto__ = inbetween;"
10767     "inbetween.__proto__ = p;"
10768     "for (var i = 0; i < 10; i++) {"
10769     "  o.y;"
10770     // Now it should be ICed and keep a reference to y defined on p
10771     "}"
10772     "inbetween.y = 42;"
10773     "var result = 0;"
10774     "for (var i = 0; i < 10; i++) {"
10775     "  result += o.y;"
10776     "}"
10777     "result");
10778   CHECK_EQ(42 * 10, value->Int32Value());
10779 }
10780
10781
10782 // Test the case when we stored callback into
10783 // a stub, but it got invalidated later on due to override on
10784 // global object which is between interceptor and callbacks' holders.
10785 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
10786   v8::HandleScope scope(v8::Isolate::GetCurrent());
10787   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10788   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10789   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
10790   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
10791
10792   LocalContext context;
10793   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10794   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
10795
10796   v8::Handle<Value> value = CompileRun(
10797     "o.__proto__ = this;"
10798     "this.__proto__ = p;"
10799     "for (var i = 0; i < 10; i++) {"
10800     "  if (o.y != 239) throw 'oops: ' + o.y;"
10801     // Now it should be ICed and keep a reference to y defined on p
10802     "}"
10803     "this.y = 42;"
10804     "var result = 0;"
10805     "for (var i = 0; i < 10; i++) {"
10806     "  result += o.y;"
10807     "}"
10808     "result");
10809   CHECK_EQ(42 * 10, value->Int32Value());
10810 }
10811
10812
10813 static void InterceptorLoadICGetter0(
10814     Local<String> name,
10815     const v8::PropertyCallbackInfo<v8::Value>& info) {
10816   ApiTestFuzzer::Fuzz();
10817   CHECK(v8_str("x")->Equals(name));
10818   info.GetReturnValue().Set(v8::Integer::New(0));
10819 }
10820
10821
10822 THREADED_TEST(InterceptorReturningZero) {
10823   CheckInterceptorLoadIC(InterceptorLoadICGetter0,
10824      "o.x == undefined ? 1 : 0",
10825      0);
10826 }
10827
10828
10829 static void InterceptorStoreICSetter(
10830     Local<String> key,
10831     Local<Value> value,
10832     const v8::PropertyCallbackInfo<v8::Value>& info) {
10833   CHECK(v8_str("x")->Equals(key));
10834   CHECK_EQ(42, value->Int32Value());
10835   info.GetReturnValue().Set(value);
10836 }
10837
10838
10839 // This test should hit the store IC for the interceptor case.
10840 THREADED_TEST(InterceptorStoreIC) {
10841   v8::HandleScope scope(v8::Isolate::GetCurrent());
10842   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10843   templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
10844                                  InterceptorStoreICSetter,
10845                                  0, 0, 0, v8_str("data"));
10846   LocalContext context;
10847   context->Global()->Set(v8_str("o"), templ->NewInstance());
10848   CompileRun(
10849       "for (var i = 0; i < 1000; i++) {"
10850       "  o.x = 42;"
10851       "}");
10852 }
10853
10854
10855 THREADED_TEST(InterceptorStoreICWithNoSetter) {
10856   v8::HandleScope scope(v8::Isolate::GetCurrent());
10857   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10858   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10859   LocalContext context;
10860   context->Global()->Set(v8_str("o"), templ->NewInstance());
10861   v8::Handle<Value> value = CompileRun(
10862     "for (var i = 0; i < 1000; i++) {"
10863     "  o.y = 239;"
10864     "}"
10865     "42 + o.y");
10866   CHECK_EQ(239 + 42, value->Int32Value());
10867 }
10868
10869
10870
10871
10872 v8::Handle<Value> call_ic_function;
10873 v8::Handle<Value> call_ic_function2;
10874 v8::Handle<Value> call_ic_function3;
10875
10876 static void InterceptorCallICGetter(
10877     Local<String> name,
10878     const v8::PropertyCallbackInfo<v8::Value>& info) {
10879   ApiTestFuzzer::Fuzz();
10880   CHECK(v8_str("x")->Equals(name));
10881   info.GetReturnValue().Set(call_ic_function);
10882 }
10883
10884
10885 // This test should hit the call IC for the interceptor case.
10886 THREADED_TEST(InterceptorCallIC) {
10887   v8::HandleScope scope(v8::Isolate::GetCurrent());
10888   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10889   templ->SetNamedPropertyHandler(InterceptorCallICGetter);
10890   LocalContext context;
10891   context->Global()->Set(v8_str("o"), templ->NewInstance());
10892   call_ic_function =
10893       v8_compile("function f(x) { return x + 1; }; f")->Run();
10894   v8::Handle<Value> value = CompileRun(
10895     "var result = 0;"
10896     "for (var i = 0; i < 1000; i++) {"
10897     "  result = o.x(41);"
10898     "}");
10899   CHECK_EQ(42, value->Int32Value());
10900 }
10901
10902
10903 // This test checks that if interceptor doesn't provide
10904 // a value, we can fetch regular value.
10905 THREADED_TEST(InterceptorCallICSeesOthers) {
10906   v8::HandleScope scope(v8::Isolate::GetCurrent());
10907   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10908   templ->SetNamedPropertyHandler(NoBlockGetterX);
10909   LocalContext context;
10910   context->Global()->Set(v8_str("o"), templ->NewInstance());
10911   v8::Handle<Value> value = CompileRun(
10912     "o.x = function f(x) { return x + 1; };"
10913     "var result = 0;"
10914     "for (var i = 0; i < 7; i++) {"
10915     "  result = o.x(41);"
10916     "}");
10917   CHECK_EQ(42, value->Int32Value());
10918 }
10919
10920
10921 static v8::Handle<Value> call_ic_function4;
10922 static void InterceptorCallICGetter4(
10923     Local<String> name,
10924     const v8::PropertyCallbackInfo<v8::Value>& info) {
10925   ApiTestFuzzer::Fuzz();
10926   CHECK(v8_str("x")->Equals(name));
10927   info.GetReturnValue().Set(call_ic_function4);
10928 }
10929
10930
10931 // This test checks that if interceptor provides a function,
10932 // even if we cached shadowed variant, interceptor's function
10933 // is invoked
10934 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
10935   v8::HandleScope scope(v8::Isolate::GetCurrent());
10936   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10937   templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
10938   LocalContext context;
10939   context->Global()->Set(v8_str("o"), templ->NewInstance());
10940   call_ic_function4 =
10941       v8_compile("function f(x) { return x - 1; }; f")->Run();
10942   v8::Handle<Value> value = CompileRun(
10943     "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
10944     "var result = 0;"
10945     "for (var i = 0; i < 1000; i++) {"
10946     "  result = o.x(42);"
10947     "}");
10948   CHECK_EQ(41, value->Int32Value());
10949 }
10950
10951
10952 // Test the case when we stored cacheable lookup into
10953 // a stub, but it got invalidated later on
10954 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
10955   v8::HandleScope scope(v8::Isolate::GetCurrent());
10956   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10957   templ->SetNamedPropertyHandler(NoBlockGetterX);
10958   LocalContext context;
10959   context->Global()->Set(v8_str("o"), templ->NewInstance());
10960   v8::Handle<Value> value = CompileRun(
10961     "proto1 = new Object();"
10962     "proto2 = new Object();"
10963     "o.__proto__ = proto1;"
10964     "proto1.__proto__ = proto2;"
10965     "proto2.y = function(x) { return x + 1; };"
10966     // Invoke it many times to compile a stub
10967     "for (var i = 0; i < 7; i++) {"
10968     "  o.y(42);"
10969     "}"
10970     "proto1.y = function(x) { return x - 1; };"
10971     "var result = 0;"
10972     "for (var i = 0; i < 7; i++) {"
10973     "  result += o.y(42);"
10974     "}");
10975   CHECK_EQ(41 * 7, value->Int32Value());
10976 }
10977
10978
10979 // This test checks that if interceptor doesn't provide a function,
10980 // cached constant function is used
10981 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
10982   v8::HandleScope scope(v8::Isolate::GetCurrent());
10983   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10984   templ->SetNamedPropertyHandler(NoBlockGetterX);
10985   LocalContext context;
10986   context->Global()->Set(v8_str("o"), templ->NewInstance());
10987   v8::Handle<Value> value = CompileRun(
10988     "function inc(x) { return x + 1; };"
10989     "inc(1);"
10990     "o.x = inc;"
10991     "var result = 0;"
10992     "for (var i = 0; i < 1000; i++) {"
10993     "  result = o.x(42);"
10994     "}");
10995   CHECK_EQ(43, value->Int32Value());
10996 }
10997
10998
10999 static v8::Handle<Value> call_ic_function5;
11000 static void InterceptorCallICGetter5(
11001     Local<String> name,
11002     const v8::PropertyCallbackInfo<v8::Value>& info) {
11003   ApiTestFuzzer::Fuzz();
11004   if (v8_str("x")->Equals(name))
11005     info.GetReturnValue().Set(call_ic_function5);
11006 }
11007
11008
11009 // This test checks that if interceptor provides a function,
11010 // even if we cached constant function, interceptor's function
11011 // is invoked
11012 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
11013   v8::HandleScope scope(v8::Isolate::GetCurrent());
11014   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11015   templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
11016   LocalContext context;
11017   context->Global()->Set(v8_str("o"), templ->NewInstance());
11018   call_ic_function5 =
11019       v8_compile("function f(x) { return x - 1; }; f")->Run();
11020   v8::Handle<Value> value = CompileRun(
11021     "function inc(x) { return x + 1; };"
11022     "inc(1);"
11023     "o.x = inc;"
11024     "var result = 0;"
11025     "for (var i = 0; i < 1000; i++) {"
11026     "  result = o.x(42);"
11027     "}");
11028   CHECK_EQ(41, value->Int32Value());
11029 }
11030
11031
11032 static v8::Handle<Value> call_ic_function6;
11033 static void InterceptorCallICGetter6(
11034     Local<String> name,
11035     const v8::PropertyCallbackInfo<v8::Value>& info) {
11036   ApiTestFuzzer::Fuzz();
11037   if (v8_str("x")->Equals(name))
11038     info.GetReturnValue().Set(call_ic_function6);
11039 }
11040
11041
11042 // Same test as above, except the code is wrapped in a function
11043 // to test the optimized compiler.
11044 THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
11045   i::FLAG_allow_natives_syntax = true;
11046   v8::HandleScope scope(v8::Isolate::GetCurrent());
11047   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11048   templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
11049   LocalContext context;
11050   context->Global()->Set(v8_str("o"), templ->NewInstance());
11051   call_ic_function6 =
11052       v8_compile("function f(x) { return x - 1; }; f")->Run();
11053   v8::Handle<Value> value = CompileRun(
11054     "function inc(x) { return x + 1; };"
11055     "inc(1);"
11056     "o.x = inc;"
11057     "function test() {"
11058     "  var result = 0;"
11059     "  for (var i = 0; i < 1000; i++) {"
11060     "    result = o.x(42);"
11061     "  }"
11062     "  return result;"
11063     "};"
11064     "test();"
11065     "test();"
11066     "test();"
11067     "%OptimizeFunctionOnNextCall(test);"
11068     "test()");
11069   CHECK_EQ(41, value->Int32Value());
11070 }
11071
11072
11073 // Test the case when we stored constant function into
11074 // a stub, but it got invalidated later on
11075 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
11076   v8::HandleScope scope(v8::Isolate::GetCurrent());
11077   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11078   templ->SetNamedPropertyHandler(NoBlockGetterX);
11079   LocalContext context;
11080   context->Global()->Set(v8_str("o"), templ->NewInstance());
11081   v8::Handle<Value> value = CompileRun(
11082     "function inc(x) { return x + 1; };"
11083     "inc(1);"
11084     "proto1 = new Object();"
11085     "proto2 = new Object();"
11086     "o.__proto__ = proto1;"
11087     "proto1.__proto__ = proto2;"
11088     "proto2.y = inc;"
11089     // Invoke it many times to compile a stub
11090     "for (var i = 0; i < 7; i++) {"
11091     "  o.y(42);"
11092     "}"
11093     "proto1.y = function(x) { return x - 1; };"
11094     "var result = 0;"
11095     "for (var i = 0; i < 7; i++) {"
11096     "  result += o.y(42);"
11097     "}");
11098   CHECK_EQ(41 * 7, value->Int32Value());
11099 }
11100
11101
11102 // Test the case when we stored constant function into
11103 // a stub, but it got invalidated later on due to override on
11104 // global object which is between interceptor and constant function' holders.
11105 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
11106   v8::HandleScope scope(v8::Isolate::GetCurrent());
11107   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11108   templ->SetNamedPropertyHandler(NoBlockGetterX);
11109   LocalContext context;
11110   context->Global()->Set(v8_str("o"), templ->NewInstance());
11111   v8::Handle<Value> value = CompileRun(
11112     "function inc(x) { return x + 1; };"
11113     "inc(1);"
11114     "o.__proto__ = this;"
11115     "this.__proto__.y = inc;"
11116     // Invoke it many times to compile a stub
11117     "for (var i = 0; i < 7; i++) {"
11118     "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
11119     "}"
11120     "this.y = function(x) { return x - 1; };"
11121     "var result = 0;"
11122     "for (var i = 0; i < 7; i++) {"
11123     "  result += o.y(42);"
11124     "}");
11125   CHECK_EQ(41 * 7, value->Int32Value());
11126 }
11127
11128
11129 // Test the case when actual function to call sits on global object.
11130 THREADED_TEST(InterceptorCallICCachedFromGlobal) {
11131   v8::HandleScope scope(v8::Isolate::GetCurrent());
11132   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
11133   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11134
11135   LocalContext context;
11136   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11137
11138   v8::Handle<Value> value = CompileRun(
11139     "try {"
11140     "  o.__proto__ = this;"
11141     "  for (var i = 0; i < 10; i++) {"
11142     "    var v = o.parseFloat('239');"
11143     "    if (v != 239) throw v;"
11144       // Now it should be ICed and keep a reference to parseFloat.
11145     "  }"
11146     "  var result = 0;"
11147     "  for (var i = 0; i < 10; i++) {"
11148     "    result += o.parseFloat('239');"
11149     "  }"
11150     "  result"
11151     "} catch(e) {"
11152     "  e"
11153     "};");
11154   CHECK_EQ(239 * 10, value->Int32Value());
11155 }
11156
11157 static void InterceptorCallICFastApi(
11158     Local<String> name,
11159     const v8::PropertyCallbackInfo<v8::Value>& info) {
11160   ApiTestFuzzer::Fuzz();
11161   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
11162   int* call_count =
11163       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
11164   ++(*call_count);
11165   if ((*call_count) % 20 == 0) {
11166     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
11167   }
11168 }
11169
11170 static void FastApiCallback_TrivialSignature(
11171     const v8::FunctionCallbackInfo<v8::Value>& args) {
11172   ApiTestFuzzer::Fuzz();
11173   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
11174   v8::Isolate* isolate = v8::Isolate::GetCurrent();
11175   CHECK_EQ(isolate, args.GetIsolate());
11176   CHECK_EQ(args.This(), args.Holder());
11177   CHECK(args.Data()->Equals(v8_str("method_data")));
11178   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
11179 }
11180
11181 static void FastApiCallback_SimpleSignature(
11182     const v8::FunctionCallbackInfo<v8::Value>& args) {
11183   ApiTestFuzzer::Fuzz();
11184   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
11185   v8::Isolate* isolate = v8::Isolate::GetCurrent();
11186   CHECK_EQ(isolate, args.GetIsolate());
11187   CHECK_EQ(args.This()->GetPrototype(), args.Holder());
11188   CHECK(args.Data()->Equals(v8_str("method_data")));
11189   // Note, we're using HasRealNamedProperty instead of Has to avoid
11190   // invoking the interceptor again.
11191   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
11192   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
11193 }
11194
11195
11196 // Helper to maximize the odds of object moving.
11197 static void GenerateSomeGarbage() {
11198   CompileRun(
11199       "var garbage;"
11200       "for (var i = 0; i < 1000; i++) {"
11201       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
11202       "}"
11203       "garbage = undefined;");
11204 }
11205
11206
11207 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
11208   static int count = 0;
11209   if (count++ % 3 == 0) {
11210     HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
11211         // This should move the stub
11212     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
11213   }
11214 }
11215
11216
11217 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
11218   LocalContext context;
11219   v8::HandleScope scope(context->GetIsolate());
11220   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
11221   nativeobject_templ->Set("callback",
11222                           v8::FunctionTemplate::New(DirectApiCallback));
11223   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11224   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11225   // call the api function multiple times to ensure direct call stub creation.
11226   CompileRun(
11227         "function f() {"
11228         "  for (var i = 1; i <= 30; i++) {"
11229         "    nativeobject.callback();"
11230         "  }"
11231         "}"
11232         "f();");
11233 }
11234
11235
11236 void ThrowingDirectApiCallback(
11237     const v8::FunctionCallbackInfo<v8::Value>& args) {
11238   v8::ThrowException(v8_str("g"));
11239 }
11240
11241
11242 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
11243   LocalContext context;
11244   v8::HandleScope scope(context->GetIsolate());
11245   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
11246   nativeobject_templ->Set("callback",
11247                           v8::FunctionTemplate::New(ThrowingDirectApiCallback));
11248   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11249   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11250   // call the api function multiple times to ensure direct call stub creation.
11251   v8::Handle<Value> result = CompileRun(
11252       "var result = '';"
11253       "function f() {"
11254       "  for (var i = 1; i <= 5; i++) {"
11255       "    try { nativeobject.callback(); } catch (e) { result += e; }"
11256       "  }"
11257       "}"
11258       "f(); result;");
11259   CHECK_EQ(v8_str("ggggg"), result);
11260 }
11261
11262
11263 static Handle<Value> DoDirectGetter() {
11264   if (++p_getter_count % 3 == 0) {
11265     HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
11266     GenerateSomeGarbage();
11267   }
11268   return v8_str("Direct Getter Result");
11269 }
11270
11271 static void DirectGetterCallback(
11272     Local<String> name,
11273     const v8::PropertyCallbackInfo<v8::Value>& info) {
11274   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
11275   info.GetReturnValue().Set(DoDirectGetter());
11276 }
11277
11278
11279 template<typename Accessor>
11280 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
11281   LocalContext context;
11282   v8::HandleScope scope(context->GetIsolate());
11283   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
11284   obj->SetAccessor(v8_str("p1"), accessor);
11285   context->Global()->Set(v8_str("o1"), obj->NewInstance());
11286   p_getter_count = 0;
11287   v8::Handle<v8::Value> result = CompileRun(
11288       "function f() {"
11289       "  for (var i = 0; i < 30; i++) o1.p1;"
11290       "  return o1.p1"
11291       "}"
11292       "f();");
11293   CHECK_EQ(v8_str("Direct Getter Result"), result);
11294   CHECK_EQ(31, p_getter_count);
11295 }
11296
11297
11298 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
11299   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
11300 }
11301
11302
11303 void ThrowingDirectGetterCallback(
11304     Local<String> name,
11305     const v8::PropertyCallbackInfo<v8::Value>& info) {
11306   v8::ThrowException(v8_str("g"));
11307 }
11308
11309
11310 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
11311   LocalContext context;
11312   v8::HandleScope scope(context->GetIsolate());
11313   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
11314   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
11315   context->Global()->Set(v8_str("o1"), obj->NewInstance());
11316   v8::Handle<Value> result = CompileRun(
11317       "var result = '';"
11318       "for (var i = 0; i < 5; i++) {"
11319       "    try { o1.p1; } catch (e) { result += e; }"
11320       "}"
11321       "result;");
11322   CHECK_EQ(v8_str("ggggg"), result);
11323 }
11324
11325
11326 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
11327   int interceptor_call_count = 0;
11328   v8::HandleScope scope(v8::Isolate::GetCurrent());
11329   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11330   v8::Handle<v8::FunctionTemplate> method_templ =
11331       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
11332                                 v8_str("method_data"),
11333                                 v8::Handle<v8::Signature>());
11334   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11335   proto_templ->Set(v8_str("method"), method_templ);
11336   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11337   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11338                                  NULL, NULL, NULL, NULL,
11339                                  v8::External::New(&interceptor_call_count));
11340   LocalContext context;
11341   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11342   GenerateSomeGarbage();
11343   context->Global()->Set(v8_str("o"), fun->NewInstance());
11344   CompileRun(
11345       "var result = 0;"
11346       "for (var i = 0; i < 100; i++) {"
11347       "  result = o.method(41);"
11348       "}");
11349   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
11350   CHECK_EQ(100, interceptor_call_count);
11351 }
11352
11353
11354 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
11355   int interceptor_call_count = 0;
11356   v8::HandleScope scope(v8::Isolate::GetCurrent());
11357   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11358   v8::Handle<v8::FunctionTemplate> method_templ =
11359       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11360                                 v8_str("method_data"),
11361                                 v8::Signature::New(fun_templ));
11362   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11363   proto_templ->Set(v8_str("method"), method_templ);
11364   fun_templ->SetHiddenPrototype(true);
11365   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11366   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11367                                  NULL, NULL, NULL, NULL,
11368                                  v8::External::New(&interceptor_call_count));
11369   LocalContext context;
11370   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11371   GenerateSomeGarbage();
11372   context->Global()->Set(v8_str("o"), fun->NewInstance());
11373   CompileRun(
11374       "o.foo = 17;"
11375       "var receiver = {};"
11376       "receiver.__proto__ = o;"
11377       "var result = 0;"
11378       "for (var i = 0; i < 100; i++) {"
11379       "  result = receiver.method(41);"
11380       "}");
11381   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
11382   CHECK_EQ(100, interceptor_call_count);
11383 }
11384
11385
11386 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
11387   int interceptor_call_count = 0;
11388   v8::HandleScope scope(v8::Isolate::GetCurrent());
11389   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11390   v8::Handle<v8::FunctionTemplate> method_templ =
11391       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11392                                 v8_str("method_data"),
11393                                 v8::Signature::New(fun_templ));
11394   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11395   proto_templ->Set(v8_str("method"), method_templ);
11396   fun_templ->SetHiddenPrototype(true);
11397   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11398   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11399                                  NULL, NULL, NULL, NULL,
11400                                  v8::External::New(&interceptor_call_count));
11401   LocalContext context;
11402   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11403   GenerateSomeGarbage();
11404   context->Global()->Set(v8_str("o"), fun->NewInstance());
11405   CompileRun(
11406       "o.foo = 17;"
11407       "var receiver = {};"
11408       "receiver.__proto__ = o;"
11409       "var result = 0;"
11410       "var saved_result = 0;"
11411       "for (var i = 0; i < 100; i++) {"
11412       "  result = receiver.method(41);"
11413       "  if (i == 50) {"
11414       "    saved_result = result;"
11415       "    receiver = {method: function(x) { return x - 1 }};"
11416       "  }"
11417       "}");
11418   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
11419   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11420   CHECK_GE(interceptor_call_count, 50);
11421 }
11422
11423
11424 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
11425   int interceptor_call_count = 0;
11426   v8::HandleScope scope(v8::Isolate::GetCurrent());
11427   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11428   v8::Handle<v8::FunctionTemplate> method_templ =
11429       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11430                                 v8_str("method_data"),
11431                                 v8::Signature::New(fun_templ));
11432   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11433   proto_templ->Set(v8_str("method"), method_templ);
11434   fun_templ->SetHiddenPrototype(true);
11435   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11436   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11437                                  NULL, NULL, NULL, NULL,
11438                                  v8::External::New(&interceptor_call_count));
11439   LocalContext context;
11440   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11441   GenerateSomeGarbage();
11442   context->Global()->Set(v8_str("o"), fun->NewInstance());
11443   CompileRun(
11444       "o.foo = 17;"
11445       "var receiver = {};"
11446       "receiver.__proto__ = o;"
11447       "var result = 0;"
11448       "var saved_result = 0;"
11449       "for (var i = 0; i < 100; i++) {"
11450       "  result = receiver.method(41);"
11451       "  if (i == 50) {"
11452       "    saved_result = result;"
11453       "    o.method = function(x) { return x - 1 };"
11454       "  }"
11455       "}");
11456   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
11457   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11458   CHECK_GE(interceptor_call_count, 50);
11459 }
11460
11461
11462 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
11463   int interceptor_call_count = 0;
11464   v8::HandleScope scope(v8::Isolate::GetCurrent());
11465   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11466   v8::Handle<v8::FunctionTemplate> method_templ =
11467       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11468                                 v8_str("method_data"),
11469                                 v8::Signature::New(fun_templ));
11470   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11471   proto_templ->Set(v8_str("method"), method_templ);
11472   fun_templ->SetHiddenPrototype(true);
11473   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11474   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11475                                  NULL, NULL, NULL, NULL,
11476                                  v8::External::New(&interceptor_call_count));
11477   LocalContext context;
11478   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11479   GenerateSomeGarbage();
11480   context->Global()->Set(v8_str("o"), fun->NewInstance());
11481   v8::TryCatch try_catch;
11482   CompileRun(
11483       "o.foo = 17;"
11484       "var receiver = {};"
11485       "receiver.__proto__ = o;"
11486       "var result = 0;"
11487       "var saved_result = 0;"
11488       "for (var i = 0; i < 100; i++) {"
11489       "  result = receiver.method(41);"
11490       "  if (i == 50) {"
11491       "    saved_result = result;"
11492       "    receiver = 333;"
11493       "  }"
11494       "}");
11495   CHECK(try_catch.HasCaught());
11496   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
11497            try_catch.Exception()->ToString());
11498   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11499   CHECK_GE(interceptor_call_count, 50);
11500 }
11501
11502
11503 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
11504   int interceptor_call_count = 0;
11505   v8::HandleScope scope(v8::Isolate::GetCurrent());
11506   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11507   v8::Handle<v8::FunctionTemplate> method_templ =
11508       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11509                                 v8_str("method_data"),
11510                                 v8::Signature::New(fun_templ));
11511   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11512   proto_templ->Set(v8_str("method"), method_templ);
11513   fun_templ->SetHiddenPrototype(true);
11514   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11515   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11516                                  NULL, NULL, NULL, NULL,
11517                                  v8::External::New(&interceptor_call_count));
11518   LocalContext context;
11519   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11520   GenerateSomeGarbage();
11521   context->Global()->Set(v8_str("o"), fun->NewInstance());
11522   v8::TryCatch try_catch;
11523   CompileRun(
11524       "o.foo = 17;"
11525       "var receiver = {};"
11526       "receiver.__proto__ = o;"
11527       "var result = 0;"
11528       "var saved_result = 0;"
11529       "for (var i = 0; i < 100; i++) {"
11530       "  result = receiver.method(41);"
11531       "  if (i == 50) {"
11532       "    saved_result = result;"
11533       "    receiver = {method: receiver.method};"
11534       "  }"
11535       "}");
11536   CHECK(try_catch.HasCaught());
11537   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
11538            try_catch.Exception()->ToString());
11539   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11540   CHECK_GE(interceptor_call_count, 50);
11541 }
11542
11543
11544 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
11545   v8::HandleScope scope(v8::Isolate::GetCurrent());
11546   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11547   v8::Handle<v8::FunctionTemplate> method_templ =
11548       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
11549                                 v8_str("method_data"),
11550                                 v8::Handle<v8::Signature>());
11551   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11552   proto_templ->Set(v8_str("method"), method_templ);
11553   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
11554   USE(templ);
11555   LocalContext context;
11556   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11557   GenerateSomeGarbage();
11558   context->Global()->Set(v8_str("o"), fun->NewInstance());
11559   CompileRun(
11560       "var result = 0;"
11561       "for (var i = 0; i < 100; i++) {"
11562       "  result = o.method(41);"
11563       "}");
11564
11565   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
11566 }
11567
11568
11569 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
11570   v8::HandleScope scope(v8::Isolate::GetCurrent());
11571   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11572   v8::Handle<v8::FunctionTemplate> method_templ =
11573       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11574                                 v8_str("method_data"),
11575                                 v8::Signature::New(fun_templ));
11576   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11577   proto_templ->Set(v8_str("method"), method_templ);
11578   fun_templ->SetHiddenPrototype(true);
11579   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
11580   CHECK(!templ.IsEmpty());
11581   LocalContext context;
11582   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11583   GenerateSomeGarbage();
11584   context->Global()->Set(v8_str("o"), fun->NewInstance());
11585   CompileRun(
11586       "o.foo = 17;"
11587       "var receiver = {};"
11588       "receiver.__proto__ = o;"
11589       "var result = 0;"
11590       "for (var i = 0; i < 100; i++) {"
11591       "  result = receiver.method(41);"
11592       "}");
11593
11594   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
11595 }
11596
11597
11598 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
11599   v8::HandleScope scope(v8::Isolate::GetCurrent());
11600   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11601   v8::Handle<v8::FunctionTemplate> method_templ =
11602       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11603                                 v8_str("method_data"),
11604                                 v8::Signature::New(fun_templ));
11605   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11606   proto_templ->Set(v8_str("method"), method_templ);
11607   fun_templ->SetHiddenPrototype(true);
11608   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
11609   CHECK(!templ.IsEmpty());
11610   LocalContext context;
11611   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11612   GenerateSomeGarbage();
11613   context->Global()->Set(v8_str("o"), fun->NewInstance());
11614   CompileRun(
11615       "o.foo = 17;"
11616       "var receiver = {};"
11617       "receiver.__proto__ = o;"
11618       "var result = 0;"
11619       "var saved_result = 0;"
11620       "for (var i = 0; i < 100; i++) {"
11621       "  result = receiver.method(41);"
11622       "  if (i == 50) {"
11623       "    saved_result = result;"
11624       "    receiver = {method: function(x) { return x - 1 }};"
11625       "  }"
11626       "}");
11627   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
11628   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11629 }
11630
11631
11632 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
11633   v8::HandleScope scope(v8::Isolate::GetCurrent());
11634   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11635   v8::Handle<v8::FunctionTemplate> method_templ =
11636       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11637                                 v8_str("method_data"),
11638                                 v8::Signature::New(fun_templ));
11639   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11640   proto_templ->Set(v8_str("method"), method_templ);
11641   fun_templ->SetHiddenPrototype(true);
11642   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
11643   CHECK(!templ.IsEmpty());
11644   LocalContext context;
11645   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11646   GenerateSomeGarbage();
11647   context->Global()->Set(v8_str("o"), fun->NewInstance());
11648   v8::TryCatch try_catch;
11649   CompileRun(
11650       "o.foo = 17;"
11651       "var receiver = {};"
11652       "receiver.__proto__ = o;"
11653       "var result = 0;"
11654       "var saved_result = 0;"
11655       "for (var i = 0; i < 100; i++) {"
11656       "  result = receiver.method(41);"
11657       "  if (i == 50) {"
11658       "    saved_result = result;"
11659       "    receiver = 333;"
11660       "  }"
11661       "}");
11662   CHECK(try_catch.HasCaught());
11663   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
11664            try_catch.Exception()->ToString());
11665   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11666 }
11667
11668
11669 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
11670   v8::HandleScope scope(v8::Isolate::GetCurrent());
11671   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11672   v8::Handle<v8::FunctionTemplate> method_templ =
11673       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11674                                 v8_str("method_data"),
11675                                 v8::Signature::New(fun_templ));
11676   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11677   proto_templ->Set(v8_str("method"), method_templ);
11678   fun_templ->SetHiddenPrototype(true);
11679   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
11680   CHECK(!templ.IsEmpty());
11681   LocalContext context;
11682   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11683   GenerateSomeGarbage();
11684   context->Global()->Set(v8_str("o"), fun->NewInstance());
11685   v8::TryCatch try_catch;
11686   CompileRun(
11687       "o.foo = 17;"
11688       "var receiver = {};"
11689       "receiver.__proto__ = o;"
11690       "var result = 0;"
11691       "var saved_result = 0;"
11692       "for (var i = 0; i < 100; i++) {"
11693       "  result = receiver.method(41);"
11694       "  if (i == 50) {"
11695       "    saved_result = result;"
11696       "    receiver = Object.create(receiver);"
11697       "  }"
11698       "}");
11699   CHECK(try_catch.HasCaught());
11700   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
11701            try_catch.Exception()->ToString());
11702   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11703 }
11704
11705
11706 v8::Handle<Value> keyed_call_ic_function;
11707
11708 static void InterceptorKeyedCallICGetter(
11709     Local<String> name,
11710     const v8::PropertyCallbackInfo<v8::Value>& info) {
11711   ApiTestFuzzer::Fuzz();
11712   if (v8_str("x")->Equals(name)) {
11713     info.GetReturnValue().Set(keyed_call_ic_function);
11714   }
11715 }
11716
11717
11718 // Test the case when we stored cacheable lookup into
11719 // a stub, but the function name changed (to another cacheable function).
11720 THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
11721   v8::HandleScope scope(v8::Isolate::GetCurrent());
11722   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11723   templ->SetNamedPropertyHandler(NoBlockGetterX);
11724   LocalContext context;
11725   context->Global()->Set(v8_str("o"), templ->NewInstance());
11726   CompileRun(
11727     "proto = new Object();"
11728     "proto.y = function(x) { return x + 1; };"
11729     "proto.z = function(x) { return x - 1; };"
11730     "o.__proto__ = proto;"
11731     "var result = 0;"
11732     "var method = 'y';"
11733     "for (var i = 0; i < 10; i++) {"
11734     "  if (i == 5) { method = 'z'; };"
11735     "  result += o[method](41);"
11736     "}");
11737   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11738 }
11739
11740
11741 // Test the case when we stored cacheable lookup into
11742 // a stub, but the function name changed (and the new function is present
11743 // both before and after the interceptor in the prototype chain).
11744 THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
11745   v8::HandleScope scope(v8::Isolate::GetCurrent());
11746   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11747   templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
11748   LocalContext context;
11749   context->Global()->Set(v8_str("proto1"), templ->NewInstance());
11750   keyed_call_ic_function =
11751       v8_compile("function f(x) { return x - 1; }; f")->Run();
11752   CompileRun(
11753     "o = new Object();"
11754     "proto2 = new Object();"
11755     "o.y = function(x) { return x + 1; };"
11756     "proto2.y = function(x) { return x + 2; };"
11757     "o.__proto__ = proto1;"
11758     "proto1.__proto__ = proto2;"
11759     "var result = 0;"
11760     "var method = 'x';"
11761     "for (var i = 0; i < 10; i++) {"
11762     "  if (i == 5) { method = 'y'; };"
11763     "  result += o[method](41);"
11764     "}");
11765   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11766 }
11767
11768
11769 // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
11770 // on the global object.
11771 THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
11772   v8::HandleScope scope(v8::Isolate::GetCurrent());
11773   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11774   templ->SetNamedPropertyHandler(NoBlockGetterX);
11775   LocalContext context;
11776   context->Global()->Set(v8_str("o"), templ->NewInstance());
11777   CompileRun(
11778     "function inc(x) { return x + 1; };"
11779     "inc(1);"
11780     "function dec(x) { return x - 1; };"
11781     "dec(1);"
11782     "o.__proto__ = this;"
11783     "this.__proto__.x = inc;"
11784     "this.__proto__.y = dec;"
11785     "var result = 0;"
11786     "var method = 'x';"
11787     "for (var i = 0; i < 10; i++) {"
11788     "  if (i == 5) { method = 'y'; };"
11789     "  result += o[method](41);"
11790     "}");
11791   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11792 }
11793
11794
11795 // Test the case when actual function to call sits on global object.
11796 THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
11797   v8::HandleScope scope(v8::Isolate::GetCurrent());
11798   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
11799   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11800   LocalContext context;
11801   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11802
11803   CompileRun(
11804     "function len(x) { return x.length; };"
11805     "o.__proto__ = this;"
11806     "var m = 'parseFloat';"
11807     "var result = 0;"
11808     "for (var i = 0; i < 10; i++) {"
11809     "  if (i == 5) {"
11810     "    m = 'len';"
11811     "    saved_result = result;"
11812     "  };"
11813     "  result = o[m]('239');"
11814     "}");
11815   CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
11816   CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11817 }
11818
11819
11820 // Test the map transition before the interceptor.
11821 THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
11822   v8::HandleScope scope(v8::Isolate::GetCurrent());
11823   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
11824   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11825   LocalContext context;
11826   context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
11827
11828   CompileRun(
11829     "var o = new Object();"
11830     "o.__proto__ = proto;"
11831     "o.method = function(x) { return x + 1; };"
11832     "var m = 'method';"
11833     "var result = 0;"
11834     "for (var i = 0; i < 10; i++) {"
11835     "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
11836     "  result += o[m](41);"
11837     "}");
11838   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11839 }
11840
11841
11842 // Test the map transition after the interceptor.
11843 THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
11844   v8::HandleScope scope(v8::Isolate::GetCurrent());
11845   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
11846   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11847   LocalContext context;
11848   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11849
11850   CompileRun(
11851     "var proto = new Object();"
11852     "o.__proto__ = proto;"
11853     "proto.method = function(x) { return x + 1; };"
11854     "var m = 'method';"
11855     "var result = 0;"
11856     "for (var i = 0; i < 10; i++) {"
11857     "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
11858     "  result += o[m](41);"
11859     "}");
11860   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11861 }
11862
11863
11864 static int interceptor_call_count = 0;
11865
11866 static void InterceptorICRefErrorGetter(
11867     Local<String> name,
11868     const v8::PropertyCallbackInfo<v8::Value>& info) {
11869   ApiTestFuzzer::Fuzz();
11870   if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
11871     info.GetReturnValue().Set(call_ic_function2);
11872   }
11873 }
11874
11875
11876 // This test should hit load and call ICs for the interceptor case.
11877 // Once in a while, the interceptor will reply that a property was not
11878 // found in which case we should get a reference error.
11879 THREADED_TEST(InterceptorICReferenceErrors) {
11880   v8::HandleScope scope(v8::Isolate::GetCurrent());
11881   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11882   templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
11883   LocalContext context(0, templ, v8::Handle<Value>());
11884   call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
11885   v8::Handle<Value> value = CompileRun(
11886     "function f() {"
11887     "  for (var i = 0; i < 1000; i++) {"
11888     "    try { x; } catch(e) { return true; }"
11889     "  }"
11890     "  return false;"
11891     "};"
11892     "f();");
11893   CHECK_EQ(true, value->BooleanValue());
11894   interceptor_call_count = 0;
11895   value = CompileRun(
11896     "function g() {"
11897     "  for (var i = 0; i < 1000; i++) {"
11898     "    try { x(42); } catch(e) { return true; }"
11899     "  }"
11900     "  return false;"
11901     "};"
11902     "g();");
11903   CHECK_EQ(true, value->BooleanValue());
11904 }
11905
11906
11907 static int interceptor_ic_exception_get_count = 0;
11908
11909 static void InterceptorICExceptionGetter(
11910     Local<String> name,
11911     const v8::PropertyCallbackInfo<v8::Value>& info) {
11912   ApiTestFuzzer::Fuzz();
11913   if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
11914     info.GetReturnValue().Set(call_ic_function3);
11915   }
11916   if (interceptor_ic_exception_get_count == 20) {
11917     v8::ThrowException(v8_num(42));
11918     return;
11919   }
11920 }
11921
11922
11923 // Test interceptor load/call IC where the interceptor throws an
11924 // exception once in a while.
11925 THREADED_TEST(InterceptorICGetterExceptions) {
11926   interceptor_ic_exception_get_count = 0;
11927   v8::HandleScope scope(v8::Isolate::GetCurrent());
11928   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11929   templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
11930   LocalContext context(0, templ, v8::Handle<Value>());
11931   call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
11932   v8::Handle<Value> value = CompileRun(
11933     "function f() {"
11934     "  for (var i = 0; i < 100; i++) {"
11935     "    try { x; } catch(e) { return true; }"
11936     "  }"
11937     "  return false;"
11938     "};"
11939     "f();");
11940   CHECK_EQ(true, value->BooleanValue());
11941   interceptor_ic_exception_get_count = 0;
11942   value = CompileRun(
11943     "function f() {"
11944     "  for (var i = 0; i < 100; i++) {"
11945     "    try { x(42); } catch(e) { return true; }"
11946     "  }"
11947     "  return false;"
11948     "};"
11949     "f();");
11950   CHECK_EQ(true, value->BooleanValue());
11951 }
11952
11953
11954 static int interceptor_ic_exception_set_count = 0;
11955
11956 static void InterceptorICExceptionSetter(
11957       Local<String> key,
11958       Local<Value> value,
11959       const v8::PropertyCallbackInfo<v8::Value>& info) {
11960   ApiTestFuzzer::Fuzz();
11961   if (++interceptor_ic_exception_set_count > 20) {
11962     v8::ThrowException(v8_num(42));
11963   }
11964 }
11965
11966
11967 // Test interceptor store IC where the interceptor throws an exception
11968 // once in a while.
11969 THREADED_TEST(InterceptorICSetterExceptions) {
11970   interceptor_ic_exception_set_count = 0;
11971   v8::HandleScope scope(v8::Isolate::GetCurrent());
11972   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11973   templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
11974   LocalContext context(0, templ, v8::Handle<Value>());
11975   v8::Handle<Value> value = CompileRun(
11976     "function f() {"
11977     "  for (var i = 0; i < 100; i++) {"
11978     "    try { x = 42; } catch(e) { return true; }"
11979     "  }"
11980     "  return false;"
11981     "};"
11982     "f();");
11983   CHECK_EQ(true, value->BooleanValue());
11984 }
11985
11986
11987 // Test that we ignore null interceptors.
11988 THREADED_TEST(NullNamedInterceptor) {
11989   v8::HandleScope scope(v8::Isolate::GetCurrent());
11990   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11991   templ->SetNamedPropertyHandler(
11992       static_cast<v8::NamedPropertyGetterCallback>(0));
11993   LocalContext context;
11994   templ->Set("x", v8_num(42));
11995   v8::Handle<v8::Object> obj = templ->NewInstance();
11996   context->Global()->Set(v8_str("obj"), obj);
11997   v8::Handle<Value> value = CompileRun("obj.x");
11998   CHECK(value->IsInt32());
11999   CHECK_EQ(42, value->Int32Value());
12000 }
12001
12002
12003 // Test that we ignore null interceptors.
12004 THREADED_TEST(NullIndexedInterceptor) {
12005   v8::HandleScope scope(v8::Isolate::GetCurrent());
12006   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
12007   templ->SetIndexedPropertyHandler(
12008       static_cast<v8::IndexedPropertyGetterCallback>(0));
12009   LocalContext context;
12010   templ->Set("42", v8_num(42));
12011   v8::Handle<v8::Object> obj = templ->NewInstance();
12012   context->Global()->Set(v8_str("obj"), obj);
12013   v8::Handle<Value> value = CompileRun("obj[42]");
12014   CHECK(value->IsInt32());
12015   CHECK_EQ(42, value->Int32Value());
12016 }
12017
12018
12019 THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
12020   v8::HandleScope scope(v8::Isolate::GetCurrent());
12021   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
12022   templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
12023   LocalContext env;
12024   env->Global()->Set(v8_str("obj"),
12025                      templ->GetFunction()->NewInstance());
12026   ExpectTrue("obj.x === 42");
12027   ExpectTrue("!obj.propertyIsEnumerable('x')");
12028 }
12029
12030
12031 static void ThrowingGetter(Local<String> name,
12032                            const v8::PropertyCallbackInfo<v8::Value>& info) {
12033   ApiTestFuzzer::Fuzz();
12034   ThrowException(Handle<Value>());
12035   info.GetReturnValue().SetUndefined();
12036 }
12037
12038
12039 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
12040   LocalContext context;
12041   HandleScope scope(context->GetIsolate());
12042
12043   Local<FunctionTemplate> templ = FunctionTemplate::New();
12044   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12045   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12046
12047   Local<Object> instance = templ->GetFunction()->NewInstance();
12048
12049   Local<Object> another = Object::New();
12050   another->SetPrototype(instance);
12051
12052   Local<Object> with_js_getter = CompileRun(
12053       "o = {};\n"
12054       "o.__defineGetter__('f', function() { throw undefined; });\n"
12055       "o\n").As<Object>();
12056   CHECK(!with_js_getter.IsEmpty());
12057
12058   TryCatch try_catch;
12059
12060   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
12061   CHECK(try_catch.HasCaught());
12062   try_catch.Reset();
12063   CHECK(result.IsEmpty());
12064
12065   result = another->GetRealNamedProperty(v8_str("f"));
12066   CHECK(try_catch.HasCaught());
12067   try_catch.Reset();
12068   CHECK(result.IsEmpty());
12069
12070   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
12071   CHECK(try_catch.HasCaught());
12072   try_catch.Reset();
12073   CHECK(result.IsEmpty());
12074
12075   result = another->Get(v8_str("f"));
12076   CHECK(try_catch.HasCaught());
12077   try_catch.Reset();
12078   CHECK(result.IsEmpty());
12079
12080   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
12081   CHECK(try_catch.HasCaught());
12082   try_catch.Reset();
12083   CHECK(result.IsEmpty());
12084
12085   result = with_js_getter->Get(v8_str("f"));
12086   CHECK(try_catch.HasCaught());
12087   try_catch.Reset();
12088   CHECK(result.IsEmpty());
12089 }
12090
12091
12092 static void ThrowingCallbackWithTryCatch(
12093     const v8::FunctionCallbackInfo<v8::Value>& args) {
12094   TryCatch try_catch;
12095   // Verboseness is important: it triggers message delivery which can call into
12096   // external code.
12097   try_catch.SetVerbose(true);
12098   CompileRun("throw 'from JS';");
12099   CHECK(try_catch.HasCaught());
12100   CHECK(!i::Isolate::Current()->has_pending_exception());
12101   CHECK(!i::Isolate::Current()->has_scheduled_exception());
12102 }
12103
12104
12105 static int call_depth;
12106
12107
12108 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
12109   TryCatch try_catch;
12110 }
12111
12112
12113 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
12114   if (--call_depth) CompileRun("throw 'ThrowInJS';");
12115 }
12116
12117
12118 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
12119   if (--call_depth) ThrowException(v8_str("ThrowViaApi"));
12120 }
12121
12122
12123 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
12124   Handle<String> errorMessageString = message->Get();
12125   CHECK(!errorMessageString.IsEmpty());
12126   message->GetStackTrace();
12127   message->GetScriptResourceName();
12128 }
12129
12130
12131 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
12132   LocalContext context;
12133   HandleScope scope(context->GetIsolate());
12134
12135   Local<Function> func =
12136       FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction();
12137   context->Global()->Set(v8_str("func"), func);
12138
12139   MessageCallback callbacks[] =
12140       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12141   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12142     MessageCallback callback = callbacks[i];
12143     if (callback != NULL) {
12144       V8::AddMessageListener(callback);
12145     }
12146     // Some small number to control number of times message handler should
12147     // throw an exception.
12148     call_depth = 5;
12149     ExpectFalse(
12150         "var thrown = false;\n"
12151         "try { func(); } catch(e) { thrown = true; }\n"
12152         "thrown\n");
12153     if (callback != NULL) {
12154       V8::RemoveMessageListeners(callback);
12155     }
12156   }
12157 }
12158
12159
12160 static void ParentGetter(Local<String> name,
12161                          const v8::PropertyCallbackInfo<v8::Value>& info) {
12162   ApiTestFuzzer::Fuzz();
12163   info.GetReturnValue().Set(v8_num(1));
12164 }
12165
12166
12167 static void ChildGetter(Local<String> name,
12168                         const v8::PropertyCallbackInfo<v8::Value>& info) {
12169   ApiTestFuzzer::Fuzz();
12170   info.GetReturnValue().Set(v8_num(42));
12171 }
12172
12173
12174 THREADED_TEST(Overriding) {
12175   i::FLAG_es5_readonly = true;
12176   LocalContext context;
12177   v8::HandleScope scope(context->GetIsolate());
12178
12179   // Parent template.
12180   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
12181   Local<ObjectTemplate> parent_instance_templ =
12182       parent_templ->InstanceTemplate();
12183   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
12184
12185   // Template that inherits from the parent template.
12186   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
12187   Local<ObjectTemplate> child_instance_templ =
12188       child_templ->InstanceTemplate();
12189   child_templ->Inherit(parent_templ);
12190   // Override 'f'.  The child version of 'f' should get called for child
12191   // instances.
12192   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
12193   // Add 'g' twice.  The 'g' added last should get called for instances.
12194   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
12195   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
12196
12197   // Add 'h' as an accessor to the proto template with ReadOnly attributes
12198   // so 'h' can be shadowed on the instance object.
12199   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
12200   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
12201       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12202
12203   // Add 'i' as an accessor to the instance template with ReadOnly attributes
12204   // but the attribute does not have effect because it is duplicated with
12205   // NULL setter.
12206   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
12207       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12208
12209
12210
12211   // Instantiate the child template.
12212   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
12213
12214   // Check that the child function overrides the parent one.
12215   context->Global()->Set(v8_str("o"), instance);
12216   Local<Value> value = v8_compile("o.f")->Run();
12217   // Check that the 'g' that was added last is hit.
12218   CHECK_EQ(42, value->Int32Value());
12219   value = v8_compile("o.g")->Run();
12220   CHECK_EQ(42, value->Int32Value());
12221
12222   // Check that 'h' cannot be shadowed.
12223   value = v8_compile("o.h = 3; o.h")->Run();
12224   CHECK_EQ(1, value->Int32Value());
12225
12226   // Check that 'i' cannot be shadowed or changed.
12227   value = v8_compile("o.i = 3; o.i")->Run();
12228   CHECK_EQ(42, value->Int32Value());
12229 }
12230
12231
12232 static void IsConstructHandler(
12233     const v8::FunctionCallbackInfo<v8::Value>& args) {
12234   ApiTestFuzzer::Fuzz();
12235   args.GetReturnValue().Set(args.IsConstructCall());
12236 }
12237
12238
12239 THREADED_TEST(IsConstructCall) {
12240   v8::HandleScope scope(v8::Isolate::GetCurrent());
12241
12242   // Function template with call handler.
12243   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
12244   templ->SetCallHandler(IsConstructHandler);
12245
12246   LocalContext context;
12247
12248   context->Global()->Set(v8_str("f"), templ->GetFunction());
12249   Local<Value> value = v8_compile("f()")->Run();
12250   CHECK(!value->BooleanValue());
12251   value = v8_compile("new f()")->Run();
12252   CHECK(value->BooleanValue());
12253 }
12254
12255
12256 THREADED_TEST(ObjectProtoToString) {
12257   v8::HandleScope scope(v8::Isolate::GetCurrent());
12258   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
12259   templ->SetClassName(v8_str("MyClass"));
12260
12261   LocalContext context;
12262
12263   Local<String> customized_tostring = v8_str("customized toString");
12264
12265   // Replace Object.prototype.toString
12266   v8_compile("Object.prototype.toString = function() {"
12267                   "  return 'customized toString';"
12268                   "}")->Run();
12269
12270   // Normal ToString call should call replaced Object.prototype.toString
12271   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
12272   Local<String> value = instance->ToString();
12273   CHECK(value->IsString() && value->Equals(customized_tostring));
12274
12275   // ObjectProtoToString should not call replace toString function.
12276   value = instance->ObjectProtoToString();
12277   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
12278
12279   // Check global
12280   value = context->Global()->ObjectProtoToString();
12281   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
12282
12283   // Check ordinary object
12284   Local<Value> object = v8_compile("new Object()")->Run();
12285   value = object.As<v8::Object>()->ObjectProtoToString();
12286   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
12287 }
12288
12289
12290 THREADED_TEST(ObjectGetConstructorName) {
12291   LocalContext context;
12292   v8::HandleScope scope(context->GetIsolate());
12293   v8_compile("function Parent() {};"
12294              "function Child() {};"
12295              "Child.prototype = new Parent();"
12296              "var outer = { inner: function() { } };"
12297              "var p = new Parent();"
12298              "var c = new Child();"
12299              "var x = new outer.inner();")->Run();
12300
12301   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
12302   CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
12303       v8_str("Parent")));
12304
12305   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
12306   CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
12307       v8_str("Child")));
12308
12309   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
12310   CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
12311       v8_str("outer.inner")));
12312 }
12313
12314
12315 bool ApiTestFuzzer::fuzzing_ = false;
12316 i::Semaphore ApiTestFuzzer::all_tests_done_(0);
12317 int ApiTestFuzzer::active_tests_;
12318 int ApiTestFuzzer::tests_being_run_;
12319 int ApiTestFuzzer::current_;
12320
12321
12322 // We are in a callback and want to switch to another thread (if we
12323 // are currently running the thread fuzzing test).
12324 void ApiTestFuzzer::Fuzz() {
12325   if (!fuzzing_) return;
12326   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
12327   test->ContextSwitch();
12328 }
12329
12330
12331 // Let the next thread go.  Since it is also waiting on the V8 lock it may
12332 // not start immediately.
12333 bool ApiTestFuzzer::NextThread() {
12334   int test_position = GetNextTestNumber();
12335   const char* test_name = RegisterThreadedTest::nth(current_)->name();
12336   if (test_position == current_) {
12337     if (kLogThreading)
12338       printf("Stay with %s\n", test_name);
12339     return false;
12340   }
12341   if (kLogThreading) {
12342     printf("Switch from %s to %s\n",
12343            test_name,
12344            RegisterThreadedTest::nth(test_position)->name());
12345   }
12346   current_ = test_position;
12347   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
12348   return true;
12349 }
12350
12351
12352 void ApiTestFuzzer::Run() {
12353   // When it is our turn...
12354   gate_.Wait();
12355   {
12356     // ... get the V8 lock and start running the test.
12357     v8::Locker locker(CcTest::default_isolate());
12358     CallTest();
12359   }
12360   // This test finished.
12361   active_ = false;
12362   active_tests_--;
12363   // If it was the last then signal that fact.
12364   if (active_tests_ == 0) {
12365     all_tests_done_.Signal();
12366   } else {
12367     // Otherwise select a new test and start that.
12368     NextThread();
12369   }
12370 }
12371
12372
12373 static unsigned linear_congruential_generator;
12374
12375
12376 void ApiTestFuzzer::SetUp(PartOfTest part) {
12377   linear_congruential_generator = i::FLAG_testing_prng_seed;
12378   fuzzing_ = true;
12379   int count = RegisterThreadedTest::count();
12380   int start =  count * part / (LAST_PART + 1);
12381   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
12382   active_tests_ = tests_being_run_ = end - start + 1;
12383   for (int i = 0; i < tests_being_run_; i++) {
12384     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
12385   }
12386   for (int i = 0; i < active_tests_; i++) {
12387     RegisterThreadedTest::nth(i)->fuzzer_->Start();
12388   }
12389 }
12390
12391
12392 static void CallTestNumber(int test_number) {
12393   (RegisterThreadedTest::nth(test_number)->callback())();
12394 }
12395
12396
12397 void ApiTestFuzzer::RunAllTests() {
12398   // Set off the first test.
12399   current_ = -1;
12400   NextThread();
12401   // Wait till they are all done.
12402   all_tests_done_.Wait();
12403 }
12404
12405
12406 int ApiTestFuzzer::GetNextTestNumber() {
12407   int next_test;
12408   do {
12409     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
12410     linear_congruential_generator *= 1664525u;
12411     linear_congruential_generator += 1013904223u;
12412   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
12413   return next_test;
12414 }
12415
12416
12417 void ApiTestFuzzer::ContextSwitch() {
12418   // If the new thread is the same as the current thread there is nothing to do.
12419   if (NextThread()) {
12420     // Now it can start.
12421     v8::Unlocker unlocker(CcTest::default_isolate());
12422     // Wait till someone starts us again.
12423     gate_.Wait();
12424     // And we're off.
12425   }
12426 }
12427
12428
12429 void ApiTestFuzzer::TearDown() {
12430   fuzzing_ = false;
12431   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
12432     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
12433     if (fuzzer != NULL) fuzzer->Join();
12434   }
12435 }
12436
12437
12438 // Lets not be needlessly self-referential.
12439 TEST(Threading1) {
12440   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
12441   ApiTestFuzzer::RunAllTests();
12442   ApiTestFuzzer::TearDown();
12443 }
12444
12445
12446 TEST(Threading2) {
12447   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
12448   ApiTestFuzzer::RunAllTests();
12449   ApiTestFuzzer::TearDown();
12450 }
12451
12452
12453 TEST(Threading3) {
12454   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
12455   ApiTestFuzzer::RunAllTests();
12456   ApiTestFuzzer::TearDown();
12457 }
12458
12459
12460 TEST(Threading4) {
12461   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
12462   ApiTestFuzzer::RunAllTests();
12463   ApiTestFuzzer::TearDown();
12464 }
12465
12466
12467 void ApiTestFuzzer::CallTest() {
12468   if (kLogThreading)
12469     printf("Start test %d\n", test_number_);
12470   CallTestNumber(test_number_);
12471   if (kLogThreading)
12472     printf("End test %d\n", test_number_);
12473 }
12474
12475
12476 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
12477   CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
12478   ApiTestFuzzer::Fuzz();
12479   v8::Unlocker unlocker(CcTest::default_isolate());
12480   const char* code = "throw 7;";
12481   {
12482     v8::Locker nested_locker(CcTest::default_isolate());
12483     v8::HandleScope scope(args.GetIsolate());
12484     v8::Handle<Value> exception;
12485     { v8::TryCatch try_catch;
12486       v8::Handle<Value> value = CompileRun(code);
12487       CHECK(value.IsEmpty());
12488       CHECK(try_catch.HasCaught());
12489       // Make sure to wrap the exception in a new handle because
12490       // the handle returned from the TryCatch is destroyed
12491       // when the TryCatch is destroyed.
12492       exception = Local<Value>::New(try_catch.Exception());
12493     }
12494     v8::ThrowException(exception);
12495   }
12496 }
12497
12498
12499 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
12500   CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
12501   ApiTestFuzzer::Fuzz();
12502   v8::Unlocker unlocker(CcTest::default_isolate());
12503   const char* code = "throw 7;";
12504   {
12505     v8::Locker nested_locker(CcTest::default_isolate());
12506     v8::HandleScope scope(args.GetIsolate());
12507     v8::Handle<Value> value = CompileRun(code);
12508     CHECK(value.IsEmpty());
12509     args.GetReturnValue().Set(v8_str("foo"));
12510   }
12511 }
12512
12513
12514 // These are locking tests that don't need to be run again
12515 // as part of the locking aggregation tests.
12516 TEST(NestedLockers) {
12517   v8::Locker locker(CcTest::default_isolate());
12518   CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
12519   LocalContext env;
12520   v8::HandleScope scope(env->GetIsolate());
12521   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
12522   Local<Function> fun = fun_templ->GetFunction();
12523   env->Global()->Set(v8_str("throw_in_js"), fun);
12524   Local<Script> script = v8_compile("(function () {"
12525                                     "  try {"
12526                                     "    throw_in_js();"
12527                                     "    return 42;"
12528                                     "  } catch (e) {"
12529                                     "    return e * 13;"
12530                                     "  }"
12531                                     "})();");
12532   CHECK_EQ(91, script->Run()->Int32Value());
12533 }
12534
12535
12536 // These are locking tests that don't need to be run again
12537 // as part of the locking aggregation tests.
12538 TEST(NestedLockersNoTryCatch) {
12539   v8::Locker locker(CcTest::default_isolate());
12540   LocalContext env;
12541   v8::HandleScope scope(env->GetIsolate());
12542   Local<v8::FunctionTemplate> fun_templ =
12543       v8::FunctionTemplate::New(ThrowInJSNoCatch);
12544   Local<Function> fun = fun_templ->GetFunction();
12545   env->Global()->Set(v8_str("throw_in_js"), fun);
12546   Local<Script> script = v8_compile("(function () {"
12547                                     "  try {"
12548                                     "    throw_in_js();"
12549                                     "    return 42;"
12550                                     "  } catch (e) {"
12551                                     "    return e * 13;"
12552                                     "  }"
12553                                     "})();");
12554   CHECK_EQ(91, script->Run()->Int32Value());
12555 }
12556
12557
12558 THREADED_TEST(RecursiveLocking) {
12559   v8::Locker locker(CcTest::default_isolate());
12560   {
12561     v8::Locker locker2(CcTest::default_isolate());
12562     CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
12563   }
12564 }
12565
12566
12567 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
12568   ApiTestFuzzer::Fuzz();
12569   v8::Unlocker unlocker(CcTest::default_isolate());
12570 }
12571
12572
12573 THREADED_TEST(LockUnlockLock) {
12574   {
12575     v8::Locker locker(CcTest::default_isolate());
12576     v8::HandleScope scope(CcTest::default_isolate());
12577     LocalContext env;
12578     Local<v8::FunctionTemplate> fun_templ =
12579         v8::FunctionTemplate::New(UnlockForAMoment);
12580     Local<Function> fun = fun_templ->GetFunction();
12581     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
12582     Local<Script> script = v8_compile("(function () {"
12583                                       "  unlock_for_a_moment();"
12584                                       "  return 42;"
12585                                       "})();");
12586     CHECK_EQ(42, script->Run()->Int32Value());
12587   }
12588   {
12589     v8::Locker locker(CcTest::default_isolate());
12590     v8::HandleScope scope(CcTest::default_isolate());
12591     LocalContext env;
12592     Local<v8::FunctionTemplate> fun_templ =
12593         v8::FunctionTemplate::New(UnlockForAMoment);
12594     Local<Function> fun = fun_templ->GetFunction();
12595     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
12596     Local<Script> script = v8_compile("(function () {"
12597                                       "  unlock_for_a_moment();"
12598                                       "  return 42;"
12599                                       "})();");
12600     CHECK_EQ(42, script->Run()->Int32Value());
12601   }
12602 }
12603
12604
12605 static int GetGlobalObjectsCount() {
12606   i::Isolate::Current()->heap()->EnsureHeapIsIterable();
12607   int count = 0;
12608   i::HeapIterator it(HEAP);
12609   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
12610     if (object->IsJSGlobalObject()) count++;
12611   return count;
12612 }
12613
12614
12615 static void CheckSurvivingGlobalObjectsCount(int expected) {
12616   // We need to collect all garbage twice to be sure that everything
12617   // has been collected.  This is because inline caches are cleared in
12618   // the first garbage collection but some of the maps have already
12619   // been marked at that point.  Therefore some of the maps are not
12620   // collected until the second garbage collection.
12621   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
12622   HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
12623   int count = GetGlobalObjectsCount();
12624 #ifdef DEBUG
12625   if (count != expected) HEAP->TracePathToGlobal();
12626 #endif
12627   CHECK_EQ(expected, count);
12628 }
12629
12630
12631 TEST(DontLeakGlobalObjects) {
12632   // Regression test for issues 1139850 and 1174891.
12633
12634   v8::V8::Initialize();
12635
12636   for (int i = 0; i < 5; i++) {
12637     { v8::HandleScope scope(v8::Isolate::GetCurrent());
12638       LocalContext context;
12639     }
12640     v8::V8::ContextDisposedNotification();
12641     CheckSurvivingGlobalObjectsCount(0);
12642
12643     { v8::HandleScope scope(v8::Isolate::GetCurrent());
12644       LocalContext context;
12645       v8_compile("Date")->Run();
12646     }
12647     v8::V8::ContextDisposedNotification();
12648     CheckSurvivingGlobalObjectsCount(0);
12649
12650     { v8::HandleScope scope(v8::Isolate::GetCurrent());
12651       LocalContext context;
12652       v8_compile("/aaa/")->Run();
12653     }
12654     v8::V8::ContextDisposedNotification();
12655     CheckSurvivingGlobalObjectsCount(0);
12656
12657     { v8::HandleScope scope(v8::Isolate::GetCurrent());
12658       const char* extension_list[] = { "v8/gc" };
12659       v8::ExtensionConfiguration extensions(1, extension_list);
12660       LocalContext context(&extensions);
12661       v8_compile("gc();")->Run();
12662     }
12663     v8::V8::ContextDisposedNotification();
12664     CheckSurvivingGlobalObjectsCount(0);
12665   }
12666 }
12667
12668 template<class T>
12669 struct CopyablePersistentTraits {
12670   typedef Persistent<T, CopyablePersistentTraits<T> > CopyablePersistent;
12671   static const bool kResetInDestructor = true;
12672   template<class S, class M>
12673   static V8_INLINE void Copy(const Persistent<S, M>& source,
12674                              CopyablePersistent* dest) {
12675     // do nothing, just allow copy
12676   }
12677 };
12678
12679
12680 TEST(CopyablePersistent) {
12681   LocalContext context;
12682   v8::Isolate* isolate = context->GetIsolate();
12683   i::GlobalHandles* globals =
12684       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
12685   int initial_handles = globals->global_handles_count();
12686   {
12687     v8::Persistent<v8::Object, CopyablePersistentTraits<v8::Object> > handle1;
12688     {
12689       v8::HandleScope scope(isolate);
12690       handle1.Reset(isolate, v8::Object::New());
12691     }
12692     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
12693     v8::Persistent<v8::Object, CopyablePersistentTraits<v8::Object> > handle2;
12694     handle2 = handle1;
12695     CHECK(handle1 == handle2);
12696     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
12697     v8::Persistent<v8::Object, CopyablePersistentTraits<v8::Object> >
12698     handle3(handle2);
12699     CHECK(handle1 == handle3);
12700     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
12701   }
12702   // Verify autodispose
12703   CHECK_EQ(initial_handles, globals->global_handles_count());
12704 }
12705
12706
12707 static void WeakApiCallback(
12708     const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
12709   Local<Value> value = data.GetValue()->Get(v8_str("key"));
12710   CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
12711   data.GetParameter()->Reset();
12712   delete data.GetParameter();
12713 }
12714
12715
12716 TEST(WeakCallbackApi) {
12717   LocalContext context;
12718   v8::Isolate* isolate = context->GetIsolate();
12719   i::GlobalHandles* globals =
12720       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
12721   int initial_handles = globals->global_handles_count();
12722   {
12723     v8::HandleScope scope(isolate);
12724     v8::Local<v8::Object> obj = v8::Object::New();
12725     obj->Set(v8_str("key"), v8::Integer::New(231, isolate));
12726     v8::Persistent<v8::Object>* handle =
12727         new v8::Persistent<v8::Object>(isolate, obj);
12728     handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
12729                                                              WeakApiCallback);
12730   }
12731   reinterpret_cast<i::Isolate*>(isolate)->heap()->
12732       CollectAllGarbage(i::Heap::kNoGCFlags);
12733   // Verify disposed.
12734   CHECK_EQ(initial_handles, globals->global_handles_count());
12735 }
12736
12737
12738 v8::Persistent<v8::Object> some_object;
12739 v8::Persistent<v8::Object> bad_handle;
12740
12741 void NewPersistentHandleCallback(v8::Isolate* isolate,
12742                                  v8::Persistent<v8::Value>* handle,
12743                                  void*) {
12744   v8::HandleScope scope(isolate);
12745   bad_handle.Reset(isolate, some_object);
12746   handle->Dispose();
12747 }
12748
12749
12750 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
12751   LocalContext context;
12752   v8::Isolate* isolate = context->GetIsolate();
12753
12754   v8::Persistent<v8::Object> handle1, handle2;
12755   {
12756     v8::HandleScope scope(isolate);
12757     some_object.Reset(isolate, v8::Object::New());
12758     handle1.Reset(isolate, v8::Object::New());
12759     handle2.Reset(isolate, v8::Object::New());
12760   }
12761   // Note: order is implementation dependent alas: currently
12762   // global handle nodes are processed by PostGarbageCollectionProcessing
12763   // in reverse allocation order, so if second allocated handle is deleted,
12764   // weak callback of the first handle would be able to 'reallocate' it.
12765   handle1.MakeWeak<v8::Value, void>(NULL, NewPersistentHandleCallback);
12766   handle2.Dispose();
12767   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
12768 }
12769
12770
12771 v8::Persistent<v8::Object> to_be_disposed;
12772
12773 void DisposeAndForceGcCallback(v8::Isolate* isolate,
12774                                v8::Persistent<v8::Value>* handle,
12775                                void*) {
12776   to_be_disposed.Dispose();
12777   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
12778   handle->Dispose();
12779 }
12780
12781
12782 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
12783   LocalContext context;
12784   v8::Isolate* isolate = context->GetIsolate();
12785
12786   v8::Persistent<v8::Object> handle1, handle2;
12787   {
12788     v8::HandleScope scope(isolate);
12789     handle1.Reset(isolate, v8::Object::New());
12790     handle2.Reset(isolate, v8::Object::New());
12791   }
12792   handle1.MakeWeak<v8::Value, void>(NULL, DisposeAndForceGcCallback);
12793   to_be_disposed.Reset(isolate, handle2);
12794   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
12795 }
12796
12797 void DisposingCallback(v8::Isolate* isolate,
12798                        v8::Persistent<v8::Value>* handle,
12799                        void*) {
12800   handle->Dispose();
12801 }
12802
12803 void HandleCreatingCallback(v8::Isolate* isolate,
12804                             v8::Persistent<v8::Value>* handle,
12805                             void*) {
12806   v8::HandleScope scope(isolate);
12807   v8::Persistent<v8::Object>(isolate, v8::Object::New());
12808   handle->Dispose();
12809 }
12810
12811
12812 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
12813   LocalContext context;
12814   v8::Isolate* isolate = context->GetIsolate();
12815
12816   v8::Persistent<v8::Object> handle1, handle2, handle3;
12817   {
12818     v8::HandleScope scope(isolate);
12819     handle3.Reset(isolate, v8::Object::New());
12820     handle2.Reset(isolate, v8::Object::New());
12821     handle1.Reset(isolate, v8::Object::New());
12822   }
12823   handle2.MakeWeak<v8::Value, void>(NULL, DisposingCallback);
12824   handle3.MakeWeak<v8::Value, void>(NULL, HandleCreatingCallback);
12825   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
12826 }
12827
12828
12829 THREADED_TEST(CheckForCrossContextObjectLiterals) {
12830   v8::V8::Initialize();
12831
12832   const int nof = 2;
12833   const char* sources[nof] = {
12834     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
12835     "Object()"
12836   };
12837
12838   for (int i = 0; i < nof; i++) {
12839     const char* source = sources[i];
12840     { v8::HandleScope scope(v8::Isolate::GetCurrent());
12841       LocalContext context;
12842       CompileRun(source);
12843     }
12844     { v8::HandleScope scope(v8::Isolate::GetCurrent());
12845       LocalContext context;
12846       CompileRun(source);
12847     }
12848   }
12849 }
12850
12851
12852 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
12853   v8::HandleScope inner(env->GetIsolate());
12854   env->Enter();
12855   v8::Handle<Value> three = v8_num(3);
12856   v8::Handle<Value> value = inner.Close(three);
12857   env->Exit();
12858   return value;
12859 }
12860
12861
12862 THREADED_TEST(NestedHandleScopeAndContexts) {
12863   v8::Isolate* isolate = v8::Isolate::GetCurrent();
12864   v8::HandleScope outer(isolate);
12865   v8::Local<Context> env = Context::New(isolate);
12866   env->Enter();
12867   v8::Handle<Value> value = NestedScope(env);
12868   v8::Handle<String> str(value->ToString());
12869   CHECK(!str.IsEmpty());
12870   env->Exit();
12871 }
12872
12873
12874 static bool MatchPointers(void* key1, void* key2) {
12875   return key1 == key2;
12876 }
12877
12878
12879 struct SymbolInfo {
12880   size_t id;
12881   size_t size;
12882   std::string name;
12883 };
12884
12885
12886 class SetFunctionEntryHookTest {
12887  public:
12888   SetFunctionEntryHookTest() {
12889     CHECK(instance_ == NULL);
12890     instance_ = this;
12891   }
12892   ~SetFunctionEntryHookTest() {
12893     CHECK(instance_ == this);
12894     instance_ = NULL;
12895   }
12896   void Reset() {
12897     symbols_.clear();
12898     symbol_locations_.clear();
12899     invocations_.clear();
12900   }
12901   void RunTest();
12902   void OnJitEvent(const v8::JitCodeEvent* event);
12903   static void JitEvent(const v8::JitCodeEvent* event) {
12904     CHECK(instance_ != NULL);
12905     instance_->OnJitEvent(event);
12906   }
12907
12908   void OnEntryHook(uintptr_t function,
12909                    uintptr_t return_addr_location);
12910   static void EntryHook(uintptr_t function,
12911                         uintptr_t return_addr_location) {
12912     CHECK(instance_ != NULL);
12913     instance_->OnEntryHook(function, return_addr_location);
12914   }
12915
12916   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
12917     CHECK(instance_ != NULL);
12918     args.GetReturnValue().Set(v8_num(42));
12919   }
12920   void RunLoopInNewEnv(v8::Isolate* isolate);
12921
12922   // Records addr as location of symbol.
12923   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
12924
12925   // Finds the symbol containing addr
12926   SymbolInfo* FindSymbolForAddr(i::Address addr);
12927   // Returns the number of invocations where the caller name contains
12928   // \p caller_name and the function name contains \p function_name.
12929   int CountInvocations(const char* caller_name,
12930                        const char* function_name);
12931
12932   i::Handle<i::JSFunction> foo_func_;
12933   i::Handle<i::JSFunction> bar_func_;
12934
12935   typedef std::map<size_t, SymbolInfo> SymbolMap;
12936   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
12937   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
12938   SymbolMap symbols_;
12939   SymbolLocationMap symbol_locations_;
12940   InvocationMap invocations_;
12941
12942   static SetFunctionEntryHookTest* instance_;
12943 };
12944 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
12945
12946
12947 // Returns true if addr is in the range [start, start+len).
12948 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
12949   if (start <= addr && start + len > addr)
12950     return true;
12951
12952   return false;
12953 }
12954
12955 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
12956                                               SymbolInfo* symbol) {
12957   // Insert the symbol at the new location.
12958   SymbolLocationMap::iterator it =
12959       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
12960   // Now erase symbols to the left and right that overlap this one.
12961   while (it != symbol_locations_.begin()) {
12962     SymbolLocationMap::iterator left = it;
12963     --left;
12964     if (!Overlaps(left->first, left->second->size, addr))
12965       break;
12966     symbol_locations_.erase(left);
12967   }
12968
12969   // Now erase symbols to the left and right that overlap this one.
12970   while (true) {
12971     SymbolLocationMap::iterator right = it;
12972     ++right;
12973     if (right == symbol_locations_.end())
12974         break;
12975     if (!Overlaps(addr, symbol->size, right->first))
12976       break;
12977     symbol_locations_.erase(right);
12978   }
12979 }
12980
12981
12982 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
12983   switch (event->type) {
12984     case v8::JitCodeEvent::CODE_ADDED: {
12985         CHECK(event->code_start != NULL);
12986         CHECK_NE(0, static_cast<int>(event->code_len));
12987         CHECK(event->name.str != NULL);
12988         size_t symbol_id = symbols_.size();
12989
12990         // Record the new symbol.
12991         SymbolInfo& info = symbols_[symbol_id];
12992         info.id = symbol_id;
12993         info.size = event->code_len;
12994         info.name.assign(event->name.str, event->name.str + event->name.len);
12995
12996         // And record it's location.
12997         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
12998       }
12999       break;
13000
13001     case v8::JitCodeEvent::CODE_MOVED: {
13002         // We would like to never see code move that we haven't seen before,
13003         // but the code creation event does not happen until the line endings
13004         // have been calculated (this is so that we can report the line in the
13005         // script at which the function source is found, see
13006         // Compiler::RecordFunctionCompilation) and the line endings
13007         // calculations can cause a GC, which can move the newly created code
13008         // before its existence can be logged.
13009         SymbolLocationMap::iterator it(
13010             symbol_locations_.find(
13011                 reinterpret_cast<i::Address>(event->code_start)));
13012         if (it != symbol_locations_.end()) {
13013           // Found a symbol at this location, move it.
13014           SymbolInfo* info = it->second;
13015           symbol_locations_.erase(it);
13016           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13017                          info);
13018         }
13019       }
13020     default:
13021       break;
13022   }
13023 }
13024
13025 void SetFunctionEntryHookTest::OnEntryHook(
13026     uintptr_t function, uintptr_t return_addr_location) {
13027   // Get the function's code object.
13028   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13029       reinterpret_cast<i::Address>(function));
13030   CHECK(function_code != NULL);
13031
13032   // Then try and look up the caller's code object.
13033   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13034
13035   // Count the invocation.
13036   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13037   SymbolInfo* function_symbol =
13038       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13039   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13040
13041   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13042     // Check that we have a symbol for the "bar" function at the right location.
13043     SymbolLocationMap::iterator it(
13044         symbol_locations_.find(function_code->instruction_start()));
13045     CHECK(it != symbol_locations_.end());
13046   }
13047
13048   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13049     // Check that we have a symbol for "foo" at the right location.
13050     SymbolLocationMap::iterator it(
13051         symbol_locations_.find(function_code->instruction_start()));
13052     CHECK(it != symbol_locations_.end());
13053   }
13054 }
13055
13056
13057 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
13058   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13059   // Do we have a direct hit on a symbol?
13060   if (it != symbol_locations_.end()) {
13061     if (it->first == addr)
13062       return it->second;
13063   }
13064
13065   // If not a direct hit, it'll have to be the previous symbol.
13066   if (it == symbol_locations_.begin())
13067     return NULL;
13068
13069   --it;
13070   size_t offs = addr - it->first;
13071   if (offs < it->second->size)
13072     return it->second;
13073
13074   return NULL;
13075 }
13076
13077
13078 int SetFunctionEntryHookTest::CountInvocations(
13079     const char* caller_name, const char* function_name) {
13080   InvocationMap::iterator it(invocations_.begin());
13081   int invocations = 0;
13082   for (; it != invocations_.end(); ++it) {
13083     SymbolInfo* caller = it->first.first;
13084     SymbolInfo* function = it->first.second;
13085
13086     // Filter out non-matching functions.
13087     if (function_name != NULL) {
13088       if (function->name.find(function_name) == std::string::npos)
13089         continue;
13090     }
13091
13092     // Filter out non-matching callers.
13093     if (caller_name != NULL) {
13094       if (caller == NULL)
13095         continue;
13096       if (caller->name.find(caller_name) == std::string::npos)
13097         continue;
13098     }
13099
13100     // It matches add the invocation count to the tally.
13101     invocations += it->second;
13102   }
13103
13104   return invocations;
13105 }
13106
13107
13108 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
13109   v8::HandleScope outer(isolate);
13110   v8::Local<Context> env = Context::New(isolate);
13111   env->Enter();
13112
13113   Local<ObjectTemplate> t = ObjectTemplate::New();
13114   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(RuntimeCallback));
13115   env->Global()->Set(v8_str("obj"), t->NewInstance());
13116
13117   const char* script =
13118       "function bar() {\n"
13119       "  var sum = 0;\n"
13120       "  for (i = 0; i < 100; ++i)\n"
13121       "    sum = foo(i);\n"
13122       "  return sum;\n"
13123       "}\n"
13124       "function foo(i) { return i * i; }\n"
13125       "// Invoke on the runtime function.\n"
13126       "obj.asdf()";
13127   CompileRun(script);
13128   bar_func_ = i::Handle<i::JSFunction>::cast(
13129           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
13130   ASSERT(!bar_func_.is_null());
13131
13132   foo_func_ =
13133       i::Handle<i::JSFunction>::cast(
13134            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
13135   ASSERT(!foo_func_.is_null());
13136
13137   v8::Handle<v8::Value> value = CompileRun("bar();");
13138   CHECK(value->IsNumber());
13139   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13140
13141   // Test the optimized codegen path.
13142   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
13143                      "bar();");
13144   CHECK(value->IsNumber());
13145   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13146
13147   env->Exit();
13148 }
13149
13150
13151 void SetFunctionEntryHookTest::RunTest() {
13152   // Work in a new isolate throughout.
13153   v8::Isolate* isolate = v8::Isolate::New();
13154
13155   // Test setting the entry hook on the new isolate.
13156   CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13157
13158   // Replacing the hook, once set should fail.
13159   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13160
13161   {
13162     v8::Isolate::Scope scope(isolate);
13163
13164     v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
13165
13166     RunLoopInNewEnv(isolate);
13167
13168     // Check the exepected invocation counts.
13169     CHECK_EQ(2, CountInvocations(NULL, "bar"));
13170     CHECK_EQ(200, CountInvocations("bar", "foo"));
13171     CHECK_EQ(200, CountInvocations(NULL, "foo"));
13172
13173     // Verify that we have an entry hook on some specific stubs.
13174     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
13175     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
13176     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
13177   }
13178   isolate->Dispose();
13179
13180   Reset();
13181
13182   // Make sure a second isolate is unaffected by the previous entry hook.
13183   isolate = v8::Isolate::New();
13184   {
13185     v8::Isolate::Scope scope(isolate);
13186
13187     // Reset the entry count to zero and set the entry hook.
13188     RunLoopInNewEnv(isolate);
13189
13190     // We should record no invocations in this isolate.
13191     CHECK_EQ(0, static_cast<int>(invocations_.size()));
13192   }
13193   // Since the isolate has been used, we shouldn't be able to set an entry
13194   // hook anymore.
13195   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13196
13197   isolate->Dispose();
13198 }
13199
13200
13201 TEST(SetFunctionEntryHook) {
13202   // FunctionEntryHook does not work well with experimental natives.
13203   // Experimental natives are compiled during snapshot deserialization.
13204   // This test breaks because InstallGetter (function from snapshot that
13205   // only gets called from experimental natives) is compiled with entry hooks.
13206   i::FLAG_allow_natives_syntax = true;
13207   i::FLAG_use_inlining = false;
13208
13209   SetFunctionEntryHookTest test;
13210   test.RunTest();
13211 }
13212
13213
13214 static i::HashMap* code_map = NULL;
13215 static i::HashMap* jitcode_line_info = NULL;
13216 static int saw_bar = 0;
13217 static int move_events = 0;
13218
13219
13220 static bool FunctionNameIs(const char* expected,
13221                            const v8::JitCodeEvent* event) {
13222   // Log lines for functions are of the general form:
13223   // "LazyCompile:<type><function_name>", where the type is one of
13224   // "*", "~" or "".
13225   static const char kPreamble[] = "LazyCompile:";
13226   static size_t kPreambleLen = sizeof(kPreamble) - 1;
13227
13228   if (event->name.len < sizeof(kPreamble) - 1 ||
13229       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
13230     return false;
13231   }
13232
13233   const char* tail = event->name.str + kPreambleLen;
13234   size_t tail_len = event->name.len - kPreambleLen;
13235   size_t expected_len = strlen(expected);
13236   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
13237     --tail_len;
13238     ++tail;
13239   }
13240
13241   // Check for tails like 'bar :1'.
13242   if (tail_len > expected_len + 2 &&
13243       tail[expected_len] == ' ' &&
13244       tail[expected_len + 1] == ':' &&
13245       tail[expected_len + 2] &&
13246       !strncmp(tail, expected, expected_len)) {
13247     return true;
13248   }
13249
13250   if (tail_len != expected_len)
13251     return false;
13252
13253   return strncmp(tail, expected, expected_len) == 0;
13254 }
13255
13256
13257 static void event_handler(const v8::JitCodeEvent* event) {
13258   CHECK(event != NULL);
13259   CHECK(code_map != NULL);
13260   CHECK(jitcode_line_info != NULL);
13261
13262   class DummyJitCodeLineInfo {
13263   };
13264
13265   switch (event->type) {
13266     case v8::JitCodeEvent::CODE_ADDED: {
13267         CHECK(event->code_start != NULL);
13268         CHECK_NE(0, static_cast<int>(event->code_len));
13269         CHECK(event->name.str != NULL);
13270         i::HashMap::Entry* entry =
13271             code_map->Lookup(event->code_start,
13272                              i::ComputePointerHash(event->code_start),
13273                              true);
13274         entry->value = reinterpret_cast<void*>(event->code_len);
13275
13276         if (FunctionNameIs("bar", event)) {
13277           ++saw_bar;
13278         }
13279       }
13280       break;
13281
13282     case v8::JitCodeEvent::CODE_MOVED: {
13283         uint32_t hash = i::ComputePointerHash(event->code_start);
13284         // We would like to never see code move that we haven't seen before,
13285         // but the code creation event does not happen until the line endings
13286         // have been calculated (this is so that we can report the line in the
13287         // script at which the function source is found, see
13288         // Compiler::RecordFunctionCompilation) and the line endings
13289         // calculations can cause a GC, which can move the newly created code
13290         // before its existence can be logged.
13291         i::HashMap::Entry* entry =
13292             code_map->Lookup(event->code_start, hash, false);
13293         if (entry != NULL) {
13294           ++move_events;
13295
13296           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
13297           code_map->Remove(event->code_start, hash);
13298
13299           entry = code_map->Lookup(event->new_code_start,
13300                                    i::ComputePointerHash(event->new_code_start),
13301                                    true);
13302           CHECK(entry != NULL);
13303           entry->value = reinterpret_cast<void*>(event->code_len);
13304         }
13305       }
13306       break;
13307
13308     case v8::JitCodeEvent::CODE_REMOVED:
13309       // Object/code removal events are currently not dispatched from the GC.
13310       CHECK(false);
13311       break;
13312
13313     // For CODE_START_LINE_INFO_RECORDING event, we will create one
13314     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
13315     // record it in jitcode_line_info.
13316     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
13317         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
13318         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
13319         temp_event->user_data = line_info;
13320         i::HashMap::Entry* entry =
13321             jitcode_line_info->Lookup(line_info,
13322                                       i::ComputePointerHash(line_info),
13323                                       true);
13324         entry->value = reinterpret_cast<void*>(line_info);
13325       }
13326       break;
13327     // For these two events, we will check whether the event->user_data
13328     // data structure is created before during CODE_START_LINE_INFO_RECORDING
13329     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
13330     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
13331         CHECK(event->user_data != NULL);
13332         uint32_t hash = i::ComputePointerHash(event->user_data);
13333         i::HashMap::Entry* entry =
13334             jitcode_line_info->Lookup(event->user_data, hash, false);
13335         CHECK(entry != NULL);
13336         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
13337       }
13338       break;
13339
13340     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
13341         CHECK(event->user_data != NULL);
13342         uint32_t hash = i::ComputePointerHash(event->user_data);
13343         i::HashMap::Entry* entry =
13344             jitcode_line_info->Lookup(event->user_data, hash, false);
13345         CHECK(entry != NULL);
13346       }
13347       break;
13348
13349     default:
13350       // Impossible event.
13351       CHECK(false);
13352       break;
13353   }
13354 }
13355
13356
13357 TEST(SetJitCodeEventHandler) {
13358   i::FLAG_stress_compaction = true;
13359   i::FLAG_incremental_marking = false;
13360   const char* script =
13361     "function bar() {"
13362     "  var sum = 0;"
13363     "  for (i = 0; i < 100; ++i)"
13364     "    sum = foo(i);"
13365     "  return sum;"
13366     "}"
13367     "function foo(i) { return i * i; };"
13368     "bar();";
13369
13370   // Run this test in a new isolate to make sure we don't
13371   // have remnants of state from other code.
13372   v8::Isolate* isolate = v8::Isolate::New();
13373   isolate->Enter();
13374
13375   {
13376     v8::HandleScope scope(isolate);
13377     i::HashMap code(MatchPointers);
13378     code_map = &code;
13379
13380     i::HashMap lineinfo(MatchPointers);
13381     jitcode_line_info = &lineinfo;
13382
13383     saw_bar = 0;
13384     move_events = 0;
13385
13386     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
13387
13388     // Generate new code objects sparsely distributed across several
13389     // different fragmented code-space pages.
13390     const int kIterations = 10;
13391     for (int i = 0; i < kIterations; ++i) {
13392       LocalContext env;
13393       i::AlwaysAllocateScope always_allocate;
13394       SimulateFullSpace(HEAP->code_space());
13395       CompileRun(script);
13396
13397       // Keep a strong reference to the code object in the handle scope.
13398       i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
13399           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
13400       i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
13401           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
13402
13403       // Clear the compilation cache to get more wastage.
13404       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
13405     }
13406
13407     // Force code movement.
13408     HEAP->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
13409
13410     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
13411
13412     CHECK_LE(kIterations, saw_bar);
13413     CHECK_LT(0, move_events);
13414
13415     code_map = NULL;
13416     jitcode_line_info = NULL;
13417   }
13418
13419   isolate->Exit();
13420   isolate->Dispose();
13421
13422   // Do this in a new isolate.
13423   isolate = v8::Isolate::New();
13424   isolate->Enter();
13425
13426   // Verify that we get callbacks for existing code objects when we
13427   // request enumeration of existing code.
13428   {
13429     v8::HandleScope scope(isolate);
13430     LocalContext env;
13431     CompileRun(script);
13432
13433     // Now get code through initial iteration.
13434     i::HashMap code(MatchPointers);
13435     code_map = &code;
13436
13437     i::HashMap lineinfo(MatchPointers);
13438     jitcode_line_info = &lineinfo;
13439
13440     V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
13441     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
13442
13443     jitcode_line_info = NULL;
13444     // We expect that we got some events. Note that if we could get code removal
13445     // notifications, we could compare two collections, one created by listening
13446     // from the time of creation of an isolate, and the other by subscribing
13447     // with EnumExisting.
13448     CHECK_LT(0, code.occupancy());
13449
13450     code_map = NULL;
13451   }
13452
13453   isolate->Exit();
13454   isolate->Dispose();
13455 }
13456
13457
13458 static int64_t cast(intptr_t x) { return static_cast<int64_t>(x); }
13459
13460
13461 THREADED_TEST(ExternalAllocatedMemory) {
13462   v8::Isolate* isolate = v8::Isolate::GetCurrent();
13463   v8::HandleScope outer(isolate);
13464   v8::Local<Context> env(Context::New(isolate));
13465   CHECK(!env.IsEmpty());
13466   const intptr_t kSize = 1024*1024;
13467   int64_t baseline = cast(isolate->AdjustAmountOfExternalAllocatedMemory(0));
13468   CHECK_EQ(baseline + cast(kSize),
13469            cast(isolate->AdjustAmountOfExternalAllocatedMemory(kSize)));
13470   CHECK_EQ(baseline,
13471            cast(isolate->AdjustAmountOfExternalAllocatedMemory(-kSize)));
13472 }
13473
13474
13475 THREADED_TEST(DisposeEnteredContext) {
13476   LocalContext outer;
13477   v8::Isolate* isolate = outer->GetIsolate();
13478   v8::Persistent<v8::Context> inner;
13479   {
13480     v8::HandleScope scope(isolate);
13481     inner.Reset(isolate, v8::Context::New(isolate));
13482   }
13483   v8::HandleScope scope(isolate);
13484   {
13485     // Don't want a handle here, so do this unsafely
13486     v8::Handle<v8::Context> inner_local =
13487         v8::Utils::Convert<i::Object, v8::Context>(
13488             v8::Utils::OpenPersistent(inner));
13489     inner_local->Enter();
13490     inner.Dispose();
13491     inner.Clear();
13492     inner_local->Exit();
13493   }
13494 }
13495
13496
13497 // Regression test for issue 54, object templates with internal fields
13498 // but no accessors or interceptors did not get their internal field
13499 // count set on instances.
13500 THREADED_TEST(Regress54) {
13501   LocalContext context;
13502   v8::Isolate* isolate = context->GetIsolate();
13503   v8::HandleScope outer(isolate);
13504   static v8::Persistent<v8::ObjectTemplate> templ;
13505   if (templ.IsEmpty()) {
13506     v8::HandleScope inner(isolate);
13507     v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
13508     local->SetInternalFieldCount(1);
13509     templ.Reset(isolate, inner.Close(local));
13510   }
13511   v8::Handle<v8::Object> result =
13512       v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
13513   CHECK_EQ(1, result->InternalFieldCount());
13514 }
13515
13516
13517 // If part of the threaded tests, this test makes ThreadingTest fail
13518 // on mac.
13519 TEST(CatchStackOverflow) {
13520   LocalContext context;
13521   v8::HandleScope scope(context->GetIsolate());
13522   v8::TryCatch try_catch;
13523   v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
13524     "function f() {"
13525     "  return f();"
13526     "}"
13527     ""
13528     "f();"));
13529   v8::Handle<v8::Value> result = script->Run();
13530   CHECK(result.IsEmpty());
13531 }
13532
13533
13534 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
13535                                     const char* resource_name,
13536                                     int line_offset) {
13537   v8::HandleScope scope(v8::Isolate::GetCurrent());
13538   v8::TryCatch try_catch;
13539   v8::Handle<v8::Value> result = script->Run();
13540   CHECK(result.IsEmpty());
13541   CHECK(try_catch.HasCaught());
13542   v8::Handle<v8::Message> message = try_catch.Message();
13543   CHECK(!message.IsEmpty());
13544   CHECK_EQ(10 + line_offset, message->GetLineNumber());
13545   CHECK_EQ(91, message->GetStartPosition());
13546   CHECK_EQ(92, message->GetEndPosition());
13547   CHECK_EQ(2, message->GetStartColumn());
13548   CHECK_EQ(3, message->GetEndColumn());
13549   v8::String::Utf8Value line(message->GetSourceLine());
13550   CHECK_EQ("  throw 'nirk';", *line);
13551   v8::String::Utf8Value name(message->GetScriptResourceName());
13552   CHECK_EQ(resource_name, *name);
13553 }
13554
13555
13556 THREADED_TEST(TryCatchSourceInfo) {
13557   LocalContext context;
13558   v8::HandleScope scope(context->GetIsolate());
13559   v8::Handle<v8::String> source = v8::String::New(
13560       "function Foo() {\n"
13561       "  return Bar();\n"
13562       "}\n"
13563       "\n"
13564       "function Bar() {\n"
13565       "  return Baz();\n"
13566       "}\n"
13567       "\n"
13568       "function Baz() {\n"
13569       "  throw 'nirk';\n"
13570       "}\n"
13571       "\n"
13572       "Foo();\n");
13573
13574   const char* resource_name;
13575   v8::Handle<v8::Script> script;
13576   resource_name = "test.js";
13577   script = v8::Script::Compile(source, v8::String::New(resource_name));
13578   CheckTryCatchSourceInfo(script, resource_name, 0);
13579
13580   resource_name = "test1.js";
13581   v8::ScriptOrigin origin1(v8::String::New(resource_name));
13582   script = v8::Script::Compile(source, &origin1);
13583   CheckTryCatchSourceInfo(script, resource_name, 0);
13584
13585   resource_name = "test2.js";
13586   v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
13587   script = v8::Script::Compile(source, &origin2);
13588   CheckTryCatchSourceInfo(script, resource_name, 7);
13589 }
13590
13591
13592 THREADED_TEST(CompilationCache) {
13593   LocalContext context;
13594   v8::HandleScope scope(context->GetIsolate());
13595   v8::Handle<v8::String> source0 = v8::String::New("1234");
13596   v8::Handle<v8::String> source1 = v8::String::New("1234");
13597   v8::Handle<v8::Script> script0 =
13598       v8::Script::Compile(source0, v8::String::New("test.js"));
13599   v8::Handle<v8::Script> script1 =
13600       v8::Script::Compile(source1, v8::String::New("test.js"));
13601   v8::Handle<v8::Script> script2 =
13602       v8::Script::Compile(source0);  // different origin
13603   CHECK_EQ(1234, script0->Run()->Int32Value());
13604   CHECK_EQ(1234, script1->Run()->Int32Value());
13605   CHECK_EQ(1234, script2->Run()->Int32Value());
13606 }
13607
13608
13609 static void FunctionNameCallback(
13610     const v8::FunctionCallbackInfo<v8::Value>& args) {
13611   ApiTestFuzzer::Fuzz();
13612   args.GetReturnValue().Set(v8_num(42));
13613 }
13614
13615
13616 THREADED_TEST(CallbackFunctionName) {
13617   LocalContext context;
13618   v8::HandleScope scope(context->GetIsolate());
13619   Local<ObjectTemplate> t = ObjectTemplate::New();
13620   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
13621   context->Global()->Set(v8_str("obj"), t->NewInstance());
13622   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
13623   CHECK(value->IsString());
13624   v8::String::Utf8Value name(value);
13625   CHECK_EQ("asdf", *name);
13626 }
13627
13628
13629 THREADED_TEST(DateAccess) {
13630   LocalContext context;
13631   v8::HandleScope scope(context->GetIsolate());
13632   v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
13633   CHECK(date->IsDate());
13634   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
13635 }
13636
13637
13638 void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
13639   v8::Handle<v8::Object> obj = val.As<v8::Object>();
13640   v8::Handle<v8::Array> props = obj->GetPropertyNames();
13641   CHECK_EQ(elmc, props->Length());
13642   for (int i = 0; i < elmc; i++) {
13643     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
13644     CHECK_EQ(elmv[i], *elm);
13645   }
13646 }
13647
13648
13649 void CheckOwnProperties(v8::Handle<v8::Value> val,
13650                         int elmc,
13651                         const char* elmv[]) {
13652   v8::Handle<v8::Object> obj = val.As<v8::Object>();
13653   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
13654   CHECK_EQ(elmc, props->Length());
13655   for (int i = 0; i < elmc; i++) {
13656     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
13657     CHECK_EQ(elmv[i], *elm);
13658   }
13659 }
13660
13661
13662 THREADED_TEST(PropertyEnumeration) {
13663   LocalContext context;
13664   v8::HandleScope scope(context->GetIsolate());
13665   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
13666       "var result = [];"
13667       "result[0] = {};"
13668       "result[1] = {a: 1, b: 2};"
13669       "result[2] = [1, 2, 3];"
13670       "var proto = {x: 1, y: 2, z: 3};"
13671       "var x = { __proto__: proto, w: 0, z: 1 };"
13672       "result[3] = x;"
13673       "result;"))->Run();
13674   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
13675   CHECK_EQ(4, elms->Length());
13676   int elmc0 = 0;
13677   const char** elmv0 = NULL;
13678   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
13679   CheckOwnProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
13680   int elmc1 = 2;
13681   const char* elmv1[] = {"a", "b"};
13682   CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
13683   CheckOwnProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
13684   int elmc2 = 3;
13685   const char* elmv2[] = {"0", "1", "2"};
13686   CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
13687   CheckOwnProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
13688   int elmc3 = 4;
13689   const char* elmv3[] = {"w", "z", "x", "y"};
13690   CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
13691   int elmc4 = 2;
13692   const char* elmv4[] = {"w", "z"};
13693   CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4);
13694 }
13695
13696
13697 THREADED_TEST(PropertyEnumeration2) {
13698   LocalContext context;
13699   v8::HandleScope scope(context->GetIsolate());
13700   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
13701       "var result = [];"
13702       "result[0] = {};"
13703       "result[1] = {a: 1, b: 2};"
13704       "result[2] = [1, 2, 3];"
13705       "var proto = {x: 1, y: 2, z: 3};"
13706       "var x = { __proto__: proto, w: 0, z: 1 };"
13707       "result[3] = x;"
13708       "result;"))->Run();
13709   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
13710   CHECK_EQ(4, elms->Length());
13711   int elmc0 = 0;
13712   const char** elmv0 = NULL;
13713   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
13714
13715   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
13716   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
13717   CHECK_EQ(0, props->Length());
13718   for (uint32_t i = 0; i < props->Length(); i++) {
13719     printf("p[%d]\n", i);
13720   }
13721 }
13722
13723 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
13724                                   Local<Value> name,
13725                                   v8::AccessType type,
13726                                   Local<Value> data) {
13727   return type != v8::ACCESS_SET;
13728 }
13729
13730
13731 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
13732                                     uint32_t key,
13733                                     v8::AccessType type,
13734                                     Local<Value> data) {
13735   return type != v8::ACCESS_SET;
13736 }
13737
13738
13739 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
13740   LocalContext context;
13741   v8::HandleScope scope(context->GetIsolate());
13742   Local<ObjectTemplate> templ = ObjectTemplate::New();
13743   templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
13744                                  IndexedSetAccessBlocker);
13745   templ->Set(v8_str("x"), v8::True());
13746   Local<v8::Object> instance = templ->NewInstance();
13747   context->Global()->Set(v8_str("obj"), instance);
13748   Local<Value> value = CompileRun("obj.x");
13749   CHECK(value->BooleanValue());
13750 }
13751
13752
13753 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
13754                                   Local<Value> name,
13755                                   v8::AccessType type,
13756                                   Local<Value> data) {
13757   return false;
13758 }
13759
13760
13761 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
13762                                     uint32_t key,
13763                                     v8::AccessType type,
13764                                     Local<Value> data) {
13765   return false;
13766 }
13767
13768
13769
13770 THREADED_TEST(AccessChecksReenabledCorrectly) {
13771   LocalContext context;
13772   v8::HandleScope scope(context->GetIsolate());
13773   Local<ObjectTemplate> templ = ObjectTemplate::New();
13774   templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
13775                                  IndexedGetAccessBlocker);
13776   templ->Set(v8_str("a"), v8_str("a"));
13777   // Add more than 8 (see kMaxFastProperties) properties
13778   // so that the constructor will force copying map.
13779   // Cannot sprintf, gcc complains unsafety.
13780   char buf[4];
13781   for (char i = '0'; i <= '9' ; i++) {
13782     buf[0] = i;
13783     for (char j = '0'; j <= '9'; j++) {
13784       buf[1] = j;
13785       for (char k = '0'; k <= '9'; k++) {
13786         buf[2] = k;
13787         buf[3] = 0;
13788         templ->Set(v8_str(buf), v8::Number::New(k));
13789       }
13790     }
13791   }
13792
13793   Local<v8::Object> instance_1 = templ->NewInstance();
13794   context->Global()->Set(v8_str("obj_1"), instance_1);
13795
13796   Local<Value> value_1 = CompileRun("obj_1.a");
13797   CHECK(value_1->IsUndefined());
13798
13799   Local<v8::Object> instance_2 = templ->NewInstance();
13800   context->Global()->Set(v8_str("obj_2"), instance_2);
13801
13802   Local<Value> value_2 = CompileRun("obj_2.a");
13803   CHECK(value_2->IsUndefined());
13804 }
13805
13806
13807 // This tests that access check information remains on the global
13808 // object template when creating contexts.
13809 THREADED_TEST(AccessControlRepeatedContextCreation) {
13810   v8::Isolate* isolate = v8::Isolate::GetCurrent();
13811   v8::HandleScope handle_scope(isolate);
13812   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
13813   global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
13814                                            IndexedSetAccessBlocker);
13815   i::Handle<i::ObjectTemplateInfo> internal_template =
13816       v8::Utils::OpenHandle(*global_template);
13817   CHECK(!internal_template->constructor()->IsUndefined());
13818   i::Handle<i::FunctionTemplateInfo> constructor(
13819       i::FunctionTemplateInfo::cast(internal_template->constructor()));
13820   CHECK(!constructor->access_check_info()->IsUndefined());
13821   v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
13822   CHECK(!context0.IsEmpty());
13823   CHECK(!constructor->access_check_info()->IsUndefined());
13824 }
13825
13826
13827 THREADED_TEST(TurnOnAccessCheck) {
13828   v8::Isolate* isolate = v8::Isolate::GetCurrent();
13829   v8::HandleScope handle_scope(isolate);
13830
13831   // Create an environment with access check to the global object disabled by
13832   // default.
13833   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
13834   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
13835                                            IndexedGetAccessBlocker,
13836                                            v8::Handle<v8::Value>(),
13837                                            false);
13838   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
13839   Context::Scope context_scope(context);
13840
13841   // Set up a property and a number of functions.
13842   context->Global()->Set(v8_str("a"), v8_num(1));
13843   CompileRun("function f1() {return a;}"
13844              "function f2() {return a;}"
13845              "function g1() {return h();}"
13846              "function g2() {return h();}"
13847              "function h() {return 1;}");
13848   Local<Function> f1 =
13849       Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
13850   Local<Function> f2 =
13851       Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
13852   Local<Function> g1 =
13853       Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
13854   Local<Function> g2 =
13855       Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
13856   Local<Function> h =
13857       Local<Function>::Cast(context->Global()->Get(v8_str("h")));
13858
13859   // Get the global object.
13860   v8::Handle<v8::Object> global = context->Global();
13861
13862   // Call f1 one time and f2 a number of times. This will ensure that f1 still
13863   // uses the runtime system to retreive property a whereas f2 uses global load
13864   // inline cache.
13865   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
13866   for (int i = 0; i < 4; i++) {
13867     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
13868   }
13869
13870   // Same for g1 and g2.
13871   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
13872   for (int i = 0; i < 4; i++) {
13873     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
13874   }
13875
13876   // Detach the global and turn on access check.
13877   context->DetachGlobal();
13878   context->Global()->TurnOnAccessCheck();
13879
13880   // Failing access check to property get results in undefined.
13881   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
13882   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
13883
13884   // Failing access check to function call results in exception.
13885   CHECK(g1->Call(global, 0, NULL).IsEmpty());
13886   CHECK(g2->Call(global, 0, NULL).IsEmpty());
13887
13888   // No failing access check when just returning a constant.
13889   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
13890 }
13891
13892
13893 static const char* kPropertyA = "a";
13894 static const char* kPropertyH = "h";
13895
13896 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
13897                                        Local<Value> name,
13898                                        v8::AccessType type,
13899                                        Local<Value> data) {
13900   if (!name->IsString()) return false;
13901   i::Handle<i::String> name_handle =
13902       v8::Utils::OpenHandle(String::Cast(*name));
13903   return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
13904       && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
13905 }
13906
13907
13908 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
13909   v8::Isolate* isolate = v8::Isolate::GetCurrent();
13910   v8::HandleScope handle_scope(isolate);
13911
13912   // Create an environment with access check to the global object disabled by
13913   // default. When the registered access checker will block access to properties
13914   // a and h.
13915   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
13916   global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
13917                                            IndexedGetAccessBlocker,
13918                                            v8::Handle<v8::Value>(),
13919                                            false);
13920   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
13921   Context::Scope context_scope(context);
13922
13923   // Set up a property and a number of functions.
13924   context->Global()->Set(v8_str("a"), v8_num(1));
13925   static const char* source = "function f1() {return a;}"
13926                               "function f2() {return a;}"
13927                               "function g1() {return h();}"
13928                               "function g2() {return h();}"
13929                               "function h() {return 1;}";
13930
13931   CompileRun(source);
13932   Local<Function> f1;
13933   Local<Function> f2;
13934   Local<Function> g1;
13935   Local<Function> g2;
13936   Local<Function> h;
13937   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
13938   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
13939   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
13940   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
13941   h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
13942
13943   // Get the global object.
13944   v8::Handle<v8::Object> global = context->Global();
13945
13946   // Call f1 one time and f2 a number of times. This will ensure that f1 still
13947   // uses the runtime system to retreive property a whereas f2 uses global load
13948   // inline cache.
13949   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
13950   for (int i = 0; i < 4; i++) {
13951     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
13952   }
13953
13954   // Same for g1 and g2.
13955   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
13956   for (int i = 0; i < 4; i++) {
13957     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
13958   }
13959
13960   // Detach the global and turn on access check now blocking access to property
13961   // a and function h.
13962   context->DetachGlobal();
13963   context->Global()->TurnOnAccessCheck();
13964
13965   // Failing access check to property get results in undefined.
13966   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
13967   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
13968
13969   // Failing access check to function call results in exception.
13970   CHECK(g1->Call(global, 0, NULL).IsEmpty());
13971   CHECK(g2->Call(global, 0, NULL).IsEmpty());
13972
13973   // No failing access check when just returning a constant.
13974   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
13975
13976   // Now compile the source again. And get the newly compiled functions, except
13977   // for h for which access is blocked.
13978   CompileRun(source);
13979   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
13980   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
13981   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
13982   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
13983   CHECK(context->Global()->Get(v8_str("h"))->IsUndefined());
13984
13985   // Failing access check to property get results in undefined.
13986   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
13987   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
13988
13989   // Failing access check to function call results in exception.
13990   CHECK(g1->Call(global, 0, NULL).IsEmpty());
13991   CHECK(g2->Call(global, 0, NULL).IsEmpty());
13992 }
13993
13994
13995 // This test verifies that pre-compilation (aka preparsing) can be called
13996 // without initializing the whole VM. Thus we cannot run this test in a
13997 // multi-threaded setup.
13998 TEST(PreCompile) {
13999   // TODO(155): This test would break without the initialization of V8. This is
14000   // a workaround for now to make this test not fail.
14001   v8::V8::Initialize();
14002   const char* script = "function foo(a) { return a+1; }";
14003   v8::ScriptData* sd =
14004       v8::ScriptData::PreCompile(script, i::StrLength(script));
14005   CHECK_NE(sd->Length(), 0);
14006   CHECK_NE(sd->Data(), NULL);
14007   CHECK(!sd->HasError());
14008   delete sd;
14009 }
14010
14011
14012 TEST(PreCompileWithError) {
14013   v8::V8::Initialize();
14014   const char* script = "function foo(a) { return 1 * * 2; }";
14015   v8::ScriptData* sd =
14016       v8::ScriptData::PreCompile(script, i::StrLength(script));
14017   CHECK(sd->HasError());
14018   delete sd;
14019 }
14020
14021
14022 TEST(Regress31661) {
14023   v8::V8::Initialize();
14024   const char* script = " The Definintive Guide";
14025   v8::ScriptData* sd =
14026       v8::ScriptData::PreCompile(script, i::StrLength(script));
14027   CHECK(sd->HasError());
14028   delete sd;
14029 }
14030
14031
14032 // Tests that ScriptData can be serialized and deserialized.
14033 TEST(PreCompileSerialization) {
14034   v8::V8::Initialize();
14035   const char* script = "function foo(a) { return a+1; }";
14036   v8::ScriptData* sd =
14037       v8::ScriptData::PreCompile(script, i::StrLength(script));
14038
14039   // Serialize.
14040   int serialized_data_length = sd->Length();
14041   char* serialized_data = i::NewArray<char>(serialized_data_length);
14042   i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
14043
14044   // Deserialize.
14045   v8::ScriptData* deserialized_sd =
14046       v8::ScriptData::New(serialized_data, serialized_data_length);
14047
14048   // Verify that the original is the same as the deserialized.
14049   CHECK_EQ(sd->Length(), deserialized_sd->Length());
14050   CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
14051   CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
14052
14053   delete sd;
14054   delete deserialized_sd;
14055 }
14056
14057
14058 // Attempts to deserialize bad data.
14059 TEST(PreCompileDeserializationError) {
14060   v8::V8::Initialize();
14061   const char* data = "DONT CARE";
14062   int invalid_size = 3;
14063   v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
14064
14065   CHECK_EQ(0, sd->Length());
14066
14067   delete sd;
14068 }
14069
14070
14071 // Attempts to deserialize bad data.
14072 TEST(PreCompileInvalidPreparseDataError) {
14073   v8::V8::Initialize();
14074   LocalContext context;
14075   v8::HandleScope scope(context->GetIsolate());
14076
14077   const char* script = "function foo(){ return 5;}\n"
14078       "function bar(){ return 6 + 7;}  foo();";
14079   v8::ScriptData* sd =
14080       v8::ScriptData::PreCompile(script, i::StrLength(script));
14081   CHECK(!sd->HasError());
14082   // ScriptDataImpl private implementation details
14083   const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
14084   const int kFunctionEntrySize = i::FunctionEntry::kSize;
14085   const int kFunctionEntryStartOffset = 0;
14086   const int kFunctionEntryEndOffset = 1;
14087   unsigned* sd_data =
14088       reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
14089
14090   // Overwrite function bar's end position with 0.
14091   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
14092   v8::TryCatch try_catch;
14093
14094   Local<String> source = String::New(script);
14095   Local<Script> compiled_script = Script::New(source, NULL, sd);
14096   CHECK(try_catch.HasCaught());
14097   String::Utf8Value exception_value(try_catch.Message()->Get());
14098   CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
14099            *exception_value);
14100
14101   try_catch.Reset();
14102
14103   // Overwrite function bar's start position with 200.  The function entry
14104   // will not be found when searching for it by position and we should fall
14105   // back on eager compilation.
14106   sd = v8::ScriptData::PreCompile(script, i::StrLength(script));
14107   sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
14108   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
14109       200;
14110   compiled_script = Script::New(source, NULL, sd);
14111   CHECK(!try_catch.HasCaught());
14112
14113   delete sd;
14114 }
14115
14116
14117 // Verifies that the Handle<String> and const char* versions of the API produce
14118 // the same results (at least for one trivial case).
14119 TEST(PreCompileAPIVariationsAreSame) {
14120   v8::V8::Initialize();
14121   v8::HandleScope scope(v8::Isolate::GetCurrent());
14122
14123   const char* cstring = "function foo(a) { return a+1; }";
14124
14125   v8::ScriptData* sd_from_cstring =
14126       v8::ScriptData::PreCompile(cstring, i::StrLength(cstring));
14127
14128   TestAsciiResource* resource = new TestAsciiResource(cstring);
14129   v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
14130       v8::String::NewExternal(resource));
14131
14132   v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
14133       v8::String::New(cstring));
14134
14135   CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
14136   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
14137                      sd_from_external_string->Data(),
14138                      sd_from_cstring->Length()));
14139
14140   CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
14141   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
14142                      sd_from_string->Data(),
14143                      sd_from_cstring->Length()));
14144
14145
14146   delete sd_from_cstring;
14147   delete sd_from_external_string;
14148   delete sd_from_string;
14149 }
14150
14151
14152 // This tests that we do not allow dictionary load/call inline caches
14153 // to use functions that have not yet been compiled.  The potential
14154 // problem of loading a function that has not yet been compiled can
14155 // arise because we share code between contexts via the compilation
14156 // cache.
14157 THREADED_TEST(DictionaryICLoadedFunction) {
14158   v8::HandleScope scope(v8::Isolate::GetCurrent());
14159   // Test LoadIC.
14160   for (int i = 0; i < 2; i++) {
14161     LocalContext context;
14162     context->Global()->Set(v8_str("tmp"), v8::True());
14163     context->Global()->Delete(v8_str("tmp"));
14164     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
14165   }
14166   // Test CallIC.
14167   for (int i = 0; i < 2; i++) {
14168     LocalContext context;
14169     context->Global()->Set(v8_str("tmp"), v8::True());
14170     context->Global()->Delete(v8_str("tmp"));
14171     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
14172   }
14173 }
14174
14175
14176 // Test that cross-context new calls use the context of the callee to
14177 // create the new JavaScript object.
14178 THREADED_TEST(CrossContextNew) {
14179   v8::Isolate* isolate = v8::Isolate::GetCurrent();
14180   v8::HandleScope scope(isolate);
14181   v8::Local<Context> context0 = Context::New(isolate);
14182   v8::Local<Context> context1 = Context::New(isolate);
14183
14184   // Allow cross-domain access.
14185   Local<String> token = v8_str("<security token>");
14186   context0->SetSecurityToken(token);
14187   context1->SetSecurityToken(token);
14188
14189   // Set an 'x' property on the Object prototype and define a
14190   // constructor function in context0.
14191   context0->Enter();
14192   CompileRun("Object.prototype.x = 42; function C() {};");
14193   context0->Exit();
14194
14195   // Call the constructor function from context0 and check that the
14196   // result has the 'x' property.
14197   context1->Enter();
14198   context1->Global()->Set(v8_str("other"), context0->Global());
14199   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
14200   CHECK(value->IsInt32());
14201   CHECK_EQ(42, value->Int32Value());
14202   context1->Exit();
14203 }
14204
14205
14206 class RegExpInterruptTest {
14207  public:
14208   RegExpInterruptTest() : block_(0) {}
14209   ~RegExpInterruptTest() {}
14210   void RunTest() {
14211     gc_count_ = 0;
14212     gc_during_regexp_ = 0;
14213     regexp_success_ = false;
14214     gc_success_ = false;
14215     GCThread gc_thread(this);
14216     gc_thread.Start();
14217     v8::Locker::StartPreemption(1);
14218
14219     LongRunningRegExp();
14220     {
14221       v8::Unlocker unlock(CcTest::default_isolate());
14222       gc_thread.Join();
14223     }
14224     v8::Locker::StopPreemption();
14225     CHECK(regexp_success_);
14226     CHECK(gc_success_);
14227   }
14228
14229  private:
14230   // Number of garbage collections required.
14231   static const int kRequiredGCs = 5;
14232
14233   class GCThread : public i::Thread {
14234    public:
14235     explicit GCThread(RegExpInterruptTest* test)
14236         : Thread("GCThread"), test_(test) {}
14237     virtual void Run() {
14238       test_->CollectGarbage();
14239     }
14240    private:
14241      RegExpInterruptTest* test_;
14242   };
14243
14244   void CollectGarbage() {
14245     block_.Wait();
14246     while (gc_during_regexp_ < kRequiredGCs) {
14247       {
14248         v8::Locker lock(CcTest::default_isolate());
14249         // TODO(lrn): Perhaps create some garbage before collecting.
14250         HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
14251         gc_count_++;
14252       }
14253       i::OS::Sleep(1);
14254     }
14255     gc_success_ = true;
14256   }
14257
14258   void LongRunningRegExp() {
14259     block_.Signal();  // Enable garbage collection thread on next preemption.
14260     int rounds = 0;
14261     while (gc_during_regexp_ < kRequiredGCs) {
14262       int gc_before = gc_count_;
14263       {
14264         // Match 15-30 "a"'s against 14 and a "b".
14265         const char* c_source =
14266             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
14267             ".exec('aaaaaaaaaaaaaaab') === null";
14268         Local<String> source = String::New(c_source);
14269         Local<Script> script = Script::Compile(source);
14270         Local<Value> result = script->Run();
14271         if (!result->BooleanValue()) {
14272           gc_during_regexp_ = kRequiredGCs;  // Allow gc thread to exit.
14273           return;
14274         }
14275       }
14276       {
14277         // Match 15-30 "a"'s against 15 and a "b".
14278         const char* c_source =
14279             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
14280             ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
14281         Local<String> source = String::New(c_source);
14282         Local<Script> script = Script::Compile(source);
14283         Local<Value> result = script->Run();
14284         if (!result->BooleanValue()) {
14285           gc_during_regexp_ = kRequiredGCs;
14286           return;
14287         }
14288       }
14289       int gc_after = gc_count_;
14290       gc_during_regexp_ += gc_after - gc_before;
14291       rounds++;
14292       i::OS::Sleep(1);
14293     }
14294     regexp_success_ = true;
14295   }
14296
14297   i::Semaphore block_;
14298   int gc_count_;
14299   int gc_during_regexp_;
14300   bool regexp_success_;
14301   bool gc_success_;
14302 };
14303
14304
14305 // Test that a regular expression execution can be interrupted and
14306 // survive a garbage collection.
14307 TEST(RegExpInterruption) {
14308   v8::Locker lock(CcTest::default_isolate());
14309   v8::V8::Initialize();
14310   v8::HandleScope scope(CcTest::default_isolate());
14311   Local<Context> local_env;
14312   {
14313     LocalContext env;
14314     local_env = env.local();
14315   }
14316
14317   // Local context should still be live.
14318   CHECK(!local_env.IsEmpty());
14319   local_env->Enter();
14320
14321   // Should complete without problems.
14322   RegExpInterruptTest().RunTest();
14323
14324   local_env->Exit();
14325 }
14326
14327
14328 class ApplyInterruptTest {
14329  public:
14330   ApplyInterruptTest() : block_(0) {}
14331   ~ApplyInterruptTest() {}
14332   void RunTest() {
14333     gc_count_ = 0;
14334     gc_during_apply_ = 0;
14335     apply_success_ = false;
14336     gc_success_ = false;
14337     GCThread gc_thread(this);
14338     gc_thread.Start();
14339     v8::Locker::StartPreemption(1);
14340
14341     LongRunningApply();
14342     {
14343       v8::Unlocker unlock(CcTest::default_isolate());
14344       gc_thread.Join();
14345     }
14346     v8::Locker::StopPreemption();
14347     CHECK(apply_success_);
14348     CHECK(gc_success_);
14349   }
14350
14351  private:
14352   // Number of garbage collections required.
14353   static const int kRequiredGCs = 2;
14354
14355   class GCThread : public i::Thread {
14356    public:
14357     explicit GCThread(ApplyInterruptTest* test)
14358         : Thread("GCThread"), test_(test) {}
14359     virtual void Run() {
14360       test_->CollectGarbage();
14361     }
14362    private:
14363      ApplyInterruptTest* test_;
14364   };
14365
14366   void CollectGarbage() {
14367     block_.Wait();
14368     while (gc_during_apply_ < kRequiredGCs) {
14369       {
14370         v8::Locker lock(CcTest::default_isolate());
14371         HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
14372         gc_count_++;
14373       }
14374       i::OS::Sleep(1);
14375     }
14376     gc_success_ = true;
14377   }
14378
14379   void LongRunningApply() {
14380     block_.Signal();
14381     int rounds = 0;
14382     while (gc_during_apply_ < kRequiredGCs) {
14383       int gc_before = gc_count_;
14384       {
14385         const char* c_source =
14386             "function do_very_little(bar) {"
14387             "  this.foo = bar;"
14388             "}"
14389             "for (var i = 0; i < 100000; i++) {"
14390             "  do_very_little.apply(this, ['bar']);"
14391             "}";
14392         Local<String> source = String::New(c_source);
14393         Local<Script> script = Script::Compile(source);
14394         Local<Value> result = script->Run();
14395         // Check that no exception was thrown.
14396         CHECK(!result.IsEmpty());
14397       }
14398       int gc_after = gc_count_;
14399       gc_during_apply_ += gc_after - gc_before;
14400       rounds++;
14401     }
14402     apply_success_ = true;
14403   }
14404
14405   i::Semaphore block_;
14406   int gc_count_;
14407   int gc_during_apply_;
14408   bool apply_success_;
14409   bool gc_success_;
14410 };
14411
14412
14413 // Test that nothing bad happens if we get a preemption just when we were
14414 // about to do an apply().
14415 TEST(ApplyInterruption) {
14416   v8::Locker lock(CcTest::default_isolate());
14417   v8::V8::Initialize();
14418   v8::HandleScope scope(CcTest::default_isolate());
14419   Local<Context> local_env;
14420   {
14421     LocalContext env;
14422     local_env = env.local();
14423   }
14424
14425   // Local context should still be live.
14426   CHECK(!local_env.IsEmpty());
14427   local_env->Enter();
14428
14429   // Should complete without problems.
14430   ApplyInterruptTest().RunTest();
14431
14432   local_env->Exit();
14433 }
14434
14435
14436 // Verify that we can clone an object
14437 TEST(ObjectClone) {
14438   LocalContext env;
14439   v8::HandleScope scope(env->GetIsolate());
14440
14441   const char* sample =
14442     "var rv = {};"      \
14443     "rv.alpha = 'hello';" \
14444     "rv.beta = 123;"     \
14445     "rv;";
14446
14447   // Create an object, verify basics.
14448   Local<Value> val = CompileRun(sample);
14449   CHECK(val->IsObject());
14450   Local<v8::Object> obj = val.As<v8::Object>();
14451   obj->Set(v8_str("gamma"), v8_str("cloneme"));
14452
14453   CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
14454   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
14455   CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
14456
14457   // Clone it.
14458   Local<v8::Object> clone = obj->Clone();
14459   CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
14460   CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
14461   CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
14462
14463   // Set a property on the clone, verify each object.
14464   clone->Set(v8_str("beta"), v8::Integer::New(456));
14465   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
14466   CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
14467 }
14468
14469
14470 class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
14471  public:
14472   explicit AsciiVectorResource(i::Vector<const char> vector)
14473       : data_(vector) {}
14474   virtual ~AsciiVectorResource() {}
14475   virtual size_t length() const { return data_.length(); }
14476   virtual const char* data() const { return data_.start(); }
14477  private:
14478   i::Vector<const char> data_;
14479 };
14480
14481
14482 class UC16VectorResource : public v8::String::ExternalStringResource {
14483  public:
14484   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
14485       : data_(vector) {}
14486   virtual ~UC16VectorResource() {}
14487   virtual size_t length() const { return data_.length(); }
14488   virtual const i::uc16* data() const { return data_.start(); }
14489  private:
14490   i::Vector<const i::uc16> data_;
14491 };
14492
14493
14494 static void MorphAString(i::String* string,
14495                          AsciiVectorResource* ascii_resource,
14496                          UC16VectorResource* uc16_resource) {
14497   CHECK(i::StringShape(string).IsExternal());
14498   if (string->IsOneByteRepresentation()) {
14499     // Check old map is not internalized or long.
14500     CHECK(string->map() == HEAP->external_ascii_string_map());
14501     // Morph external string to be TwoByte string.
14502     string->set_map(HEAP->external_string_map());
14503     i::ExternalTwoByteString* morphed =
14504          i::ExternalTwoByteString::cast(string);
14505     morphed->set_resource(uc16_resource);
14506   } else {
14507     // Check old map is not internalized or long.
14508     CHECK(string->map() == HEAP->external_string_map());
14509     // Morph external string to be ASCII string.
14510     string->set_map(HEAP->external_ascii_string_map());
14511     i::ExternalAsciiString* morphed =
14512          i::ExternalAsciiString::cast(string);
14513     morphed->set_resource(ascii_resource);
14514   }
14515 }
14516
14517
14518 // Test that we can still flatten a string if the components it is built up
14519 // from have been turned into 16 bit strings in the mean time.
14520 THREADED_TEST(MorphCompositeStringTest) {
14521   char utf_buffer[129];
14522   const char* c_string = "Now is the time for all good men"
14523                          " to come to the aid of the party";
14524   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
14525   {
14526     LocalContext env;
14527     i::Factory* factory = i::Isolate::Current()->factory();
14528     v8::HandleScope scope(env->GetIsolate());
14529     AsciiVectorResource ascii_resource(
14530         i::Vector<const char>(c_string, i::StrLength(c_string)));
14531     UC16VectorResource uc16_resource(
14532         i::Vector<const uint16_t>(two_byte_string,
14533                                   i::StrLength(c_string)));
14534
14535     Local<String> lhs(v8::Utils::ToLocal(
14536         factory->NewExternalStringFromAscii(&ascii_resource)));
14537     Local<String> rhs(v8::Utils::ToLocal(
14538         factory->NewExternalStringFromAscii(&ascii_resource)));
14539
14540     env->Global()->Set(v8_str("lhs"), lhs);
14541     env->Global()->Set(v8_str("rhs"), rhs);
14542
14543     CompileRun(
14544         "var cons = lhs + rhs;"
14545         "var slice = lhs.substring(1, lhs.length - 1);"
14546         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
14547
14548     CHECK(lhs->IsOneByte());
14549     CHECK(rhs->IsOneByte());
14550
14551     MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
14552     MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
14553
14554     // This should UTF-8 without flattening, since everything is ASCII.
14555     Handle<String> cons = v8_compile("cons")->Run().As<String>();
14556     CHECK_EQ(128, cons->Utf8Length());
14557     int nchars = -1;
14558     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
14559     CHECK_EQ(128, nchars);
14560     CHECK_EQ(0, strcmp(
14561         utf_buffer,
14562         "Now is the time for all good men to come to the aid of the party"
14563         "Now is the time for all good men to come to the aid of the party"));
14564
14565     // Now do some stuff to make sure the strings are flattened, etc.
14566     CompileRun(
14567         "/[^a-z]/.test(cons);"
14568         "/[^a-z]/.test(slice);"
14569         "/[^a-z]/.test(slice_on_cons);");
14570     const char* expected_cons =
14571         "Now is the time for all good men to come to the aid of the party"
14572         "Now is the time for all good men to come to the aid of the party";
14573     const char* expected_slice =
14574         "ow is the time for all good men to come to the aid of the part";
14575     const char* expected_slice_on_cons =
14576         "ow is the time for all good men to come to the aid of the party"
14577         "Now is the time for all good men to come to the aid of the part";
14578     CHECK_EQ(String::New(expected_cons),
14579              env->Global()->Get(v8_str("cons")));
14580     CHECK_EQ(String::New(expected_slice),
14581              env->Global()->Get(v8_str("slice")));
14582     CHECK_EQ(String::New(expected_slice_on_cons),
14583              env->Global()->Get(v8_str("slice_on_cons")));
14584   }
14585   i::DeleteArray(two_byte_string);
14586 }
14587
14588
14589 TEST(CompileExternalTwoByteSource) {
14590   LocalContext context;
14591   v8::HandleScope scope(context->GetIsolate());
14592
14593   // This is a very short list of sources, which currently is to check for a
14594   // regression caused by r2703.
14595   const char* ascii_sources[] = {
14596     "0.5",
14597     "-0.5",   // This mainly testes PushBack in the Scanner.
14598     "--0.5",  // This mainly testes PushBack in the Scanner.
14599     NULL
14600   };
14601
14602   // Compile the sources as external two byte strings.
14603   for (int i = 0; ascii_sources[i] != NULL; i++) {
14604     uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
14605     UC16VectorResource uc16_resource(
14606         i::Vector<const uint16_t>(two_byte_string,
14607                                   i::StrLength(ascii_sources[i])));
14608     v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
14609     v8::Script::Compile(source);
14610     i::DeleteArray(two_byte_string);
14611   }
14612 }
14613
14614
14615 class RegExpStringModificationTest {
14616  public:
14617   RegExpStringModificationTest()
14618       : block_(0),
14619         morphs_(0),
14620         morphs_during_regexp_(0),
14621         ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
14622         uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
14623   ~RegExpStringModificationTest() {}
14624   void RunTest() {
14625     i::Factory* factory = i::Isolate::Current()->factory();
14626
14627     regexp_success_ = false;
14628     morph_success_ = false;
14629
14630     // Initialize the contents of two_byte_content_ to be a uc16 representation
14631     // of "aaaaaaaaaaaaaab".
14632     for (int i = 0; i < 14; i++) {
14633       two_byte_content_[i] = 'a';
14634     }
14635     two_byte_content_[14] = 'b';
14636
14637     // Create the input string for the regexp - the one we are going to change
14638     // properties of.
14639     input_ = factory->NewExternalStringFromAscii(&ascii_resource_);
14640
14641     // Inject the input as a global variable.
14642     i::Handle<i::String> input_name =
14643         factory->NewStringFromAscii(i::Vector<const char>("input", 5));
14644     i::Isolate::Current()->native_context()->global_object()->SetProperty(
14645         *input_name,
14646         *input_,
14647         NONE,
14648         i::kNonStrictMode)->ToObjectChecked();
14649
14650     MorphThread morph_thread(this);
14651     morph_thread.Start();
14652     v8::Locker::StartPreemption(1);
14653     LongRunningRegExp();
14654     {
14655       v8::Unlocker unlock(CcTest::default_isolate());
14656       morph_thread.Join();
14657     }
14658     v8::Locker::StopPreemption();
14659     CHECK(regexp_success_);
14660     CHECK(morph_success_);
14661   }
14662
14663  private:
14664   // Number of string modifications required.
14665   static const int kRequiredModifications = 5;
14666   static const int kMaxModifications = 100;
14667
14668   class MorphThread : public i::Thread {
14669    public:
14670     explicit MorphThread(RegExpStringModificationTest* test)
14671         : Thread("MorphThread"), test_(test) {}
14672     virtual void Run() {
14673       test_->MorphString();
14674     }
14675    private:
14676      RegExpStringModificationTest* test_;
14677   };
14678
14679   void MorphString() {
14680     block_.Wait();
14681     while (morphs_during_regexp_ < kRequiredModifications &&
14682            morphs_ < kMaxModifications) {
14683       {
14684         v8::Locker lock(CcTest::default_isolate());
14685         // Swap string between ascii and two-byte representation.
14686         i::String* string = *input_;
14687         MorphAString(string, &ascii_resource_, &uc16_resource_);
14688         morphs_++;
14689       }
14690       i::OS::Sleep(1);
14691     }
14692     morph_success_ = true;
14693   }
14694
14695   void LongRunningRegExp() {
14696     block_.Signal();  // Enable morphing thread on next preemption.
14697     while (morphs_during_regexp_ < kRequiredModifications &&
14698            morphs_ < kMaxModifications) {
14699       int morphs_before = morphs_;
14700       {
14701         v8::HandleScope scope(v8::Isolate::GetCurrent());
14702         // Match 15-30 "a"'s against 14 and a "b".
14703         const char* c_source =
14704             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
14705             ".exec(input) === null";
14706         Local<String> source = String::New(c_source);
14707         Local<Script> script = Script::Compile(source);
14708         Local<Value> result = script->Run();
14709         CHECK(result->IsTrue());
14710       }
14711       int morphs_after = morphs_;
14712       morphs_during_regexp_ += morphs_after - morphs_before;
14713     }
14714     regexp_success_ = true;
14715   }
14716
14717   i::uc16 two_byte_content_[15];
14718   i::Semaphore block_;
14719   int morphs_;
14720   int morphs_during_regexp_;
14721   bool regexp_success_;
14722   bool morph_success_;
14723   i::Handle<i::String> input_;
14724   AsciiVectorResource ascii_resource_;
14725   UC16VectorResource uc16_resource_;
14726 };
14727
14728
14729 // Test that a regular expression execution can be interrupted and
14730 // the string changed without failing.
14731 TEST(RegExpStringModification) {
14732   v8::Locker lock(CcTest::default_isolate());
14733   v8::V8::Initialize();
14734   v8::HandleScope scope(CcTest::default_isolate());
14735   Local<Context> local_env;
14736   {
14737     LocalContext env;
14738     local_env = env.local();
14739   }
14740
14741   // Local context should still be live.
14742   CHECK(!local_env.IsEmpty());
14743   local_env->Enter();
14744
14745   // Should complete without problems.
14746   RegExpStringModificationTest().RunTest();
14747
14748   local_env->Exit();
14749 }
14750
14751
14752 // Test that we cannot set a property on the global object if there
14753 // is a read-only property in the prototype chain.
14754 TEST(ReadOnlyPropertyInGlobalProto) {
14755   i::FLAG_es5_readonly = true;
14756   v8::HandleScope scope(v8::Isolate::GetCurrent());
14757   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14758   LocalContext context(0, templ);
14759   v8::Handle<v8::Object> global = context->Global();
14760   v8::Handle<v8::Object> global_proto =
14761       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
14762   global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
14763   global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
14764   // Check without 'eval' or 'with'.
14765   v8::Handle<v8::Value> res =
14766       CompileRun("function f() { x = 42; return x; }; f()");
14767   CHECK_EQ(v8::Integer::New(0), res);
14768   // Check with 'eval'.
14769   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
14770   CHECK_EQ(v8::Integer::New(0), res);
14771   // Check with 'with'.
14772   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
14773   CHECK_EQ(v8::Integer::New(0), res);
14774 }
14775
14776 static int force_set_set_count = 0;
14777 static int force_set_get_count = 0;
14778 bool pass_on_get = false;
14779
14780 static void ForceSetGetter(v8::Local<v8::String> name,
14781                            const v8::PropertyCallbackInfo<v8::Value>& info) {
14782   force_set_get_count++;
14783   if (pass_on_get) {
14784     return;
14785   }
14786   info.GetReturnValue().Set(3);
14787 }
14788
14789 static void ForceSetSetter(v8::Local<v8::String> name,
14790                            v8::Local<v8::Value> value,
14791                            const v8::PropertyCallbackInfo<void>& info) {
14792   force_set_set_count++;
14793 }
14794
14795 static void ForceSetInterceptSetter(
14796     v8::Local<v8::String> name,
14797     v8::Local<v8::Value> value,
14798     const v8::PropertyCallbackInfo<v8::Value>& info) {
14799   force_set_set_count++;
14800   info.GetReturnValue().SetUndefined();
14801 }
14802
14803
14804 TEST(ForceSet) {
14805   force_set_get_count = 0;
14806   force_set_set_count = 0;
14807   pass_on_get = false;
14808
14809   v8::HandleScope scope(v8::Isolate::GetCurrent());
14810   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14811   v8::Handle<v8::String> access_property = v8::String::New("a");
14812   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
14813   LocalContext context(NULL, templ);
14814   v8::Handle<v8::Object> global = context->Global();
14815
14816   // Ordinary properties
14817   v8::Handle<v8::String> simple_property = v8::String::New("p");
14818   global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
14819   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
14820   // This should fail because the property is read-only
14821   global->Set(simple_property, v8::Int32::New(5));
14822   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
14823   // This should succeed even though the property is read-only
14824   global->ForceSet(simple_property, v8::Int32::New(6));
14825   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
14826
14827   // Accessors
14828   CHECK_EQ(0, force_set_set_count);
14829   CHECK_EQ(0, force_set_get_count);
14830   CHECK_EQ(3, global->Get(access_property)->Int32Value());
14831   // CHECK_EQ the property shouldn't override it, just call the setter
14832   // which in this case does nothing.
14833   global->Set(access_property, v8::Int32::New(7));
14834   CHECK_EQ(3, global->Get(access_property)->Int32Value());
14835   CHECK_EQ(1, force_set_set_count);
14836   CHECK_EQ(2, force_set_get_count);
14837   // Forcing the property to be set should override the accessor without
14838   // calling it
14839   global->ForceSet(access_property, v8::Int32::New(8));
14840   CHECK_EQ(8, global->Get(access_property)->Int32Value());
14841   CHECK_EQ(1, force_set_set_count);
14842   CHECK_EQ(2, force_set_get_count);
14843 }
14844
14845
14846 TEST(ForceSetWithInterceptor) {
14847   force_set_get_count = 0;
14848   force_set_set_count = 0;
14849   pass_on_get = false;
14850
14851   v8::HandleScope scope(v8::Isolate::GetCurrent());
14852   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14853   templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
14854   LocalContext context(NULL, templ);
14855   v8::Handle<v8::Object> global = context->Global();
14856
14857   v8::Handle<v8::String> some_property = v8::String::New("a");
14858   CHECK_EQ(0, force_set_set_count);
14859   CHECK_EQ(0, force_set_get_count);
14860   CHECK_EQ(3, global->Get(some_property)->Int32Value());
14861   // Setting the property shouldn't override it, just call the setter
14862   // which in this case does nothing.
14863   global->Set(some_property, v8::Int32::New(7));
14864   CHECK_EQ(3, global->Get(some_property)->Int32Value());
14865   CHECK_EQ(1, force_set_set_count);
14866   CHECK_EQ(2, force_set_get_count);
14867   // Getting the property when the interceptor returns an empty handle
14868   // should yield undefined, since the property isn't present on the
14869   // object itself yet.
14870   pass_on_get = true;
14871   CHECK(global->Get(some_property)->IsUndefined());
14872   CHECK_EQ(1, force_set_set_count);
14873   CHECK_EQ(3, force_set_get_count);
14874   // Forcing the property to be set should cause the value to be
14875   // set locally without calling the interceptor.
14876   global->ForceSet(some_property, v8::Int32::New(8));
14877   CHECK_EQ(8, global->Get(some_property)->Int32Value());
14878   CHECK_EQ(1, force_set_set_count);
14879   CHECK_EQ(4, force_set_get_count);
14880   // Reenabling the interceptor should cause it to take precedence over
14881   // the property
14882   pass_on_get = false;
14883   CHECK_EQ(3, global->Get(some_property)->Int32Value());
14884   CHECK_EQ(1, force_set_set_count);
14885   CHECK_EQ(5, force_set_get_count);
14886   // The interceptor should also work for other properties
14887   CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
14888   CHECK_EQ(1, force_set_set_count);
14889   CHECK_EQ(6, force_set_get_count);
14890 }
14891
14892
14893 THREADED_TEST(ForceDelete) {
14894   v8::HandleScope scope(v8::Isolate::GetCurrent());
14895   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14896   LocalContext context(NULL, templ);
14897   v8::Handle<v8::Object> global = context->Global();
14898
14899   // Ordinary properties
14900   v8::Handle<v8::String> simple_property = v8::String::New("p");
14901   global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
14902   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
14903   // This should fail because the property is dont-delete.
14904   CHECK(!global->Delete(simple_property));
14905   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
14906   // This should succeed even though the property is dont-delete.
14907   CHECK(global->ForceDelete(simple_property));
14908   CHECK(global->Get(simple_property)->IsUndefined());
14909 }
14910
14911
14912 static int force_delete_interceptor_count = 0;
14913 static bool pass_on_delete = false;
14914
14915
14916 static void ForceDeleteDeleter(
14917     v8::Local<v8::String> name,
14918     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
14919   force_delete_interceptor_count++;
14920   if (pass_on_delete) return;
14921   info.GetReturnValue().Set(true);
14922 }
14923
14924
14925 THREADED_TEST(ForceDeleteWithInterceptor) {
14926   force_delete_interceptor_count = 0;
14927   pass_on_delete = false;
14928
14929   v8::HandleScope scope(v8::Isolate::GetCurrent());
14930   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14931   templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
14932   LocalContext context(NULL, templ);
14933   v8::Handle<v8::Object> global = context->Global();
14934
14935   v8::Handle<v8::String> some_property = v8::String::New("a");
14936   global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
14937
14938   // Deleting a property should get intercepted and nothing should
14939   // happen.
14940   CHECK_EQ(0, force_delete_interceptor_count);
14941   CHECK(global->Delete(some_property));
14942   CHECK_EQ(1, force_delete_interceptor_count);
14943   CHECK_EQ(42, global->Get(some_property)->Int32Value());
14944   // Deleting the property when the interceptor returns an empty
14945   // handle should not delete the property since it is DontDelete.
14946   pass_on_delete = true;
14947   CHECK(!global->Delete(some_property));
14948   CHECK_EQ(2, force_delete_interceptor_count);
14949   CHECK_EQ(42, global->Get(some_property)->Int32Value());
14950   // Forcing the property to be deleted should delete the value
14951   // without calling the interceptor.
14952   CHECK(global->ForceDelete(some_property));
14953   CHECK(global->Get(some_property)->IsUndefined());
14954   CHECK_EQ(2, force_delete_interceptor_count);
14955 }
14956
14957
14958 // Make sure that forcing a delete invalidates any IC stubs, so we
14959 // don't read the hole value.
14960 THREADED_TEST(ForceDeleteIC) {
14961   LocalContext context;
14962   v8::HandleScope scope(context->GetIsolate());
14963   // Create a DontDelete variable on the global object.
14964   CompileRun("this.__proto__ = { foo: 'horse' };"
14965              "var foo = 'fish';"
14966              "function f() { return foo.length; }");
14967   // Initialize the IC for foo in f.
14968   CompileRun("for (var i = 0; i < 4; i++) f();");
14969   // Make sure the value of foo is correct before the deletion.
14970   CHECK_EQ(4, CompileRun("f()")->Int32Value());
14971   // Force the deletion of foo.
14972   CHECK(context->Global()->ForceDelete(v8_str("foo")));
14973   // Make sure the value for foo is read from the prototype, and that
14974   // we don't get in trouble with reading the deleted cell value
14975   // sentinel.
14976   CHECK_EQ(5, CompileRun("f()")->Int32Value());
14977 }
14978
14979
14980 TEST(InlinedFunctionAcrossContexts) {
14981   i::FLAG_allow_natives_syntax = true;
14982   v8::Isolate* isolate = v8::Isolate::GetCurrent();
14983   v8::HandleScope outer_scope(isolate);
14984   v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
14985   v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
14986   ctx1->Enter();
14987
14988   {
14989     v8::HandleScope inner_scope(v8::Isolate::GetCurrent());
14990     CompileRun("var G = 42; function foo() { return G; }");
14991     v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
14992     ctx2->Enter();
14993     ctx2->Global()->Set(v8_str("o"), foo);
14994     v8::Local<v8::Value> res = CompileRun(
14995         "function f() { return o(); }"
14996         "for (var i = 0; i < 10; ++i) f();"
14997         "%OptimizeFunctionOnNextCall(f);"
14998         "f();");
14999     CHECK_EQ(42, res->Int32Value());
15000     ctx2->Exit();
15001     v8::Handle<v8::String> G_property = v8::String::New("G");
15002     CHECK(ctx1->Global()->ForceDelete(G_property));
15003     ctx2->Enter();
15004     ExpectString(
15005         "(function() {"
15006         "  try {"
15007         "    return f();"
15008         "  } catch(e) {"
15009         "    return e.toString();"
15010         "  }"
15011         " })()",
15012         "ReferenceError: G is not defined");
15013     ctx2->Exit();
15014     ctx1->Exit();
15015   }
15016 }
15017
15018
15019 static v8::Local<Context> calling_context0;
15020 static v8::Local<Context> calling_context1;
15021 static v8::Local<Context> calling_context2;
15022
15023
15024 // Check that the call to the callback is initiated in
15025 // calling_context2, the directly calling context is calling_context1
15026 // and the callback itself is in calling_context0.
15027 static void GetCallingContextCallback(
15028     const v8::FunctionCallbackInfo<v8::Value>& args) {
15029   ApiTestFuzzer::Fuzz();
15030   CHECK(Context::GetCurrent() == calling_context0);
15031   CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
15032   CHECK(Context::GetCalling() == calling_context1);
15033   CHECK(Context::GetEntered() == calling_context2);
15034   args.GetReturnValue().Set(42);
15035 }
15036
15037
15038 THREADED_TEST(GetCurrentContextWhenNotInContext) {
15039   i::Isolate* isolate = i::Isolate::Current();
15040   CHECK(isolate != NULL);
15041   CHECK(isolate->context() == NULL);
15042   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15043   v8::HandleScope scope(v8_isolate);
15044   // The following should not crash, but return an empty handle.
15045   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15046   CHECK(current.IsEmpty());
15047 }
15048
15049
15050 THREADED_TEST(GetCallingContext) {
15051   v8::Isolate* isolate = v8::Isolate::GetCurrent();
15052   v8::HandleScope scope(isolate);
15053
15054   Local<Context> calling_context0(Context::New(isolate));
15055   Local<Context> calling_context1(Context::New(isolate));
15056   Local<Context> calling_context2(Context::New(isolate));
15057   ::calling_context0 = calling_context0;
15058   ::calling_context1 = calling_context1;
15059   ::calling_context2 = calling_context2;
15060
15061   // Allow cross-domain access.
15062   Local<String> token = v8_str("<security token>");
15063   calling_context0->SetSecurityToken(token);
15064   calling_context1->SetSecurityToken(token);
15065   calling_context2->SetSecurityToken(token);
15066
15067   // Create an object with a C++ callback in context0.
15068   calling_context0->Enter();
15069   Local<v8::FunctionTemplate> callback_templ =
15070       v8::FunctionTemplate::New(GetCallingContextCallback);
15071   calling_context0->Global()->Set(v8_str("callback"),
15072                                   callback_templ->GetFunction());
15073   calling_context0->Exit();
15074
15075   // Expose context0 in context1 and set up a function that calls the
15076   // callback function.
15077   calling_context1->Enter();
15078   calling_context1->Global()->Set(v8_str("context0"),
15079                                   calling_context0->Global());
15080   CompileRun("function f() { context0.callback() }");
15081   calling_context1->Exit();
15082
15083   // Expose context1 in context2 and call the callback function in
15084   // context0 indirectly through f in context1.
15085   calling_context2->Enter();
15086   calling_context2->Global()->Set(v8_str("context1"),
15087                                   calling_context1->Global());
15088   CompileRun("context1.f()");
15089   calling_context2->Exit();
15090   ::calling_context0.Clear();
15091   ::calling_context1.Clear();
15092   ::calling_context2.Clear();
15093 }
15094
15095
15096 // Check that a variable declaration with no explicit initialization
15097 // value does shadow an existing property in the prototype chain.
15098 THREADED_TEST(InitGlobalVarInProtoChain) {
15099   i::FLAG_es52_globals = true;
15100   LocalContext context;
15101   v8::HandleScope scope(context->GetIsolate());
15102   // Introduce a variable in the prototype chain.
15103   CompileRun("__proto__.x = 42");
15104   v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
15105   CHECK(!result->IsUndefined());
15106   CHECK_EQ(43, result->Int32Value());
15107 }
15108
15109
15110 // Regression test for issue 398.
15111 // If a function is added to an object, creating a constant function
15112 // field, and the result is cloned, replacing the constant function on the
15113 // original should not affect the clone.
15114 // See http://code.google.com/p/v8/issues/detail?id=398
15115 THREADED_TEST(ReplaceConstantFunction) {
15116   LocalContext context;
15117   v8::HandleScope scope(context->GetIsolate());
15118   v8::Handle<v8::Object> obj = v8::Object::New();
15119   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
15120   v8::Handle<v8::String> foo_string = v8::String::New("foo");
15121   obj->Set(foo_string, func_templ->GetFunction());
15122   v8::Handle<v8::Object> obj_clone = obj->Clone();
15123   obj_clone->Set(foo_string, v8::String::New("Hello"));
15124   CHECK(!obj->Get(foo_string)->IsUndefined());
15125 }
15126
15127
15128 // Regression test for http://crbug.com/16276.
15129 THREADED_TEST(Regress16276) {
15130   LocalContext context;
15131   v8::HandleScope scope(context->GetIsolate());
15132   // Force the IC in f to be a dictionary load IC.
15133   CompileRun("function f(obj) { return obj.x; }\n"
15134              "var obj = { x: { foo: 42 }, y: 87 };\n"
15135              "var x = obj.x;\n"
15136              "delete obj.y;\n"
15137              "for (var i = 0; i < 5; i++) f(obj);");
15138   // Detach the global object to make 'this' refer directly to the
15139   // global object (not the proxy), and make sure that the dictionary
15140   // load IC doesn't mess up loading directly from the global object.
15141   context->DetachGlobal();
15142   CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
15143 }
15144
15145 static void CheckElementValue(i::Isolate* isolate,
15146                               int expected,
15147                               i::Handle<i::Object> obj,
15148                               int offset) {
15149   i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
15150   CHECK_EQ(expected, i::Smi::cast(element)->value());
15151 }
15152
15153
15154 THREADED_TEST(PixelArray) {
15155   LocalContext context;
15156   i::Isolate* isolate = i::Isolate::Current();
15157   i::Factory* factory = isolate->factory();
15158   v8::HandleScope scope(context->GetIsolate());
15159   const int kElementCount = 260;
15160   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
15161   i::Handle<i::ExternalPixelArray> pixels =
15162       i::Handle<i::ExternalPixelArray>::cast(
15163           factory->NewExternalArray(kElementCount,
15164                                     v8::kExternalPixelArray,
15165                                     pixel_data));
15166   // Force GC to trigger verification.
15167   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15168   for (int i = 0; i < kElementCount; i++) {
15169     pixels->set(i, i % 256);
15170   }
15171   // Force GC to trigger verification.
15172   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15173   for (int i = 0; i < kElementCount; i++) {
15174     CHECK_EQ(i % 256, pixels->get_scalar(i));
15175     CHECK_EQ(i % 256, pixel_data[i]);
15176   }
15177
15178   v8::Handle<v8::Object> obj = v8::Object::New();
15179   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15180   // Set the elements to be the pixels.
15181   // jsobj->set_elements(*pixels);
15182   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
15183   CheckElementValue(isolate, 1, jsobj, 1);
15184   obj->Set(v8_str("field"), v8::Int32::New(1503));
15185   context->Global()->Set(v8_str("pixels"), obj);
15186   v8::Handle<v8::Value> result = CompileRun("pixels.field");
15187   CHECK_EQ(1503, result->Int32Value());
15188   result = CompileRun("pixels[1]");
15189   CHECK_EQ(1, result->Int32Value());
15190
15191   result = CompileRun("var sum = 0;"
15192                       "for (var i = 0; i < 8; i++) {"
15193                       "  sum += pixels[i] = pixels[i] = -i;"
15194                       "}"
15195                       "sum;");
15196   CHECK_EQ(-28, result->Int32Value());
15197
15198   result = CompileRun("var sum = 0;"
15199                       "for (var i = 0; i < 8; i++) {"
15200                       "  sum += pixels[i] = pixels[i] = 0;"
15201                       "}"
15202                       "sum;");
15203   CHECK_EQ(0, result->Int32Value());
15204
15205   result = CompileRun("var sum = 0;"
15206                       "for (var i = 0; i < 8; i++) {"
15207                       "  sum += pixels[i] = pixels[i] = 255;"
15208                       "}"
15209                       "sum;");
15210   CHECK_EQ(8 * 255, result->Int32Value());
15211
15212   result = CompileRun("var sum = 0;"
15213                       "for (var i = 0; i < 8; i++) {"
15214                       "  sum += pixels[i] = pixels[i] = 256 + i;"
15215                       "}"
15216                       "sum;");
15217   CHECK_EQ(2076, result->Int32Value());
15218
15219   result = CompileRun("var sum = 0;"
15220                       "for (var i = 0; i < 8; i++) {"
15221                       "  sum += pixels[i] = pixels[i] = i;"
15222                       "}"
15223                       "sum;");
15224   CHECK_EQ(28, result->Int32Value());
15225
15226   result = CompileRun("var sum = 0;"
15227                       "for (var i = 0; i < 8; i++) {"
15228                       "  sum += pixels[i];"
15229                       "}"
15230                       "sum;");
15231   CHECK_EQ(28, result->Int32Value());
15232
15233   i::Handle<i::Smi> value(i::Smi::FromInt(2),
15234                           reinterpret_cast<i::Isolate*>(context->GetIsolate()));
15235   i::Handle<i::Object> no_failure;
15236   no_failure =
15237       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
15238   ASSERT(!no_failure.is_null());
15239   i::USE(no_failure);
15240   CheckElementValue(isolate, 2, jsobj, 1);
15241   *value.location() = i::Smi::FromInt(256);
15242   no_failure =
15243       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
15244   ASSERT(!no_failure.is_null());
15245   i::USE(no_failure);
15246   CheckElementValue(isolate, 255, jsobj, 1);
15247   *value.location() = i::Smi::FromInt(-1);
15248   no_failure =
15249       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
15250   ASSERT(!no_failure.is_null());
15251   i::USE(no_failure);
15252   CheckElementValue(isolate, 0, jsobj, 1);
15253
15254   result = CompileRun("for (var i = 0; i < 8; i++) {"
15255                       "  pixels[i] = (i * 65) - 109;"
15256                       "}"
15257                       "pixels[1] + pixels[6];");
15258   CHECK_EQ(255, result->Int32Value());
15259   CheckElementValue(isolate, 0, jsobj, 0);
15260   CheckElementValue(isolate, 0, jsobj, 1);
15261   CheckElementValue(isolate, 21, jsobj, 2);
15262   CheckElementValue(isolate, 86, jsobj, 3);
15263   CheckElementValue(isolate, 151, jsobj, 4);
15264   CheckElementValue(isolate, 216, jsobj, 5);
15265   CheckElementValue(isolate, 255, jsobj, 6);
15266   CheckElementValue(isolate, 255, jsobj, 7);
15267   result = CompileRun("var sum = 0;"
15268                       "for (var i = 0; i < 8; i++) {"
15269                       "  sum += pixels[i];"
15270                       "}"
15271                       "sum;");
15272   CHECK_EQ(984, result->Int32Value());
15273
15274   result = CompileRun("for (var i = 0; i < 8; i++) {"
15275                       "  pixels[i] = (i * 1.1);"
15276                       "}"
15277                       "pixels[1] + pixels[6];");
15278   CHECK_EQ(8, result->Int32Value());
15279   CheckElementValue(isolate, 0, jsobj, 0);
15280   CheckElementValue(isolate, 1, jsobj, 1);
15281   CheckElementValue(isolate, 2, jsobj, 2);
15282   CheckElementValue(isolate, 3, jsobj, 3);
15283   CheckElementValue(isolate, 4, jsobj, 4);
15284   CheckElementValue(isolate, 6, jsobj, 5);
15285   CheckElementValue(isolate, 7, jsobj, 6);
15286   CheckElementValue(isolate, 8, jsobj, 7);
15287
15288   result = CompileRun("for (var i = 0; i < 8; i++) {"
15289                       "  pixels[7] = undefined;"
15290                       "}"
15291                       "pixels[7];");
15292   CHECK_EQ(0, result->Int32Value());
15293   CheckElementValue(isolate, 0, jsobj, 7);
15294
15295   result = CompileRun("for (var i = 0; i < 8; i++) {"
15296                       "  pixels[6] = '2.3';"
15297                       "}"
15298                       "pixels[6];");
15299   CHECK_EQ(2, result->Int32Value());
15300   CheckElementValue(isolate, 2, jsobj, 6);
15301
15302   result = CompileRun("for (var i = 0; i < 8; i++) {"
15303                       "  pixels[5] = NaN;"
15304                       "}"
15305                       "pixels[5];");
15306   CHECK_EQ(0, result->Int32Value());
15307   CheckElementValue(isolate, 0, jsobj, 5);
15308
15309   result = CompileRun("for (var i = 0; i < 8; i++) {"
15310                       "  pixels[8] = Infinity;"
15311                       "}"
15312                       "pixels[8];");
15313   CHECK_EQ(255, result->Int32Value());
15314   CheckElementValue(isolate, 255, jsobj, 8);
15315
15316   result = CompileRun("for (var i = 0; i < 8; i++) {"
15317                       "  pixels[9] = -Infinity;"
15318                       "}"
15319                       "pixels[9];");
15320   CHECK_EQ(0, result->Int32Value());
15321   CheckElementValue(isolate, 0, jsobj, 9);
15322
15323   result = CompileRun("pixels[3] = 33;"
15324                       "delete pixels[3];"
15325                       "pixels[3];");
15326   CHECK_EQ(33, result->Int32Value());
15327
15328   result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15329                       "pixels[2] = 12; pixels[3] = 13;"
15330                       "pixels.__defineGetter__('2',"
15331                       "function() { return 120; });"
15332                       "pixels[2];");
15333   CHECK_EQ(12, result->Int32Value());
15334
15335   result = CompileRun("var js_array = new Array(40);"
15336                       "js_array[0] = 77;"
15337                       "js_array;");
15338   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15339
15340   result = CompileRun("pixels[1] = 23;"
15341                       "pixels.__proto__ = [];"
15342                       "js_array.__proto__ = pixels;"
15343                       "js_array.concat(pixels);");
15344   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15345   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15346
15347   result = CompileRun("pixels[1] = 23;");
15348   CHECK_EQ(23, result->Int32Value());
15349
15350   // Test for index greater than 255.  Regression test for:
15351   // http://code.google.com/p/chromium/issues/detail?id=26337.
15352   result = CompileRun("pixels[256] = 255;");
15353   CHECK_EQ(255, result->Int32Value());
15354   result = CompileRun("var i = 0;"
15355                       "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15356                       "i");
15357   CHECK_EQ(255, result->Int32Value());
15358
15359   // Make sure that pixel array ICs recognize when a non-pixel array
15360   // is passed to it.
15361   result = CompileRun("function pa_load(p) {"
15362                       "  var sum = 0;"
15363                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
15364                       "  return sum;"
15365                       "}"
15366                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15367                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15368                       "just_ints = new Object();"
15369                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15370                       "for (var i = 0; i < 10; ++i) {"
15371                       "  result = pa_load(just_ints);"
15372                       "}"
15373                       "result");
15374   CHECK_EQ(32640, result->Int32Value());
15375
15376   // Make sure that pixel array ICs recognize out-of-bound accesses.
15377   result = CompileRun("function pa_load(p, start) {"
15378                       "  var sum = 0;"
15379                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
15380                       "  return sum;"
15381                       "}"
15382                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15383                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15384                       "for (var i = 0; i < 10; ++i) {"
15385                       "  result = pa_load(pixels,-10);"
15386                       "}"
15387                       "result");
15388   CHECK_EQ(0, result->Int32Value());
15389
15390   // Make sure that generic ICs properly handles a pixel array.
15391   result = CompileRun("function pa_load(p) {"
15392                       "  var sum = 0;"
15393                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
15394                       "  return sum;"
15395                       "}"
15396                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15397                       "just_ints = new Object();"
15398                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15399                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15400                       "for (var i = 0; i < 10; ++i) {"
15401                       "  result = pa_load(pixels);"
15402                       "}"
15403                       "result");
15404   CHECK_EQ(32640, result->Int32Value());
15405
15406   // Make sure that generic load ICs recognize out-of-bound accesses in
15407   // pixel arrays.
15408   result = CompileRun("function pa_load(p, start) {"
15409                       "  var sum = 0;"
15410                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
15411                       "  return sum;"
15412                       "}"
15413                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15414                       "just_ints = new Object();"
15415                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15416                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
15417                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15418                       "for (var i = 0; i < 10; ++i) {"
15419                       "  result = pa_load(pixels,-10);"
15420                       "}"
15421                       "result");
15422   CHECK_EQ(0, result->Int32Value());
15423
15424   // Make sure that generic ICs properly handles other types than pixel
15425   // arrays (that the inlined fast pixel array test leaves the right information
15426   // in the right registers).
15427   result = CompileRun("function pa_load(p) {"
15428                       "  var sum = 0;"
15429                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
15430                       "  return sum;"
15431                       "}"
15432                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15433                       "just_ints = new Object();"
15434                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15435                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15436                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15437                       "sparse_array = new Object();"
15438                       "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
15439                       "sparse_array[1000000] = 3;"
15440                       "for (var i = 0; i < 10; ++i) {"
15441                       "  result = pa_load(sparse_array);"
15442                       "}"
15443                       "result");
15444   CHECK_EQ(32640, result->Int32Value());
15445
15446   // Make sure that pixel array store ICs clamp values correctly.
15447   result = CompileRun("function pa_store(p) {"
15448                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15449                       "}"
15450                       "pa_store(pixels);"
15451                       "var sum = 0;"
15452                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15453                       "sum");
15454   CHECK_EQ(48896, result->Int32Value());
15455
15456   // Make sure that pixel array stores correctly handle accesses outside
15457   // of the pixel array..
15458   result = CompileRun("function pa_store(p,start) {"
15459                       "  for (var j = 0; j < 256; j++) {"
15460                       "    p[j+start] = j * 2;"
15461                       "  }"
15462                       "}"
15463                       "pa_store(pixels,0);"
15464                       "pa_store(pixels,-128);"
15465                       "var sum = 0;"
15466                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15467                       "sum");
15468   CHECK_EQ(65280, result->Int32Value());
15469
15470   // Make sure that the generic store stub correctly handle accesses outside
15471   // of the pixel array..
15472   result = CompileRun("function pa_store(p,start) {"
15473                       "  for (var j = 0; j < 256; j++) {"
15474                       "    p[j+start] = j * 2;"
15475                       "  }"
15476                       "}"
15477                       "pa_store(pixels,0);"
15478                       "just_ints = new Object();"
15479                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15480                       "pa_store(just_ints, 0);"
15481                       "pa_store(pixels,-128);"
15482                       "var sum = 0;"
15483                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15484                       "sum");
15485   CHECK_EQ(65280, result->Int32Value());
15486
15487   // Make sure that the generic keyed store stub clamps pixel array values
15488   // correctly.
15489   result = CompileRun("function pa_store(p) {"
15490                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15491                       "}"
15492                       "pa_store(pixels);"
15493                       "just_ints = new Object();"
15494                       "pa_store(just_ints);"
15495                       "pa_store(pixels);"
15496                       "var sum = 0;"
15497                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15498                       "sum");
15499   CHECK_EQ(48896, result->Int32Value());
15500
15501   // Make sure that pixel array loads are optimized by crankshaft.
15502   result = CompileRun("function pa_load(p) {"
15503                       "  var sum = 0;"
15504                       "  for (var i=0; i<256; ++i) {"
15505                       "    sum += p[i];"
15506                       "  }"
15507                       "  return sum; "
15508                       "}"
15509                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15510                       "for (var i = 0; i < 5000; ++i) {"
15511                       "  result = pa_load(pixels);"
15512                       "}"
15513                       "result");
15514   CHECK_EQ(32640, result->Int32Value());
15515
15516   // Make sure that pixel array stores are optimized by crankshaft.
15517   result = CompileRun("function pa_init(p) {"
15518                       "for (var i = 0; i < 256; ++i) { p[i] = i; }"
15519                       "}"
15520                       "function pa_load(p) {"
15521                       "  var sum = 0;"
15522                       "  for (var i=0; i<256; ++i) {"
15523                       "    sum += p[i];"
15524                       "  }"
15525                       "  return sum; "
15526                       "}"
15527                       "for (var i = 0; i < 5000; ++i) {"
15528                       "  pa_init(pixels);"
15529                       "}"
15530                       "result = pa_load(pixels);"
15531                       "result");
15532   CHECK_EQ(32640, result->Int32Value());
15533
15534   free(pixel_data);
15535 }
15536
15537
15538 THREADED_TEST(PixelArrayInfo) {
15539   LocalContext context;
15540   v8::HandleScope scope(context->GetIsolate());
15541   for (int size = 0; size < 100; size += 10) {
15542     uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
15543     v8::Handle<v8::Object> obj = v8::Object::New();
15544     obj->SetIndexedPropertiesToPixelData(pixel_data, size);
15545     CHECK(obj->HasIndexedPropertiesInPixelData());
15546     CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
15547     CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
15548     free(pixel_data);
15549   }
15550 }
15551
15552
15553 static void NotHandledIndexedPropertyGetter(
15554     uint32_t index,
15555     const v8::PropertyCallbackInfo<v8::Value>& info) {
15556   ApiTestFuzzer::Fuzz();
15557 }
15558
15559
15560 static void NotHandledIndexedPropertySetter(
15561     uint32_t index,
15562     Local<Value> value,
15563     const v8::PropertyCallbackInfo<v8::Value>& info) {
15564   ApiTestFuzzer::Fuzz();
15565 }
15566
15567
15568 THREADED_TEST(PixelArrayWithInterceptor) {
15569   LocalContext context;
15570   i::Factory* factory = i::Isolate::Current()->factory();
15571   v8::HandleScope scope(context->GetIsolate());
15572   const int kElementCount = 260;
15573   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
15574   i::Handle<i::ExternalPixelArray> pixels =
15575       i::Handle<i::ExternalPixelArray>::cast(
15576           factory->NewExternalArray(kElementCount,
15577                                     v8::kExternalPixelArray,
15578                                     pixel_data));
15579   for (int i = 0; i < kElementCount; i++) {
15580     pixels->set(i, i % 256);
15581   }
15582   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
15583   templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
15584                                    NotHandledIndexedPropertySetter);
15585   v8::Handle<v8::Object> obj = templ->NewInstance();
15586   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
15587   context->Global()->Set(v8_str("pixels"), obj);
15588   v8::Handle<v8::Value> result = CompileRun("pixels[1]");
15589   CHECK_EQ(1, result->Int32Value());
15590   result = CompileRun("var sum = 0;"
15591                       "for (var i = 0; i < 8; i++) {"
15592                       "  sum += pixels[i] = pixels[i] = -i;"
15593                       "}"
15594                       "sum;");
15595   CHECK_EQ(-28, result->Int32Value());
15596   result = CompileRun("pixels.hasOwnProperty('1')");
15597   CHECK(result->BooleanValue());
15598   free(pixel_data);
15599 }
15600
15601
15602 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
15603   switch (array_type) {
15604     case v8::kExternalByteArray:
15605     case v8::kExternalUnsignedByteArray:
15606     case v8::kExternalPixelArray:
15607       return 1;
15608       break;
15609     case v8::kExternalShortArray:
15610     case v8::kExternalUnsignedShortArray:
15611       return 2;
15612       break;
15613     case v8::kExternalIntArray:
15614     case v8::kExternalUnsignedIntArray:
15615     case v8::kExternalFloatArray:
15616       return 4;
15617       break;
15618     case v8::kExternalDoubleArray:
15619       return 8;
15620       break;
15621     default:
15622       UNREACHABLE();
15623       return -1;
15624   }
15625   UNREACHABLE();
15626   return -1;
15627 }
15628
15629
15630 template <class ExternalArrayClass, class ElementType>
15631 static void ObjectWithExternalArrayTestHelper(
15632     Handle<Context> context,
15633     v8::Handle<Object> obj,
15634     int element_count,
15635     v8::ExternalArrayType array_type,
15636     int64_t low, int64_t high) {
15637   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15638   i::Isolate* isolate = jsobj->GetIsolate();
15639   obj->Set(v8_str("field"), v8::Int32::New(1503));
15640   context->Global()->Set(v8_str("ext_array"), obj);
15641   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
15642   CHECK_EQ(1503, result->Int32Value());
15643   result = CompileRun("ext_array[1]");
15644   CHECK_EQ(1, result->Int32Value());
15645
15646   // Check pass through of assigned smis
15647   result = CompileRun("var sum = 0;"
15648                       "for (var i = 0; i < 8; i++) {"
15649                       "  sum += ext_array[i] = ext_array[i] = -i;"
15650                       "}"
15651                       "sum;");
15652   CHECK_EQ(-28, result->Int32Value());
15653
15654   // Check assigned smis
15655   result = CompileRun("for (var i = 0; i < 8; i++) {"
15656                       "  ext_array[i] = i;"
15657                       "}"
15658                       "var sum = 0;"
15659                       "for (var i = 0; i < 8; i++) {"
15660                       "  sum += ext_array[i];"
15661                       "}"
15662                       "sum;");
15663   CHECK_EQ(28, result->Int32Value());
15664
15665   // Check assigned smis in reverse order
15666   result = CompileRun("for (var i = 8; --i >= 0; ) {"
15667                       "  ext_array[i] = i;"
15668                       "}"
15669                       "var sum = 0;"
15670                       "for (var i = 0; i < 8; i++) {"
15671                       "  sum += ext_array[i];"
15672                       "}"
15673                       "sum;");
15674   CHECK_EQ(28, result->Int32Value());
15675
15676   // Check pass through of assigned HeapNumbers
15677   result = CompileRun("var sum = 0;"
15678                       "for (var i = 0; i < 16; i+=2) {"
15679                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
15680                       "}"
15681                       "sum;");
15682   CHECK_EQ(-28, result->Int32Value());
15683
15684   // Check assigned HeapNumbers
15685   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
15686                       "  ext_array[i] = (i * 0.5);"
15687                       "}"
15688                       "var sum = 0;"
15689                       "for (var i = 0; i < 16; i+=2) {"
15690                       "  sum += ext_array[i];"
15691                       "}"
15692                       "sum;");
15693   CHECK_EQ(28, result->Int32Value());
15694
15695   // Check assigned HeapNumbers in reverse order
15696   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
15697                       "  ext_array[i] = (i * 0.5);"
15698                       "}"
15699                       "var sum = 0;"
15700                       "for (var i = 0; i < 16; i+=2) {"
15701                       "  sum += ext_array[i];"
15702                       "}"
15703                       "sum;");
15704   CHECK_EQ(28, result->Int32Value());
15705
15706   i::ScopedVector<char> test_buf(1024);
15707
15708   // Check legal boundary conditions.
15709   // The repeated loads and stores ensure the ICs are exercised.
15710   const char* boundary_program =
15711       "var res = 0;"
15712       "for (var i = 0; i < 16; i++) {"
15713       "  ext_array[i] = %lld;"
15714       "  if (i > 8) {"
15715       "    res = ext_array[i];"
15716       "  }"
15717       "}"
15718       "res;";
15719   i::OS::SNPrintF(test_buf,
15720                   boundary_program,
15721                   low);
15722   result = CompileRun(test_buf.start());
15723   CHECK_EQ(low, result->IntegerValue());
15724
15725   i::OS::SNPrintF(test_buf,
15726                   boundary_program,
15727                   high);
15728   result = CompileRun(test_buf.start());
15729   CHECK_EQ(high, result->IntegerValue());
15730
15731   // Check misprediction of type in IC.
15732   result = CompileRun("var tmp_array = ext_array;"
15733                       "var sum = 0;"
15734                       "for (var i = 0; i < 8; i++) {"
15735                       "  tmp_array[i] = i;"
15736                       "  sum += tmp_array[i];"
15737                       "  if (i == 4) {"
15738                       "    tmp_array = {};"
15739                       "  }"
15740                       "}"
15741                       "sum;");
15742   // Force GC to trigger verification.
15743   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15744   CHECK_EQ(28, result->Int32Value());
15745
15746   // Make sure out-of-range loads do not throw.
15747   i::OS::SNPrintF(test_buf,
15748                   "var caught_exception = false;"
15749                   "try {"
15750                   "  ext_array[%d];"
15751                   "} catch (e) {"
15752                   "  caught_exception = true;"
15753                   "}"
15754                   "caught_exception;",
15755                   element_count);
15756   result = CompileRun(test_buf.start());
15757   CHECK_EQ(false, result->BooleanValue());
15758
15759   // Make sure out-of-range stores do not throw.
15760   i::OS::SNPrintF(test_buf,
15761                   "var caught_exception = false;"
15762                   "try {"
15763                   "  ext_array[%d] = 1;"
15764                   "} catch (e) {"
15765                   "  caught_exception = true;"
15766                   "}"
15767                   "caught_exception;",
15768                   element_count);
15769   result = CompileRun(test_buf.start());
15770   CHECK_EQ(false, result->BooleanValue());
15771
15772   // Check other boundary conditions, values and operations.
15773   result = CompileRun("for (var i = 0; i < 8; i++) {"
15774                       "  ext_array[7] = undefined;"
15775                       "}"
15776                       "ext_array[7];");
15777   CHECK_EQ(0, result->Int32Value());
15778   if (array_type == v8::kExternalDoubleArray ||
15779       array_type == v8::kExternalFloatArray) {
15780     CHECK_EQ(static_cast<int>(i::OS::nan_value()),
15781              static_cast<int>(
15782                  jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
15783   } else {
15784     CheckElementValue(isolate, 0, jsobj, 7);
15785   }
15786
15787   result = CompileRun("for (var i = 0; i < 8; i++) {"
15788                       "  ext_array[6] = '2.3';"
15789                       "}"
15790                       "ext_array[6];");
15791   CHECK_EQ(2, result->Int32Value());
15792   CHECK_EQ(2,
15793            static_cast<int>(
15794                jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
15795
15796   if (array_type != v8::kExternalFloatArray &&
15797       array_type != v8::kExternalDoubleArray) {
15798     // Though the specification doesn't state it, be explicit about
15799     // converting NaNs and +/-Infinity to zero.
15800     result = CompileRun("for (var i = 0; i < 8; i++) {"
15801                         "  ext_array[i] = 5;"
15802                         "}"
15803                         "for (var i = 0; i < 8; i++) {"
15804                         "  ext_array[i] = NaN;"
15805                         "}"
15806                         "ext_array[5];");
15807     CHECK_EQ(0, result->Int32Value());
15808     CheckElementValue(isolate, 0, jsobj, 5);
15809
15810     result = CompileRun("for (var i = 0; i < 8; i++) {"
15811                         "  ext_array[i] = 5;"
15812                         "}"
15813                         "for (var i = 0; i < 8; i++) {"
15814                         "  ext_array[i] = Infinity;"
15815                         "}"
15816                         "ext_array[5];");
15817     int expected_value =
15818         (array_type == v8::kExternalPixelArray) ? 255 : 0;
15819     CHECK_EQ(expected_value, result->Int32Value());
15820     CheckElementValue(isolate, expected_value, jsobj, 5);
15821
15822     result = CompileRun("for (var i = 0; i < 8; i++) {"
15823                         "  ext_array[i] = 5;"
15824                         "}"
15825                         "for (var i = 0; i < 8; i++) {"
15826                         "  ext_array[i] = -Infinity;"
15827                         "}"
15828                         "ext_array[5];");
15829     CHECK_EQ(0, result->Int32Value());
15830     CheckElementValue(isolate, 0, jsobj, 5);
15831
15832     // Check truncation behavior of integral arrays.
15833     const char* unsigned_data =
15834         "var source_data = [0.6, 10.6];"
15835         "var expected_results = [0, 10];";
15836     const char* signed_data =
15837         "var source_data = [0.6, 10.6, -0.6, -10.6];"
15838         "var expected_results = [0, 10, 0, -10];";
15839     const char* pixel_data =
15840         "var source_data = [0.6, 10.6];"
15841         "var expected_results = [1, 11];";
15842     bool is_unsigned =
15843         (array_type == v8::kExternalUnsignedByteArray ||
15844          array_type == v8::kExternalUnsignedShortArray ||
15845          array_type == v8::kExternalUnsignedIntArray);
15846     bool is_pixel_data = array_type == v8::kExternalPixelArray;
15847
15848     i::OS::SNPrintF(test_buf,
15849                     "%s"
15850                     "var all_passed = true;"
15851                     "for (var i = 0; i < source_data.length; i++) {"
15852                     "  for (var j = 0; j < 8; j++) {"
15853                     "    ext_array[j] = source_data[i];"
15854                     "  }"
15855                     "  all_passed = all_passed &&"
15856                     "               (ext_array[5] == expected_results[i]);"
15857                     "}"
15858                     "all_passed;",
15859                     (is_unsigned ?
15860                          unsigned_data :
15861                          (is_pixel_data ? pixel_data : signed_data)));
15862     result = CompileRun(test_buf.start());
15863     CHECK_EQ(true, result->BooleanValue());
15864   }
15865
15866   i::Handle<ExternalArrayClass> array(
15867       ExternalArrayClass::cast(jsobj->elements()));
15868   for (int i = 0; i < element_count; i++) {
15869     array->set(i, static_cast<ElementType>(i));
15870   }
15871
15872   // Test complex assignments
15873   result = CompileRun("function ee_op_test_complex_func(sum) {"
15874                       " for (var i = 0; i < 40; ++i) {"
15875                       "   sum += (ext_array[i] += 1);"
15876                       "   sum += (ext_array[i] -= 1);"
15877                       " } "
15878                       " return sum;"
15879                       "}"
15880                       "sum=0;"
15881                       "for (var i=0;i<10000;++i) {"
15882                       "  sum=ee_op_test_complex_func(sum);"
15883                       "}"
15884                       "sum;");
15885   CHECK_EQ(16000000, result->Int32Value());
15886
15887   // Test count operations
15888   result = CompileRun("function ee_op_test_count_func(sum) {"
15889                       " for (var i = 0; i < 40; ++i) {"
15890                       "   sum += (++ext_array[i]);"
15891                       "   sum += (--ext_array[i]);"
15892                       " } "
15893                       " return sum;"
15894                       "}"
15895                       "sum=0;"
15896                       "for (var i=0;i<10000;++i) {"
15897                       "  sum=ee_op_test_count_func(sum);"
15898                       "}"
15899                       "sum;");
15900   CHECK_EQ(16000000, result->Int32Value());
15901
15902   result = CompileRun("ext_array[3] = 33;"
15903                       "delete ext_array[3];"
15904                       "ext_array[3];");
15905   CHECK_EQ(33, result->Int32Value());
15906
15907   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
15908                       "ext_array[2] = 12; ext_array[3] = 13;"
15909                       "ext_array.__defineGetter__('2',"
15910                       "function() { return 120; });"
15911                       "ext_array[2];");
15912   CHECK_EQ(12, result->Int32Value());
15913
15914   result = CompileRun("var js_array = new Array(40);"
15915                       "js_array[0] = 77;"
15916                       "js_array;");
15917   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15918
15919   result = CompileRun("ext_array[1] = 23;"
15920                       "ext_array.__proto__ = [];"
15921                       "js_array.__proto__ = ext_array;"
15922                       "js_array.concat(ext_array);");
15923   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15924   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15925
15926   result = CompileRun("ext_array[1] = 23;");
15927   CHECK_EQ(23, result->Int32Value());
15928 }
15929
15930
15931 template <class ExternalArrayClass, class ElementType>
15932 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
15933                                     int64_t low,
15934                                     int64_t high) {
15935   LocalContext context;
15936   i::Isolate* isolate = i::Isolate::Current();
15937   i::Factory* factory = isolate->factory();
15938   v8::HandleScope scope(context->GetIsolate());
15939   const int kElementCount = 40;
15940   int element_size = ExternalArrayElementSize(array_type);
15941   ElementType* array_data =
15942       static_cast<ElementType*>(malloc(kElementCount * element_size));
15943   i::Handle<ExternalArrayClass> array =
15944       i::Handle<ExternalArrayClass>::cast(
15945           factory->NewExternalArray(kElementCount, array_type, array_data));
15946   // Force GC to trigger verification.
15947   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15948   for (int i = 0; i < kElementCount; i++) {
15949     array->set(i, static_cast<ElementType>(i));
15950   }
15951   // Force GC to trigger verification.
15952   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
15953   for (int i = 0; i < kElementCount; i++) {
15954     CHECK_EQ(static_cast<int64_t>(i),
15955              static_cast<int64_t>(array->get_scalar(i)));
15956     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
15957   }
15958
15959   v8::Handle<v8::Object> obj = v8::Object::New();
15960   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15961   // Set the elements to be the external array.
15962   obj->SetIndexedPropertiesToExternalArrayData(array_data,
15963                                                array_type,
15964                                                kElementCount);
15965   CHECK_EQ(1,
15966            static_cast<int>(
15967                jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
15968
15969   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
15970       context.local(), obj, kElementCount, array_type, low, high);
15971
15972   v8::Handle<v8::Value> result;
15973
15974   // Test more complex manipulations which cause eax to contain values
15975   // that won't be completely overwritten by loads from the arrays.
15976   // This catches bugs in the instructions used for the KeyedLoadIC
15977   // for byte and word types.
15978   {
15979     const int kXSize = 300;
15980     const int kYSize = 300;
15981     const int kLargeElementCount = kXSize * kYSize * 4;
15982     ElementType* large_array_data =
15983         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
15984     v8::Handle<v8::Object> large_obj = v8::Object::New();
15985     // Set the elements to be the external array.
15986     large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
15987                                                        array_type,
15988                                                        kLargeElementCount);
15989     context->Global()->Set(v8_str("large_array"), large_obj);
15990     // Initialize contents of a few rows.
15991     for (int x = 0; x < 300; x++) {
15992       int row = 0;
15993       int offset = row * 300 * 4;
15994       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
15995       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
15996       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
15997       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
15998       row = 150;
15999       offset = row * 300 * 4;
16000       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16001       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16002       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16003       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16004       row = 298;
16005       offset = row * 300 * 4;
16006       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16007       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16008       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16009       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16010     }
16011     // The goal of the code below is to make "offset" large enough
16012     // that the computation of the index (which goes into eax) has
16013     // high bits set which will not be overwritten by a byte or short
16014     // load.
16015     result = CompileRun("var failed = false;"
16016                         "var offset = 0;"
16017                         "for (var i = 0; i < 300; i++) {"
16018                         "  if (large_array[4 * i] != 127 ||"
16019                         "      large_array[4 * i + 1] != 0 ||"
16020                         "      large_array[4 * i + 2] != 0 ||"
16021                         "      large_array[4 * i + 3] != 127) {"
16022                         "    failed = true;"
16023                         "  }"
16024                         "}"
16025                         "offset = 150 * 300 * 4;"
16026                         "for (var i = 0; i < 300; i++) {"
16027                         "  if (large_array[offset + 4 * i] != 127 ||"
16028                         "      large_array[offset + 4 * i + 1] != 0 ||"
16029                         "      large_array[offset + 4 * i + 2] != 0 ||"
16030                         "      large_array[offset + 4 * i + 3] != 127) {"
16031                         "    failed = true;"
16032                         "  }"
16033                         "}"
16034                         "offset = 298 * 300 * 4;"
16035                         "for (var i = 0; i < 300; i++) {"
16036                         "  if (large_array[offset + 4 * i] != 127 ||"
16037                         "      large_array[offset + 4 * i + 1] != 0 ||"
16038                         "      large_array[offset + 4 * i + 2] != 0 ||"
16039                         "      large_array[offset + 4 * i + 3] != 127) {"
16040                         "    failed = true;"
16041                         "  }"
16042                         "}"
16043                         "!failed;");
16044     CHECK_EQ(true, result->BooleanValue());
16045     free(large_array_data);
16046   }
16047
16048   // The "" property descriptor is overloaded to store information about
16049   // the external array. Ensure that setting and accessing the "" property
16050   // works (it should overwrite the information cached about the external
16051   // array in the DescriptorArray) in various situations.
16052   result = CompileRun("ext_array[''] = 23; ext_array['']");
16053   CHECK_EQ(23, result->Int32Value());
16054
16055   // Property "" set after the external array is associated with the object.
16056   {
16057     v8::Handle<v8::Object> obj2 = v8::Object::New();
16058     obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
16059     obj2->Set(v8_str(""), v8::Int32::New(1503));
16060     // Set the elements to be the external array.
16061     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16062                                                   array_type,
16063                                                   kElementCount);
16064     context->Global()->Set(v8_str("ext_array"), obj2);
16065     result = CompileRun("ext_array['']");
16066     CHECK_EQ(1503, result->Int32Value());
16067   }
16068
16069   // Property "" set after the external array is associated with the object.
16070   {
16071     v8::Handle<v8::Object> obj2 = v8::Object::New();
16072     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
16073     // Set the elements to be the external array.
16074     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16075                                                   array_type,
16076                                                   kElementCount);
16077     obj2->Set(v8_str(""), v8::Int32::New(1503));
16078     context->Global()->Set(v8_str("ext_array"), obj2);
16079     result = CompileRun("ext_array['']");
16080     CHECK_EQ(1503, result->Int32Value());
16081   }
16082
16083   // Should reuse the map from previous test.
16084   {
16085     v8::Handle<v8::Object> obj2 = v8::Object::New();
16086     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
16087     // Set the elements to be the external array. Should re-use the map
16088     // from previous test.
16089     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16090                                                   array_type,
16091                                                   kElementCount);
16092     context->Global()->Set(v8_str("ext_array"), obj2);
16093     result = CompileRun("ext_array['']");
16094   }
16095
16096   // Property "" is a constant function that shouldn't not be interfered with
16097   // when an external array is set.
16098   {
16099     v8::Handle<v8::Object> obj2 = v8::Object::New();
16100     // Start
16101     obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
16102
16103     // Add a constant function to an object.
16104     context->Global()->Set(v8_str("ext_array"), obj2);
16105     result = CompileRun("ext_array[''] = function() {return 1503;};"
16106                         "ext_array['']();");
16107
16108     // Add an external array transition to the same map that
16109     // has the constant transition.
16110     v8::Handle<v8::Object> obj3 = v8::Object::New();
16111     obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
16112     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16113                                                   array_type,
16114                                                   kElementCount);
16115     context->Global()->Set(v8_str("ext_array"), obj3);
16116   }
16117
16118   // If a external array transition is in the map, it should get clobbered
16119   // by a constant function.
16120   {
16121     // Add an external array transition.
16122     v8::Handle<v8::Object> obj3 = v8::Object::New();
16123     obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
16124     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16125                                                   array_type,
16126                                                   kElementCount);
16127
16128     // Add a constant function to the same map that just got an external array
16129     // transition.
16130     v8::Handle<v8::Object> obj2 = v8::Object::New();
16131     obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
16132     context->Global()->Set(v8_str("ext_array"), obj2);
16133     result = CompileRun("ext_array[''] = function() {return 1503;};"
16134                         "ext_array['']();");
16135   }
16136
16137   free(array_data);
16138 }
16139
16140
16141 THREADED_TEST(ExternalByteArray) {
16142   ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
16143       v8::kExternalByteArray,
16144       -128,
16145       127);
16146 }
16147
16148
16149 THREADED_TEST(ExternalUnsignedByteArray) {
16150   ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
16151       v8::kExternalUnsignedByteArray,
16152       0,
16153       255);
16154 }
16155
16156
16157 THREADED_TEST(ExternalPixelArray) {
16158   ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
16159       v8::kExternalPixelArray,
16160       0,
16161       255);
16162 }
16163
16164
16165 THREADED_TEST(ExternalShortArray) {
16166   ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
16167       v8::kExternalShortArray,
16168       -32768,
16169       32767);
16170 }
16171
16172
16173 THREADED_TEST(ExternalUnsignedShortArray) {
16174   ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
16175       v8::kExternalUnsignedShortArray,
16176       0,
16177       65535);
16178 }
16179
16180
16181 THREADED_TEST(ExternalIntArray) {
16182   ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
16183       v8::kExternalIntArray,
16184       INT_MIN,   // -2147483648
16185       INT_MAX);  //  2147483647
16186 }
16187
16188
16189 THREADED_TEST(ExternalUnsignedIntArray) {
16190   ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
16191       v8::kExternalUnsignedIntArray,
16192       0,
16193       UINT_MAX);  // 4294967295
16194 }
16195
16196
16197 THREADED_TEST(ExternalFloatArray) {
16198   ExternalArrayTestHelper<i::ExternalFloatArray, float>(
16199       v8::kExternalFloatArray,
16200       -500,
16201       500);
16202 }
16203
16204
16205 THREADED_TEST(ExternalDoubleArray) {
16206   ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
16207       v8::kExternalDoubleArray,
16208       -500,
16209       500);
16210 }
16211
16212
16213 THREADED_TEST(ExternalArrays) {
16214   TestExternalByteArray();
16215   TestExternalUnsignedByteArray();
16216   TestExternalShortArray();
16217   TestExternalUnsignedShortArray();
16218   TestExternalIntArray();
16219   TestExternalUnsignedIntArray();
16220   TestExternalFloatArray();
16221 }
16222
16223
16224 void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
16225   LocalContext context;
16226   v8::HandleScope scope(context->GetIsolate());
16227   for (int size = 0; size < 100; size += 10) {
16228     int element_size = ExternalArrayElementSize(array_type);
16229     void* external_data = malloc(size * element_size);
16230     v8::Handle<v8::Object> obj = v8::Object::New();
16231     obj->SetIndexedPropertiesToExternalArrayData(
16232         external_data, array_type, size);
16233     CHECK(obj->HasIndexedPropertiesInExternalArrayData());
16234     CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16235     CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
16236     CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
16237     free(external_data);
16238   }
16239 }
16240
16241
16242 THREADED_TEST(ExternalArrayInfo) {
16243   ExternalArrayInfoTestHelper(v8::kExternalByteArray);
16244   ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
16245   ExternalArrayInfoTestHelper(v8::kExternalShortArray);
16246   ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
16247   ExternalArrayInfoTestHelper(v8::kExternalIntArray);
16248   ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
16249   ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
16250   ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
16251   ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
16252 }
16253
16254
16255 void ExternalArrayLimitTestHelper(v8::ExternalArrayType array_type, int size) {
16256   v8::Handle<v8::Object> obj = v8::Object::New();
16257   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16258   last_location = last_message = NULL;
16259   obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16260   CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16261   CHECK_NE(NULL, last_location);
16262   CHECK_NE(NULL, last_message);
16263 }
16264
16265
16266 TEST(ExternalArrayLimits) {
16267   LocalContext context;
16268   v8::HandleScope scope(context->GetIsolate());
16269   ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0x40000000);
16270   ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0xffffffff);
16271   ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0x40000000);
16272   ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0xffffffff);
16273   ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0x40000000);
16274   ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0xffffffff);
16275   ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0x40000000);
16276   ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0xffffffff);
16277   ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0x40000000);
16278   ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0xffffffff);
16279   ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0x40000000);
16280   ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0xffffffff);
16281   ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0x40000000);
16282   ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0xffffffff);
16283   ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0x40000000);
16284   ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0xffffffff);
16285   ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0x40000000);
16286   ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0xffffffff);
16287 }
16288
16289
16290 template <typename ElementType, typename TypedArray,
16291           class ExternalArrayClass>
16292 void TypedArrayTestHelper(v8::ExternalArrayType array_type,
16293                           int64_t low, int64_t high) {
16294   const int kElementCount = 50;
16295
16296   i::ScopedVector<ElementType> backing_store(kElementCount+2);
16297
16298   LocalContext env;
16299   v8::Isolate* isolate = env->GetIsolate();
16300   v8::HandleScope handle_scope(isolate);
16301
16302   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
16303       backing_store.start(), (kElementCount+2)*sizeof(ElementType));
16304   Local<TypedArray> ta =
16305       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
16306   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
16307   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16308   CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16309   CHECK_EQ(kElementCount*sizeof(ElementType),
16310            static_cast<int>(ta->ByteLength()));
16311   CHECK_EQ(ab, ta->Buffer());
16312
16313   ElementType* data = backing_store.start() + 2;
16314   for (int i = 0; i < kElementCount; i++) {
16315     data[i] = static_cast<ElementType>(i);
16316   }
16317
16318   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16319       env.local(), ta, kElementCount, array_type, low, high);
16320 }
16321
16322
16323 THREADED_TEST(Uint8Array) {
16324   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUnsignedByteArray>(
16325       v8::kExternalUnsignedByteArray, 0, 0xFF);
16326 }
16327
16328
16329 THREADED_TEST(Int8Array) {
16330   TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalByteArray>(
16331       v8::kExternalByteArray, -0x80, 0x7F);
16332 }
16333
16334
16335 THREADED_TEST(Uint16Array) {
16336   TypedArrayTestHelper<uint16_t,
16337                        v8::Uint16Array,
16338                        i::ExternalUnsignedShortArray>(
16339       v8::kExternalUnsignedShortArray, 0, 0xFFFF);
16340 }
16341
16342
16343 THREADED_TEST(Int16Array) {
16344   TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalShortArray>(
16345       v8::kExternalShortArray, -0x8000, 0x7FFF);
16346 }
16347
16348
16349 THREADED_TEST(Uint32Array) {
16350   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUnsignedIntArray>(
16351       v8::kExternalUnsignedIntArray, 0, UINT_MAX);
16352 }
16353
16354
16355 THREADED_TEST(Int32Array) {
16356   TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalIntArray>(
16357       v8::kExternalIntArray, INT_MIN, INT_MAX);
16358 }
16359
16360
16361 THREADED_TEST(Float32Array) {
16362   TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloatArray>(
16363       v8::kExternalFloatArray, -500, 500);
16364 }
16365
16366
16367 THREADED_TEST(Float64Array) {
16368   TypedArrayTestHelper<double, v8::Float64Array, i::ExternalDoubleArray>(
16369       v8::kExternalDoubleArray, -500, 500);
16370 }
16371
16372
16373 THREADED_TEST(Uint8ClampedArray) {
16374   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, i::ExternalPixelArray>(
16375       v8::kExternalPixelArray, 0, 0xFF);
16376 }
16377
16378
16379 THREADED_TEST(DataView) {
16380   const int kSize = 50;
16381
16382   i::ScopedVector<uint8_t> backing_store(kSize+2);
16383
16384   LocalContext env;
16385   v8::Isolate* isolate = env->GetIsolate();
16386   v8::HandleScope handle_scope(isolate);
16387
16388   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
16389       backing_store.start(), 2 + kSize);
16390   Local<v8::DataView> dv =
16391       v8::DataView::New(ab, 2, kSize);
16392   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
16393   CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
16394   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16395   CHECK_EQ(ab, dv->Buffer());
16396 }
16397
16398
16399 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
16400   THREADED_TEST(Is##View) {                                                   \
16401     LocalContext env;                                                         \
16402     v8::Isolate* isolate = env->GetIsolate();                                 \
16403     v8::HandleScope handle_scope(isolate);                                    \
16404                                                                               \
16405     Handle<Value> result = CompileRun(                                        \
16406         "var ab = new ArrayBuffer(128);"                                      \
16407         "new " #View "(ab)");                                                 \
16408     CHECK(result->IsArrayBufferView());                                       \
16409     CHECK(result->Is##View());                                                \
16410     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
16411   }
16412
16413 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16414 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16415 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16416 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16417 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16418 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16419 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16420 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16421 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16422 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
16423
16424 #undef IS_ARRAY_BUFFER_VIEW_TEST
16425
16426
16427
16428 THREADED_TEST(ScriptContextDependence) {
16429   LocalContext c1;
16430   v8::HandleScope scope(c1->GetIsolate());
16431   const char *source = "foo";
16432   v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
16433   v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
16434   c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
16435   CHECK_EQ(dep->Run()->Int32Value(), 100);
16436   CHECK_EQ(indep->Run()->Int32Value(), 100);
16437   LocalContext c2;
16438   c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
16439   CHECK_EQ(dep->Run()->Int32Value(), 100);
16440   CHECK_EQ(indep->Run()->Int32Value(), 101);
16441 }
16442
16443
16444 THREADED_TEST(StackTrace) {
16445   LocalContext context;
16446   v8::HandleScope scope(context->GetIsolate());
16447   v8::TryCatch try_catch;
16448   const char *source = "function foo() { FAIL.FAIL; }; foo();";
16449   v8::Handle<v8::String> src = v8::String::New(source);
16450   v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
16451   v8::Script::New(src, origin)->Run();
16452   CHECK(try_catch.HasCaught());
16453   v8::String::Utf8Value stack(try_catch.StackTrace());
16454   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16455 }
16456
16457
16458 // Checks that a StackFrame has certain expected values.
16459 void checkStackFrame(const char* expected_script_name,
16460     const char* expected_func_name, int expected_line_number,
16461     int expected_column, bool is_eval, bool is_constructor,
16462     v8::Handle<v8::StackFrame> frame) {
16463   v8::HandleScope scope(v8::Isolate::GetCurrent());
16464   v8::String::Utf8Value func_name(frame->GetFunctionName());
16465   v8::String::Utf8Value script_name(frame->GetScriptName());
16466   if (*script_name == NULL) {
16467     // The situation where there is no associated script, like for evals.
16468     CHECK(expected_script_name == NULL);
16469   } else {
16470     CHECK(strstr(*script_name, expected_script_name) != NULL);
16471   }
16472   CHECK(strstr(*func_name, expected_func_name) != NULL);
16473   CHECK_EQ(expected_line_number, frame->GetLineNumber());
16474   CHECK_EQ(expected_column, frame->GetColumn());
16475   CHECK_EQ(is_eval, frame->IsEval());
16476   CHECK_EQ(is_constructor, frame->IsConstructor());
16477 }
16478
16479
16480 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
16481   v8::HandleScope scope(args.GetIsolate());
16482   const char* origin = "capture-stack-trace-test";
16483   const int kOverviewTest = 1;
16484   const int kDetailedTest = 2;
16485
16486   ASSERT(args.Length() == 1);
16487
16488   int testGroup = args[0]->Int32Value();
16489   if (testGroup == kOverviewTest) {
16490     v8::Handle<v8::StackTrace> stackTrace =
16491         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
16492     CHECK_EQ(4, stackTrace->GetFrameCount());
16493     checkStackFrame(origin, "bar", 2, 10, false, false,
16494                     stackTrace->GetFrame(0));
16495     checkStackFrame(origin, "foo", 6, 3, false, false,
16496                     stackTrace->GetFrame(1));
16497     // This is the source string inside the eval which has the call to foo.
16498     checkStackFrame(NULL, "", 1, 5, false, false,
16499                     stackTrace->GetFrame(2));
16500     // The last frame is an anonymous function which has the initial eval call.
16501     checkStackFrame(origin, "", 8, 7, false, false,
16502                     stackTrace->GetFrame(3));
16503
16504     CHECK(stackTrace->AsArray()->IsArray());
16505   } else if (testGroup == kDetailedTest) {
16506     v8::Handle<v8::StackTrace> stackTrace =
16507         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
16508     CHECK_EQ(4, stackTrace->GetFrameCount());
16509     checkStackFrame(origin, "bat", 4, 22, false, false,
16510                     stackTrace->GetFrame(0));
16511     checkStackFrame(origin, "baz", 8, 3, false, true,
16512                     stackTrace->GetFrame(1));
16513 #ifdef ENABLE_DEBUGGER_SUPPORT
16514     bool is_eval = true;
16515 #else  // ENABLE_DEBUGGER_SUPPORT
16516     bool is_eval = false;
16517 #endif  // ENABLE_DEBUGGER_SUPPORT
16518
16519     // This is the source string inside the eval which has the call to baz.
16520     checkStackFrame(NULL, "", 1, 5, is_eval, false,
16521                     stackTrace->GetFrame(2));
16522     // The last frame is an anonymous function which has the initial eval call.
16523     checkStackFrame(origin, "", 10, 1, false, false,
16524                     stackTrace->GetFrame(3));
16525
16526     CHECK(stackTrace->AsArray()->IsArray());
16527   }
16528 }
16529
16530
16531 // Tests the C++ StackTrace API.
16532 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
16533 // THREADED_TEST(CaptureStackTrace) {
16534 TEST(CaptureStackTrace) {
16535   v8::HandleScope scope(v8::Isolate::GetCurrent());
16536   v8::Handle<v8::String> origin = v8::String::New("capture-stack-trace-test");
16537   Local<ObjectTemplate> templ = ObjectTemplate::New();
16538   templ->Set(v8_str("AnalyzeStackInNativeCode"),
16539              v8::FunctionTemplate::New(AnalyzeStackInNativeCode));
16540   LocalContext context(0, templ);
16541
16542   // Test getting OVERVIEW information. Should ignore information that is not
16543   // script name, function name, line number, and column offset.
16544   const char *overview_source =
16545     "function bar() {\n"
16546     "  var y; AnalyzeStackInNativeCode(1);\n"
16547     "}\n"
16548     "function foo() {\n"
16549     "\n"
16550     "  bar();\n"
16551     "}\n"
16552     "var x;eval('new foo();');";
16553   v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
16554   v8::Handle<Value> overview_result(
16555       v8::Script::New(overview_src, origin)->Run());
16556   CHECK(!overview_result.IsEmpty());
16557   CHECK(overview_result->IsObject());
16558
16559   // Test getting DETAILED information.
16560   const char *detailed_source =
16561     "function bat() {AnalyzeStackInNativeCode(2);\n"
16562     "}\n"
16563     "\n"
16564     "function baz() {\n"
16565     "  bat();\n"
16566     "}\n"
16567     "eval('new baz();');";
16568   v8::Handle<v8::String> detailed_src = v8::String::New(detailed_source);
16569   // Make the script using a non-zero line and column offset.
16570   v8::Handle<v8::Integer> line_offset = v8::Integer::New(3);
16571   v8::Handle<v8::Integer> column_offset = v8::Integer::New(5);
16572   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
16573   v8::Handle<v8::Script> detailed_script(
16574       v8::Script::New(detailed_src, &detailed_origin));
16575   v8::Handle<Value> detailed_result(detailed_script->Run());
16576   CHECK(!detailed_result.IsEmpty());
16577   CHECK(detailed_result->IsObject());
16578 }
16579
16580
16581 static void StackTraceForUncaughtExceptionListener(
16582     v8::Handle<v8::Message> message,
16583     v8::Handle<Value>) {
16584   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16585   CHECK_EQ(2, stack_trace->GetFrameCount());
16586   checkStackFrame("origin", "foo", 2, 3, false, false,
16587                   stack_trace->GetFrame(0));
16588   checkStackFrame("origin", "bar", 5, 3, false, false,
16589                   stack_trace->GetFrame(1));
16590 }
16591
16592
16593 TEST(CaptureStackTraceForUncaughtException) {
16594   report_count = 0;
16595   LocalContext env;
16596   v8::HandleScope scope(env->GetIsolate());
16597   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
16598   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16599
16600   Script::Compile(v8_str("function foo() {\n"
16601                          "  throw 1;\n"
16602                          "};\n"
16603                          "function bar() {\n"
16604                          "  foo();\n"
16605                          "};"),
16606                   v8_str("origin"))->Run();
16607   v8::Local<v8::Object> global = env->Global();
16608   Local<Value> trouble = global->Get(v8_str("bar"));
16609   CHECK(trouble->IsFunction());
16610   Function::Cast(*trouble)->Call(global, 0, NULL);
16611   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16612   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
16613 }
16614
16615
16616 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
16617   LocalContext env;
16618   v8::HandleScope scope(env->GetIsolate());
16619   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
16620                                                     1024,
16621                                                     v8::StackTrace::kDetailed);
16622
16623   CompileRun(
16624       "var setters = ['column', 'lineNumber', 'scriptName',\n"
16625       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
16626       "    'isConstructor'];\n"
16627       "for (var i = 0; i < setters.length; i++) {\n"
16628       "  var prop = setters[i];\n"
16629       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
16630       "}\n");
16631   CompileRun("throw 'exception';");
16632   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16633 }
16634
16635
16636 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
16637                                      v8::Handle<v8::Value> data) {
16638   // Use the frame where JavaScript is called from.
16639   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16640   CHECK(!stack_trace.IsEmpty());
16641   int frame_count = stack_trace->GetFrameCount();
16642   CHECK_EQ(3, frame_count);
16643   int line_number[] = {1, 2, 5};
16644   for (int i = 0; i < frame_count; i++) {
16645     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16646   }
16647 }
16648
16649
16650 // Test that we only return the stack trace at the site where the exception
16651 // is first thrown (not where it is rethrown).
16652 TEST(RethrowStackTrace) {
16653   LocalContext env;
16654   v8::HandleScope scope(env->GetIsolate());
16655   // We make sure that
16656   // - the stack trace of the ReferenceError in g() is reported.
16657   // - the stack trace is not overwritten when e1 is rethrown by t().
16658   // - the stack trace of e2 does not overwrite that of e1.
16659   const char* source =
16660       "function g() { error; }          \n"
16661       "function f() { g(); }            \n"
16662       "function t(e) { throw e; }       \n"
16663       "try {                            \n"
16664       "  f();                           \n"
16665       "} catch (e1) {                   \n"
16666       "  try {                          \n"
16667       "    error;                       \n"
16668       "  } catch (e2) {                 \n"
16669       "    t(e1);                       \n"
16670       "  }                              \n"
16671       "}                                \n";
16672   v8::V8::AddMessageListener(RethrowStackTraceHandler);
16673   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16674   CompileRun(source);
16675   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16676   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
16677 }
16678
16679
16680 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
16681                                               v8::Handle<v8::Value> data) {
16682   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16683   CHECK(!stack_trace.IsEmpty());
16684   int frame_count = stack_trace->GetFrameCount();
16685   CHECK_EQ(2, frame_count);
16686   int line_number[] = {3, 7};
16687   for (int i = 0; i < frame_count; i++) {
16688     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16689   }
16690 }
16691
16692
16693 // Test that we do not recognize identity for primitive exceptions.
16694 TEST(RethrowPrimitiveStackTrace) {
16695   LocalContext env;
16696   v8::HandleScope scope(env->GetIsolate());
16697   // We do not capture stack trace for non Error objects on creation time.
16698   // Instead, we capture the stack trace on last throw.
16699   const char* source =
16700       "function g() { throw 404; }      \n"
16701       "function f() { g(); }            \n"
16702       "function t(e) { throw e; }       \n"
16703       "try {                            \n"
16704       "  f();                           \n"
16705       "} catch (e1) {                   \n"
16706       "  t(e1)                          \n"
16707       "}                                \n";
16708   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
16709   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16710   CompileRun(source);
16711   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16712   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
16713 }
16714
16715
16716 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
16717                                               v8::Handle<v8::Value> data) {
16718   // Use the frame where JavaScript is called from.
16719   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16720   CHECK(!stack_trace.IsEmpty());
16721   CHECK_EQ(1, stack_trace->GetFrameCount());
16722   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
16723 }
16724
16725
16726 // Test that the stack trace is captured when the error object is created and
16727 // not where it is thrown.
16728 TEST(RethrowExistingStackTrace) {
16729   LocalContext env;
16730   v8::HandleScope scope(env->GetIsolate());
16731   const char* source =
16732       "var e = new Error();           \n"
16733       "throw e;                       \n";
16734   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
16735   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16736   CompileRun(source);
16737   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16738   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
16739 }
16740
16741
16742 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
16743                                                v8::Handle<v8::Value> data) {
16744   // Use the frame where JavaScript is called from.
16745   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16746   CHECK(!stack_trace.IsEmpty());
16747   CHECK_EQ(1, stack_trace->GetFrameCount());
16748   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
16749 }
16750
16751
16752 // Test that the stack trace is captured where the bogus Error object is thrown.
16753 TEST(RethrowBogusErrorStackTrace) {
16754   LocalContext env;
16755   v8::HandleScope scope(env->GetIsolate());
16756   const char* source =
16757       "var e = {__proto__: new Error()} \n"
16758       "throw e;                         \n";
16759   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
16760   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16761   CompileRun(source);
16762   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16763   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
16764 }
16765
16766
16767 void AnalyzeStackOfEvalWithSourceURL(
16768     const v8::FunctionCallbackInfo<v8::Value>& args) {
16769   v8::HandleScope scope(args.GetIsolate());
16770   v8::Handle<v8::StackTrace> stackTrace =
16771       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
16772   CHECK_EQ(5, stackTrace->GetFrameCount());
16773   v8::Handle<v8::String> url = v8_str("eval_url");
16774   for (int i = 0; i < 3; i++) {
16775     v8::Handle<v8::String> name =
16776         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
16777     CHECK(!name.IsEmpty());
16778     CHECK_EQ(url, name);
16779   }
16780 }
16781
16782
16783 TEST(SourceURLInStackTrace) {
16784   v8::HandleScope scope(v8::Isolate::GetCurrent());
16785   Local<ObjectTemplate> templ = ObjectTemplate::New();
16786   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
16787              v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
16788   LocalContext context(0, templ);
16789
16790   const char *source =
16791     "function outer() {\n"
16792     "function bar() {\n"
16793     "  AnalyzeStackOfEvalWithSourceURL();\n"
16794     "}\n"
16795     "function foo() {\n"
16796     "\n"
16797     "  bar();\n"
16798     "}\n"
16799     "foo();\n"
16800     "}\n"
16801     "eval('(' + outer +')()%s');";
16802
16803   i::ScopedVector<char> code(1024);
16804   i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
16805   CHECK(CompileRun(code.start())->IsUndefined());
16806   i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
16807   CHECK(CompileRun(code.start())->IsUndefined());
16808 }
16809
16810
16811 static int scriptIdInStack[2];
16812
16813 void AnalyzeScriptIdInStack(
16814     const v8::FunctionCallbackInfo<v8::Value>& args) {
16815   v8::HandleScope scope(args.GetIsolate());
16816   v8::Handle<v8::StackTrace> stackTrace =
16817       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kScriptId);
16818   CHECK_EQ(2, stackTrace->GetFrameCount());
16819   for (int i = 0; i < 2; i++) {
16820     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
16821   }
16822 }
16823
16824
16825 TEST(ScriptIdInStackTrace) {
16826   v8::HandleScope scope(v8::Isolate::GetCurrent());
16827   Local<ObjectTemplate> templ = ObjectTemplate::New();
16828   templ->Set(v8_str("AnalyzeScriptIdInStack"),
16829              v8::FunctionTemplate::New(AnalyzeScriptIdInStack));
16830   LocalContext context(0, templ);
16831
16832   v8::Handle<v8::String> scriptSource = v8::String::New(
16833     "function foo() {\n"
16834     "  AnalyzeScriptIdInStack();"
16835     "}\n"
16836     "foo();\n");
16837   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
16838   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
16839   script->Run();
16840   for (int i = 0; i < 2; i++) {
16841     CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
16842     CHECK_EQ(scriptIdInStack[i], script->GetId());
16843   }
16844 }
16845
16846
16847 void AnalyzeStackOfInlineScriptWithSourceURL(
16848     const v8::FunctionCallbackInfo<v8::Value>& args) {
16849   v8::HandleScope scope(args.GetIsolate());
16850   v8::Handle<v8::StackTrace> stackTrace =
16851       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
16852   CHECK_EQ(4, stackTrace->GetFrameCount());
16853   v8::Handle<v8::String> url = v8_str("url");
16854   for (int i = 0; i < 3; i++) {
16855     v8::Handle<v8::String> name =
16856         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
16857     CHECK(!name.IsEmpty());
16858     CHECK_EQ(url, name);
16859   }
16860 }
16861
16862
16863 TEST(InlineScriptWithSourceURLInStackTrace) {
16864   v8::HandleScope scope(v8::Isolate::GetCurrent());
16865   Local<ObjectTemplate> templ = ObjectTemplate::New();
16866   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
16867              v8::FunctionTemplate::New(
16868                  AnalyzeStackOfInlineScriptWithSourceURL));
16869   LocalContext context(0, templ);
16870
16871   const char *source =
16872     "function outer() {\n"
16873     "function bar() {\n"
16874     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
16875     "}\n"
16876     "function foo() {\n"
16877     "\n"
16878     "  bar();\n"
16879     "}\n"
16880     "foo();\n"
16881     "}\n"
16882     "outer()\n%s";
16883
16884   i::ScopedVector<char> code(1024);
16885   i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
16886   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
16887   i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
16888   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
16889 }
16890
16891
16892 void AnalyzeStackOfDynamicScriptWithSourceURL(
16893     const v8::FunctionCallbackInfo<v8::Value>& args) {
16894   v8::HandleScope scope(args.GetIsolate());
16895   v8::Handle<v8::StackTrace> stackTrace =
16896       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
16897   CHECK_EQ(4, stackTrace->GetFrameCount());
16898   v8::Handle<v8::String> url = v8_str("source_url");
16899   for (int i = 0; i < 3; i++) {
16900     v8::Handle<v8::String> name =
16901         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
16902     CHECK(!name.IsEmpty());
16903     CHECK_EQ(url, name);
16904   }
16905 }
16906
16907
16908 TEST(DynamicWithSourceURLInStackTrace) {
16909   v8::HandleScope scope(v8::Isolate::GetCurrent());
16910   Local<ObjectTemplate> templ = ObjectTemplate::New();
16911   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
16912              v8::FunctionTemplate::New(
16913                  AnalyzeStackOfDynamicScriptWithSourceURL));
16914   LocalContext context(0, templ);
16915
16916   const char *source =
16917     "function outer() {\n"
16918     "function bar() {\n"
16919     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
16920     "}\n"
16921     "function foo() {\n"
16922     "\n"
16923     "  bar();\n"
16924     "}\n"
16925     "foo();\n"
16926     "}\n"
16927     "outer()\n%s";
16928
16929   i::ScopedVector<char> code(1024);
16930   i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
16931   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
16932   i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
16933   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
16934 }
16935
16936
16937 static void CreateGarbageInOldSpace() {
16938   i::Factory* factory = i::Isolate::Current()->factory();
16939   v8::HandleScope scope(v8::Isolate::GetCurrent());
16940   i::AlwaysAllocateScope always_allocate;
16941   for (int i = 0; i < 1000; i++) {
16942     factory->NewFixedArray(1000, i::TENURED);
16943   }
16944 }
16945
16946
16947 // Test that idle notification can be handled and eventually returns true.
16948 TEST(IdleNotification) {
16949   const intptr_t MB = 1024 * 1024;
16950   LocalContext env;
16951   v8::HandleScope scope(env->GetIsolate());
16952   intptr_t initial_size = HEAP->SizeOfObjects();
16953   CreateGarbageInOldSpace();
16954   intptr_t size_with_garbage = HEAP->SizeOfObjects();
16955   CHECK_GT(size_with_garbage, initial_size + MB);
16956   bool finished = false;
16957   for (int i = 0; i < 200 && !finished; i++) {
16958     finished = v8::V8::IdleNotification();
16959   }
16960   intptr_t final_size = HEAP->SizeOfObjects();
16961   CHECK(finished);
16962   CHECK_LT(final_size, initial_size + 1);
16963 }
16964
16965
16966 // Test that idle notification can be handled and eventually collects garbage.
16967 TEST(IdleNotificationWithSmallHint) {
16968   const intptr_t MB = 1024 * 1024;
16969   const int IdlePauseInMs = 900;
16970   LocalContext env;
16971   v8::HandleScope scope(env->GetIsolate());
16972   intptr_t initial_size = HEAP->SizeOfObjects();
16973   CreateGarbageInOldSpace();
16974   intptr_t size_with_garbage = HEAP->SizeOfObjects();
16975   CHECK_GT(size_with_garbage, initial_size + MB);
16976   bool finished = false;
16977   for (int i = 0; i < 200 && !finished; i++) {
16978     finished = v8::V8::IdleNotification(IdlePauseInMs);
16979   }
16980   intptr_t final_size = HEAP->SizeOfObjects();
16981   CHECK(finished);
16982   CHECK_LT(final_size, initial_size + 1);
16983 }
16984
16985
16986 // Test that idle notification can be handled and eventually collects garbage.
16987 TEST(IdleNotificationWithLargeHint) {
16988   const intptr_t MB = 1024 * 1024;
16989   const int IdlePauseInMs = 900;
16990   LocalContext env;
16991   v8::HandleScope scope(env->GetIsolate());
16992   intptr_t initial_size = HEAP->SizeOfObjects();
16993   CreateGarbageInOldSpace();
16994   intptr_t size_with_garbage = HEAP->SizeOfObjects();
16995   CHECK_GT(size_with_garbage, initial_size + MB);
16996   bool finished = false;
16997   for (int i = 0; i < 200 && !finished; i++) {
16998     finished = v8::V8::IdleNotification(IdlePauseInMs);
16999   }
17000   intptr_t final_size = HEAP->SizeOfObjects();
17001   CHECK(finished);
17002   CHECK_LT(final_size, initial_size + 1);
17003 }
17004
17005
17006 TEST(Regress2107) {
17007   const intptr_t MB = 1024 * 1024;
17008   const int kShortIdlePauseInMs = 100;
17009   const int kLongIdlePauseInMs = 1000;
17010   LocalContext env;
17011   v8::Isolate* isolate = env->GetIsolate();
17012   v8::HandleScope scope(env->GetIsolate());
17013   intptr_t initial_size = HEAP->SizeOfObjects();
17014   // Send idle notification to start a round of incremental GCs.
17015   v8::V8::IdleNotification(kShortIdlePauseInMs);
17016   // Emulate 7 page reloads.
17017   for (int i = 0; i < 7; i++) {
17018     {
17019       v8::HandleScope inner_scope(env->GetIsolate());
17020       v8::Local<v8::Context> ctx = v8::Context::New(isolate);
17021       ctx->Enter();
17022       CreateGarbageInOldSpace();
17023       ctx->Exit();
17024     }
17025     v8::V8::ContextDisposedNotification();
17026     v8::V8::IdleNotification(kLongIdlePauseInMs);
17027   }
17028   // Create garbage and check that idle notification still collects it.
17029   CreateGarbageInOldSpace();
17030   intptr_t size_with_garbage = HEAP->SizeOfObjects();
17031   CHECK_GT(size_with_garbage, initial_size + MB);
17032   bool finished = false;
17033   for (int i = 0; i < 200 && !finished; i++) {
17034     finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
17035   }
17036   intptr_t final_size = HEAP->SizeOfObjects();
17037   CHECK_LT(final_size, initial_size + 1);
17038 }
17039
17040 static uint32_t* stack_limit;
17041
17042 static void GetStackLimitCallback(
17043     const v8::FunctionCallbackInfo<v8::Value>& args) {
17044   stack_limit = reinterpret_cast<uint32_t*>(
17045       i::Isolate::Current()->stack_guard()->real_climit());
17046 }
17047
17048
17049 // Uses the address of a local variable to determine the stack top now.
17050 // Given a size, returns an address that is that far from the current
17051 // top of stack.
17052 static uint32_t* ComputeStackLimit(uint32_t size) {
17053   uint32_t* answer = &size - (size / sizeof(size));
17054   // If the size is very large and the stack is very near the bottom of
17055   // memory then the calculation above may wrap around and give an address
17056   // that is above the (downwards-growing) stack.  In that case we return
17057   // a very low address.
17058   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17059   return answer;
17060 }
17061
17062
17063 // We need at least 165kB for an x64 debug build with clang and ASAN.
17064 static const int stack_breathing_room = 256 * i::KB;
17065
17066
17067 TEST(SetResourceConstraints) {
17068   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
17069
17070   // Set stack limit.
17071   v8::ResourceConstraints constraints;
17072   constraints.set_stack_limit(set_limit);
17073   CHECK(v8::SetResourceConstraints(&constraints));
17074
17075   // Execute a script.
17076   LocalContext env;
17077   v8::HandleScope scope(env->GetIsolate());
17078   Local<v8::FunctionTemplate> fun_templ =
17079       v8::FunctionTemplate::New(GetStackLimitCallback);
17080   Local<Function> fun = fun_templ->GetFunction();
17081   env->Global()->Set(v8_str("get_stack_limit"), fun);
17082   CompileRun("get_stack_limit();");
17083
17084   CHECK(stack_limit == set_limit);
17085 }
17086
17087
17088 TEST(SetResourceConstraintsInThread) {
17089   uint32_t* set_limit;
17090   {
17091     v8::Locker locker(CcTest::default_isolate());
17092     set_limit = ComputeStackLimit(stack_breathing_room);
17093
17094     // Set stack limit.
17095     v8::ResourceConstraints constraints;
17096     constraints.set_stack_limit(set_limit);
17097     CHECK(v8::SetResourceConstraints(&constraints));
17098
17099     // Execute a script.
17100     v8::HandleScope scope(CcTest::default_isolate());
17101     LocalContext env;
17102     Local<v8::FunctionTemplate> fun_templ =
17103         v8::FunctionTemplate::New(GetStackLimitCallback);
17104     Local<Function> fun = fun_templ->GetFunction();
17105     env->Global()->Set(v8_str("get_stack_limit"), fun);
17106     CompileRun("get_stack_limit();");
17107
17108     CHECK(stack_limit == set_limit);
17109   }
17110   {
17111     v8::Locker locker(CcTest::default_isolate());
17112     CHECK(stack_limit == set_limit);
17113   }
17114 }
17115
17116
17117 THREADED_TEST(GetHeapStatistics) {
17118   LocalContext c1;
17119   v8::HandleScope scope(c1->GetIsolate());
17120   v8::HeapStatistics heap_statistics;
17121   CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17122   CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
17123   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
17124   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17125   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
17126 }
17127
17128
17129 class VisitorImpl : public v8::ExternalResourceVisitor {
17130  public:
17131   explicit VisitorImpl(TestResource** resource) {
17132     for (int i = 0; i < 4; i++) {
17133       resource_[i] = resource[i];
17134       found_resource_[i] = false;
17135     }
17136   }
17137   virtual ~VisitorImpl() {}
17138   virtual void VisitExternalString(v8::Handle<v8::String> string) {
17139     if (!string->IsExternal()) {
17140       CHECK(string->IsExternalAscii());
17141       return;
17142     }
17143     v8::String::ExternalStringResource* resource =
17144         string->GetExternalStringResource();
17145     CHECK(resource);
17146     for (int i = 0; i < 4; i++) {
17147       if (resource_[i] == resource) {
17148         CHECK(!found_resource_[i]);
17149         found_resource_[i] = true;
17150       }
17151     }
17152   }
17153   void CheckVisitedResources() {
17154     for (int i = 0; i < 4; i++) {
17155       CHECK(found_resource_[i]);
17156     }
17157   }
17158
17159  private:
17160   v8::String::ExternalStringResource* resource_[4];
17161   bool found_resource_[4];
17162 };
17163
17164
17165 TEST(VisitExternalStrings) {
17166   LocalContext env;
17167   v8::HandleScope scope(env->GetIsolate());
17168   const char* string = "Some string";
17169   uint16_t* two_byte_string = AsciiToTwoByteString(string);
17170   TestResource* resource[4];
17171   resource[0] = new TestResource(two_byte_string);
17172   v8::Local<v8::String> string0 = v8::String::NewExternal(resource[0]);
17173   resource[1] = new TestResource(two_byte_string);
17174   v8::Local<v8::String> string1 = v8::String::NewExternal(resource[1]);
17175
17176   // Externalized symbol.
17177   resource[2] = new TestResource(two_byte_string);
17178   v8::Local<v8::String> string2 = v8::String::NewSymbol(string);
17179   CHECK(string2->MakeExternal(resource[2]));
17180
17181   // Symbolized External.
17182   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
17183   v8::Local<v8::String> string3 = v8::String::NewExternal(resource[3]);
17184   HEAP->CollectAllAvailableGarbage();  // Tenure string.
17185   // Turn into a symbol.
17186   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
17187   CHECK(!HEAP->InternalizeString(*string3_i)->IsFailure());
17188   CHECK(string3_i->IsInternalizedString());
17189
17190   // We need to add usages for string* to avoid warnings in GCC 4.7
17191   CHECK(string0->IsExternal());
17192   CHECK(string1->IsExternal());
17193   CHECK(string2->IsExternal());
17194   CHECK(string3->IsExternal());
17195
17196   VisitorImpl visitor(resource);
17197   v8::V8::VisitExternalResources(&visitor);
17198   visitor.CheckVisitedResources();
17199 }
17200
17201
17202 static double DoubleFromBits(uint64_t value) {
17203   double target;
17204   i::OS::MemCopy(&target, &value, sizeof(target));
17205   return target;
17206 }
17207
17208
17209 static uint64_t DoubleToBits(double value) {
17210   uint64_t target;
17211   i::OS::MemCopy(&target, &value, sizeof(target));
17212   return target;
17213 }
17214
17215
17216 static double DoubleToDateTime(double input) {
17217   double date_limit = 864e13;
17218   if (std::isnan(input) || input < -date_limit || input > date_limit) {
17219     return i::OS::nan_value();
17220   }
17221   return (input < 0) ? -(floor(-input)) : floor(input);
17222 }
17223
17224
17225 // We don't have a consistent way to write 64-bit constants syntactically, so we
17226 // split them into two 32-bit constants and combine them programmatically.
17227 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17228   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17229 }
17230
17231
17232 THREADED_TEST(QuietSignalingNaNs) {
17233   LocalContext context;
17234   v8::HandleScope scope(context->GetIsolate());
17235   v8::TryCatch try_catch;
17236
17237   // Special double values.
17238   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
17239   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
17240   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
17241   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
17242   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
17243   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
17244   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
17245
17246   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
17247   // on either side of the epoch.
17248   double date_limit = 864e13;
17249
17250   double test_values[] = {
17251       snan,
17252       qnan,
17253       infinity,
17254       max_normal,
17255       date_limit + 1,
17256       date_limit,
17257       min_normal,
17258       max_denormal,
17259       min_denormal,
17260       0,
17261       -0,
17262       -min_denormal,
17263       -max_denormal,
17264       -min_normal,
17265       -date_limit,
17266       -date_limit - 1,
17267       -max_normal,
17268       -infinity,
17269       -qnan,
17270       -snan
17271   };
17272   int num_test_values = 20;
17273
17274   for (int i = 0; i < num_test_values; i++) {
17275     double test_value = test_values[i];
17276
17277     // Check that Number::New preserves non-NaNs and quiets SNaNs.
17278     v8::Handle<v8::Value> number = v8::Number::New(test_value);
17279     double stored_number = number->NumberValue();
17280     if (!std::isnan(test_value)) {
17281       CHECK_EQ(test_value, stored_number);
17282     } else {
17283       uint64_t stored_bits = DoubleToBits(stored_number);
17284       // Check if quiet nan (bits 51..62 all set).
17285 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17286       // Most significant fraction bit for quiet nan is set to 0
17287       // on MIPS architecture. Allowed by IEEE-754.
17288       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17289 #else
17290       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
17291 #endif
17292     }
17293
17294     // Check that Date::New preserves non-NaNs in the date range and
17295     // quiets SNaNs.
17296     v8::Handle<v8::Value> date = v8::Date::New(test_value);
17297     double expected_stored_date = DoubleToDateTime(test_value);
17298     double stored_date = date->NumberValue();
17299     if (!std::isnan(expected_stored_date)) {
17300       CHECK_EQ(expected_stored_date, stored_date);
17301     } else {
17302       uint64_t stored_bits = DoubleToBits(stored_date);
17303       // Check if quiet nan (bits 51..62 all set).
17304 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17305       // Most significant fraction bit for quiet nan is set to 0
17306       // on MIPS architecture. Allowed by IEEE-754.
17307       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17308 #else
17309       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
17310 #endif
17311     }
17312   }
17313 }
17314
17315
17316 static void SpaghettiIncident(
17317     const v8::FunctionCallbackInfo<v8::Value>& args) {
17318   v8::HandleScope scope(args.GetIsolate());
17319   v8::TryCatch tc;
17320   v8::Handle<v8::String> str(args[0]->ToString());
17321   USE(str);
17322   if (tc.HasCaught())
17323     tc.ReThrow();
17324 }
17325
17326
17327 // Test that an exception can be propagated down through a spaghetti
17328 // stack using ReThrow.
17329 THREADED_TEST(SpaghettiStackReThrow) {
17330   v8::HandleScope scope(v8::Isolate::GetCurrent());
17331   LocalContext context;
17332   context->Global()->Set(
17333       v8::String::New("s"),
17334       v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
17335   v8::TryCatch try_catch;
17336   CompileRun(
17337       "var i = 0;"
17338       "var o = {"
17339       "  toString: function () {"
17340       "    if (i == 10) {"
17341       "      throw 'Hey!';"
17342       "    } else {"
17343       "      i++;"
17344       "      return s(o);"
17345       "    }"
17346       "  }"
17347       "};"
17348       "s(o);");
17349   CHECK(try_catch.HasCaught());
17350   v8::String::Utf8Value value(try_catch.Exception());
17351   CHECK_EQ(0, strcmp(*value, "Hey!"));
17352 }
17353
17354
17355 TEST(Regress528) {
17356   v8::V8::Initialize();
17357   v8::Isolate* isolate = v8::Isolate::GetCurrent();
17358   v8::HandleScope scope(isolate);
17359   v8::Local<Context> other_context;
17360   int gc_count;
17361
17362   // Create a context used to keep the code from aging in the compilation
17363   // cache.
17364   other_context = Context::New(isolate);
17365
17366   // Context-dependent context data creates reference from the compilation
17367   // cache to the global object.
17368   const char* source_simple = "1";
17369   {
17370     v8::HandleScope scope(isolate);
17371     v8::Local<Context> context = Context::New(isolate);
17372
17373     context->Enter();
17374     Local<v8::String> obj = v8::String::New("");
17375     context->SetEmbedderData(0, obj);
17376     CompileRun(source_simple);
17377     context->Exit();
17378   }
17379   v8::V8::ContextDisposedNotification();
17380   for (gc_count = 1; gc_count < 10; gc_count++) {
17381     other_context->Enter();
17382     CompileRun(source_simple);
17383     other_context->Exit();
17384     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
17385     if (GetGlobalObjectsCount() == 1) break;
17386   }
17387   CHECK_GE(2, gc_count);
17388   CHECK_EQ(1, GetGlobalObjectsCount());
17389
17390   // Eval in a function creates reference from the compilation cache to the
17391   // global object.
17392   const char* source_eval = "function f(){eval('1')}; f()";
17393   {
17394     v8::HandleScope scope(isolate);
17395     v8::Local<Context> context = Context::New(isolate);
17396
17397     context->Enter();
17398     CompileRun(source_eval);
17399     context->Exit();
17400   }
17401   v8::V8::ContextDisposedNotification();
17402   for (gc_count = 1; gc_count < 10; gc_count++) {
17403     other_context->Enter();
17404     CompileRun(source_eval);
17405     other_context->Exit();
17406     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
17407     if (GetGlobalObjectsCount() == 1) break;
17408   }
17409   CHECK_GE(2, gc_count);
17410   CHECK_EQ(1, GetGlobalObjectsCount());
17411
17412   // Looking up the line number for an exception creates reference from the
17413   // compilation cache to the global object.
17414   const char* source_exception = "function f(){throw 1;} f()";
17415   {
17416     v8::HandleScope scope(isolate);
17417     v8::Local<Context> context = Context::New(isolate);
17418
17419     context->Enter();
17420     v8::TryCatch try_catch;
17421     CompileRun(source_exception);
17422     CHECK(try_catch.HasCaught());
17423     v8::Handle<v8::Message> message = try_catch.Message();
17424     CHECK(!message.IsEmpty());
17425     CHECK_EQ(1, message->GetLineNumber());
17426     context->Exit();
17427   }
17428   v8::V8::ContextDisposedNotification();
17429   for (gc_count = 1; gc_count < 10; gc_count++) {
17430     other_context->Enter();
17431     CompileRun(source_exception);
17432     other_context->Exit();
17433     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
17434     if (GetGlobalObjectsCount() == 1) break;
17435   }
17436   CHECK_GE(2, gc_count);
17437   CHECK_EQ(1, GetGlobalObjectsCount());
17438
17439   v8::V8::ContextDisposedNotification();
17440 }
17441
17442
17443 THREADED_TEST(ScriptOrigin) {
17444   LocalContext env;
17445   v8::HandleScope scope(env->GetIsolate());
17446   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
17447   v8::Handle<v8::String> script = v8::String::New(
17448       "function f() {}\n\nfunction g() {}");
17449   v8::Script::Compile(script, &origin)->Run();
17450   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
17451       env->Global()->Get(v8::String::New("f")));
17452   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
17453       env->Global()->Get(v8::String::New("g")));
17454
17455   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
17456   CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
17457   CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
17458
17459   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
17460   CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
17461   CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
17462 }
17463
17464
17465 THREADED_TEST(FunctionGetInferredName) {
17466   LocalContext env;
17467   v8::HandleScope scope(env->GetIsolate());
17468   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
17469   v8::Handle<v8::String> script = v8::String::New(
17470       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
17471   v8::Script::Compile(script, &origin)->Run();
17472   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
17473       env->Global()->Get(v8::String::New("f")));
17474   CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
17475 }
17476
17477
17478 THREADED_TEST(ScriptLineNumber) {
17479   LocalContext env;
17480   v8::HandleScope scope(env->GetIsolate());
17481   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
17482   v8::Handle<v8::String> script = v8::String::New(
17483       "function f() {}\n\nfunction g() {}");
17484   v8::Script::Compile(script, &origin)->Run();
17485   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
17486       env->Global()->Get(v8::String::New("f")));
17487   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
17488       env->Global()->Get(v8::String::New("g")));
17489   CHECK_EQ(0, f->GetScriptLineNumber());
17490   CHECK_EQ(2, g->GetScriptLineNumber());
17491 }
17492
17493
17494 THREADED_TEST(ScriptColumnNumber) {
17495   LocalContext env;
17496   v8::HandleScope scope(env->GetIsolate());
17497   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
17498       v8::Integer::New(3), v8::Integer::New(2));
17499   v8::Handle<v8::String> script = v8::String::New(
17500       "function foo() {}\n\n     function bar() {}");
17501   v8::Script::Compile(script, &origin)->Run();
17502   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
17503       env->Global()->Get(v8::String::New("foo")));
17504   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
17505       env->Global()->Get(v8::String::New("bar")));
17506   CHECK_EQ(14, foo->GetScriptColumnNumber());
17507   CHECK_EQ(17, bar->GetScriptColumnNumber());
17508 }
17509
17510
17511 THREADED_TEST(FunctionGetScriptId) {
17512   LocalContext env;
17513   v8::HandleScope scope(env->GetIsolate());
17514   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
17515       v8::Integer::New(3), v8::Integer::New(2));
17516   v8::Handle<v8::String> scriptSource = v8::String::New(
17517       "function foo() {}\n\n     function bar() {}");
17518   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
17519   script->Run();
17520   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
17521       env->Global()->Get(v8::String::New("foo")));
17522   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
17523       env->Global()->Get(v8::String::New("bar")));
17524   CHECK_EQ(script->Id(), foo->GetScriptId());
17525   CHECK_EQ(script->Id(), bar->GetScriptId());
17526 }
17527
17528
17529 static void GetterWhichReturns42(
17530     Local<String> name,
17531     const v8::PropertyCallbackInfo<v8::Value>& info) {
17532   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
17533   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
17534   info.GetReturnValue().Set(v8_num(42));
17535 }
17536
17537
17538 static void SetterWhichSetsYOnThisTo23(
17539     Local<String> name,
17540     Local<Value> value,
17541     const v8::PropertyCallbackInfo<void>& info) {
17542   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
17543   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
17544   info.This()->Set(v8_str("y"), v8_num(23));
17545 }
17546
17547
17548 void FooGetInterceptor(Local<String> name,
17549                        const v8::PropertyCallbackInfo<v8::Value>& info) {
17550   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
17551   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
17552   if (!name->Equals(v8_str("foo"))) return;
17553   info.GetReturnValue().Set(v8_num(42));
17554 }
17555
17556
17557 void FooSetInterceptor(Local<String> name,
17558                        Local<Value> value,
17559                        const v8::PropertyCallbackInfo<v8::Value>& info) {
17560   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
17561   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
17562   if (!name->Equals(v8_str("foo"))) return;
17563   info.This()->Set(v8_str("y"), v8_num(23));
17564   info.GetReturnValue().Set(v8_num(23));
17565 }
17566
17567
17568 TEST(SetterOnConstructorPrototype) {
17569   v8::HandleScope scope(v8::Isolate::GetCurrent());
17570   Local<ObjectTemplate> templ = ObjectTemplate::New();
17571   templ->SetAccessor(v8_str("x"),
17572                      GetterWhichReturns42,
17573                      SetterWhichSetsYOnThisTo23);
17574   LocalContext context;
17575   context->Global()->Set(v8_str("P"), templ->NewInstance());
17576   CompileRun("function C1() {"
17577              "  this.x = 23;"
17578              "};"
17579              "C1.prototype = P;"
17580              "function C2() {"
17581              "  this.x = 23"
17582              "};"
17583              "C2.prototype = { };"
17584              "C2.prototype.__proto__ = P;");
17585
17586   v8::Local<v8::Script> script;
17587   script = v8::Script::Compile(v8_str("new C1();"));
17588   for (int i = 0; i < 10; i++) {
17589     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
17590     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
17591     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
17592   }
17593
17594   script = v8::Script::Compile(v8_str("new C2();"));
17595   for (int i = 0; i < 10; i++) {
17596     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
17597     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
17598     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
17599   }
17600 }
17601
17602
17603 static void NamedPropertyGetterWhichReturns42(
17604     Local<String> name,
17605     const v8::PropertyCallbackInfo<v8::Value>& info) {
17606   info.GetReturnValue().Set(v8_num(42));
17607 }
17608
17609
17610 static void NamedPropertySetterWhichSetsYOnThisTo23(
17611     Local<String> name,
17612     Local<Value> value,
17613     const v8::PropertyCallbackInfo<v8::Value>& info) {
17614   if (name->Equals(v8_str("x"))) {
17615     info.This()->Set(v8_str("y"), v8_num(23));
17616   }
17617 }
17618
17619
17620 THREADED_TEST(InterceptorOnConstructorPrototype) {
17621   v8::HandleScope scope(v8::Isolate::GetCurrent());
17622   Local<ObjectTemplate> templ = ObjectTemplate::New();
17623   templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
17624                                  NamedPropertySetterWhichSetsYOnThisTo23);
17625   LocalContext context;
17626   context->Global()->Set(v8_str("P"), templ->NewInstance());
17627   CompileRun("function C1() {"
17628              "  this.x = 23;"
17629              "};"
17630              "C1.prototype = P;"
17631              "function C2() {"
17632              "  this.x = 23"
17633              "};"
17634              "C2.prototype = { };"
17635              "C2.prototype.__proto__ = P;");
17636
17637   v8::Local<v8::Script> script;
17638   script = v8::Script::Compile(v8_str("new C1();"));
17639   for (int i = 0; i < 10; i++) {
17640     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
17641     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
17642     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
17643   }
17644
17645   script = v8::Script::Compile(v8_str("new C2();"));
17646   for (int i = 0; i < 10; i++) {
17647     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
17648     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
17649     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
17650   }
17651 }
17652
17653
17654 TEST(Regress618) {
17655   const char* source = "function C1() {"
17656                        "  this.x = 23;"
17657                        "};"
17658                        "C1.prototype = P;";
17659
17660   LocalContext context;
17661   v8::HandleScope scope(context->GetIsolate());
17662   v8::Local<v8::Script> script;
17663
17664   // Use a simple object as prototype.
17665   v8::Local<v8::Object> prototype = v8::Object::New();
17666   prototype->Set(v8_str("y"), v8_num(42));
17667   context->Global()->Set(v8_str("P"), prototype);
17668
17669   // This compile will add the code to the compilation cache.
17670   CompileRun(source);
17671
17672   script = v8::Script::Compile(v8_str("new C1();"));
17673   // Allow enough iterations for the inobject slack tracking logic
17674   // to finalize instance size and install the fast construct stub.
17675   for (int i = 0; i < 256; i++) {
17676     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
17677     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
17678     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
17679   }
17680
17681   // Use an API object with accessors as prototype.
17682   Local<ObjectTemplate> templ = ObjectTemplate::New();
17683   templ->SetAccessor(v8_str("x"),
17684                      GetterWhichReturns42,
17685                      SetterWhichSetsYOnThisTo23);
17686   context->Global()->Set(v8_str("P"), templ->NewInstance());
17687
17688   // This compile will get the code from the compilation cache.
17689   CompileRun(source);
17690
17691   script = v8::Script::Compile(v8_str("new C1();"));
17692   for (int i = 0; i < 10; i++) {
17693     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
17694     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
17695     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
17696   }
17697 }
17698
17699 int prologue_call_count = 0;
17700 int epilogue_call_count = 0;
17701 int prologue_call_count_second = 0;
17702 int epilogue_call_count_second = 0;
17703
17704 void PrologueCallback(v8::GCType, v8::GCCallbackFlags) {
17705   ++prologue_call_count;
17706 }
17707
17708
17709 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags) {
17710   ++epilogue_call_count;
17711 }
17712
17713
17714 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
17715   ++prologue_call_count_second;
17716 }
17717
17718
17719 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
17720   ++epilogue_call_count_second;
17721 }
17722
17723
17724 TEST(GCCallbacks) {
17725   LocalContext context;
17726
17727   v8::V8::AddGCPrologueCallback(PrologueCallback);
17728   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
17729   CHECK_EQ(0, prologue_call_count);
17730   CHECK_EQ(0, epilogue_call_count);
17731   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
17732   CHECK_EQ(1, prologue_call_count);
17733   CHECK_EQ(1, epilogue_call_count);
17734   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
17735   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
17736   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
17737   CHECK_EQ(2, prologue_call_count);
17738   CHECK_EQ(2, epilogue_call_count);
17739   CHECK_EQ(1, prologue_call_count_second);
17740   CHECK_EQ(1, epilogue_call_count_second);
17741   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
17742   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
17743   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
17744   CHECK_EQ(2, prologue_call_count);
17745   CHECK_EQ(2, epilogue_call_count);
17746   CHECK_EQ(2, prologue_call_count_second);
17747   CHECK_EQ(2, epilogue_call_count_second);
17748   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
17749   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
17750   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
17751   CHECK_EQ(2, prologue_call_count);
17752   CHECK_EQ(2, epilogue_call_count);
17753   CHECK_EQ(2, prologue_call_count_second);
17754   CHECK_EQ(2, epilogue_call_count_second);
17755 }
17756
17757
17758 THREADED_TEST(AddToJSFunctionResultCache) {
17759   i::FLAG_stress_compaction = false;
17760   i::FLAG_allow_natives_syntax = true;
17761   v8::HandleScope scope(v8::Isolate::GetCurrent());
17762
17763   LocalContext context;
17764
17765   const char* code =
17766       "(function() {"
17767       "  var key0 = 'a';"
17768       "  var key1 = 'b';"
17769       "  var r0 = %_GetFromCache(0, key0);"
17770       "  var r1 = %_GetFromCache(0, key1);"
17771       "  var r0_ = %_GetFromCache(0, key0);"
17772       "  if (r0 !== r0_)"
17773       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
17774       "  var r1_ = %_GetFromCache(0, key1);"
17775       "  if (r1 !== r1_)"
17776       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
17777       "  return 'PASSED';"
17778       "})()";
17779   HEAP->ClearJSFunctionResultCaches();
17780   ExpectString(code, "PASSED");
17781 }
17782
17783
17784 static const int k0CacheSize = 16;
17785
17786 THREADED_TEST(FillJSFunctionResultCache) {
17787   i::FLAG_allow_natives_syntax = true;
17788   LocalContext context;
17789   v8::HandleScope scope(context->GetIsolate());
17790
17791   const char* code =
17792       "(function() {"
17793       "  var k = 'a';"
17794       "  var r = %_GetFromCache(0, k);"
17795       "  for (var i = 0; i < 16; i++) {"
17796       "    %_GetFromCache(0, 'a' + i);"
17797       "  };"
17798       "  if (r === %_GetFromCache(0, k))"
17799       "    return 'FAILED: k0CacheSize is too small';"
17800       "  return 'PASSED';"
17801       "})()";
17802   HEAP->ClearJSFunctionResultCaches();
17803   ExpectString(code, "PASSED");
17804 }
17805
17806
17807 THREADED_TEST(RoundRobinGetFromCache) {
17808   i::FLAG_allow_natives_syntax = true;
17809   LocalContext context;
17810   v8::HandleScope scope(context->GetIsolate());
17811
17812   const char* code =
17813       "(function() {"
17814       "  var keys = [];"
17815       "  for (var i = 0; i < 16; i++) keys.push(i);"
17816       "  var values = [];"
17817       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
17818       "  for (var i = 0; i < 16; i++) {"
17819       "    var v = %_GetFromCache(0, keys[i]);"
17820       "    if (v.toString() !== values[i].toString())"
17821       "      return 'Wrong value for ' + "
17822       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
17823       "  };"
17824       "  return 'PASSED';"
17825       "})()";
17826   HEAP->ClearJSFunctionResultCaches();
17827   ExpectString(code, "PASSED");
17828 }
17829
17830
17831 THREADED_TEST(ReverseGetFromCache) {
17832   i::FLAG_allow_natives_syntax = true;
17833   LocalContext context;
17834   v8::HandleScope scope(context->GetIsolate());
17835
17836   const char* code =
17837       "(function() {"
17838       "  var keys = [];"
17839       "  for (var i = 0; i < 16; i++) keys.push(i);"
17840       "  var values = [];"
17841       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
17842       "  for (var i = 15; i >= 16; i--) {"
17843       "    var v = %_GetFromCache(0, keys[i]);"
17844       "    if (v !== values[i])"
17845       "      return 'Wrong value for ' + "
17846       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
17847       "  };"
17848       "  return 'PASSED';"
17849       "})()";
17850   HEAP->ClearJSFunctionResultCaches();
17851   ExpectString(code, "PASSED");
17852 }
17853
17854
17855 THREADED_TEST(TestEviction) {
17856   i::FLAG_allow_natives_syntax = true;
17857   LocalContext context;
17858   v8::HandleScope scope(context->GetIsolate());
17859
17860   const char* code =
17861       "(function() {"
17862       "  for (var i = 0; i < 2*16; i++) {"
17863       "    %_GetFromCache(0, 'a' + i);"
17864       "  };"
17865       "  return 'PASSED';"
17866       "})()";
17867   HEAP->ClearJSFunctionResultCaches();
17868   ExpectString(code, "PASSED");
17869 }
17870
17871
17872 THREADED_TEST(TwoByteStringInAsciiCons) {
17873   // See Chromium issue 47824.
17874   LocalContext context;
17875   v8::HandleScope scope(context->GetIsolate());
17876
17877   const char* init_code =
17878       "var str1 = 'abelspendabel';"
17879       "var str2 = str1 + str1 + str1;"
17880       "str2;";
17881   Local<Value> result = CompileRun(init_code);
17882
17883   Local<Value> indexof = CompileRun("str2.indexOf('els')");
17884   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
17885
17886   CHECK(result->IsString());
17887   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
17888   int length = string->length();
17889   CHECK(string->IsOneByteRepresentation());
17890
17891   FlattenString(string);
17892   i::Handle<i::String> flat_string = FlattenGetString(string);
17893
17894   CHECK(string->IsOneByteRepresentation());
17895   CHECK(flat_string->IsOneByteRepresentation());
17896
17897   // Create external resource.
17898   uint16_t* uc16_buffer = new uint16_t[length + 1];
17899
17900   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
17901   uc16_buffer[length] = 0;
17902
17903   TestResource resource(uc16_buffer);
17904
17905   flat_string->MakeExternal(&resource);
17906
17907   CHECK(flat_string->IsTwoByteRepresentation());
17908
17909   // If the cons string has been short-circuited, skip the following checks.
17910   if (!string.is_identical_to(flat_string)) {
17911     // At this point, we should have a Cons string which is flat and ASCII,
17912     // with a first half that is a two-byte string (although it only contains
17913     // ASCII characters). This is a valid sequence of steps, and it can happen
17914     // in real pages.
17915     CHECK(string->IsOneByteRepresentation());
17916     i::ConsString* cons = i::ConsString::cast(*string);
17917     CHECK_EQ(0, cons->second()->length());
17918     CHECK(cons->first()->IsTwoByteRepresentation());
17919   }
17920
17921   // Check that some string operations work.
17922
17923   // Atom RegExp.
17924   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
17925   CHECK_EQ(6, reresult->Int32Value());
17926
17927   // Nonatom RegExp.
17928   reresult = CompileRun("str2.match(/abe./g).length;");
17929   CHECK_EQ(6, reresult->Int32Value());
17930
17931   reresult = CompileRun("str2.search(/bel/g);");
17932   CHECK_EQ(1, reresult->Int32Value());
17933
17934   reresult = CompileRun("str2.search(/be./g);");
17935   CHECK_EQ(1, reresult->Int32Value());
17936
17937   ExpectTrue("/bel/g.test(str2);");
17938
17939   ExpectTrue("/be./g.test(str2);");
17940
17941   reresult = CompileRun("/bel/g.exec(str2);");
17942   CHECK(!reresult->IsNull());
17943
17944   reresult = CompileRun("/be./g.exec(str2);");
17945   CHECK(!reresult->IsNull());
17946
17947   ExpectString("str2.substring(2, 10);", "elspenda");
17948
17949   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
17950
17951   ExpectString("str2.charAt(2);", "e");
17952
17953   ExpectObject("str2.indexOf('els');", indexof);
17954
17955   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
17956
17957   reresult = CompileRun("str2.charCodeAt(2);");
17958   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
17959 }
17960
17961
17962 TEST(ContainsOnlyOneByte) {
17963   v8::V8::Initialize();
17964   v8::Isolate* isolate = v8::Isolate::GetCurrent();
17965   v8::HandleScope scope(isolate);
17966   // Make a buffer long enough that it won't automatically be converted.
17967   const int length = 512;
17968   // Ensure word aligned assignment.
17969   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
17970   i::SmartArrayPointer<uintptr_t>
17971   aligned_contents(new uintptr_t[aligned_length]);
17972   uint16_t* string_contents = reinterpret_cast<uint16_t*>(*aligned_contents);
17973   // Set to contain only one byte.
17974   for (int i = 0; i < length-1; i++) {
17975     string_contents[i] = 0x41;
17976   }
17977   string_contents[length-1] = 0;
17978   // Simple case.
17979   Handle<String> string;
17980   string = String::NewExternal(new TestResource(string_contents));
17981   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
17982   // Counter example.
17983   string = String::NewFromTwoByte(isolate, string_contents);
17984   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
17985   // Test left right and balanced cons strings.
17986   Handle<String> base = String::NewFromUtf8(isolate, "a");
17987   Handle<String> left = base;
17988   Handle<String> right = base;
17989   for (int i = 0; i < 1000; i++) {
17990     left = String::Concat(base, left);
17991     right = String::Concat(right, base);
17992   }
17993   Handle<String> balanced = String::Concat(left, base);
17994   balanced = String::Concat(balanced, right);
17995   Handle<String> cons_strings[] = {left, balanced, right};
17996   Handle<String> two_byte =
17997       String::NewExternal(new TestResource(string_contents));
17998   for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
17999     // Base assumptions.
18000     string = cons_strings[i];
18001     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18002     // Test left and right concatentation.
18003     string = String::Concat(two_byte, cons_strings[i]);
18004     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18005     string = String::Concat(cons_strings[i], two_byte);
18006     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18007   }
18008   // Set bits in different positions
18009   // for strings of different lengths and alignments.
18010   for (int alignment = 0; alignment < 7; alignment++) {
18011     for (int size = 2; alignment + size < length; size *= 2) {
18012       int zero_offset = size + alignment;
18013       string_contents[zero_offset] = 0;
18014       for (int i = 0; i < size; i++) {
18015         int shift = 8 + (i % 7);
18016         string_contents[alignment + i] = 1 << shift;
18017         string =
18018             String::NewExternal(new TestResource(string_contents + alignment));
18019         CHECK_EQ(size, string->Length());
18020         CHECK(!string->ContainsOnlyOneByte());
18021         string_contents[alignment + i] = 0x41;
18022       }
18023       string_contents[zero_offset] = 0x41;
18024     }
18025   }
18026 }
18027
18028
18029 // Failed access check callback that performs a GC on each invocation.
18030 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
18031                                  v8::AccessType type,
18032                                  Local<v8::Value> data) {
18033   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
18034 }
18035
18036
18037 TEST(GCInFailedAccessCheckCallback) {
18038   // Install a failed access check callback that performs a GC on each
18039   // invocation. Then force the callback to be called from va
18040
18041   v8::V8::Initialize();
18042   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
18043
18044   v8::HandleScope scope(v8::Isolate::GetCurrent());
18045
18046   // Create an ObjectTemplate for global objects and install access
18047   // check callbacks that will block access.
18048   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
18049   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
18050                                            IndexedGetAccessBlocker,
18051                                            v8::Handle<v8::Value>(),
18052                                            false);
18053
18054   // Create a context and set an x property on it's global object.
18055   LocalContext context0(NULL, global_template);
18056   context0->Global()->Set(v8_str("x"), v8_num(42));
18057   v8::Handle<v8::Object> global0 = context0->Global();
18058
18059   // Create a context with a different security token so that the
18060   // failed access check callback will be called on each access.
18061   LocalContext context1(NULL, global_template);
18062   context1->Global()->Set(v8_str("other"), global0);
18063
18064   // Get property with failed access check.
18065   ExpectUndefined("other.x");
18066
18067   // Get element with failed access check.
18068   ExpectUndefined("other[0]");
18069
18070   // Set property with failed access check.
18071   v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
18072   CHECK(result->IsObject());
18073
18074   // Set element with failed access check.
18075   result = CompileRun("other[0] = new Object()");
18076   CHECK(result->IsObject());
18077
18078   // Get property attribute with failed access check.
18079   ExpectFalse("\'x\' in other");
18080
18081   // Get property attribute for element with failed access check.
18082   ExpectFalse("0 in other");
18083
18084   // Delete property.
18085   ExpectFalse("delete other.x");
18086
18087   // Delete element.
18088   CHECK_EQ(false, global0->Delete(0));
18089
18090   // DefineAccessor.
18091   CHECK_EQ(false,
18092            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
18093
18094   // Define JavaScript accessor.
18095   ExpectUndefined("Object.prototype.__defineGetter__.call("
18096                   "    other, \'x\', function() { return 42; })");
18097
18098   // LookupAccessor.
18099   ExpectUndefined("Object.prototype.__lookupGetter__.call("
18100                   "    other, \'x\')");
18101
18102   // HasLocalElement.
18103   ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
18104
18105   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
18106   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
18107   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
18108
18109   // Reset the failed access check callback so it does not influence
18110   // the other tests.
18111   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
18112 }
18113
18114
18115 TEST(DefaultIsolateGetCurrent) {
18116   CHECK(v8::Isolate::GetCurrent() != NULL);
18117   v8::Isolate* isolate = v8::Isolate::GetCurrent();
18118   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
18119   printf("*** %s\n", "DefaultIsolateGetCurrent success");
18120 }
18121
18122
18123 TEST(IsolateNewDispose) {
18124   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
18125   v8::Isolate* isolate = v8::Isolate::New();
18126   CHECK(isolate != NULL);
18127   CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
18128   CHECK(current_isolate != isolate);
18129   CHECK(current_isolate == v8::Isolate::GetCurrent());
18130
18131   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18132   last_location = last_message = NULL;
18133   isolate->Dispose();
18134   CHECK_EQ(last_location, NULL);
18135   CHECK_EQ(last_message, NULL);
18136 }
18137
18138
18139 TEST(IsolateEnterExitDefault) {
18140   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
18141   CHECK(current_isolate != NULL);  // Default isolate.
18142   v8::HandleScope scope(current_isolate);
18143   LocalContext context;
18144   ExpectString("'hello'", "hello");
18145   current_isolate->Enter();
18146   ExpectString("'still working'", "still working");
18147   current_isolate->Exit();
18148   ExpectString("'still working 2'", "still working 2");
18149   current_isolate->Exit();
18150   // Default isolate is always, well, 'default current'.
18151   CHECK_EQ(v8::Isolate::GetCurrent(), current_isolate);
18152   // Still working since default isolate is auto-entering any thread
18153   // that has no isolate and attempts to execute V8 APIs.
18154   ExpectString("'still working 3'", "still working 3");
18155 }
18156
18157
18158 TEST(DisposeDefaultIsolate) {
18159   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18160
18161   // Run some V8 code to trigger default isolate to become 'current'.
18162   v8::HandleScope scope(v8::Isolate::GetCurrent());
18163   LocalContext context;
18164   ExpectString("'run some V8'", "run some V8");
18165
18166   v8::Isolate* isolate = v8::Isolate::GetCurrent();
18167   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
18168   last_location = last_message = NULL;
18169   isolate->Dispose();
18170   // It is not possible to dispose default isolate via Isolate API.
18171   CHECK_NE(last_location, NULL);
18172   CHECK_NE(last_message, NULL);
18173 }
18174
18175
18176 TEST(RunDefaultAndAnotherIsolate) {
18177   v8::HandleScope scope(v8::Isolate::GetCurrent());
18178   LocalContext context;
18179
18180   // Enter new isolate.
18181   v8::Isolate* isolate = v8::Isolate::New();
18182   CHECK(isolate);
18183   isolate->Enter();
18184   { // Need this block because subsequent Exit() will deallocate Heap,
18185     // so we need all scope objects to be deconstructed when it happens.
18186     v8::HandleScope scope_new(isolate);
18187     LocalContext context_new;
18188
18189     // Run something in new isolate.
18190     CompileRun("var foo = 153;");
18191     ExpectTrue("function f() { return foo == 153; }; f()");
18192   }
18193   isolate->Exit();
18194
18195   // This runs automatically in default isolate.
18196   // Variables in another isolate should be not available.
18197   ExpectTrue("function f() {"
18198              "  try {"
18199              "    foo;"
18200              "    return false;"
18201              "  } catch(e) {"
18202              "    return true;"
18203              "  }"
18204              "};"
18205              "var bar = 371;"
18206              "f()");
18207
18208   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18209   last_location = last_message = NULL;
18210   isolate->Dispose();
18211   CHECK_EQ(last_location, NULL);
18212   CHECK_EQ(last_message, NULL);
18213
18214   // Check that default isolate still runs.
18215   ExpectTrue("function f() { return bar == 371; }; f()");
18216 }
18217
18218
18219 TEST(DisposeIsolateWhenInUse) {
18220   v8::Isolate* isolate = v8::Isolate::New();
18221   CHECK(isolate);
18222   isolate->Enter();
18223   v8::HandleScope scope(isolate);
18224   LocalContext context;
18225   // Run something in this isolate.
18226   ExpectTrue("true");
18227   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18228   last_location = last_message = NULL;
18229   // Still entered, should fail.
18230   isolate->Dispose();
18231   CHECK_NE(last_location, NULL);
18232   CHECK_NE(last_message, NULL);
18233 }
18234
18235
18236 TEST(RunTwoIsolatesOnSingleThread) {
18237   // Run isolate 1.
18238   v8::Isolate* isolate1 = v8::Isolate::New();
18239   isolate1->Enter();
18240   v8::Persistent<v8::Context> context1;
18241   {
18242     v8::HandleScope scope(isolate1);
18243     context1.Reset(isolate1, Context::New(isolate1));
18244   }
18245
18246   {
18247     v8::HandleScope scope(isolate1);
18248     v8::Local<v8::Context> context =
18249         v8::Local<v8::Context>::New(isolate1, context1);
18250     v8::Context::Scope context_scope(context);
18251     // Run something in new isolate.
18252     CompileRun("var foo = 'isolate 1';");
18253     ExpectString("function f() { return foo; }; f()", "isolate 1");
18254   }
18255
18256   // Run isolate 2.
18257   v8::Isolate* isolate2 = v8::Isolate::New();
18258   v8::Persistent<v8::Context> context2;
18259
18260   {
18261     v8::Isolate::Scope iscope(isolate2);
18262     v8::HandleScope scope(isolate2);
18263     context2.Reset(isolate2, Context::New(isolate2));
18264     v8::Local<v8::Context> context =
18265         v8::Local<v8::Context>::New(isolate2, context2);
18266     v8::Context::Scope context_scope(context);
18267
18268     // Run something in new isolate.
18269     CompileRun("var foo = 'isolate 2';");
18270     ExpectString("function f() { return foo; }; f()", "isolate 2");
18271   }
18272
18273   {
18274     v8::HandleScope scope(isolate1);
18275     v8::Local<v8::Context> context =
18276         v8::Local<v8::Context>::New(isolate1, context1);
18277     v8::Context::Scope context_scope(context);
18278     // Now again in isolate 1
18279     ExpectString("function f() { return foo; }; f()", "isolate 1");
18280   }
18281
18282   isolate1->Exit();
18283
18284   // Run some stuff in default isolate.
18285   v8::Persistent<v8::Context> context_default;
18286   {
18287     v8::Isolate* isolate = v8::Isolate::GetCurrent();
18288     v8::Isolate::Scope iscope(isolate);
18289     v8::HandleScope scope(isolate);
18290     context_default.Reset(isolate, Context::New(isolate));
18291   }
18292
18293   {
18294     v8::HandleScope scope(v8::Isolate::GetCurrent());
18295     v8::Local<v8::Context> context =
18296         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context_default);
18297     v8::Context::Scope context_scope(context);
18298     // Variables in other isolates should be not available, verify there
18299     // is an exception.
18300     ExpectTrue("function f() {"
18301                "  try {"
18302                "    foo;"
18303                "    return false;"
18304                "  } catch(e) {"
18305                "    return true;"
18306                "  }"
18307                "};"
18308                "var isDefaultIsolate = true;"
18309                "f()");
18310   }
18311
18312   isolate1->Enter();
18313
18314   {
18315     v8::Isolate::Scope iscope(isolate2);
18316     v8::HandleScope scope(v8::Isolate::GetCurrent());
18317     v8::Local<v8::Context> context =
18318         v8::Local<v8::Context>::New(isolate2, context2);
18319     v8::Context::Scope context_scope(context);
18320     ExpectString("function f() { return foo; }; f()", "isolate 2");
18321   }
18322
18323   {
18324     v8::HandleScope scope(v8::Isolate::GetCurrent());
18325     v8::Local<v8::Context> context =
18326         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
18327     v8::Context::Scope context_scope(context);
18328     ExpectString("function f() { return foo; }; f()", "isolate 1");
18329   }
18330
18331   {
18332     v8::Isolate::Scope iscope(isolate2);
18333     context2.Dispose();
18334   }
18335
18336   context1.Dispose();
18337   isolate1->Exit();
18338
18339   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18340   last_location = last_message = NULL;
18341
18342   isolate1->Dispose();
18343   CHECK_EQ(last_location, NULL);
18344   CHECK_EQ(last_message, NULL);
18345
18346   isolate2->Dispose();
18347   CHECK_EQ(last_location, NULL);
18348   CHECK_EQ(last_message, NULL);
18349
18350   // Check that default isolate still runs.
18351   {
18352     v8::HandleScope scope(v8::Isolate::GetCurrent());
18353     v8::Local<v8::Context> context =
18354         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context_default);
18355     v8::Context::Scope context_scope(context);
18356     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
18357   }
18358 }
18359
18360
18361 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
18362   v8::Isolate::Scope isolate_scope(isolate);
18363   v8::HandleScope scope(isolate);
18364   LocalContext context;
18365   i::ScopedVector<char> code(1024);
18366   i::OS::SNPrintF(code, "function fib(n) {"
18367                         "  if (n <= 2) return 1;"
18368                         "  return fib(n-1) + fib(n-2);"
18369                         "}"
18370                         "fib(%d)", limit);
18371   Local<Value> value = CompileRun(code.start());
18372   CHECK(value->IsNumber());
18373   return static_cast<int>(value->NumberValue());
18374 }
18375
18376 class IsolateThread : public v8::internal::Thread {
18377  public:
18378   IsolateThread(v8::Isolate* isolate, int fib_limit)
18379       : Thread("IsolateThread"),
18380         isolate_(isolate),
18381         fib_limit_(fib_limit),
18382         result_(0) { }
18383
18384   void Run() {
18385     result_ = CalcFibonacci(isolate_, fib_limit_);
18386   }
18387
18388   int result() { return result_; }
18389
18390  private:
18391   v8::Isolate* isolate_;
18392   int fib_limit_;
18393   int result_;
18394 };
18395
18396
18397 TEST(MultipleIsolatesOnIndividualThreads) {
18398   v8::Isolate* isolate1 = v8::Isolate::New();
18399   v8::Isolate* isolate2 = v8::Isolate::New();
18400
18401   IsolateThread thread1(isolate1, 21);
18402   IsolateThread thread2(isolate2, 12);
18403
18404   // Compute some fibonacci numbers on 3 threads in 3 isolates.
18405   thread1.Start();
18406   thread2.Start();
18407
18408   int result1 = CalcFibonacci(v8::Isolate::GetCurrent(), 21);
18409   int result2 = CalcFibonacci(v8::Isolate::GetCurrent(), 12);
18410
18411   thread1.Join();
18412   thread2.Join();
18413
18414   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
18415   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
18416   CHECK_EQ(result1, 10946);
18417   CHECK_EQ(result2, 144);
18418   CHECK_EQ(result1, thread1.result());
18419   CHECK_EQ(result2, thread2.result());
18420
18421   isolate1->Dispose();
18422   isolate2->Dispose();
18423 }
18424
18425
18426 TEST(IsolateDifferentContexts) {
18427   v8::Isolate* isolate = v8::Isolate::New();
18428   Local<v8::Context> context;
18429   {
18430     v8::Isolate::Scope isolate_scope(isolate);
18431     v8::HandleScope handle_scope(isolate);
18432     context = v8::Context::New(isolate);
18433     v8::Context::Scope context_scope(context);
18434     Local<Value> v = CompileRun("2");
18435     CHECK(v->IsNumber());
18436     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
18437   }
18438   {
18439     v8::Isolate::Scope isolate_scope(isolate);
18440     v8::HandleScope handle_scope(isolate);
18441     context = v8::Context::New(isolate);
18442     v8::Context::Scope context_scope(context);
18443     Local<Value> v = CompileRun("22");
18444     CHECK(v->IsNumber());
18445     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
18446   }
18447 }
18448
18449 class InitDefaultIsolateThread : public v8::internal::Thread {
18450  public:
18451   enum TestCase {
18452     IgnoreOOM,
18453     SetResourceConstraints,
18454     SetFatalHandler,
18455     SetCounterFunction,
18456     SetCreateHistogramFunction,
18457     SetAddHistogramSampleFunction
18458   };
18459
18460   explicit InitDefaultIsolateThread(TestCase testCase)
18461       : Thread("InitDefaultIsolateThread"),
18462         testCase_(testCase),
18463         result_(false) { }
18464
18465   void Run() {
18466     switch (testCase_) {
18467     case IgnoreOOM:
18468       v8::V8::IgnoreOutOfMemoryException();
18469       break;
18470
18471     case SetResourceConstraints: {
18472       static const int K = 1024;
18473       v8::ResourceConstraints constraints;
18474       constraints.set_max_young_space_size(256 * K);
18475       constraints.set_max_old_space_size(4 * K * K);
18476       v8::SetResourceConstraints(&constraints);
18477       break;
18478     }
18479
18480     case SetFatalHandler:
18481       v8::V8::SetFatalErrorHandler(NULL);
18482       break;
18483
18484     case SetCounterFunction:
18485       v8::V8::SetCounterFunction(NULL);
18486       break;
18487
18488     case SetCreateHistogramFunction:
18489       v8::V8::SetCreateHistogramFunction(NULL);
18490       break;
18491
18492     case SetAddHistogramSampleFunction:
18493       v8::V8::SetAddHistogramSampleFunction(NULL);
18494       break;
18495     }
18496     result_ = true;
18497   }
18498
18499   bool result() { return result_; }
18500
18501  private:
18502   TestCase testCase_;
18503   bool result_;
18504 };
18505
18506
18507 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
18508   InitDefaultIsolateThread thread(testCase);
18509   thread.Start();
18510   thread.Join();
18511   CHECK_EQ(thread.result(), true);
18512 }
18513
18514
18515 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
18516   InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
18517 }
18518
18519
18520 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
18521   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
18522 }
18523
18524
18525 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
18526   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
18527 }
18528
18529
18530 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
18531   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
18532 }
18533
18534
18535 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
18536   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
18537 }
18538
18539
18540 TEST(InitializeDefaultIsolateOnSecondaryThread6) {
18541   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
18542 }
18543
18544
18545 TEST(StringCheckMultipleContexts) {
18546   const char* code =
18547       "(function() { return \"a\".charAt(0); })()";
18548
18549   {
18550     // Run the code twice in the first context to initialize the call IC.
18551     LocalContext context1;
18552     v8::HandleScope scope(context1->GetIsolate());
18553     ExpectString(code, "a");
18554     ExpectString(code, "a");
18555   }
18556
18557   {
18558     // Change the String.prototype in the second context and check
18559     // that the right function gets called.
18560     LocalContext context2;
18561     v8::HandleScope scope(context2->GetIsolate());
18562     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
18563     ExpectString(code, "not a");
18564   }
18565 }
18566
18567
18568 TEST(NumberCheckMultipleContexts) {
18569   const char* code =
18570       "(function() { return (42).toString(); })()";
18571
18572   {
18573     // Run the code twice in the first context to initialize the call IC.
18574     LocalContext context1;
18575     v8::HandleScope scope(context1->GetIsolate());
18576     ExpectString(code, "42");
18577     ExpectString(code, "42");
18578   }
18579
18580   {
18581     // Change the Number.prototype in the second context and check
18582     // that the right function gets called.
18583     LocalContext context2;
18584     v8::HandleScope scope(context2->GetIsolate());
18585     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
18586     ExpectString(code, "not 42");
18587   }
18588 }
18589
18590
18591 TEST(BooleanCheckMultipleContexts) {
18592   const char* code =
18593       "(function() { return true.toString(); })()";
18594
18595   {
18596     // Run the code twice in the first context to initialize the call IC.
18597     LocalContext context1;
18598     v8::HandleScope scope(context1->GetIsolate());
18599     ExpectString(code, "true");
18600     ExpectString(code, "true");
18601   }
18602
18603   {
18604     // Change the Boolean.prototype in the second context and check
18605     // that the right function gets called.
18606     LocalContext context2;
18607     v8::HandleScope scope(context2->GetIsolate());
18608     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
18609     ExpectString(code, "");
18610   }
18611 }
18612
18613
18614 TEST(DontDeleteCellLoadIC) {
18615   const char* function_code =
18616       "function readCell() { while (true) { return cell; } }";
18617
18618   {
18619     // Run the code twice in the first context to initialize the load
18620     // IC for a don't delete cell.
18621     LocalContext context1;
18622     v8::HandleScope scope(context1->GetIsolate());
18623     CompileRun("var cell = \"first\";");
18624     ExpectBoolean("delete cell", false);
18625     CompileRun(function_code);
18626     ExpectString("readCell()", "first");
18627     ExpectString("readCell()", "first");
18628   }
18629
18630   {
18631     // Use a deletable cell in the second context.
18632     LocalContext context2;
18633     v8::HandleScope scope(context2->GetIsolate());
18634     CompileRun("cell = \"second\";");
18635     CompileRun(function_code);
18636     ExpectString("readCell()", "second");
18637     ExpectBoolean("delete cell", true);
18638     ExpectString("(function() {"
18639                  "  try {"
18640                  "    return readCell();"
18641                  "  } catch(e) {"
18642                  "    return e.toString();"
18643                  "  }"
18644                  "})()",
18645                  "ReferenceError: cell is not defined");
18646     CompileRun("cell = \"new_second\";");
18647     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
18648     ExpectString("readCell()", "new_second");
18649     ExpectString("readCell()", "new_second");
18650   }
18651 }
18652
18653
18654 TEST(DontDeleteCellLoadICForceDelete) {
18655   const char* function_code =
18656       "function readCell() { while (true) { return cell; } }";
18657
18658   // Run the code twice to initialize the load IC for a don't delete
18659   // cell.
18660   LocalContext context;
18661   v8::HandleScope scope(context->GetIsolate());
18662   CompileRun("var cell = \"value\";");
18663   ExpectBoolean("delete cell", false);
18664   CompileRun(function_code);
18665   ExpectString("readCell()", "value");
18666   ExpectString("readCell()", "value");
18667
18668   // Delete the cell using the API and check the inlined code works
18669   // correctly.
18670   CHECK(context->Global()->ForceDelete(v8_str("cell")));
18671   ExpectString("(function() {"
18672                "  try {"
18673                "    return readCell();"
18674                "  } catch(e) {"
18675                "    return e.toString();"
18676                "  }"
18677                "})()",
18678                "ReferenceError: cell is not defined");
18679 }
18680
18681
18682 TEST(DontDeleteCellLoadICAPI) {
18683   const char* function_code =
18684       "function readCell() { while (true) { return cell; } }";
18685
18686   // Run the code twice to initialize the load IC for a don't delete
18687   // cell created using the API.
18688   LocalContext context;
18689   v8::HandleScope scope(context->GetIsolate());
18690   context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
18691   ExpectBoolean("delete cell", false);
18692   CompileRun(function_code);
18693   ExpectString("readCell()", "value");
18694   ExpectString("readCell()", "value");
18695
18696   // Delete the cell using the API and check the inlined code works
18697   // correctly.
18698   CHECK(context->Global()->ForceDelete(v8_str("cell")));
18699   ExpectString("(function() {"
18700                "  try {"
18701                "    return readCell();"
18702                "  } catch(e) {"
18703                "    return e.toString();"
18704                "  }"
18705                "})()",
18706                "ReferenceError: cell is not defined");
18707 }
18708
18709
18710 class Visitor42 : public v8::PersistentHandleVisitor {
18711  public:
18712   explicit Visitor42(v8::Persistent<v8::Object>* object)
18713       : counter_(0), object_(object) { }
18714
18715   virtual void VisitPersistentHandle(Persistent<Value>* value,
18716                                      uint16_t class_id) {
18717     if (class_id != 42) return;
18718     CHECK_EQ(42, value->WrapperClassId());
18719     v8::Isolate* isolate = v8::Isolate::GetCurrent();
18720     v8::HandleScope handle_scope(isolate);
18721     v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
18722     v8::Handle<v8::Value> object =
18723         v8::Local<v8::Object>::New(isolate, *object_);
18724     CHECK(handle->IsObject());
18725     CHECK_EQ(Handle<Object>::Cast(handle), object);
18726     ++counter_;
18727   }
18728
18729   int counter_;
18730   v8::Persistent<v8::Object>* object_;
18731 };
18732
18733
18734 TEST(PersistentHandleVisitor) {
18735   LocalContext context;
18736   v8::Isolate* isolate = context->GetIsolate();
18737   v8::HandleScope scope(isolate);
18738   v8::Persistent<v8::Object> object(isolate, v8::Object::New());
18739   CHECK_EQ(0, object.WrapperClassId());
18740   object.SetWrapperClassId(42);
18741   CHECK_EQ(42, object.WrapperClassId());
18742
18743   Visitor42 visitor(&object);
18744   v8::V8::VisitHandlesWithClassIds(&visitor);
18745   CHECK_EQ(1, visitor.counter_);
18746
18747   object.Dispose();
18748 }
18749
18750
18751 TEST(WrapperClassId) {
18752   LocalContext context;
18753   v8::Isolate* isolate = context->GetIsolate();
18754   v8::HandleScope scope(isolate);
18755   v8::Persistent<v8::Object> object(isolate, v8::Object::New());
18756   CHECK_EQ(0, object.WrapperClassId());
18757   object.SetWrapperClassId(65535);
18758   CHECK_EQ(65535, object.WrapperClassId());
18759   object.Dispose();
18760 }
18761
18762
18763 TEST(PersistentHandleInNewSpaceVisitor) {
18764   LocalContext context;
18765   v8::Isolate* isolate = context->GetIsolate();
18766   v8::HandleScope scope(isolate);
18767   v8::Persistent<v8::Object> object1(isolate, v8::Object::New());
18768   CHECK_EQ(0, object1.WrapperClassId());
18769   object1.SetWrapperClassId(42);
18770   CHECK_EQ(42, object1.WrapperClassId());
18771
18772   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
18773
18774   v8::Persistent<v8::Object> object2(isolate, v8::Object::New());
18775   CHECK_EQ(0, object2.WrapperClassId());
18776   object2.SetWrapperClassId(42);
18777   CHECK_EQ(42, object2.WrapperClassId());
18778
18779   Visitor42 visitor(&object2);
18780   v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
18781   CHECK_EQ(1, visitor.counter_);
18782
18783   object1.Dispose();
18784   object2.Dispose();
18785 }
18786
18787
18788 TEST(RegExp) {
18789   LocalContext context;
18790   v8::HandleScope scope(context->GetIsolate());
18791
18792   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
18793   CHECK(re->IsRegExp());
18794   CHECK(re->GetSource()->Equals(v8_str("foo")));
18795   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
18796
18797   re = v8::RegExp::New(v8_str("bar"),
18798                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18799                                                       v8::RegExp::kGlobal));
18800   CHECK(re->IsRegExp());
18801   CHECK(re->GetSource()->Equals(v8_str("bar")));
18802   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
18803            static_cast<int>(re->GetFlags()));
18804
18805   re = v8::RegExp::New(v8_str("baz"),
18806                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18807                                                       v8::RegExp::kMultiline));
18808   CHECK(re->IsRegExp());
18809   CHECK(re->GetSource()->Equals(v8_str("baz")));
18810   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
18811            static_cast<int>(re->GetFlags()));
18812
18813   re = CompileRun("/quux/").As<v8::RegExp>();
18814   CHECK(re->IsRegExp());
18815   CHECK(re->GetSource()->Equals(v8_str("quux")));
18816   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
18817
18818   re = CompileRun("/quux/gm").As<v8::RegExp>();
18819   CHECK(re->IsRegExp());
18820   CHECK(re->GetSource()->Equals(v8_str("quux")));
18821   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
18822            static_cast<int>(re->GetFlags()));
18823
18824   // Override the RegExp constructor and check the API constructor
18825   // still works.
18826   CompileRun("RegExp = function() {}");
18827
18828   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
18829   CHECK(re->IsRegExp());
18830   CHECK(re->GetSource()->Equals(v8_str("foobar")));
18831   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
18832
18833   re = v8::RegExp::New(v8_str("foobarbaz"),
18834                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18835                                                       v8::RegExp::kMultiline));
18836   CHECK(re->IsRegExp());
18837   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
18838   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
18839            static_cast<int>(re->GetFlags()));
18840
18841   context->Global()->Set(v8_str("re"), re);
18842   ExpectTrue("re.test('FoobarbaZ')");
18843
18844   // RegExps are objects on which you can set properties.
18845   re->Set(v8_str("property"), v8::Integer::New(32));
18846   v8::Handle<v8::Value> value(CompileRun("re.property"));
18847   CHECK_EQ(32, value->Int32Value());
18848
18849   v8::TryCatch try_catch;
18850   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
18851   CHECK(re.IsEmpty());
18852   CHECK(try_catch.HasCaught());
18853   context->Global()->Set(v8_str("ex"), try_catch.Exception());
18854   ExpectTrue("ex instanceof SyntaxError");
18855 }
18856
18857
18858 THREADED_TEST(Equals) {
18859   LocalContext localContext;
18860   v8::HandleScope handleScope(localContext->GetIsolate());
18861
18862   v8::Handle<v8::Object> globalProxy = localContext->Global();
18863   v8::Handle<Value> global = globalProxy->GetPrototype();
18864
18865   CHECK(global->StrictEquals(global));
18866   CHECK(!global->StrictEquals(globalProxy));
18867   CHECK(!globalProxy->StrictEquals(global));
18868   CHECK(globalProxy->StrictEquals(globalProxy));
18869
18870   CHECK(global->Equals(global));
18871   CHECK(!global->Equals(globalProxy));
18872   CHECK(!globalProxy->Equals(global));
18873   CHECK(globalProxy->Equals(globalProxy));
18874 }
18875
18876
18877 static void Getter(v8::Local<v8::String> property,
18878                    const v8::PropertyCallbackInfo<v8::Value>& info ) {
18879   info.GetReturnValue().Set(v8_str("42!"));
18880 }
18881
18882
18883 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
18884   v8::Handle<v8::Array> result = v8::Array::New();
18885   result->Set(0, v8_str("universalAnswer"));
18886   info.GetReturnValue().Set(result);
18887 }
18888
18889
18890 TEST(NamedEnumeratorAndForIn) {
18891   LocalContext context;
18892   v8::HandleScope handle_scope(context->GetIsolate());
18893   v8::Context::Scope context_scope(context.local());
18894
18895   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
18896   tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
18897   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
18898   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
18899         "var result = []; for (var k in o) result.push(k); result"));
18900   CHECK_EQ(1, result->Length());
18901   CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
18902 }
18903
18904
18905 TEST(DefinePropertyPostDetach) {
18906   LocalContext context;
18907   v8::HandleScope scope(context->GetIsolate());
18908   v8::Handle<v8::Object> proxy = context->Global();
18909   v8::Handle<v8::Function> define_property =
18910       CompileRun("(function() {"
18911                  "  Object.defineProperty("
18912                  "    this,"
18913                  "    1,"
18914                  "    { configurable: true, enumerable: true, value: 3 });"
18915                  "})").As<Function>();
18916   context->DetachGlobal();
18917   define_property->Call(proxy, 0, NULL);
18918 }
18919
18920
18921 static void InstallContextId(v8::Handle<Context> context, int id) {
18922   Context::Scope scope(context);
18923   CompileRun("Object.prototype").As<Object>()->
18924       Set(v8_str("context_id"), v8::Integer::New(id));
18925 }
18926
18927
18928 static void CheckContextId(v8::Handle<Object> object, int expected) {
18929   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
18930 }
18931
18932
18933 THREADED_TEST(CreationContext) {
18934   HandleScope handle_scope(v8::Isolate::GetCurrent());
18935   Handle<Context> context1 = Context::New(v8::Isolate::GetCurrent());
18936   InstallContextId(context1, 1);
18937   Handle<Context> context2 = Context::New(v8::Isolate::GetCurrent());
18938   InstallContextId(context2, 2);
18939   Handle<Context> context3 = Context::New(v8::Isolate::GetCurrent());
18940   InstallContextId(context3, 3);
18941
18942   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
18943
18944   Local<Object> object1;
18945   Local<Function> func1;
18946   {
18947     Context::Scope scope(context1);
18948     object1 = Object::New();
18949     func1 = tmpl->GetFunction();
18950   }
18951
18952   Local<Object> object2;
18953   Local<Function> func2;
18954   {
18955     Context::Scope scope(context2);
18956     object2 = Object::New();
18957     func2 = tmpl->GetFunction();
18958   }
18959
18960   Local<Object> instance1;
18961   Local<Object> instance2;
18962
18963   {
18964     Context::Scope scope(context3);
18965     instance1 = func1->NewInstance();
18966     instance2 = func2->NewInstance();
18967   }
18968
18969   CHECK(object1->CreationContext() == context1);
18970   CheckContextId(object1, 1);
18971   CHECK(func1->CreationContext() == context1);
18972   CheckContextId(func1, 1);
18973   CHECK(instance1->CreationContext() == context1);
18974   CheckContextId(instance1, 1);
18975   CHECK(object2->CreationContext() == context2);
18976   CheckContextId(object2, 2);
18977   CHECK(func2->CreationContext() == context2);
18978   CheckContextId(func2, 2);
18979   CHECK(instance2->CreationContext() == context2);
18980   CheckContextId(instance2, 2);
18981
18982   {
18983     Context::Scope scope(context1);
18984     CHECK(object1->CreationContext() == context1);
18985     CheckContextId(object1, 1);
18986     CHECK(func1->CreationContext() == context1);
18987     CheckContextId(func1, 1);
18988     CHECK(instance1->CreationContext() == context1);
18989     CheckContextId(instance1, 1);
18990     CHECK(object2->CreationContext() == context2);
18991     CheckContextId(object2, 2);
18992     CHECK(func2->CreationContext() == context2);
18993     CheckContextId(func2, 2);
18994     CHECK(instance2->CreationContext() == context2);
18995     CheckContextId(instance2, 2);
18996   }
18997
18998   {
18999     Context::Scope scope(context2);
19000     CHECK(object1->CreationContext() == context1);
19001     CheckContextId(object1, 1);
19002     CHECK(func1->CreationContext() == context1);
19003     CheckContextId(func1, 1);
19004     CHECK(instance1->CreationContext() == context1);
19005     CheckContextId(instance1, 1);
19006     CHECK(object2->CreationContext() == context2);
19007     CheckContextId(object2, 2);
19008     CHECK(func2->CreationContext() == context2);
19009     CheckContextId(func2, 2);
19010     CHECK(instance2->CreationContext() == context2);
19011     CheckContextId(instance2, 2);
19012   }
19013 }
19014
19015
19016 THREADED_TEST(CreationContextOfJsFunction) {
19017   HandleScope handle_scope(v8::Isolate::GetCurrent());
19018   Handle<Context> context = Context::New(v8::Isolate::GetCurrent());
19019   InstallContextId(context, 1);
19020
19021   Local<Object> function;
19022   {
19023     Context::Scope scope(context);
19024     function = CompileRun("function foo() {}; foo").As<Object>();
19025   }
19026
19027   CHECK(function->CreationContext() == context);
19028   CheckContextId(function, 1);
19029 }
19030
19031
19032 void HasOwnPropertyIndexedPropertyGetter(
19033     uint32_t index,
19034     const v8::PropertyCallbackInfo<v8::Value>& info) {
19035   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
19036 }
19037
19038
19039 void HasOwnPropertyNamedPropertyGetter(
19040     Local<String> property,
19041     const v8::PropertyCallbackInfo<v8::Value>& info) {
19042   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
19043 }
19044
19045
19046 void HasOwnPropertyIndexedPropertyQuery(
19047     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19048   if (index == 42) info.GetReturnValue().Set(1);
19049 }
19050
19051
19052 void HasOwnPropertyNamedPropertyQuery(
19053     Local<String> property,
19054     const v8::PropertyCallbackInfo<v8::Integer>& info) {
19055   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
19056 }
19057
19058
19059 void HasOwnPropertyNamedPropertyQuery2(
19060     Local<String> property,
19061     const v8::PropertyCallbackInfo<v8::Integer>& info) {
19062   if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
19063 }
19064
19065
19066 void HasOwnPropertyAccessorGetter(
19067     Local<String> property,
19068     const v8::PropertyCallbackInfo<v8::Value>& info) {
19069   info.GetReturnValue().Set(v8_str("yes"));
19070 }
19071
19072
19073 TEST(HasOwnProperty) {
19074   LocalContext env;
19075   v8::HandleScope scope(env->GetIsolate());
19076   { // Check normal properties and defined getters.
19077     Handle<Value> value = CompileRun(
19078         "function Foo() {"
19079         "    this.foo = 11;"
19080         "    this.__defineGetter__('baz', function() { return 1; });"
19081         "};"
19082         "function Bar() { "
19083         "    this.bar = 13;"
19084         "    this.__defineGetter__('bla', function() { return 2; });"
19085         "};"
19086         "Bar.prototype = new Foo();"
19087         "new Bar();");
19088     CHECK(value->IsObject());
19089     Handle<Object> object = value->ToObject();
19090     CHECK(object->Has(v8_str("foo")));
19091     CHECK(!object->HasOwnProperty(v8_str("foo")));
19092     CHECK(object->HasOwnProperty(v8_str("bar")));
19093     CHECK(object->Has(v8_str("baz")));
19094     CHECK(!object->HasOwnProperty(v8_str("baz")));
19095     CHECK(object->HasOwnProperty(v8_str("bla")));
19096   }
19097   { // Check named getter interceptors.
19098     Handle<ObjectTemplate> templ = ObjectTemplate::New();
19099     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
19100     Handle<Object> instance = templ->NewInstance();
19101     CHECK(!instance->HasOwnProperty(v8_str("42")));
19102     CHECK(instance->HasOwnProperty(v8_str("foo")));
19103     CHECK(!instance->HasOwnProperty(v8_str("bar")));
19104   }
19105   { // Check indexed getter interceptors.
19106     Handle<ObjectTemplate> templ = ObjectTemplate::New();
19107     templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
19108     Handle<Object> instance = templ->NewInstance();
19109     CHECK(instance->HasOwnProperty(v8_str("42")));
19110     CHECK(!instance->HasOwnProperty(v8_str("43")));
19111     CHECK(!instance->HasOwnProperty(v8_str("foo")));
19112   }
19113   { // Check named query interceptors.
19114     Handle<ObjectTemplate> templ = ObjectTemplate::New();
19115     templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
19116     Handle<Object> instance = templ->NewInstance();
19117     CHECK(instance->HasOwnProperty(v8_str("foo")));
19118     CHECK(!instance->HasOwnProperty(v8_str("bar")));
19119   }
19120   { // Check indexed query interceptors.
19121     Handle<ObjectTemplate> templ = ObjectTemplate::New();
19122     templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
19123     Handle<Object> instance = templ->NewInstance();
19124     CHECK(instance->HasOwnProperty(v8_str("42")));
19125     CHECK(!instance->HasOwnProperty(v8_str("41")));
19126   }
19127   { // Check callbacks.
19128     Handle<ObjectTemplate> templ = ObjectTemplate::New();
19129     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
19130     Handle<Object> instance = templ->NewInstance();
19131     CHECK(instance->HasOwnProperty(v8_str("foo")));
19132     CHECK(!instance->HasOwnProperty(v8_str("bar")));
19133   }
19134   { // Check that query wins on disagreement.
19135     Handle<ObjectTemplate> templ = ObjectTemplate::New();
19136     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
19137                                    0,
19138                                    HasOwnPropertyNamedPropertyQuery2);
19139     Handle<Object> instance = templ->NewInstance();
19140     CHECK(!instance->HasOwnProperty(v8_str("foo")));
19141     CHECK(instance->HasOwnProperty(v8_str("bar")));
19142   }
19143 }
19144
19145
19146 TEST(IndexedInterceptorWithStringProto) {
19147   v8::HandleScope scope(v8::Isolate::GetCurrent());
19148   Handle<ObjectTemplate> templ = ObjectTemplate::New();
19149   templ->SetIndexedPropertyHandler(NULL,
19150                                    NULL,
19151                                    HasOwnPropertyIndexedPropertyQuery);
19152   LocalContext context;
19153   context->Global()->Set(v8_str("obj"), templ->NewInstance());
19154   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
19155   // These should be intercepted.
19156   CHECK(CompileRun("42 in obj")->BooleanValue());
19157   CHECK(CompileRun("'42' in obj")->BooleanValue());
19158   // These should fall through to the String prototype.
19159   CHECK(CompileRun("0 in obj")->BooleanValue());
19160   CHECK(CompileRun("'0' in obj")->BooleanValue());
19161   // And these should both fail.
19162   CHECK(!CompileRun("32 in obj")->BooleanValue());
19163   CHECK(!CompileRun("'32' in obj")->BooleanValue());
19164 }
19165
19166
19167 void CheckCodeGenerationAllowed() {
19168   Handle<Value> result = CompileRun("eval('42')");
19169   CHECK_EQ(42, result->Int32Value());
19170   result = CompileRun("(function(e) { return e('42'); })(eval)");
19171   CHECK_EQ(42, result->Int32Value());
19172   result = CompileRun("var f = new Function('return 42'); f()");
19173   CHECK_EQ(42, result->Int32Value());
19174 }
19175
19176
19177 void CheckCodeGenerationDisallowed() {
19178   TryCatch try_catch;
19179
19180   Handle<Value> result = CompileRun("eval('42')");
19181   CHECK(result.IsEmpty());
19182   CHECK(try_catch.HasCaught());
19183   try_catch.Reset();
19184
19185   result = CompileRun("(function(e) { return e('42'); })(eval)");
19186   CHECK(result.IsEmpty());
19187   CHECK(try_catch.HasCaught());
19188   try_catch.Reset();
19189
19190   result = CompileRun("var f = new Function('return 42'); f()");
19191   CHECK(result.IsEmpty());
19192   CHECK(try_catch.HasCaught());
19193 }
19194
19195
19196 bool CodeGenerationAllowed(Local<Context> context) {
19197   ApiTestFuzzer::Fuzz();
19198   return true;
19199 }
19200
19201
19202 bool CodeGenerationDisallowed(Local<Context> context) {
19203   ApiTestFuzzer::Fuzz();
19204   return false;
19205 }
19206
19207
19208 THREADED_TEST(AllowCodeGenFromStrings) {
19209   LocalContext context;
19210   v8::HandleScope scope(context->GetIsolate());
19211
19212   // eval and the Function constructor allowed by default.
19213   CHECK(context->IsCodeGenerationFromStringsAllowed());
19214   CheckCodeGenerationAllowed();
19215
19216   // Disallow eval and the Function constructor.
19217   context->AllowCodeGenerationFromStrings(false);
19218   CHECK(!context->IsCodeGenerationFromStringsAllowed());
19219   CheckCodeGenerationDisallowed();
19220
19221   // Allow again.
19222   context->AllowCodeGenerationFromStrings(true);
19223   CheckCodeGenerationAllowed();
19224
19225   // Disallow but setting a global callback that will allow the calls.
19226   context->AllowCodeGenerationFromStrings(false);
19227   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
19228   CHECK(!context->IsCodeGenerationFromStringsAllowed());
19229   CheckCodeGenerationAllowed();
19230
19231   // Set a callback that disallows the code generation.
19232   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
19233   CHECK(!context->IsCodeGenerationFromStringsAllowed());
19234   CheckCodeGenerationDisallowed();
19235 }
19236
19237
19238 TEST(SetErrorMessageForCodeGenFromStrings) {
19239   LocalContext context;
19240   v8::HandleScope scope(context->GetIsolate());
19241   TryCatch try_catch;
19242
19243   Handle<String> message = v8_str("Message") ;
19244   Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
19245   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
19246   context->AllowCodeGenerationFromStrings(false);
19247   context->SetErrorMessageForCodeGenerationFromStrings(message);
19248   Handle<Value> result = CompileRun("eval('42')");
19249   CHECK(result.IsEmpty());
19250   CHECK(try_catch.HasCaught());
19251   Handle<String> actual_message = try_catch.Message()->Get();
19252   CHECK(expected_message->Equals(actual_message));
19253 }
19254
19255
19256 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
19257 }
19258
19259
19260 THREADED_TEST(CallAPIFunctionOnNonObject) {
19261   LocalContext context;
19262   v8::HandleScope scope(context->GetIsolate());
19263   Handle<FunctionTemplate> templ = v8::FunctionTemplate::New(NonObjectThis);
19264   Handle<Function> function = templ->GetFunction();
19265   context->Global()->Set(v8_str("f"), function);
19266   TryCatch try_catch;
19267   CompileRun("f.call(2)");
19268 }
19269
19270
19271 // Regression test for issue 1470.
19272 THREADED_TEST(ReadOnlyIndexedProperties) {
19273   v8::HandleScope scope(v8::Isolate::GetCurrent());
19274   Local<ObjectTemplate> templ = ObjectTemplate::New();
19275
19276   LocalContext context;
19277   Local<v8::Object> obj = templ->NewInstance();
19278   context->Global()->Set(v8_str("obj"), obj);
19279   obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
19280   obj->Set(v8_str("1"), v8_str("foobar"));
19281   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
19282   obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
19283   obj->Set(v8_num(2), v8_str("foobar"));
19284   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
19285
19286   // Test non-smi case.
19287   obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
19288   obj->Set(v8_str("2000000000"), v8_str("foobar"));
19289   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
19290 }
19291
19292
19293 THREADED_TEST(Regress1516) {
19294   LocalContext context;
19295   v8::HandleScope scope(context->GetIsolate());
19296
19297   { v8::HandleScope temp_scope(context->GetIsolate());
19298     CompileRun("({'a': 0})");
19299   }
19300
19301   int elements;
19302   { i::MapCache* map_cache =
19303         i::MapCache::cast(i::Isolate::Current()->context()->map_cache());
19304     elements = map_cache->NumberOfElements();
19305     CHECK_LE(1, elements);
19306   }
19307
19308   i::Isolate::Current()->heap()->CollectAllGarbage(
19309       i::Heap::kAbortIncrementalMarkingMask);
19310   { i::Object* raw_map_cache = i::Isolate::Current()->context()->map_cache();
19311     if (raw_map_cache != i::Isolate::Current()->heap()->undefined_value()) {
19312       i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
19313       CHECK_GT(elements, map_cache->NumberOfElements());
19314     }
19315   }
19316 }
19317
19318
19319 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
19320                                                 Local<Value> name,
19321                                                 v8::AccessType type,
19322                                                 Local<Value> data) {
19323   // Only block read access to __proto__.
19324   if (type == v8::ACCESS_GET &&
19325       name->IsString() &&
19326       name->ToString()->Length() == 9 &&
19327       name->ToString()->Utf8Length() == 9) {
19328     char buffer[10];
19329     CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
19330     return strncmp(buffer, "__proto__", 9) != 0;
19331   }
19332
19333   return true;
19334 }
19335
19336
19337 THREADED_TEST(Regress93759) {
19338   v8::Isolate* isolate = v8::Isolate::GetCurrent();
19339   HandleScope scope(isolate);
19340
19341   // Template for object with security check.
19342   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New();
19343   // We don't do indexing, so any callback can be used for that.
19344   no_proto_template->SetAccessCheckCallbacks(
19345       BlockProtoNamedSecurityTestCallback,
19346       IndexedSecurityTestCallback);
19347
19348   // Templates for objects with hidden prototypes and possibly security check.
19349   Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New();
19350   hidden_proto_template->SetHiddenPrototype(true);
19351
19352   Local<FunctionTemplate> protected_hidden_proto_template =
19353       v8::FunctionTemplate::New();
19354   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
19355       BlockProtoNamedSecurityTestCallback,
19356       IndexedSecurityTestCallback);
19357   protected_hidden_proto_template->SetHiddenPrototype(true);
19358
19359   // Context for "foreign" objects used in test.
19360   Local<Context> context = v8::Context::New(isolate);
19361   context->Enter();
19362
19363   // Plain object, no security check.
19364   Local<Object> simple_object = Object::New();
19365
19366   // Object with explicit security check.
19367   Local<Object> protected_object =
19368       no_proto_template->NewInstance();
19369
19370   // JSGlobalProxy object, always have security check.
19371   Local<Object> proxy_object =
19372       context->Global();
19373
19374   // Global object, the  prototype of proxy_object. No security checks.
19375   Local<Object> global_object =
19376       proxy_object->GetPrototype()->ToObject();
19377
19378   // Hidden prototype without security check.
19379   Local<Object> hidden_prototype =
19380       hidden_proto_template->GetFunction()->NewInstance();
19381   Local<Object> object_with_hidden =
19382     Object::New();
19383   object_with_hidden->SetPrototype(hidden_prototype);
19384
19385   // Hidden prototype with security check on the hidden prototype.
19386   Local<Object> protected_hidden_prototype =
19387       protected_hidden_proto_template->GetFunction()->NewInstance();
19388   Local<Object> object_with_protected_hidden =
19389     Object::New();
19390   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
19391
19392   context->Exit();
19393
19394   // Template for object for second context. Values to test are put on it as
19395   // properties.
19396   Local<ObjectTemplate> global_template = ObjectTemplate::New();
19397   global_template->Set(v8_str("simple"), simple_object);
19398   global_template->Set(v8_str("protected"), protected_object);
19399   global_template->Set(v8_str("global"), global_object);
19400   global_template->Set(v8_str("proxy"), proxy_object);
19401   global_template->Set(v8_str("hidden"), object_with_hidden);
19402   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
19403
19404   LocalContext context2(NULL, global_template);
19405
19406   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
19407   CHECK(result1->Equals(simple_object->GetPrototype()));
19408
19409   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
19410   CHECK(result2->Equals(Undefined()));
19411
19412   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
19413   CHECK(result3->Equals(global_object->GetPrototype()));
19414
19415   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
19416   CHECK(result4->Equals(Undefined()));
19417
19418   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
19419   CHECK(result5->Equals(
19420       object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
19421
19422   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
19423   CHECK(result6->Equals(Undefined()));
19424 }
19425
19426
19427 THREADED_TEST(Regress125988) {
19428   v8::HandleScope scope(v8::Isolate::GetCurrent());
19429   Handle<FunctionTemplate> intercept = FunctionTemplate::New();
19430   AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
19431   LocalContext env;
19432   env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
19433   CompileRun("var a = new Object();"
19434              "var b = new Intercept();"
19435              "var c = new Object();"
19436              "c.__proto__ = b;"
19437              "b.__proto__ = a;"
19438              "a.x = 23;"
19439              "for (var i = 0; i < 3; i++) c.x;");
19440   ExpectBoolean("c.hasOwnProperty('x')", false);
19441   ExpectInt32("c.x", 23);
19442   CompileRun("a.y = 42;"
19443              "for (var i = 0; i < 3; i++) c.x;");
19444   ExpectBoolean("c.hasOwnProperty('x')", false);
19445   ExpectInt32("c.x", 23);
19446   ExpectBoolean("c.hasOwnProperty('y')", false);
19447   ExpectInt32("c.y", 42);
19448 }
19449
19450
19451 static void TestReceiver(Local<Value> expected_result,
19452                          Local<Value> expected_receiver,
19453                          const char* code) {
19454   Local<Value> result = CompileRun(code);
19455   CHECK(result->IsObject());
19456   CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
19457   CHECK(expected_result->Equals(result->ToObject()->Get(0)));
19458 }
19459
19460
19461 THREADED_TEST(ForeignFunctionReceiver) {
19462   v8::Isolate* isolate = v8::Isolate::GetCurrent();
19463   HandleScope scope(isolate);
19464
19465   // Create two contexts with different "id" properties ('i' and 'o').
19466   // Call a function both from its own context and from a the foreign
19467   // context, and see what "this" is bound to (returning both "this"
19468   // and "this.id" for comparison).
19469
19470   Local<Context> foreign_context = v8::Context::New(isolate);
19471   foreign_context->Enter();
19472   Local<Value> foreign_function =
19473     CompileRun("function func() { return { 0: this.id, "
19474                "                           1: this, "
19475                "                           toString: function() { "
19476                "                               return this[0];"
19477                "                           }"
19478                "                         };"
19479                "}"
19480                "var id = 'i';"
19481                "func;");
19482   CHECK(foreign_function->IsFunction());
19483   foreign_context->Exit();
19484
19485   LocalContext context;
19486
19487   Local<String> password = v8_str("Password");
19488   // Don't get hit by security checks when accessing foreign_context's
19489   // global receiver (aka. global proxy).
19490   context->SetSecurityToken(password);
19491   foreign_context->SetSecurityToken(password);
19492
19493   Local<String> i = v8_str("i");
19494   Local<String> o = v8_str("o");
19495   Local<String> id = v8_str("id");
19496
19497   CompileRun("function ownfunc() { return { 0: this.id, "
19498              "                              1: this, "
19499              "                              toString: function() { "
19500              "                                  return this[0];"
19501              "                              }"
19502              "                             };"
19503              "}"
19504              "var id = 'o';"
19505              "ownfunc");
19506   context->Global()->Set(v8_str("func"), foreign_function);
19507
19508   // Sanity check the contexts.
19509   CHECK(i->Equals(foreign_context->Global()->Get(id)));
19510   CHECK(o->Equals(context->Global()->Get(id)));
19511
19512   // Checking local function's receiver.
19513   // Calling function using its call/apply methods.
19514   TestReceiver(o, context->Global(), "ownfunc.call()");
19515   TestReceiver(o, context->Global(), "ownfunc.apply()");
19516   // Making calls through built-in functions.
19517   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
19518   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
19519   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
19520   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
19521   // Calling with environment record as base.
19522   TestReceiver(o, context->Global(), "ownfunc()");
19523   // Calling with no base.
19524   TestReceiver(o, context->Global(), "(1,ownfunc)()");
19525
19526   // Checking foreign function return value.
19527   // Calling function using its call/apply methods.
19528   TestReceiver(i, foreign_context->Global(), "func.call()");
19529   TestReceiver(i, foreign_context->Global(), "func.apply()");
19530   // Calling function using another context's call/apply methods.
19531   TestReceiver(i, foreign_context->Global(),
19532                "Function.prototype.call.call(func)");
19533   TestReceiver(i, foreign_context->Global(),
19534                "Function.prototype.call.apply(func)");
19535   TestReceiver(i, foreign_context->Global(),
19536                "Function.prototype.apply.call(func)");
19537   TestReceiver(i, foreign_context->Global(),
19538                "Function.prototype.apply.apply(func)");
19539   // Making calls through built-in functions.
19540   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
19541   // ToString(func()) is func()[0], i.e., the returned this.id.
19542   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
19543   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
19544   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
19545
19546   // TODO(1547): Make the following also return "i".
19547   // Calling with environment record as base.
19548   TestReceiver(o, context->Global(), "func()");
19549   // Calling with no base.
19550   TestReceiver(o, context->Global(), "(1,func)()");
19551 }
19552
19553
19554 uint8_t callback_fired = 0;
19555
19556
19557 void CallCompletedCallback1() {
19558   i::OS::Print("Firing callback 1.\n");
19559   callback_fired ^= 1;  // Toggle first bit.
19560 }
19561
19562
19563 void CallCompletedCallback2() {
19564   i::OS::Print("Firing callback 2.\n");
19565   callback_fired ^= 2;  // Toggle second bit.
19566 }
19567
19568
19569 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
19570   int32_t level = args[0]->Int32Value();
19571   if (level < 3) {
19572     level++;
19573     i::OS::Print("Entering recursion level %d.\n", level);
19574     char script[64];
19575     i::Vector<char> script_vector(script, sizeof(script));
19576     i::OS::SNPrintF(script_vector, "recursion(%d)", level);
19577     CompileRun(script_vector.start());
19578     i::OS::Print("Leaving recursion level %d.\n", level);
19579     CHECK_EQ(0, callback_fired);
19580   } else {
19581     i::OS::Print("Recursion ends.\n");
19582     CHECK_EQ(0, callback_fired);
19583   }
19584 }
19585
19586
19587 TEST(CallCompletedCallback) {
19588   LocalContext env;
19589   v8::HandleScope scope(env->GetIsolate());
19590   v8::Handle<v8::FunctionTemplate> recursive_runtime =
19591       v8::FunctionTemplate::New(RecursiveCall);
19592   env->Global()->Set(v8_str("recursion"),
19593                      recursive_runtime->GetFunction());
19594   // Adding the same callback a second time has no effect.
19595   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
19596   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
19597   v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
19598   i::OS::Print("--- Script (1) ---\n");
19599   Local<Script> script =
19600       v8::Script::Compile(v8::String::New("recursion(0)"));
19601   script->Run();
19602   CHECK_EQ(3, callback_fired);
19603
19604   i::OS::Print("\n--- Script (2) ---\n");
19605   callback_fired = 0;
19606   v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
19607   script->Run();
19608   CHECK_EQ(2, callback_fired);
19609
19610   i::OS::Print("\n--- Function ---\n");
19611   callback_fired = 0;
19612   Local<Function> recursive_function =
19613       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
19614   v8::Handle<Value> args[] = { v8_num(0) };
19615   recursive_function->Call(env->Global(), 1, args);
19616   CHECK_EQ(2, callback_fired);
19617 }
19618
19619
19620 void CallCompletedCallbackNoException() {
19621   v8::HandleScope scope(v8::Isolate::GetCurrent());
19622   CompileRun("1+1;");
19623 }
19624
19625
19626 void CallCompletedCallbackException() {
19627   v8::HandleScope scope(v8::Isolate::GetCurrent());
19628   CompileRun("throw 'second exception';");
19629 }
19630
19631
19632 TEST(CallCompletedCallbackOneException) {
19633   LocalContext env;
19634   v8::HandleScope scope(env->GetIsolate());
19635   v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
19636   CompileRun("throw 'exception';");
19637 }
19638
19639
19640 TEST(CallCompletedCallbackTwoExceptions) {
19641   LocalContext env;
19642   v8::HandleScope scope(env->GetIsolate());
19643   v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
19644   CompileRun("throw 'first exception';");
19645 }
19646
19647
19648 static int probes_counter = 0;
19649 static int misses_counter = 0;
19650 static int updates_counter = 0;
19651
19652
19653 static int* LookupCounter(const char* name) {
19654   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
19655     return &probes_counter;
19656   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
19657     return &misses_counter;
19658   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
19659     return &updates_counter;
19660   }
19661   return NULL;
19662 }
19663
19664
19665 static const char* kMegamorphicTestProgram =
19666     "function ClassA() { };"
19667     "function ClassB() { };"
19668     "ClassA.prototype.foo = function() { };"
19669     "ClassB.prototype.foo = function() { };"
19670     "function fooify(obj) { obj.foo(); };"
19671     "var a = new ClassA();"
19672     "var b = new ClassB();"
19673     "for (var i = 0; i < 10000; i++) {"
19674     "  fooify(a);"
19675     "  fooify(b);"
19676     "}";
19677
19678
19679 static void StubCacheHelper(bool primary) {
19680   V8::SetCounterFunction(LookupCounter);
19681   USE(kMegamorphicTestProgram);
19682 #ifdef DEBUG
19683   i::FLAG_native_code_counters = true;
19684   if (primary) {
19685     i::FLAG_test_primary_stub_cache = true;
19686   } else {
19687     i::FLAG_test_secondary_stub_cache = true;
19688   }
19689   i::FLAG_crankshaft = false;
19690   LocalContext env;
19691   v8::HandleScope scope(env->GetIsolate());
19692   int initial_probes = probes_counter;
19693   int initial_misses = misses_counter;
19694   int initial_updates = updates_counter;
19695   CompileRun(kMegamorphicTestProgram);
19696   int probes = probes_counter - initial_probes;
19697   int misses = misses_counter - initial_misses;
19698   int updates = updates_counter - initial_updates;
19699   CHECK_LT(updates, 10);
19700   CHECK_LT(misses, 10);
19701   CHECK_GE(probes, 10000);
19702 #endif
19703 }
19704
19705
19706 TEST(SecondaryStubCache) {
19707   StubCacheHelper(true);
19708 }
19709
19710
19711 TEST(PrimaryStubCache) {
19712   StubCacheHelper(false);
19713 }
19714
19715
19716 TEST(StaticGetters) {
19717   LocalContext context;
19718   i::Factory* factory = i::Isolate::Current()->factory();
19719   v8::Isolate* isolate = v8::Isolate::GetCurrent();
19720   v8::HandleScope scope(isolate);
19721   i::Handle<i::Object> undefined_value = factory->undefined_value();
19722   CHECK(*v8::Utils::OpenHandle(*v8::Undefined()) == *undefined_value);
19723   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
19724   i::Handle<i::Object> null_value = factory->null_value();
19725   CHECK(*v8::Utils::OpenHandle(*v8::Null()) == *null_value);
19726   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
19727   i::Handle<i::Object> true_value = factory->true_value();
19728   CHECK(*v8::Utils::OpenHandle(*v8::True()) == *true_value);
19729   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
19730   i::Handle<i::Object> false_value = factory->false_value();
19731   CHECK(*v8::Utils::OpenHandle(*v8::False()) == *false_value);
19732   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
19733 }
19734
19735
19736 TEST(IsolateEmbedderData) {
19737   v8::Isolate* isolate = v8::Isolate::GetCurrent();
19738   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
19739   CHECK_EQ(NULL, isolate->GetData());
19740   CHECK_EQ(NULL, i_isolate->GetData());
19741   static void* data1 = reinterpret_cast<void*>(0xacce55ed);
19742   isolate->SetData(data1);
19743   CHECK_EQ(data1, isolate->GetData());
19744   CHECK_EQ(data1, i_isolate->GetData());
19745   static void* data2 = reinterpret_cast<void*>(0xdecea5ed);
19746   i_isolate->SetData(data2);
19747   CHECK_EQ(data2, isolate->GetData());
19748   CHECK_EQ(data2, i_isolate->GetData());
19749   i_isolate->TearDown();
19750   CHECK_EQ(data2, isolate->GetData());
19751   CHECK_EQ(data2, i_isolate->GetData());
19752 }
19753
19754
19755 TEST(StringEmpty) {
19756   LocalContext context;
19757   i::Factory* factory = i::Isolate::Current()->factory();
19758   v8::Isolate* isolate = v8::Isolate::GetCurrent();
19759   v8::HandleScope scope(isolate);
19760   i::Handle<i::Object> empty_string = factory->empty_string();
19761   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty()) == *empty_string);
19762   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
19763 }
19764
19765
19766 static int instance_checked_getter_count = 0;
19767 static void InstanceCheckedGetter(
19768     Local<String> name,
19769     const v8::PropertyCallbackInfo<v8::Value>& info) {
19770   CHECK_EQ(name, v8_str("foo"));
19771   instance_checked_getter_count++;
19772   info.GetReturnValue().Set(v8_num(11));
19773 }
19774
19775
19776 static int instance_checked_setter_count = 0;
19777 static void InstanceCheckedSetter(Local<String> name,
19778                       Local<Value> value,
19779                       const v8::PropertyCallbackInfo<void>& info) {
19780   CHECK_EQ(name, v8_str("foo"));
19781   CHECK_EQ(value, v8_num(23));
19782   instance_checked_setter_count++;
19783 }
19784
19785
19786 static void CheckInstanceCheckedResult(int getters,
19787                                        int setters,
19788                                        bool expects_callbacks,
19789                                        TryCatch* try_catch) {
19790   if (expects_callbacks) {
19791     CHECK(!try_catch->HasCaught());
19792     CHECK_EQ(getters, instance_checked_getter_count);
19793     CHECK_EQ(setters, instance_checked_setter_count);
19794   } else {
19795     CHECK(try_catch->HasCaught());
19796     CHECK_EQ(0, instance_checked_getter_count);
19797     CHECK_EQ(0, instance_checked_setter_count);
19798   }
19799   try_catch->Reset();
19800 }
19801
19802
19803 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
19804   instance_checked_getter_count = 0;
19805   instance_checked_setter_count = 0;
19806   TryCatch try_catch;
19807
19808   // Test path through generic runtime code.
19809   CompileRun("obj.foo");
19810   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
19811   CompileRun("obj.foo = 23");
19812   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
19813
19814   // Test path through generated LoadIC and StoredIC.
19815   CompileRun("function test_get(o) { o.foo; }"
19816              "test_get(obj);");
19817   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
19818   CompileRun("test_get(obj);");
19819   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
19820   CompileRun("test_get(obj);");
19821   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
19822   CompileRun("function test_set(o) { o.foo = 23; }"
19823              "test_set(obj);");
19824   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
19825   CompileRun("test_set(obj);");
19826   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
19827   CompileRun("test_set(obj);");
19828   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
19829
19830   // Test path through optimized code.
19831   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
19832              "test_get(obj);");
19833   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
19834   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
19835              "test_set(obj);");
19836   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
19837
19838   // Cleanup so that closures start out fresh in next check.
19839   CompileRun("%DeoptimizeFunction(test_get);"
19840              "%ClearFunctionTypeFeedback(test_get);"
19841              "%DeoptimizeFunction(test_set);"
19842              "%ClearFunctionTypeFeedback(test_set);");
19843 }
19844
19845
19846 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
19847   v8::internal::FLAG_allow_natives_syntax = true;
19848   LocalContext context;
19849   v8::HandleScope scope(context->GetIsolate());
19850
19851   Local<FunctionTemplate> templ = FunctionTemplate::New();
19852   Local<ObjectTemplate> inst = templ->InstanceTemplate();
19853   inst->SetAccessor(v8_str("foo"),
19854                     InstanceCheckedGetter, InstanceCheckedSetter,
19855                     Handle<Value>(),
19856                     v8::DEFAULT,
19857                     v8::None,
19858                     v8::AccessorSignature::New(templ));
19859   context->Global()->Set(v8_str("f"), templ->GetFunction());
19860
19861   printf("Testing positive ...\n");
19862   CompileRun("var obj = new f();");
19863   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19864   CheckInstanceCheckedAccessors(true);
19865
19866   printf("Testing negative ...\n");
19867   CompileRun("var obj = {};"
19868              "obj.__proto__ = new f();");
19869   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19870   CheckInstanceCheckedAccessors(false);
19871 }
19872
19873
19874 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
19875   v8::internal::FLAG_allow_natives_syntax = true;
19876   LocalContext context;
19877   v8::HandleScope scope(context->GetIsolate());
19878
19879   Local<FunctionTemplate> templ = FunctionTemplate::New();
19880   Local<ObjectTemplate> inst = templ->InstanceTemplate();
19881   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
19882   inst->SetAccessor(v8_str("foo"),
19883                     InstanceCheckedGetter, InstanceCheckedSetter,
19884                     Handle<Value>(),
19885                     v8::DEFAULT,
19886                     v8::None,
19887                     v8::AccessorSignature::New(templ));
19888   context->Global()->Set(v8_str("f"), templ->GetFunction());
19889
19890   printf("Testing positive ...\n");
19891   CompileRun("var obj = new f();");
19892   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19893   CheckInstanceCheckedAccessors(true);
19894
19895   printf("Testing negative ...\n");
19896   CompileRun("var obj = {};"
19897              "obj.__proto__ = new f();");
19898   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19899   CheckInstanceCheckedAccessors(false);
19900 }
19901
19902
19903 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
19904   v8::internal::FLAG_allow_natives_syntax = true;
19905   LocalContext context;
19906   v8::HandleScope scope(context->GetIsolate());
19907
19908   Local<FunctionTemplate> templ = FunctionTemplate::New();
19909   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
19910   proto->SetAccessor(v8_str("foo"),
19911                      InstanceCheckedGetter, InstanceCheckedSetter,
19912                      Handle<Value>(),
19913                      v8::DEFAULT,
19914                      v8::None,
19915                      v8::AccessorSignature::New(templ));
19916   context->Global()->Set(v8_str("f"), templ->GetFunction());
19917
19918   printf("Testing positive ...\n");
19919   CompileRun("var obj = new f();");
19920   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19921   CheckInstanceCheckedAccessors(true);
19922
19923   printf("Testing negative ...\n");
19924   CompileRun("var obj = {};"
19925              "obj.__proto__ = new f();");
19926   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19927   CheckInstanceCheckedAccessors(false);
19928
19929   printf("Testing positive with modified prototype chain ...\n");
19930   CompileRun("var obj = new f();"
19931              "var pro = {};"
19932              "pro.__proto__ = obj.__proto__;"
19933              "obj.__proto__ = pro;");
19934   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19935   CheckInstanceCheckedAccessors(true);
19936 }
19937
19938
19939 TEST(TryFinallyMessage) {
19940   LocalContext context;
19941   v8::HandleScope scope(context->GetIsolate());
19942   {
19943     // Test that the original error message is not lost if there is a
19944     // recursive call into Javascript is done in the finally block, e.g. to
19945     // initialize an IC. (crbug.com/129171)
19946     TryCatch try_catch;
19947     const char* trigger_ic =
19948         "try {                      \n"
19949         "  throw new Error('test'); \n"
19950         "} finally {                \n"
19951         "  var x = 0;               \n"
19952         "  x++;                     \n"  // Trigger an IC initialization here.
19953         "}                          \n";
19954     CompileRun(trigger_ic);
19955     CHECK(try_catch.HasCaught());
19956     Local<Message> message = try_catch.Message();
19957     CHECK(!message.IsEmpty());
19958     CHECK_EQ(2, message->GetLineNumber());
19959   }
19960
19961   {
19962     // Test that the original exception message is indeed overwritten if
19963     // a new error is thrown in the finally block.
19964     TryCatch try_catch;
19965     const char* throw_again =
19966         "try {                       \n"
19967         "  throw new Error('test');  \n"
19968         "} finally {                 \n"
19969         "  var x = 0;                \n"
19970         "  x++;                      \n"
19971         "  throw new Error('again'); \n"  // This is the new uncaught error.
19972         "}                           \n";
19973     CompileRun(throw_again);
19974     CHECK(try_catch.HasCaught());
19975     Local<Message> message = try_catch.Message();
19976     CHECK(!message.IsEmpty());
19977     CHECK_EQ(6, message->GetLineNumber());
19978   }
19979 }
19980
19981
19982 static void Helper137002(bool do_store,
19983                          bool polymorphic,
19984                          bool remove_accessor,
19985                          bool interceptor) {
19986   LocalContext context;
19987   Local<ObjectTemplate> templ = ObjectTemplate::New();
19988   if (interceptor) {
19989     templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
19990   } else {
19991     templ->SetAccessor(v8_str("foo"),
19992                        GetterWhichReturns42,
19993                        SetterWhichSetsYOnThisTo23);
19994   }
19995   context->Global()->Set(v8_str("obj"), templ->NewInstance());
19996
19997   // Turn monomorphic on slow object with native accessor, then turn
19998   // polymorphic, finally optimize to create negative lookup and fail.
19999   CompileRun(do_store ?
20000              "function f(x) { x.foo = void 0; }" :
20001              "function f(x) { return x.foo; }");
20002   CompileRun("obj.y = void 0;");
20003   if (!interceptor) {
20004     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
20005   }
20006   CompileRun("obj.__proto__ = null;"
20007              "f(obj); f(obj); f(obj);");
20008   if (polymorphic) {
20009     CompileRun("f({});");
20010   }
20011   CompileRun("obj.y = void 0;"
20012              "%OptimizeFunctionOnNextCall(f);");
20013   if (remove_accessor) {
20014     CompileRun("delete obj.foo;");
20015   }
20016   CompileRun("var result = f(obj);");
20017   if (do_store) {
20018     CompileRun("result = obj.y;");
20019   }
20020   if (remove_accessor && !interceptor) {
20021     CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
20022   } else {
20023     CHECK_EQ(do_store ? 23 : 42,
20024              context->Global()->Get(v8_str("result"))->Int32Value());
20025   }
20026 }
20027
20028
20029 THREADED_TEST(Regress137002a) {
20030   i::FLAG_allow_natives_syntax = true;
20031   i::FLAG_compilation_cache = false;
20032   v8::HandleScope scope(v8::Isolate::GetCurrent());
20033   for (int i = 0; i < 16; i++) {
20034     Helper137002(i & 8, i & 4, i & 2, i & 1);
20035   }
20036 }
20037
20038
20039 THREADED_TEST(Regress137002b) {
20040   i::FLAG_allow_natives_syntax = true;
20041   LocalContext context;
20042   v8::HandleScope scope(context->GetIsolate());
20043   Local<ObjectTemplate> templ = ObjectTemplate::New();
20044   templ->SetAccessor(v8_str("foo"),
20045                      GetterWhichReturns42,
20046                      SetterWhichSetsYOnThisTo23);
20047   context->Global()->Set(v8_str("obj"), templ->NewInstance());
20048
20049   // Turn monomorphic on slow object with native accessor, then just
20050   // delete the property and fail.
20051   CompileRun("function load(x) { return x.foo; }"
20052              "function store(x) { x.foo = void 0; }"
20053              "function keyed_load(x, key) { return x[key]; }"
20054              // Second version of function has a different source (add void 0)
20055              // so that it does not share code with the first version.  This
20056              // ensures that the ICs are monomorphic.
20057              "function load2(x) { void 0; return x.foo; }"
20058              "function store2(x) { void 0; x.foo = void 0; }"
20059              "function keyed_load2(x, key) { void 0; return x[key]; }"
20060
20061              "obj.y = void 0;"
20062              "obj.__proto__ = null;"
20063              "var subobj = {};"
20064              "subobj.y = void 0;"
20065              "subobj.__proto__ = obj;"
20066              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20067
20068              // Make the ICs monomorphic.
20069              "load(obj); load(obj);"
20070              "load2(subobj); load2(subobj);"
20071              "store(obj); store(obj);"
20072              "store2(subobj); store2(subobj);"
20073              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
20074              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
20075
20076              // Actually test the shiny new ICs and better not crash. This
20077              // serves as a regression test for issue 142088 as well.
20078              "load(obj);"
20079              "load2(subobj);"
20080              "store(obj);"
20081              "store2(subobj);"
20082              "keyed_load(obj, 'foo');"
20083              "keyed_load2(subobj, 'foo');"
20084
20085              // Delete the accessor.  It better not be called any more now.
20086              "delete obj.foo;"
20087              "obj.y = void 0;"
20088              "subobj.y = void 0;"
20089
20090              "var load_result = load(obj);"
20091              "var load_result2 = load2(subobj);"
20092              "var keyed_load_result = keyed_load(obj, 'foo');"
20093              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
20094              "store(obj);"
20095              "store2(subobj);"
20096              "var y_from_obj = obj.y;"
20097              "var y_from_subobj = subobj.y;");
20098   CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
20099   CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
20100   CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
20101   CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
20102   CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
20103   CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
20104 }
20105
20106
20107 THREADED_TEST(Regress142088) {
20108   i::FLAG_allow_natives_syntax = true;
20109   LocalContext context;
20110   v8::HandleScope scope(context->GetIsolate());
20111   Local<ObjectTemplate> templ = ObjectTemplate::New();
20112   templ->SetAccessor(v8_str("foo"),
20113                      GetterWhichReturns42,
20114                      SetterWhichSetsYOnThisTo23);
20115   context->Global()->Set(v8_str("obj"), templ->NewInstance());
20116
20117   CompileRun("function load(x) { return x.foo; }"
20118              "var o = Object.create(obj);"
20119              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20120              "load(o); load(o); load(o); load(o);");
20121 }
20122
20123
20124 THREADED_TEST(Regress137496) {
20125   i::FLAG_expose_gc = true;
20126   LocalContext context;
20127   v8::HandleScope scope(context->GetIsolate());
20128
20129   // Compile a try-finally clause where the finally block causes a GC
20130   // while there still is a message pending for external reporting.
20131   TryCatch try_catch;
20132   try_catch.SetVerbose(true);
20133   CompileRun("try { throw new Error(); } finally { gc(); }");
20134   CHECK(try_catch.HasCaught());
20135 }
20136
20137
20138 THREADED_TEST(Regress149912) {
20139   LocalContext context;
20140   v8::HandleScope scope(context->GetIsolate());
20141   Handle<FunctionTemplate> templ = FunctionTemplate::New();
20142   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20143   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
20144   CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
20145 }
20146
20147
20148 THREADED_TEST(Regress157124) {
20149   LocalContext context;
20150   v8::HandleScope scope(context->GetIsolate());
20151   Local<ObjectTemplate> templ = ObjectTemplate::New();
20152   Local<Object> obj = templ->NewInstance();
20153   obj->GetIdentityHash();
20154   obj->DeleteHiddenValue(v8_str("Bug"));
20155 }
20156
20157
20158 THREADED_TEST(Regress2535) {
20159   i::FLAG_harmony_collections = true;
20160   LocalContext context;
20161   v8::HandleScope scope(context->GetIsolate());
20162   Local<Value> set_value = CompileRun("new Set();");
20163   Local<Object> set_object(Local<Object>::Cast(set_value));
20164   CHECK_EQ(0, set_object->InternalFieldCount());
20165   Local<Value> map_value = CompileRun("new Map();");
20166   Local<Object> map_object(Local<Object>::Cast(map_value));
20167   CHECK_EQ(0, map_object->InternalFieldCount());
20168 }
20169
20170
20171 THREADED_TEST(Regress2746) {
20172   LocalContext context;
20173   v8::HandleScope scope(context->GetIsolate());
20174   Local<Object> obj = Object::New();
20175   Local<String> key = String::New("key");
20176   obj->SetHiddenValue(key, v8::Undefined());
20177   Local<Value> value = obj->GetHiddenValue(key);
20178   CHECK(!value.IsEmpty());
20179   CHECK(value->IsUndefined());
20180 }
20181
20182
20183 THREADED_TEST(Regress260106) {
20184   LocalContext context;
20185   v8::HandleScope scope(context->GetIsolate());
20186   Local<FunctionTemplate> templ = FunctionTemplate::New(DummyCallHandler);
20187   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
20188   Local<Function> function = templ->GetFunction();
20189   CHECK(!function.IsEmpty());
20190   CHECK(function->IsFunction());
20191 }
20192
20193
20194 THREADED_TEST(JSONParseObject) {
20195   LocalContext context;
20196   HandleScope scope(context->GetIsolate());
20197   Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
20198   Handle<Object> global = context->Global();
20199   global->Set(v8_str("obj"), obj);
20200   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
20201 }
20202
20203
20204 THREADED_TEST(JSONParseNumber) {
20205   LocalContext context;
20206   HandleScope scope(context->GetIsolate());
20207   Local<Value> obj = v8::JSON::Parse(v8_str("42"));
20208   Handle<Object> global = context->Global();
20209   global->Set(v8_str("obj"), obj);
20210   ExpectString("JSON.stringify(obj)", "42");
20211 }
20212
20213
20214 #if V8_OS_POSIX
20215 class ThreadInterruptTest {
20216  public:
20217   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
20218   ~ThreadInterruptTest() {}
20219
20220   void RunTest() {
20221     InterruptThread i_thread(this);
20222     i_thread.Start();
20223
20224     sem_.Wait();
20225     CHECK_EQ(kExpectedValue, sem_value_);
20226   }
20227
20228  private:
20229   static const int kExpectedValue = 1;
20230
20231   class InterruptThread : public i::Thread {
20232    public:
20233     explicit InterruptThread(ThreadInterruptTest* test)
20234         : Thread("InterruptThread"), test_(test) {}
20235
20236     virtual void Run() {
20237       struct sigaction action;
20238
20239       // Ensure that we'll enter waiting condition
20240       i::OS::Sleep(100);
20241
20242       // Setup signal handler
20243       memset(&action, 0, sizeof(action));
20244       action.sa_handler = SignalHandler;
20245       sigaction(SIGCHLD, &action, NULL);
20246
20247       // Send signal
20248       kill(getpid(), SIGCHLD);
20249
20250       // Ensure that if wait has returned because of error
20251       i::OS::Sleep(100);
20252
20253       // Set value and signal semaphore
20254       test_->sem_value_ = 1;
20255       test_->sem_.Signal();
20256     }
20257
20258     static void SignalHandler(int signal) {
20259     }
20260
20261    private:
20262      ThreadInterruptTest* test_;
20263   };
20264
20265   i::Semaphore sem_;
20266   volatile int sem_value_;
20267 };
20268
20269
20270 THREADED_TEST(SemaphoreInterruption) {
20271   ThreadInterruptTest().RunTest();
20272 }
20273
20274
20275 static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
20276                                      Local<Value> name,
20277                                      v8::AccessType type,
20278                                      Local<Value> data) {
20279   i::PrintF("Named access blocked.\n");
20280   return false;
20281 }
20282
20283
20284 static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
20285                                      uint32_t key,
20286                                      v8::AccessType type,
20287                                      Local<Value> data) {
20288   i::PrintF("Indexed access blocked.\n");
20289   return false;
20290 }
20291
20292
20293 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
20294   CHECK(false);
20295 }
20296
20297
20298 TEST(JSONStringifyAccessCheck) {
20299   v8::V8::Initialize();
20300   v8::HandleScope scope(v8::Isolate::GetCurrent());
20301
20302   // Create an ObjectTemplate for global objects and install access
20303   // check callbacks that will block access.
20304   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
20305   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
20306                                            IndexAccessAlwaysBlocked);
20307
20308   // Create a context and set an x property on it's global object.
20309   LocalContext context0(NULL, global_template);
20310   v8::Handle<v8::Object> global0 = context0->Global();
20311   global0->Set(v8_str("x"), v8_num(42));
20312   ExpectString("JSON.stringify(this)", "{\"x\":42}");
20313
20314   for (int i = 0; i < 2; i++) {
20315     if (i == 1) {
20316       // Install a toJSON function on the second run.
20317       v8::Handle<v8::FunctionTemplate> toJSON =
20318           v8::FunctionTemplate::New(UnreachableCallback);
20319
20320       global0->Set(v8_str("toJSON"), toJSON->GetFunction());
20321     }
20322     // Create a context with a different security token so that the
20323     // failed access check callback will be called on each access.
20324     LocalContext context1(NULL, global_template);
20325     context1->Global()->Set(v8_str("other"), global0);
20326
20327     ExpectString("JSON.stringify(other)", "{}");
20328     ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
20329                  "{\"a\":{},\"b\":[\"c\"]}");
20330     ExpectString("JSON.stringify([other, 'b', 'c'])",
20331                  "[{},\"b\",\"c\"]");
20332
20333     v8::Handle<v8::Array> array = v8::Array::New(2);
20334     array->Set(0, v8_str("a"));
20335     array->Set(1, v8_str("b"));
20336     context1->Global()->Set(v8_str("array"), array);
20337     ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
20338     array->TurnOnAccessCheck();
20339     ExpectString("JSON.stringify(array)", "[]");
20340     ExpectString("JSON.stringify([array])", "[[]]");
20341     ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
20342   }
20343 }
20344
20345
20346 bool access_check_fail_thrown = false;
20347 bool catch_callback_called = false;
20348
20349
20350 // Failed access check callback that performs a GC on each invocation.
20351 void FailedAccessCheckThrows(Local<v8::Object> target,
20352                              v8::AccessType type,
20353                              Local<v8::Value> data) {
20354   access_check_fail_thrown = true;
20355   i::PrintF("Access check failed. Error thrown.\n");
20356   v8::ThrowException(v8::Exception::Error(v8_str("cross context")));
20357 }
20358
20359
20360 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
20361   for (int i = 0; i < args.Length(); i++) {
20362     i::PrintF("%s\n", *String::Utf8Value(args[i]));
20363   }
20364   catch_callback_called = true;
20365 }
20366
20367
20368 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
20369   args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
20370 }
20371
20372
20373 void CheckCorrectThrow(const char* script) {
20374   // Test that the script, when wrapped into a try-catch, triggers the catch
20375   // clause due to failed access check throwing an exception.
20376   // The subsequent try-catch should run without any exception.
20377   access_check_fail_thrown = false;
20378   catch_callback_called = false;
20379   i::ScopedVector<char> source(1024);
20380   i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
20381   CompileRun(source.start());
20382   CHECK(access_check_fail_thrown);
20383   CHECK(catch_callback_called);
20384
20385   access_check_fail_thrown = false;
20386   catch_callback_called = false;
20387   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
20388   CHECK(!access_check_fail_thrown);
20389   CHECK(!catch_callback_called);
20390 }
20391
20392
20393 TEST(AccessCheckThrows) {
20394   i::FLAG_allow_natives_syntax = true;
20395   v8::V8::Initialize();
20396   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
20397   v8::HandleScope scope(v8::Isolate::GetCurrent());
20398
20399   // Create an ObjectTemplate for global objects and install access
20400   // check callbacks that will block access.
20401   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
20402   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
20403                                            IndexAccessAlwaysBlocked);
20404
20405   // Create a context and set an x property on it's global object.
20406   LocalContext context0(NULL, global_template);
20407   context0->Global()->Set(v8_str("x"), v8_num(42));
20408   v8::Handle<v8::Object> global0 = context0->Global();
20409
20410   // Create a context with a different security token so that the
20411   // failed access check callback will be called on each access.
20412   LocalContext context1(NULL, global_template);
20413   context1->Global()->Set(v8_str("other"), global0);
20414
20415   v8::Handle<v8::FunctionTemplate> catcher_fun =
20416       v8::FunctionTemplate::New(CatcherCallback);
20417   context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
20418
20419   v8::Handle<v8::FunctionTemplate> has_own_property_fun =
20420       v8::FunctionTemplate::New(HasOwnPropertyCallback);
20421   context1->Global()->Set(v8_str("has_own_property"),
20422                           has_own_property_fun->GetFunction());
20423
20424   { v8::TryCatch try_catch;
20425     access_check_fail_thrown = false;
20426     CompileRun("other.x;");
20427     CHECK(access_check_fail_thrown);
20428     CHECK(try_catch.HasCaught());
20429   }
20430
20431   CheckCorrectThrow("other.x");
20432   CheckCorrectThrow("other[1]");
20433   CheckCorrectThrow("JSON.stringify(other)");
20434   CheckCorrectThrow("has_own_property(other, 'x')");
20435   CheckCorrectThrow("%GetProperty(other, 'x')");
20436   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
20437   CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
20438   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
20439   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
20440   CheckCorrectThrow("%HasLocalProperty(other, 'x')");
20441   CheckCorrectThrow("%HasProperty(other, 'x')");
20442   CheckCorrectThrow("%HasElement(other, 1)");
20443   CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
20444   CheckCorrectThrow("%GetPropertyNames(other)");
20445   CheckCorrectThrow("%GetLocalPropertyNames(other, true)");
20446   CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
20447                         "other, 'x', null, null, 1)");
20448
20449   // Reset the failed access check callback so it does not influence
20450   // the other tests.
20451   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
20452 }
20453
20454
20455 THREADED_TEST(Regress256330) {
20456   i::FLAG_allow_natives_syntax = true;
20457   LocalContext context;
20458   v8::HandleScope scope(context->GetIsolate());
20459   Handle<FunctionTemplate> templ = FunctionTemplate::New();
20460   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20461   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
20462   CompileRun("\"use strict\"; var o = new Bug;"
20463              "function f(o) { o.x = 10; };"
20464              "f(o); f(o); f(o);"
20465              "%OptimizeFunctionOnNextCall(f);"
20466              "f(o);");
20467   ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
20468 }
20469
20470
20471 THREADED_TEST(CrankshaftInterceptorSetter) {
20472   i::FLAG_allow_natives_syntax = true;
20473   v8::HandleScope scope(v8::Isolate::GetCurrent());
20474   Handle<FunctionTemplate> templ = FunctionTemplate::New();
20475   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
20476   LocalContext env;
20477   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
20478   CompileRun("var obj = new Obj;"
20479              // Initialize fields to avoid transitions later.
20480              "obj.age = 0;"
20481              "obj.accessor_age = 42;"
20482              "function setter(i) { this.accessor_age = i; };"
20483              "function getter() { return this.accessor_age; };"
20484              "function setAge(i) { obj.age = i; };"
20485              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
20486              "setAge(1);"
20487              "setAge(2);"
20488              "setAge(3);"
20489              "%OptimizeFunctionOnNextCall(setAge);"
20490              "setAge(4);");
20491   // All stores went through the interceptor.
20492   ExpectInt32("obj.interceptor_age", 4);
20493   ExpectInt32("obj.accessor_age", 42);
20494 }
20495
20496
20497 THREADED_TEST(CrankshaftInterceptorGetter) {
20498   i::FLAG_allow_natives_syntax = true;
20499   v8::HandleScope scope(v8::Isolate::GetCurrent());
20500   Handle<FunctionTemplate> templ = FunctionTemplate::New();
20501   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
20502   LocalContext env;
20503   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
20504   CompileRun("var obj = new Obj;"
20505              // Initialize fields to avoid transitions later.
20506              "obj.age = 1;"
20507              "obj.accessor_age = 42;"
20508              "function getter() { return this.accessor_age; };"
20509              "function getAge() { return obj.interceptor_age; };"
20510              "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
20511              "getAge();"
20512              "getAge();"
20513              "getAge();"
20514              "%OptimizeFunctionOnNextCall(getAge);");
20515   // Access through interceptor.
20516   ExpectInt32("getAge()", 1);
20517 }
20518
20519
20520 THREADED_TEST(CrankshaftInterceptorFieldRead) {
20521   i::FLAG_allow_natives_syntax = true;
20522   v8::HandleScope scope(v8::Isolate::GetCurrent());
20523   Handle<FunctionTemplate> templ = FunctionTemplate::New();
20524   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
20525   LocalContext env;
20526   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
20527   CompileRun("var obj = new Obj;"
20528              "obj.__proto__.interceptor_age = 42;"
20529              "obj.age = 100;"
20530              "function getAge() { return obj.interceptor_age; };");
20531   ExpectInt32("getAge();", 100);
20532   ExpectInt32("getAge();", 100);
20533   ExpectInt32("getAge();", 100);
20534   CompileRun("%OptimizeFunctionOnNextCall(getAge);");
20535   // Access through interceptor.
20536   ExpectInt32("getAge();", 100);
20537 }
20538
20539
20540 THREADED_TEST(CrankshaftInterceptorFieldWrite) {
20541   i::FLAG_allow_natives_syntax = true;
20542   v8::HandleScope scope(v8::Isolate::GetCurrent());
20543   Handle<FunctionTemplate> templ = FunctionTemplate::New();
20544   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
20545   LocalContext env;
20546   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
20547   CompileRun("var obj = new Obj;"
20548              "obj.age = 100000;"
20549              "function setAge(i) { obj.age = i };"
20550              "setAge(100);"
20551              "setAge(101);"
20552              "setAge(102);"
20553              "%OptimizeFunctionOnNextCall(setAge);"
20554              "setAge(103);");
20555   ExpectInt32("obj.age", 100000);
20556   ExpectInt32("obj.interceptor_age", 103);
20557 }
20558
20559
20560 #endif  // V8_OS_POSIX
20561
20562
20563 static Local<Value> function_new_expected_env;
20564 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
20565   CHECK_EQ(function_new_expected_env, info.Data());
20566   info.GetReturnValue().Set(17);
20567 }
20568
20569
20570 THREADED_TEST(FunctionNew) {
20571   LocalContext env;
20572   v8::Isolate* isolate = env->GetIsolate();
20573   v8::HandleScope scope(isolate);
20574   Local<Object> data = v8::Object::New();
20575   function_new_expected_env = data;
20576   Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
20577   env->Global()->Set(v8_str("func"), func);
20578   Local<Value> result = CompileRun("func();");
20579   CHECK_EQ(v8::Integer::New(17, isolate), result);
20580   // Verify function not cached
20581   int serial_number =
20582       i::Smi::cast(v8::Utils::OpenHandle(*func)
20583           ->shared()->get_api_func_data()->serial_number())->value();
20584   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
20585   i::Object* elm = i_isolate->native_context()->function_cache()
20586       ->GetElementNoExceptionThrown(i_isolate, serial_number);
20587   CHECK(elm->IsNull());
20588 }
20589