afb70ffeee8d84152b602232a311a392e9bc49cd
[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 <map>
31 #include <string>
32
33 #include "test/cctest/test-api.h"
34
35 #if V8_OS_POSIX
36 #include <unistd.h>  // NOLINT
37 #endif
38
39 #include "include/v8-util.h"
40 #include "src/api.h"
41 #include "src/arguments.h"
42 #include "src/base/platform/platform.h"
43 #include "src/compilation-cache.h"
44 #include "src/execution.h"
45 #include "src/objects.h"
46 #include "src/parser.h"
47 #include "src/smart-pointers.h"
48 #include "src/snapshot.h"
49 #include "src/unicode-inl.h"
50 #include "src/utils.h"
51 #include "src/vm-state.h"
52
53 static const bool kLogThreading = false;
54
55 using ::v8::Boolean;
56 using ::v8::BooleanObject;
57 using ::v8::Context;
58 using ::v8::Extension;
59 using ::v8::Function;
60 using ::v8::FunctionTemplate;
61 using ::v8::Handle;
62 using ::v8::HandleScope;
63 using ::v8::Local;
64 using ::v8::Name;
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::Symbol;
74 using ::v8::TryCatch;
75 using ::v8::Undefined;
76 using ::v8::UniqueId;
77 using ::v8::V8;
78 using ::v8::Value;
79
80
81 #define THREADED_PROFILED_TEST(Name)                                 \
82   static void Test##Name();                                          \
83   TEST(Name##WithProfiler) {                                         \
84     RunWithProfiler(&Test##Name);                                    \
85   }                                                                  \
86   THREADED_TEST(Name)
87
88
89 void RunWithProfiler(void (*test)()) {
90   LocalContext env;
91   v8::HandleScope scope(env->GetIsolate());
92   v8::Local<v8::String> profile_name =
93       v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
94   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
95
96   cpu_profiler->StartProfiling(profile_name);
97   (*test)();
98   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
99 }
100
101
102 static int signature_callback_count;
103 static Local<Value> signature_expected_receiver;
104 static void IncrementingSignatureCallback(
105     const v8::FunctionCallbackInfo<v8::Value>& args) {
106   ApiTestFuzzer::Fuzz();
107   signature_callback_count++;
108   CHECK(signature_expected_receiver->Equals(args.Holder()));
109   CHECK(signature_expected_receiver->Equals(args.This()));
110   v8::Handle<v8::Array> result =
111       v8::Array::New(args.GetIsolate(), args.Length());
112   for (int i = 0; i < args.Length(); i++)
113     result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
114   args.GetReturnValue().Set(result);
115 }
116
117
118 static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
119   info.GetReturnValue().Set(42);
120 }
121
122
123 // Tests that call v8::V8::Dispose() cannot be threaded.
124 UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
125   CHECK(v8::V8::Initialize());
126   CHECK(v8::V8::Dispose());
127 }
128
129
130 // Tests that call v8::V8::Dispose() cannot be threaded.
131 UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
132   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
133   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
134   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
135   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
136   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
137 }
138
139
140 THREADED_TEST(Handles) {
141   v8::HandleScope scope(CcTest::isolate());
142   Local<Context> local_env;
143   {
144     LocalContext env;
145     local_env = env.local();
146   }
147
148   // Local context should still be live.
149   CHECK(!local_env.IsEmpty());
150   local_env->Enter();
151
152   v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
153   CHECK(!undef.IsEmpty());
154   CHECK(undef->IsUndefined());
155
156   const char* source = "1 + 2 + 3";
157   Local<Script> script = v8_compile(source);
158   CHECK_EQ(6, script->Run()->Int32Value());
159
160   local_env->Exit();
161 }
162
163
164 THREADED_TEST(IsolateOfContext) {
165   v8::HandleScope scope(CcTest::isolate());
166   v8::Handle<Context> env = Context::New(CcTest::isolate());
167
168   CHECK(!env->GetIsolate()->InContext());
169   CHECK(env->GetIsolate() == CcTest::isolate());
170   env->Enter();
171   CHECK(env->GetIsolate()->InContext());
172   CHECK(env->GetIsolate() == CcTest::isolate());
173   env->Exit();
174   CHECK(!env->GetIsolate()->InContext());
175   CHECK(env->GetIsolate() == CcTest::isolate());
176 }
177
178
179 static void TestSignature(const char* loop_js, Local<Value> receiver,
180                           v8::Isolate* isolate) {
181   i::ScopedVector<char> source(200);
182   i::SNPrintF(source,
183               "for (var i = 0; i < 10; i++) {"
184               "  %s"
185               "}",
186               loop_js);
187   signature_callback_count = 0;
188   signature_expected_receiver = receiver;
189   bool expected_to_throw = receiver.IsEmpty();
190   v8::TryCatch try_catch;
191   CompileRun(source.start());
192   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
193   if (!expected_to_throw) {
194     CHECK_EQ(10, signature_callback_count);
195   } else {
196     CHECK(v8_str("TypeError: Illegal invocation")
197               ->Equals(try_catch.Exception()->ToString(isolate)));
198   }
199 }
200
201
202 THREADED_TEST(ReceiverSignature) {
203   LocalContext env;
204   v8::Isolate* isolate = env->GetIsolate();
205   v8::HandleScope scope(isolate);
206   // Setup templates.
207   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
208   v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
209   v8::Handle<v8::FunctionTemplate> callback_sig =
210       v8::FunctionTemplate::New(
211           isolate, IncrementingSignatureCallback, Local<Value>(), sig);
212   v8::Handle<v8::FunctionTemplate> callback =
213       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
214   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
215   sub_fun->Inherit(fun);
216   v8::Handle<v8::FunctionTemplate> unrel_fun =
217       v8::FunctionTemplate::New(isolate);
218   // Install properties.
219   v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
220   fun_proto->Set(v8_str("prop_sig"), callback_sig);
221   fun_proto->Set(v8_str("prop"), callback);
222   fun_proto->SetAccessorProperty(
223       v8_str("accessor_sig"), callback_sig, callback_sig);
224   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
225   // Instantiate templates.
226   Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
227   Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
228   // Setup global variables.
229   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
230   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
231   env->Global()->Set(v8_str("fun_instance"), fun_instance);
232   env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
233   CompileRun(
234       "var accessor_sig_key = 'accessor_sig';"
235       "var accessor_key = 'accessor';"
236       "var prop_sig_key = 'prop_sig';"
237       "var prop_key = 'prop';"
238       ""
239       "function copy_props(obj) {"
240       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
241       "  var source = Fun.prototype;"
242       "  for (var i in keys) {"
243       "    var key = keys[i];"
244       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
245       "    Object.defineProperty(obj, key, desc);"
246       "  }"
247       "}"
248       ""
249       "var obj = {};"
250       "copy_props(obj);"
251       "var unrel = new UnrelFun();"
252       "copy_props(unrel);");
253   // Test with and without ICs
254   const char* test_objects[] = {
255       "fun_instance", "sub_fun_instance", "obj", "unrel" };
256   unsigned bad_signature_start_offset = 2;
257   for (unsigned i = 0; i < arraysize(test_objects); i++) {
258     i::ScopedVector<char> source(200);
259     i::SNPrintF(
260         source, "var test_object = %s; test_object", test_objects[i]);
261     Local<Value> test_object = CompileRun(source.start());
262     TestSignature("test_object.prop();", test_object, isolate);
263     TestSignature("test_object.accessor;", test_object, isolate);
264     TestSignature("test_object[accessor_key];", test_object, isolate);
265     TestSignature("test_object.accessor = 1;", test_object, isolate);
266     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
267     if (i >= bad_signature_start_offset) test_object = Local<Value>();
268     TestSignature("test_object.prop_sig();", test_object, isolate);
269     TestSignature("test_object.accessor_sig;", test_object, isolate);
270     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
271     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
272     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
273   }
274 }
275
276
277 THREADED_TEST(HulIgennem) {
278   LocalContext env;
279   v8::Isolate* isolate = env->GetIsolate();
280   v8::HandleScope scope(isolate);
281   v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
282   Local<String> undef_str = undef->ToString(isolate);
283   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
284   undef_str->WriteUtf8(value);
285   CHECK_EQ(0, strcmp(value, "undefined"));
286   i::DeleteArray(value);
287 }
288
289
290 THREADED_TEST(Access) {
291   LocalContext env;
292   v8::Isolate* isolate = env->GetIsolate();
293   v8::HandleScope scope(isolate);
294   Local<v8::Object> obj = v8::Object::New(isolate);
295   Local<Value> foo_before = obj->Get(v8_str("foo"));
296   CHECK(foo_before->IsUndefined());
297   Local<String> bar_str = v8_str("bar");
298   obj->Set(v8_str("foo"), bar_str);
299   Local<Value> foo_after = obj->Get(v8_str("foo"));
300   CHECK(!foo_after->IsUndefined());
301   CHECK(foo_after->IsString());
302   CHECK(bar_str->Equals(foo_after));
303 }
304
305
306 THREADED_TEST(AccessElement) {
307   LocalContext env;
308   v8::HandleScope scope(env->GetIsolate());
309   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
310   Local<Value> before = obj->Get(1);
311   CHECK(before->IsUndefined());
312   Local<String> bar_str = v8_str("bar");
313   obj->Set(1, bar_str);
314   Local<Value> after = obj->Get(1);
315   CHECK(!after->IsUndefined());
316   CHECK(after->IsString());
317   CHECK(bar_str->Equals(after));
318
319   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
320   CHECK(v8_str("a")->Equals(value->Get(0)));
321   CHECK(v8_str("b")->Equals(value->Get(1)));
322 }
323
324
325 THREADED_TEST(Script) {
326   LocalContext env;
327   v8::HandleScope scope(env->GetIsolate());
328   const char* source = "1 + 2 + 3";
329   Local<Script> script = v8_compile(source);
330   CHECK_EQ(6, script->Run()->Int32Value());
331 }
332
333
334 class TestResource: public String::ExternalStringResource {
335  public:
336   explicit TestResource(uint16_t* data, int* counter = NULL,
337                         bool owning_data = true)
338       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
339     while (data[length_]) ++length_;
340   }
341
342   ~TestResource() {
343     if (owning_data_) i::DeleteArray(data_);
344     if (counter_ != NULL) ++*counter_;
345   }
346
347   const uint16_t* data() const {
348     return data_;
349   }
350
351   size_t length() const {
352     return length_;
353   }
354
355  private:
356   uint16_t* data_;
357   size_t length_;
358   int* counter_;
359   bool owning_data_;
360 };
361
362
363 class TestOneByteResource : public String::ExternalOneByteStringResource {
364  public:
365   explicit TestOneByteResource(const char* data, int* counter = NULL,
366                                size_t offset = 0)
367       : orig_data_(data),
368         data_(data + offset),
369         length_(strlen(data) - offset),
370         counter_(counter) {}
371
372   ~TestOneByteResource() {
373     i::DeleteArray(orig_data_);
374     if (counter_ != NULL) ++*counter_;
375   }
376
377   const char* data() const {
378     return data_;
379   }
380
381   size_t length() const {
382     return length_;
383   }
384
385  private:
386   const char* orig_data_;
387   const char* data_;
388   size_t length_;
389   int* counter_;
390 };
391
392
393 THREADED_TEST(ScriptUsingStringResource) {
394   int dispose_count = 0;
395   const char* c_source = "1 + 2 * 3";
396   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
397   {
398     LocalContext env;
399     v8::HandleScope scope(env->GetIsolate());
400     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
401     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
402     Local<Script> script = v8_compile(source);
403     Local<Value> value = script->Run();
404     CHECK(value->IsNumber());
405     CHECK_EQ(7, value->Int32Value());
406     CHECK(source->IsExternal());
407     CHECK_EQ(resource,
408              static_cast<TestResource*>(source->GetExternalStringResource()));
409     String::Encoding encoding = String::UNKNOWN_ENCODING;
410     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
411              source->GetExternalStringResourceBase(&encoding));
412     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
413     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
414     CHECK_EQ(0, dispose_count);
415   }
416   CcTest::i_isolate()->compilation_cache()->Clear();
417   CcTest::heap()->CollectAllAvailableGarbage();
418   CHECK_EQ(1, dispose_count);
419 }
420
421
422 THREADED_TEST(ScriptUsingOneByteStringResource) {
423   int dispose_count = 0;
424   const char* c_source = "1 + 2 * 3";
425   {
426     LocalContext env;
427     v8::HandleScope scope(env->GetIsolate());
428     TestOneByteResource* resource =
429         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
430     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
431     CHECK(source->IsExternalOneByte());
432     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
433              source->GetExternalOneByteStringResource());
434     String::Encoding encoding = String::UNKNOWN_ENCODING;
435     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
436              source->GetExternalStringResourceBase(&encoding));
437     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
438     Local<Script> script = v8_compile(source);
439     Local<Value> value = script->Run();
440     CHECK(value->IsNumber());
441     CHECK_EQ(7, value->Int32Value());
442     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
443     CHECK_EQ(0, dispose_count);
444   }
445   CcTest::i_isolate()->compilation_cache()->Clear();
446   CcTest::heap()->CollectAllAvailableGarbage();
447   CHECK_EQ(1, dispose_count);
448 }
449
450
451 THREADED_TEST(ScriptMakingExternalString) {
452   int dispose_count = 0;
453   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
454   {
455     LocalContext env;
456     v8::HandleScope scope(env->GetIsolate());
457     Local<String> source =
458         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
459     // Trigger GCs so that the newly allocated string moves to old gen.
460     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
461     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
462     CHECK_EQ(source->IsExternal(), false);
463     CHECK_EQ(source->IsExternalOneByte(), false);
464     String::Encoding encoding = String::UNKNOWN_ENCODING;
465     CHECK(!source->GetExternalStringResourceBase(&encoding));
466     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
467     bool success = source->MakeExternal(new TestResource(two_byte_source,
468                                                          &dispose_count));
469     CHECK(success);
470     Local<Script> script = v8_compile(source);
471     Local<Value> value = script->Run();
472     CHECK(value->IsNumber());
473     CHECK_EQ(7, value->Int32Value());
474     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
475     CHECK_EQ(0, dispose_count);
476   }
477   CcTest::i_isolate()->compilation_cache()->Clear();
478   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
479   CHECK_EQ(1, dispose_count);
480 }
481
482
483 THREADED_TEST(ScriptMakingExternalOneByteString) {
484   int dispose_count = 0;
485   const char* c_source = "1 + 2 * 3";
486   {
487     LocalContext env;
488     v8::HandleScope scope(env->GetIsolate());
489     Local<String> source = v8_str(c_source);
490     // Trigger GCs so that the newly allocated string moves to old gen.
491     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
492     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
493     bool success = source->MakeExternal(
494         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
495     CHECK(success);
496     Local<Script> script = v8_compile(source);
497     Local<Value> value = script->Run();
498     CHECK(value->IsNumber());
499     CHECK_EQ(7, value->Int32Value());
500     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
501     CHECK_EQ(0, dispose_count);
502   }
503   CcTest::i_isolate()->compilation_cache()->Clear();
504   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
505   CHECK_EQ(1, dispose_count);
506 }
507
508
509 TEST(MakingExternalStringConditions) {
510   LocalContext env;
511   v8::HandleScope scope(env->GetIsolate());
512
513   // Free some space in the new space so that we can check freshness.
514   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
515   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
516
517   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
518   Local<String> small_string =
519       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
520   i::DeleteArray(two_byte_string);
521
522   // We should refuse to externalize newly created small string.
523   CHECK(!small_string->CanMakeExternal());
524   // Trigger GCs so that the newly allocated string moves to old gen.
525   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
526   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
527   // Old space strings should be accepted.
528   CHECK(small_string->CanMakeExternal());
529
530   two_byte_string = AsciiToTwoByteString("small string 2");
531   small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
532   i::DeleteArray(two_byte_string);
533
534   // We should refuse externalizing newly created small string.
535   CHECK(!small_string->CanMakeExternal());
536   for (int i = 0; i < 100; i++) {
537     String::Value value(small_string);
538   }
539   // Frequently used strings should be accepted.
540   CHECK(small_string->CanMakeExternal());
541
542   const int buf_size = 10 * 1024;
543   char* buf = i::NewArray<char>(buf_size);
544   memset(buf, 'a', buf_size);
545   buf[buf_size - 1] = '\0';
546
547   two_byte_string = AsciiToTwoByteString(buf);
548   Local<String> large_string =
549       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
550   i::DeleteArray(buf);
551   i::DeleteArray(two_byte_string);
552   // Large strings should be immediately accepted.
553   CHECK(large_string->CanMakeExternal());
554 }
555
556
557 TEST(MakingExternalOneByteStringConditions) {
558   LocalContext env;
559   v8::HandleScope scope(env->GetIsolate());
560
561   // Free some space in the new space so that we can check freshness.
562   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
563   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
564
565   Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
566   // We should refuse to externalize newly created small string.
567   CHECK(!small_string->CanMakeExternal());
568   // Trigger GCs so that the newly allocated string moves to old gen.
569   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
570   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
571   // Old space strings should be accepted.
572   CHECK(small_string->CanMakeExternal());
573
574   small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
575   // We should refuse externalizing newly created small string.
576   CHECK(!small_string->CanMakeExternal());
577   for (int i = 0; i < 100; i++) {
578     String::Value value(small_string);
579   }
580   // Frequently used strings should be accepted.
581   CHECK(small_string->CanMakeExternal());
582
583   const int buf_size = 10 * 1024;
584   char* buf = i::NewArray<char>(buf_size);
585   memset(buf, 'a', buf_size);
586   buf[buf_size - 1] = '\0';
587   Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
588   i::DeleteArray(buf);
589   // Large strings should be immediately accepted.
590   CHECK(large_string->CanMakeExternal());
591 }
592
593
594 TEST(MakingExternalUnalignedOneByteString) {
595   LocalContext env;
596   v8::HandleScope scope(env->GetIsolate());
597
598   CompileRun("function cons(a, b) { return a + b; }"
599              "function slice(a) { return a.substring(1); }");
600   // Create a cons string that will land in old pointer space.
601   Local<String> cons = Local<String>::Cast(CompileRun(
602       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
603   // Create a sliced string that will land in old pointer space.
604   Local<String> slice = Local<String>::Cast(CompileRun(
605       "slice('abcdefghijklmnopqrstuvwxyz');"));
606
607   // Trigger GCs so that the newly allocated string moves to old gen.
608   SimulateFullSpace(CcTest::heap()->old_pointer_space());
609   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
610   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
611
612   // Turn into external string with unaligned resource data.
613   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
614   bool success =
615       cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
616   CHECK(success);
617   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
618   success =
619       slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
620   CHECK(success);
621
622   // Trigger GCs and force evacuation.
623   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
624   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
625 }
626
627
628 THREADED_TEST(UsingExternalString) {
629   i::Factory* factory = CcTest::i_isolate()->factory();
630   {
631     v8::HandleScope scope(CcTest::isolate());
632     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
633     Local<String> string = String::NewExternal(
634         CcTest::isolate(), new TestResource(two_byte_string));
635     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
636     // Trigger GCs so that the newly allocated string moves to old gen.
637     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
638     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
639     i::Handle<i::String> isymbol =
640         factory->InternalizeString(istring);
641     CHECK(isymbol->IsInternalizedString());
642   }
643   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
644   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
645 }
646
647
648 THREADED_TEST(UsingExternalOneByteString) {
649   i::Factory* factory = CcTest::i_isolate()->factory();
650   {
651     v8::HandleScope scope(CcTest::isolate());
652     const char* one_byte_string = "test string";
653     Local<String> string = String::NewExternal(
654         CcTest::isolate(), new TestOneByteResource(i::StrDup(one_byte_string)));
655     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
656     // Trigger GCs so that the newly allocated string moves to old gen.
657     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
658     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
659     i::Handle<i::String> isymbol =
660         factory->InternalizeString(istring);
661     CHECK(isymbol->IsInternalizedString());
662   }
663   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
664   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
665 }
666
667
668 class RandomLengthResource : public v8::String::ExternalStringResource {
669  public:
670   explicit RandomLengthResource(int length) : length_(length) {}
671   virtual const uint16_t* data() const { return string_; }
672   virtual size_t length() const { return length_; }
673
674  private:
675   uint16_t string_[10];
676   int length_;
677 };
678
679
680 class RandomLengthOneByteResource
681     : public v8::String::ExternalOneByteStringResource {
682  public:
683   explicit RandomLengthOneByteResource(int length) : length_(length) {}
684   virtual const char* data() const { return string_; }
685   virtual size_t length() const { return length_; }
686
687  private:
688   char string_[10];
689   int length_;
690 };
691
692
693 THREADED_TEST(NewExternalForVeryLongString) {
694   {
695     LocalContext env;
696     v8::HandleScope scope(env->GetIsolate());
697     v8::TryCatch try_catch;
698     RandomLengthOneByteResource r(1 << 30);
699     v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), &r);
700     CHECK(str.IsEmpty());
701     CHECK(try_catch.HasCaught());
702     String::Utf8Value exception_value(try_catch.Exception());
703     CHECK_EQ(0, strcmp("RangeError: Invalid string length", *exception_value));
704   }
705
706   {
707     LocalContext env;
708     v8::HandleScope scope(env->GetIsolate());
709     v8::TryCatch try_catch;
710     RandomLengthResource r(1 << 30);
711     v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), &r);
712     CHECK(str.IsEmpty());
713     CHECK(try_catch.HasCaught());
714     String::Utf8Value exception_value(try_catch.Exception());
715     CHECK_EQ(0, strcmp("RangeError: Invalid string length", *exception_value));
716   }
717 }
718
719
720 THREADED_TEST(ScavengeExternalString) {
721   i::FLAG_stress_compaction = false;
722   i::FLAG_gc_global = false;
723   int dispose_count = 0;
724   bool in_new_space = false;
725   {
726     v8::HandleScope scope(CcTest::isolate());
727     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
728     Local<String> string = String::NewExternal(
729         CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
730     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
731     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
732     in_new_space = CcTest::heap()->InNewSpace(*istring);
733     CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
734     CHECK_EQ(0, dispose_count);
735   }
736   CcTest::heap()->CollectGarbage(
737       in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
738   CHECK_EQ(1, dispose_count);
739 }
740
741
742 THREADED_TEST(ScavengeExternalOneByteString) {
743   i::FLAG_stress_compaction = false;
744   i::FLAG_gc_global = false;
745   int dispose_count = 0;
746   bool in_new_space = false;
747   {
748     v8::HandleScope scope(CcTest::isolate());
749     const char* one_byte_string = "test string";
750     Local<String> string = String::NewExternal(
751         CcTest::isolate(),
752         new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count));
753     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
754     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
755     in_new_space = CcTest::heap()->InNewSpace(*istring);
756     CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
757     CHECK_EQ(0, dispose_count);
758   }
759   CcTest::heap()->CollectGarbage(
760       in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
761   CHECK_EQ(1, dispose_count);
762 }
763
764
765 class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
766  public:
767   // Only used by non-threaded tests, so it can use static fields.
768   static int dispose_calls;
769   static int dispose_count;
770
771   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
772       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
773
774   void Dispose() {
775     ++dispose_calls;
776     if (dispose_) delete this;
777   }
778  private:
779   bool dispose_;
780 };
781
782
783 int TestOneByteResourceWithDisposeControl::dispose_count = 0;
784 int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
785
786
787 TEST(ExternalStringWithDisposeHandling) {
788   const char* c_source = "1 + 2 * 3";
789
790   // Use a stack allocated external string resource allocated object.
791   TestOneByteResourceWithDisposeControl::dispose_count = 0;
792   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
793   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
794   {
795     LocalContext env;
796     v8::HandleScope scope(env->GetIsolate());
797     Local<String> source =  String::NewExternal(env->GetIsolate(), &res_stack);
798     Local<Script> script = v8_compile(source);
799     Local<Value> value = script->Run();
800     CHECK(value->IsNumber());
801     CHECK_EQ(7, value->Int32Value());
802     CcTest::heap()->CollectAllAvailableGarbage();
803     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
804   }
805   CcTest::i_isolate()->compilation_cache()->Clear();
806   CcTest::heap()->CollectAllAvailableGarbage();
807   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
808   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
809
810   // Use a heap allocated external string resource allocated object.
811   TestOneByteResourceWithDisposeControl::dispose_count = 0;
812   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
813   TestOneByteResource* res_heap =
814       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
815   {
816     LocalContext env;
817     v8::HandleScope scope(env->GetIsolate());
818     Local<String> source =  String::NewExternal(env->GetIsolate(), res_heap);
819     Local<Script> script = v8_compile(source);
820     Local<Value> value = script->Run();
821     CHECK(value->IsNumber());
822     CHECK_EQ(7, value->Int32Value());
823     CcTest::heap()->CollectAllAvailableGarbage();
824     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
825   }
826   CcTest::i_isolate()->compilation_cache()->Clear();
827   CcTest::heap()->CollectAllAvailableGarbage();
828   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
829   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
830 }
831
832
833 THREADED_TEST(StringConcat) {
834   {
835     LocalContext env;
836     v8::HandleScope scope(env->GetIsolate());
837     const char* one_byte_string_1 = "function a_times_t";
838     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
839     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
840     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
841     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
842     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
843     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
844     Local<String> left = v8_str(one_byte_string_1);
845
846     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
847     Local<String> right =
848         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
849     i::DeleteArray(two_byte_source);
850
851     Local<String> source = String::Concat(left, right);
852     right = String::NewExternal(
853         env->GetIsolate(),
854         new TestOneByteResource(i::StrDup(one_byte_extern_1)));
855     source = String::Concat(source, right);
856     right = String::NewExternal(
857         env->GetIsolate(),
858         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
859     source = String::Concat(source, right);
860     right = v8_str(one_byte_string_2);
861     source = String::Concat(source, right);
862
863     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
864     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
865     i::DeleteArray(two_byte_source);
866
867     source = String::Concat(source, right);
868     right = String::NewExternal(
869         env->GetIsolate(),
870         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
871     source = String::Concat(source, right);
872     Local<Script> script = v8_compile(source);
873     Local<Value> value = script->Run();
874     CHECK(value->IsNumber());
875     CHECK_EQ(68, value->Int32Value());
876   }
877   CcTest::i_isolate()->compilation_cache()->Clear();
878   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
879   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
880 }
881
882
883 THREADED_TEST(GlobalProperties) {
884   LocalContext env;
885   v8::HandleScope scope(env->GetIsolate());
886   v8::Handle<v8::Object> global = env->Global();
887   global->Set(v8_str("pi"), v8_num(3.1415926));
888   Local<Value> pi = global->Get(v8_str("pi"));
889   CHECK_EQ(3.1415926, pi->NumberValue());
890 }
891
892
893 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
894                                  i::Address callback) {
895   ApiTestFuzzer::Fuzz();
896   CheckReturnValue(info, callback);
897   info.GetReturnValue().Set(v8_str("bad value"));
898   info.GetReturnValue().Set(v8_num(102));
899 }
900
901
902 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
903   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
904 }
905
906
907 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
908   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
909 }
910
911 static void construct_callback(
912     const v8::FunctionCallbackInfo<Value>& info) {
913   ApiTestFuzzer::Fuzz();
914   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
915   info.This()->Set(v8_str("x"), v8_num(1));
916   info.This()->Set(v8_str("y"), v8_num(2));
917   info.GetReturnValue().Set(v8_str("bad value"));
918   info.GetReturnValue().Set(info.This());
919 }
920
921
922 static void Return239Callback(
923     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
924   ApiTestFuzzer::Fuzz();
925   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
926   info.GetReturnValue().Set(v8_str("bad value"));
927   info.GetReturnValue().Set(v8_num(239));
928 }
929
930
931 template<typename Handler>
932 static void TestFunctionTemplateInitializer(Handler handler,
933                                             Handler handler_2) {
934   // Test constructor calls.
935   {
936     LocalContext env;
937     v8::Isolate* isolate = env->GetIsolate();
938     v8::HandleScope scope(isolate);
939
940     Local<v8::FunctionTemplate> fun_templ =
941         v8::FunctionTemplate::New(isolate, handler);
942     Local<Function> fun = fun_templ->GetFunction();
943     env->Global()->Set(v8_str("obj"), fun);
944     Local<Script> script = v8_compile("obj()");
945     for (int i = 0; i < 30; i++) {
946       CHECK_EQ(102, script->Run()->Int32Value());
947     }
948   }
949   // Use SetCallHandler to initialize a function template, should work like
950   // the previous one.
951   {
952     LocalContext env;
953     v8::Isolate* isolate = env->GetIsolate();
954     v8::HandleScope scope(isolate);
955
956     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
957     fun_templ->SetCallHandler(handler_2);
958     Local<Function> fun = fun_templ->GetFunction();
959     env->Global()->Set(v8_str("obj"), fun);
960     Local<Script> script = v8_compile("obj()");
961     for (int i = 0; i < 30; i++) {
962       CHECK_EQ(102, script->Run()->Int32Value());
963     }
964   }
965 }
966
967
968 template<typename Constructor, typename Accessor>
969 static void TestFunctionTemplateAccessor(Constructor constructor,
970                                          Accessor accessor) {
971   LocalContext env;
972   v8::HandleScope scope(env->GetIsolate());
973
974   Local<v8::FunctionTemplate> fun_templ =
975       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
976   fun_templ->SetClassName(v8_str("funky"));
977   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
978   Local<Function> fun = fun_templ->GetFunction();
979   env->Global()->Set(v8_str("obj"), fun);
980   Local<Value> result = v8_compile("(new obj()).toString()")->Run();
981   CHECK(v8_str("[object funky]")->Equals(result));
982   CompileRun("var obj_instance = new obj();");
983   Local<Script> script;
984   script = v8_compile("obj_instance.x");
985   for (int i = 0; i < 30; i++) {
986     CHECK_EQ(1, script->Run()->Int32Value());
987   }
988   script = v8_compile("obj_instance.m");
989   for (int i = 0; i < 30; i++) {
990     CHECK_EQ(239, script->Run()->Int32Value());
991   }
992 }
993
994
995 THREADED_PROFILED_TEST(FunctionTemplate) {
996   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
997   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
998 }
999
1000
1001 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1002   ApiTestFuzzer::Fuzz();
1003   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
1004   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1005 }
1006
1007
1008 template<typename Callback>
1009 static void TestSimpleCallback(Callback callback) {
1010   LocalContext env;
1011   v8::Isolate* isolate = env->GetIsolate();
1012   v8::HandleScope scope(isolate);
1013
1014   v8::Handle<v8::ObjectTemplate> object_template =
1015       v8::ObjectTemplate::New(isolate);
1016   object_template->Set(isolate, "callback",
1017                        v8::FunctionTemplate::New(isolate, callback));
1018   v8::Local<v8::Object> object = object_template->NewInstance();
1019   (*env)->Global()->Set(v8_str("callback_object"), object);
1020   v8::Handle<v8::Script> script;
1021   script = v8_compile("callback_object.callback(17)");
1022   for (int i = 0; i < 30; i++) {
1023     CHECK_EQ(51424, script->Run()->Int32Value());
1024   }
1025   script = v8_compile("callback_object.callback(17, 24)");
1026   for (int i = 0; i < 30; i++) {
1027     CHECK_EQ(51425, script->Run()->Int32Value());
1028   }
1029 }
1030
1031
1032 THREADED_PROFILED_TEST(SimpleCallback) {
1033   TestSimpleCallback(SimpleCallback);
1034 }
1035
1036
1037 template<typename T>
1038 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1039
1040 // constant return values
1041 static int32_t fast_return_value_int32 = 471;
1042 static uint32_t fast_return_value_uint32 = 571;
1043 static const double kFastReturnValueDouble = 2.7;
1044 // variable return values
1045 static bool fast_return_value_bool = false;
1046 enum ReturnValueOddball {
1047   kNullReturnValue,
1048   kUndefinedReturnValue,
1049   kEmptyStringReturnValue
1050 };
1051 static ReturnValueOddball fast_return_value_void;
1052 static bool fast_return_value_object_is_empty = false;
1053
1054 // Helper function to avoid compiler error: insufficient contextual information
1055 // to determine type when applying FUNCTION_ADDR to a template function.
1056 static i::Address address_of(v8::FunctionCallback callback) {
1057   return FUNCTION_ADDR(callback);
1058 }
1059
1060 template<>
1061 void FastReturnValueCallback<int32_t>(
1062     const v8::FunctionCallbackInfo<v8::Value>& info) {
1063   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1064   info.GetReturnValue().Set(fast_return_value_int32);
1065 }
1066
1067 template<>
1068 void FastReturnValueCallback<uint32_t>(
1069     const v8::FunctionCallbackInfo<v8::Value>& info) {
1070   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1071   info.GetReturnValue().Set(fast_return_value_uint32);
1072 }
1073
1074 template<>
1075 void FastReturnValueCallback<double>(
1076     const v8::FunctionCallbackInfo<v8::Value>& info) {
1077   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1078   info.GetReturnValue().Set(kFastReturnValueDouble);
1079 }
1080
1081 template<>
1082 void FastReturnValueCallback<bool>(
1083     const v8::FunctionCallbackInfo<v8::Value>& info) {
1084   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1085   info.GetReturnValue().Set(fast_return_value_bool);
1086 }
1087
1088 template<>
1089 void FastReturnValueCallback<void>(
1090     const v8::FunctionCallbackInfo<v8::Value>& info) {
1091   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1092   switch (fast_return_value_void) {
1093     case kNullReturnValue:
1094       info.GetReturnValue().SetNull();
1095       break;
1096     case kUndefinedReturnValue:
1097       info.GetReturnValue().SetUndefined();
1098       break;
1099     case kEmptyStringReturnValue:
1100       info.GetReturnValue().SetEmptyString();
1101       break;
1102   }
1103 }
1104
1105 template<>
1106 void FastReturnValueCallback<Object>(
1107     const v8::FunctionCallbackInfo<v8::Value>& info) {
1108   v8::Handle<v8::Object> object;
1109   if (!fast_return_value_object_is_empty) {
1110     object = Object::New(info.GetIsolate());
1111   }
1112   info.GetReturnValue().Set(object);
1113 }
1114
1115 template<typename T>
1116 Handle<Value> TestFastReturnValues() {
1117   LocalContext env;
1118   v8::Isolate* isolate = env->GetIsolate();
1119   v8::EscapableHandleScope scope(isolate);
1120   v8::Handle<v8::ObjectTemplate> object_template =
1121       v8::ObjectTemplate::New(isolate);
1122   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1123   object_template->Set(isolate, "callback",
1124                        v8::FunctionTemplate::New(isolate, callback));
1125   v8::Local<v8::Object> object = object_template->NewInstance();
1126   (*env)->Global()->Set(v8_str("callback_object"), object);
1127   return scope.Escape(CompileRun("callback_object.callback()"));
1128 }
1129
1130
1131 THREADED_PROFILED_TEST(FastReturnValues) {
1132   LocalContext env;
1133   v8::Isolate* isolate = env->GetIsolate();
1134   v8::HandleScope scope(isolate);
1135   v8::Handle<v8::Value> value;
1136   // check int32_t and uint32_t
1137   int32_t int_values[] = {
1138       0, 234, -723,
1139       i::Smi::kMinValue, i::Smi::kMaxValue
1140   };
1141   for (size_t i = 0; i < arraysize(int_values); i++) {
1142     for (int modifier = -1; modifier <= 1; modifier++) {
1143       int int_value = int_values[i] + modifier;
1144       // check int32_t
1145       fast_return_value_int32 = int_value;
1146       value = TestFastReturnValues<int32_t>();
1147       CHECK(value->IsInt32());
1148       CHECK(fast_return_value_int32 == value->Int32Value());
1149       // check uint32_t
1150       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1151       value = TestFastReturnValues<uint32_t>();
1152       CHECK(value->IsUint32());
1153       CHECK(fast_return_value_uint32 == value->Uint32Value());
1154     }
1155   }
1156   // check double
1157   value = TestFastReturnValues<double>();
1158   CHECK(value->IsNumber());
1159   CHECK_EQ(kFastReturnValueDouble, value->ToNumber(isolate)->Value());
1160   // check bool values
1161   for (int i = 0; i < 2; i++) {
1162     fast_return_value_bool = i == 0;
1163     value = TestFastReturnValues<bool>();
1164     CHECK(value->IsBoolean());
1165     CHECK_EQ(fast_return_value_bool, value->ToBoolean(isolate)->Value());
1166   }
1167   // check oddballs
1168   ReturnValueOddball oddballs[] = {
1169       kNullReturnValue,
1170       kUndefinedReturnValue,
1171       kEmptyStringReturnValue
1172   };
1173   for (size_t i = 0; i < arraysize(oddballs); i++) {
1174     fast_return_value_void = oddballs[i];
1175     value = TestFastReturnValues<void>();
1176     switch (fast_return_value_void) {
1177       case kNullReturnValue:
1178         CHECK(value->IsNull());
1179         break;
1180       case kUndefinedReturnValue:
1181         CHECK(value->IsUndefined());
1182         break;
1183       case kEmptyStringReturnValue:
1184         CHECK(value->IsString());
1185         CHECK_EQ(0, v8::String::Cast(*value)->Length());
1186         break;
1187     }
1188   }
1189   // check handles
1190   fast_return_value_object_is_empty = false;
1191   value = TestFastReturnValues<Object>();
1192   CHECK(value->IsObject());
1193   fast_return_value_object_is_empty = true;
1194   value = TestFastReturnValues<Object>();
1195   CHECK(value->IsUndefined());
1196 }
1197
1198
1199 THREADED_TEST(FunctionTemplateSetLength) {
1200   LocalContext env;
1201   v8::Isolate* isolate = env->GetIsolate();
1202   v8::HandleScope scope(isolate);
1203   {
1204     Local<v8::FunctionTemplate> fun_templ =
1205         v8::FunctionTemplate::New(isolate,
1206                                   handle_callback,
1207                                   Handle<v8::Value>(),
1208                                   Handle<v8::Signature>(),
1209                                   23);
1210     Local<Function> fun = fun_templ->GetFunction();
1211     env->Global()->Set(v8_str("obj"), fun);
1212     Local<Script> script = v8_compile("obj.length");
1213     CHECK_EQ(23, script->Run()->Int32Value());
1214   }
1215   {
1216     Local<v8::FunctionTemplate> fun_templ =
1217         v8::FunctionTemplate::New(isolate, handle_callback);
1218     fun_templ->SetLength(22);
1219     Local<Function> fun = fun_templ->GetFunction();
1220     env->Global()->Set(v8_str("obj"), fun);
1221     Local<Script> script = v8_compile("obj.length");
1222     CHECK_EQ(22, script->Run()->Int32Value());
1223   }
1224   {
1225     // Without setting length it defaults to 0.
1226     Local<v8::FunctionTemplate> fun_templ =
1227         v8::FunctionTemplate::New(isolate, handle_callback);
1228     Local<Function> fun = fun_templ->GetFunction();
1229     env->Global()->Set(v8_str("obj"), fun);
1230     Local<Script> script = v8_compile("obj.length");
1231     CHECK_EQ(0, script->Run()->Int32Value());
1232   }
1233 }
1234
1235
1236 static void* expected_ptr;
1237 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1238   void* ptr = v8::External::Cast(*args.Data())->Value();
1239   CHECK_EQ(expected_ptr, ptr);
1240   args.GetReturnValue().Set(true);
1241 }
1242
1243
1244 static void TestExternalPointerWrapping() {
1245   LocalContext env;
1246   v8::Isolate* isolate = env->GetIsolate();
1247   v8::HandleScope scope(isolate);
1248
1249   v8::Handle<v8::Value> data =
1250       v8::External::New(isolate, expected_ptr);
1251
1252   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
1253   obj->Set(v8_str("func"),
1254            v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
1255   env->Global()->Set(v8_str("obj"), obj);
1256
1257   CHECK(CompileRun(
1258         "function foo() {\n"
1259         "  for (var i = 0; i < 13; i++) obj.func();\n"
1260         "}\n"
1261         "foo(), true")->BooleanValue());
1262 }
1263
1264
1265 THREADED_TEST(ExternalWrap) {
1266   // Check heap allocated object.
1267   int* ptr = new int;
1268   expected_ptr = ptr;
1269   TestExternalPointerWrapping();
1270   delete ptr;
1271
1272   // Check stack allocated object.
1273   int foo;
1274   expected_ptr = &foo;
1275   TestExternalPointerWrapping();
1276
1277   // Check not aligned addresses.
1278   const int n = 100;
1279   char* s = new char[n];
1280   for (int i = 0; i < n; i++) {
1281     expected_ptr = s + i;
1282     TestExternalPointerWrapping();
1283   }
1284
1285   delete[] s;
1286
1287   // Check several invalid addresses.
1288   expected_ptr = reinterpret_cast<void*>(1);
1289   TestExternalPointerWrapping();
1290
1291   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1292   TestExternalPointerWrapping();
1293
1294   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1295   TestExternalPointerWrapping();
1296
1297 #if defined(V8_HOST_ARCH_X64)
1298   // Check a value with a leading 1 bit in x64 Smi encoding.
1299   expected_ptr = reinterpret_cast<void*>(0x400000000);
1300   TestExternalPointerWrapping();
1301
1302   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1303   TestExternalPointerWrapping();
1304
1305   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1306   TestExternalPointerWrapping();
1307 #endif
1308 }
1309
1310
1311 THREADED_TEST(FindInstanceInPrototypeChain) {
1312   LocalContext env;
1313   v8::Isolate* isolate = env->GetIsolate();
1314   v8::HandleScope scope(isolate);
1315
1316   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1317   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1318   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
1319   derived->Inherit(base);
1320
1321   Local<v8::Function> base_function = base->GetFunction();
1322   Local<v8::Function> derived_function = derived->GetFunction();
1323   Local<v8::Function> other_function = other->GetFunction();
1324
1325   Local<v8::Object> base_instance = base_function->NewInstance();
1326   Local<v8::Object> derived_instance = derived_function->NewInstance();
1327   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1328   Local<v8::Object> other_instance = other_function->NewInstance();
1329   derived_instance2->Set(v8_str("__proto__"), derived_instance);
1330   other_instance->Set(v8_str("__proto__"), derived_instance2);
1331
1332   // base_instance is only an instance of base.
1333   CHECK(
1334       base_instance->Equals(base_instance->FindInstanceInPrototypeChain(base)));
1335   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1336   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1337
1338   // derived_instance is an instance of base and derived.
1339   CHECK(derived_instance->Equals(
1340       derived_instance->FindInstanceInPrototypeChain(base)));
1341   CHECK(derived_instance->Equals(
1342       derived_instance->FindInstanceInPrototypeChain(derived)));
1343   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1344
1345   // other_instance is an instance of other and its immediate
1346   // prototype derived_instance2 is an instance of base and derived.
1347   // Note, derived_instance is an instance of base and derived too,
1348   // but it comes after derived_instance2 in the prototype chain of
1349   // other_instance.
1350   CHECK(derived_instance2->Equals(
1351       other_instance->FindInstanceInPrototypeChain(base)));
1352   CHECK(derived_instance2->Equals(
1353       other_instance->FindInstanceInPrototypeChain(derived)));
1354   CHECK(other_instance->Equals(
1355       other_instance->FindInstanceInPrototypeChain(other)));
1356 }
1357
1358
1359 THREADED_TEST(TinyInteger) {
1360   LocalContext env;
1361   v8::Isolate* isolate = env->GetIsolate();
1362   v8::HandleScope scope(isolate);
1363
1364   int32_t value = 239;
1365   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1366   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1367
1368   value_obj = v8::Integer::New(isolate, value);
1369   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1370 }
1371
1372
1373 THREADED_TEST(BigSmiInteger) {
1374   LocalContext env;
1375   v8::HandleScope scope(env->GetIsolate());
1376   v8::Isolate* isolate = CcTest::isolate();
1377
1378   int32_t value = i::Smi::kMaxValue;
1379   // We cannot add one to a Smi::kMaxValue without wrapping.
1380   if (i::SmiValuesAre31Bits()) {
1381     CHECK(i::Smi::IsValid(value));
1382     CHECK(!i::Smi::IsValid(value + 1));
1383
1384     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1385     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1386
1387     value_obj = v8::Integer::New(isolate, value);
1388     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1389   }
1390 }
1391
1392
1393 THREADED_TEST(BigInteger) {
1394   LocalContext env;
1395   v8::HandleScope scope(env->GetIsolate());
1396   v8::Isolate* isolate = CcTest::isolate();
1397
1398   // We cannot add one to a Smi::kMaxValue without wrapping.
1399   if (i::SmiValuesAre31Bits()) {
1400     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1401     // The code will not be run in that case, due to the "if" guard.
1402     int32_t value =
1403         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1404     CHECK(value > i::Smi::kMaxValue);
1405     CHECK(!i::Smi::IsValid(value));
1406
1407     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1408     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1409
1410     value_obj = v8::Integer::New(isolate, value);
1411     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1412   }
1413 }
1414
1415
1416 THREADED_TEST(TinyUnsignedInteger) {
1417   LocalContext env;
1418   v8::HandleScope scope(env->GetIsolate());
1419   v8::Isolate* isolate = CcTest::isolate();
1420
1421   uint32_t value = 239;
1422
1423   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1424   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1425
1426   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1427   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1428 }
1429
1430
1431 THREADED_TEST(BigUnsignedSmiInteger) {
1432   LocalContext env;
1433   v8::HandleScope scope(env->GetIsolate());
1434   v8::Isolate* isolate = CcTest::isolate();
1435
1436   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1437   CHECK(i::Smi::IsValid(value));
1438   CHECK(!i::Smi::IsValid(value + 1));
1439
1440   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1441   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1442
1443   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1444   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1445 }
1446
1447
1448 THREADED_TEST(BigUnsignedInteger) {
1449   LocalContext env;
1450   v8::HandleScope scope(env->GetIsolate());
1451   v8::Isolate* isolate = CcTest::isolate();
1452
1453   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1454   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1455   CHECK(!i::Smi::IsValid(value));
1456
1457   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1458   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1459
1460   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1461   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1462 }
1463
1464
1465 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
1466   LocalContext env;
1467   v8::HandleScope scope(env->GetIsolate());
1468   v8::Isolate* isolate = CcTest::isolate();
1469
1470   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1471   uint32_t value = INT32_MAX_AS_UINT + 1;
1472   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
1473
1474   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1475   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1476
1477   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1478   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1479 }
1480
1481
1482 THREADED_TEST(IsNativeError) {
1483   LocalContext env;
1484   v8::HandleScope scope(env->GetIsolate());
1485   v8::Handle<Value> syntax_error = CompileRun(
1486       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1487   CHECK(syntax_error->IsNativeError());
1488   v8::Handle<Value> not_error = CompileRun("{a:42}");
1489   CHECK(!not_error->IsNativeError());
1490   v8::Handle<Value> not_object = CompileRun("42");
1491   CHECK(!not_object->IsNativeError());
1492 }
1493
1494
1495 THREADED_TEST(IsGeneratorFunctionOrObject) {
1496   LocalContext env;
1497   v8::HandleScope scope(env->GetIsolate());
1498
1499   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
1500   v8::Handle<Value> gen = CompileRun("gen");
1501   v8::Handle<Value> genObj = CompileRun("gen()");
1502   v8::Handle<Value> object = CompileRun("{a:42}");
1503   v8::Handle<Value> func = CompileRun("func");
1504
1505   CHECK(gen->IsGeneratorFunction());
1506   CHECK(gen->IsFunction());
1507   CHECK(!gen->IsGeneratorObject());
1508
1509   CHECK(!genObj->IsGeneratorFunction());
1510   CHECK(!genObj->IsFunction());
1511   CHECK(genObj->IsGeneratorObject());
1512
1513   CHECK(!object->IsGeneratorFunction());
1514   CHECK(!object->IsFunction());
1515   CHECK(!object->IsGeneratorObject());
1516
1517   CHECK(!func->IsGeneratorFunction());
1518   CHECK(func->IsFunction());
1519   CHECK(!func->IsGeneratorObject());
1520 }
1521
1522
1523 THREADED_TEST(ArgumentsObject) {
1524   LocalContext env;
1525   v8::HandleScope scope(env->GetIsolate());
1526   v8::Handle<Value> arguments_object =
1527       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
1528   CHECK(arguments_object->IsArgumentsObject());
1529   v8::Handle<Value> array = CompileRun("[1,2,3]");
1530   CHECK(!array->IsArgumentsObject());
1531   v8::Handle<Value> object = CompileRun("{a:42}");
1532   CHECK(!object->IsArgumentsObject());
1533 }
1534
1535
1536 THREADED_TEST(IsMapOrSet) {
1537   LocalContext env;
1538   v8::HandleScope scope(env->GetIsolate());
1539   v8::Handle<Value> map = CompileRun("new Map()");
1540   v8::Handle<Value> set = CompileRun("new Set()");
1541   v8::Handle<Value> weak_map = CompileRun("new WeakMap()");
1542   v8::Handle<Value> weak_set = CompileRun("new WeakSet()");
1543   CHECK(map->IsMap());
1544   CHECK(set->IsSet());
1545   CHECK(weak_map->IsWeakMap());
1546   CHECK(weak_set->IsWeakSet());
1547
1548   CHECK(!map->IsSet());
1549   CHECK(!map->IsWeakMap());
1550   CHECK(!map->IsWeakSet());
1551
1552   CHECK(!set->IsMap());
1553   CHECK(!set->IsWeakMap());
1554   CHECK(!set->IsWeakSet());
1555
1556   CHECK(!weak_map->IsMap());
1557   CHECK(!weak_map->IsSet());
1558   CHECK(!weak_map->IsWeakSet());
1559
1560   CHECK(!weak_set->IsMap());
1561   CHECK(!weak_set->IsSet());
1562   CHECK(!weak_set->IsWeakMap());
1563
1564   v8::Handle<Value> object = CompileRun("{a:42}");
1565   CHECK(!object->IsMap());
1566   CHECK(!object->IsSet());
1567   CHECK(!object->IsWeakMap());
1568   CHECK(!object->IsWeakSet());
1569 }
1570
1571
1572 THREADED_TEST(StringObject) {
1573   LocalContext env;
1574   v8::HandleScope scope(env->GetIsolate());
1575   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1576   CHECK(boxed_string->IsStringObject());
1577   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1578   CHECK(!unboxed_string->IsStringObject());
1579   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1580   CHECK(!boxed_not_string->IsStringObject());
1581   v8::Handle<Value> not_object = CompileRun("0");
1582   CHECK(!not_object->IsStringObject());
1583   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1584   CHECK(!as_boxed.IsEmpty());
1585   Local<v8::String> the_string = as_boxed->ValueOf();
1586   CHECK(!the_string.IsEmpty());
1587   ExpectObject("\"test\"", the_string);
1588   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1589   CHECK(new_boxed_string->IsStringObject());
1590   as_boxed = new_boxed_string.As<v8::StringObject>();
1591   the_string = as_boxed->ValueOf();
1592   CHECK(!the_string.IsEmpty());
1593   ExpectObject("\"test\"", the_string);
1594 }
1595
1596
1597 THREADED_TEST(NumberObject) {
1598   LocalContext env;
1599   v8::HandleScope scope(env->GetIsolate());
1600   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1601   CHECK(boxed_number->IsNumberObject());
1602   v8::Handle<Value> unboxed_number = CompileRun("42");
1603   CHECK(!unboxed_number->IsNumberObject());
1604   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1605   CHECK(!boxed_not_number->IsNumberObject());
1606   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1607   CHECK(!as_boxed.IsEmpty());
1608   double the_number = as_boxed->ValueOf();
1609   CHECK_EQ(42.0, the_number);
1610   v8::Handle<v8::Value> new_boxed_number =
1611       v8::NumberObject::New(env->GetIsolate(), 43);
1612   CHECK(new_boxed_number->IsNumberObject());
1613   as_boxed = new_boxed_number.As<v8::NumberObject>();
1614   the_number = as_boxed->ValueOf();
1615   CHECK_EQ(43.0, the_number);
1616 }
1617
1618
1619 THREADED_TEST(BooleanObject) {
1620   LocalContext env;
1621   v8::HandleScope scope(env->GetIsolate());
1622   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1623   CHECK(boxed_boolean->IsBooleanObject());
1624   v8::Handle<Value> unboxed_boolean = CompileRun("true");
1625   CHECK(!unboxed_boolean->IsBooleanObject());
1626   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1627   CHECK(!boxed_not_boolean->IsBooleanObject());
1628   v8::Handle<v8::BooleanObject> as_boxed =
1629       boxed_boolean.As<v8::BooleanObject>();
1630   CHECK(!as_boxed.IsEmpty());
1631   bool the_boolean = as_boxed->ValueOf();
1632   CHECK_EQ(true, the_boolean);
1633   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1634   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1635   CHECK(boxed_true->IsBooleanObject());
1636   CHECK(boxed_false->IsBooleanObject());
1637   as_boxed = boxed_true.As<v8::BooleanObject>();
1638   CHECK_EQ(true, as_boxed->ValueOf());
1639   as_boxed = boxed_false.As<v8::BooleanObject>();
1640   CHECK_EQ(false, as_boxed->ValueOf());
1641 }
1642
1643
1644 THREADED_TEST(PrimitiveAndWrappedBooleans) {
1645   LocalContext env;
1646   v8::HandleScope scope(env->GetIsolate());
1647
1648   Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1649   CHECK(primitive_false->IsBoolean());
1650   CHECK(!primitive_false->IsBooleanObject());
1651   CHECK(!primitive_false->BooleanValue());
1652   CHECK(!primitive_false->IsTrue());
1653   CHECK(primitive_false->IsFalse());
1654
1655   Local<Value> false_value = BooleanObject::New(false);
1656   CHECK(!false_value->IsBoolean());
1657   CHECK(false_value->IsBooleanObject());
1658   CHECK(false_value->BooleanValue());
1659   CHECK(!false_value->IsTrue());
1660   CHECK(!false_value->IsFalse());
1661
1662   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1663   CHECK(!false_boolean_object->IsBoolean());
1664   CHECK(false_boolean_object->IsBooleanObject());
1665   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1666   // CHECK(false_boolean_object->BooleanValue());
1667   CHECK(!false_boolean_object->ValueOf());
1668   CHECK(!false_boolean_object->IsTrue());
1669   CHECK(!false_boolean_object->IsFalse());
1670
1671   Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1672   CHECK(primitive_true->IsBoolean());
1673   CHECK(!primitive_true->IsBooleanObject());
1674   CHECK(primitive_true->BooleanValue());
1675   CHECK(primitive_true->IsTrue());
1676   CHECK(!primitive_true->IsFalse());
1677
1678   Local<Value> true_value = BooleanObject::New(true);
1679   CHECK(!true_value->IsBoolean());
1680   CHECK(true_value->IsBooleanObject());
1681   CHECK(true_value->BooleanValue());
1682   CHECK(!true_value->IsTrue());
1683   CHECK(!true_value->IsFalse());
1684
1685   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1686   CHECK(!true_boolean_object->IsBoolean());
1687   CHECK(true_boolean_object->IsBooleanObject());
1688   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1689   // CHECK(true_boolean_object->BooleanValue());
1690   CHECK(true_boolean_object->ValueOf());
1691   CHECK(!true_boolean_object->IsTrue());
1692   CHECK(!true_boolean_object->IsFalse());
1693 }
1694
1695
1696 THREADED_TEST(Number) {
1697   LocalContext env;
1698   v8::HandleScope scope(env->GetIsolate());
1699   double PI = 3.1415926;
1700   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
1701   CHECK_EQ(PI, pi_obj->NumberValue());
1702 }
1703
1704
1705 THREADED_TEST(ToNumber) {
1706   LocalContext env;
1707   v8::Isolate* isolate = CcTest::isolate();
1708   v8::HandleScope scope(isolate);
1709   Local<String> str = v8_str("3.1415926");
1710   CHECK_EQ(3.1415926, str->NumberValue());
1711   v8::Handle<v8::Boolean> t = v8::True(isolate);
1712   CHECK_EQ(1.0, t->NumberValue());
1713   v8::Handle<v8::Boolean> f = v8::False(isolate);
1714   CHECK_EQ(0.0, f->NumberValue());
1715 }
1716
1717
1718 THREADED_TEST(Date) {
1719   LocalContext env;
1720   v8::HandleScope scope(env->GetIsolate());
1721   double PI = 3.1415926;
1722   Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
1723   CHECK_EQ(3.0, date->NumberValue());
1724   date.As<v8::Date>()->Set(v8_str("property"),
1725                            v8::Integer::New(env->GetIsolate(), 42));
1726   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
1727 }
1728
1729
1730 THREADED_TEST(Boolean) {
1731   LocalContext env;
1732   v8::Isolate* isolate = env->GetIsolate();
1733   v8::HandleScope scope(isolate);
1734   v8::Handle<v8::Boolean> t = v8::True(isolate);
1735   CHECK(t->Value());
1736   v8::Handle<v8::Boolean> f = v8::False(isolate);
1737   CHECK(!f->Value());
1738   v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
1739   CHECK(!u->BooleanValue());
1740   v8::Handle<v8::Primitive> n = v8::Null(isolate);
1741   CHECK(!n->BooleanValue());
1742   v8::Handle<String> str1 = v8_str("");
1743   CHECK(!str1->BooleanValue());
1744   v8::Handle<String> str2 = v8_str("x");
1745   CHECK(str2->BooleanValue());
1746   CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1747   CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1748   CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1749   CHECK(v8::Number::New(isolate, 42)->BooleanValue());
1750   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1751 }
1752
1753
1754 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
1755   ApiTestFuzzer::Fuzz();
1756   args.GetReturnValue().Set(v8_num(13.4));
1757 }
1758
1759
1760 static void GetM(Local<String> name,
1761                  const v8::PropertyCallbackInfo<v8::Value>& info) {
1762   ApiTestFuzzer::Fuzz();
1763   info.GetReturnValue().Set(v8_num(876));
1764 }
1765
1766
1767 THREADED_TEST(GlobalPrototype) {
1768   v8::Isolate* isolate = CcTest::isolate();
1769   v8::HandleScope scope(isolate);
1770   v8::Handle<v8::FunctionTemplate> func_templ =
1771       v8::FunctionTemplate::New(isolate);
1772   func_templ->PrototypeTemplate()->Set(
1773       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
1774   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1775   templ->Set(isolate, "x", v8_num(200));
1776   templ->SetAccessor(v8_str("m"), GetM);
1777   LocalContext env(0, templ);
1778   v8::Handle<Script> script(v8_compile("dummy()"));
1779   v8::Handle<Value> result(script->Run());
1780   CHECK_EQ(13.4, result->NumberValue());
1781   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1782   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1783 }
1784
1785
1786 THREADED_TEST(ObjectTemplate) {
1787   v8::Isolate* isolate = CcTest::isolate();
1788   v8::HandleScope scope(isolate);
1789   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
1790   templ1->Set(isolate, "x", v8_num(10));
1791   templ1->Set(isolate, "y", v8_num(13));
1792   LocalContext env;
1793   Local<v8::Object> instance1 = templ1->NewInstance();
1794   env->Global()->Set(v8_str("p"), instance1);
1795   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1796   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1797   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1798   fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1799   Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
1800   templ2->Set(isolate, "a", v8_num(12));
1801   templ2->Set(isolate, "b", templ1);
1802   Local<v8::Object> instance2 = templ2->NewInstance();
1803   env->Global()->Set(v8_str("q"), instance2);
1804   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1805   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1806   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1807   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1808 }
1809
1810
1811 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
1812   ApiTestFuzzer::Fuzz();
1813   args.GetReturnValue().Set(v8_num(17.2));
1814 }
1815
1816
1817 static void GetKnurd(Local<String> property,
1818                      const v8::PropertyCallbackInfo<v8::Value>& info) {
1819   ApiTestFuzzer::Fuzz();
1820   info.GetReturnValue().Set(v8_num(15.2));
1821 }
1822
1823
1824 THREADED_TEST(DescriptorInheritance) {
1825   v8::Isolate* isolate = CcTest::isolate();
1826   v8::HandleScope scope(isolate);
1827   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1828   super->PrototypeTemplate()->Set(isolate, "flabby",
1829                                   v8::FunctionTemplate::New(isolate,
1830                                                             GetFlabby));
1831   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
1832
1833   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1834
1835   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
1836   base1->Inherit(super);
1837   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
1838
1839   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
1840   base2->Inherit(super);
1841   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
1842
1843   LocalContext env;
1844
1845   env->Global()->Set(v8_str("s"), super->GetFunction());
1846   env->Global()->Set(v8_str("base1"), base1->GetFunction());
1847   env->Global()->Set(v8_str("base2"), base2->GetFunction());
1848
1849   // Checks right __proto__ chain.
1850   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1851   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1852
1853   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1854
1855   // Instance accessor should not be visible on function object or its prototype
1856   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1857   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1858   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1859
1860   env->Global()->Set(v8_str("obj"),
1861                      base1->GetFunction()->NewInstance());
1862   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1863   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1864   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1865   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1866   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1867
1868   env->Global()->Set(v8_str("obj2"),
1869                      base2->GetFunction()->NewInstance());
1870   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1871   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1872   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1873   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1874   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1875
1876   // base1 and base2 cannot cross reference to each's prototype
1877   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1878   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1879 }
1880
1881
1882 // Helper functions for Interceptor/Accessor interaction tests
1883
1884 void SimpleAccessorGetter(Local<String> name,
1885                           const v8::PropertyCallbackInfo<v8::Value>& info) {
1886   Handle<Object> self = Handle<Object>::Cast(info.This());
1887   info.GetReturnValue().Set(
1888       self->Get(String::Concat(v8_str("accessor_"), name)));
1889 }
1890
1891 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1892                           const v8::PropertyCallbackInfo<void>& info) {
1893   Handle<Object> self = Handle<Object>::Cast(info.This());
1894   self->Set(String::Concat(v8_str("accessor_"), name), value);
1895 }
1896
1897 void SymbolAccessorGetter(Local<Name> name,
1898                           const v8::PropertyCallbackInfo<v8::Value>& info) {
1899   CHECK(name->IsSymbol());
1900   Local<Symbol> sym = Local<Symbol>::Cast(name);
1901   if (sym->Name()->IsUndefined())
1902     return;
1903   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
1904 }
1905
1906 void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
1907                           const v8::PropertyCallbackInfo<void>& info) {
1908   CHECK(name->IsSymbol());
1909   Local<Symbol> sym = Local<Symbol>::Cast(name);
1910   if (sym->Name()->IsUndefined())
1911     return;
1912   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
1913 }
1914
1915 void SymbolAccessorGetterReturnsDefault(
1916     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1917   CHECK(name->IsSymbol());
1918   Local<Symbol> sym = Local<Symbol>::Cast(name);
1919   if (sym->Name()->IsUndefined()) return;
1920   info.GetReturnValue().Set(info.Data());
1921 }
1922
1923 static void ThrowingSymbolAccessorGetter(
1924     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1925   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
1926 }
1927
1928
1929 THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
1930   v8::Isolate* isolate = CcTest::isolate();
1931   v8::HandleScope scope(isolate);
1932   LocalContext env;
1933   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
1934   i::Handle<i::JSObject> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
1935   CHECK(a->map()->instance_descriptors()->IsFixedArray());
1936   CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
1937   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
1938   CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
1939   // But we should still have an ExecutableAccessorInfo.
1940   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
1941   i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
1942   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
1943   CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
1944 }
1945
1946
1947 THREADED_TEST(UndefinedIsNotEnumerable) {
1948   LocalContext env;
1949   v8::HandleScope scope(env->GetIsolate());
1950   v8::Handle<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
1951   CHECK(result->IsFalse());
1952 }
1953
1954
1955 v8::Handle<Script> call_recursively_script;
1956 static const int kTargetRecursionDepth = 200;  // near maximum
1957
1958
1959 static void CallScriptRecursivelyCall(
1960     const v8::FunctionCallbackInfo<v8::Value>& args) {
1961   ApiTestFuzzer::Fuzz();
1962   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1963   if (depth == kTargetRecursionDepth) return;
1964   args.This()->Set(v8_str("depth"),
1965                    v8::Integer::New(args.GetIsolate(), depth + 1));
1966   args.GetReturnValue().Set(call_recursively_script->Run());
1967 }
1968
1969
1970 static void CallFunctionRecursivelyCall(
1971     const v8::FunctionCallbackInfo<v8::Value>& args) {
1972   ApiTestFuzzer::Fuzz();
1973   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1974   if (depth == kTargetRecursionDepth) {
1975     printf("[depth = %d]\n", depth);
1976     return;
1977   }
1978   args.This()->Set(v8_str("depth"),
1979                    v8::Integer::New(args.GetIsolate(), depth + 1));
1980   v8::Handle<Value> function =
1981       args.This()->Get(v8_str("callFunctionRecursively"));
1982   args.GetReturnValue().Set(
1983       function.As<Function>()->Call(args.This(), 0, NULL));
1984 }
1985
1986
1987 THREADED_TEST(DeepCrossLanguageRecursion) {
1988   v8::Isolate* isolate = CcTest::isolate();
1989   v8::HandleScope scope(isolate);
1990   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
1991   global->Set(v8_str("callScriptRecursively"),
1992               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
1993   global->Set(v8_str("callFunctionRecursively"),
1994               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
1995   LocalContext env(NULL, global);
1996
1997   env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
1998   call_recursively_script = v8_compile("callScriptRecursively()");
1999   call_recursively_script->Run();
2000   call_recursively_script = v8::Handle<Script>();
2001
2002   env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
2003   CompileRun("callFunctionRecursively()");
2004 }
2005
2006
2007 static void ThrowingPropertyHandlerGet(
2008     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
2009   // Since this interceptor is used on "with" objects, the runtime will look up
2010   // @@unscopables.  Punt.
2011   if (key->IsSymbol()) return;
2012   ApiTestFuzzer::Fuzz();
2013   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
2014 }
2015
2016
2017 static void ThrowingPropertyHandlerSet(
2018     Local<Name> key, Local<Value>,
2019     const v8::PropertyCallbackInfo<v8::Value>& info) {
2020   info.GetIsolate()->ThrowException(key);
2021   info.GetReturnValue().SetUndefined();  // not the same as empty handle
2022 }
2023
2024
2025 THREADED_TEST(CallbackExceptionRegression) {
2026   v8::Isolate* isolate = CcTest::isolate();
2027   v8::HandleScope scope(isolate);
2028   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
2029   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
2030       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
2031   LocalContext env;
2032   env->Global()->Set(v8_str("obj"), obj->NewInstance());
2033   v8::Handle<Value> otto =
2034       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
2035   CHECK(v8_str("otto")->Equals(otto));
2036   v8::Handle<Value> netto =
2037       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
2038   CHECK(v8_str("netto")->Equals(netto));
2039 }
2040
2041
2042 THREADED_TEST(FunctionPrototype) {
2043   v8::Isolate* isolate = CcTest::isolate();
2044   v8::HandleScope scope(isolate);
2045   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
2046   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2047   LocalContext env;
2048   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2049   Local<Script> script = v8_compile("Foo.prototype.plak");
2050   CHECK_EQ(script->Run()->Int32Value(), 321);
2051 }
2052
2053
2054 THREADED_TEST(InternalFields) {
2055   LocalContext env;
2056   v8::Isolate* isolate = env->GetIsolate();
2057   v8::HandleScope scope(isolate);
2058
2059   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2060   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2061   instance_templ->SetInternalFieldCount(1);
2062   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2063   CHECK_EQ(1, obj->InternalFieldCount());
2064   CHECK(obj->GetInternalField(0)->IsUndefined());
2065   obj->SetInternalField(0, v8_num(17));
2066   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2067 }
2068
2069
2070 THREADED_TEST(GlobalObjectInternalFields) {
2071   v8::Isolate* isolate = CcTest::isolate();
2072   v8::HandleScope scope(isolate);
2073   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
2074   global_template->SetInternalFieldCount(1);
2075   LocalContext env(NULL, global_template);
2076   v8::Handle<v8::Object> global_proxy = env->Global();
2077   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2078   CHECK_EQ(1, global->InternalFieldCount());
2079   CHECK(global->GetInternalField(0)->IsUndefined());
2080   global->SetInternalField(0, v8_num(17));
2081   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2082 }
2083
2084
2085 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2086   LocalContext env;
2087   v8::HandleScope scope(CcTest::isolate());
2088
2089   v8::Local<v8::Object> global = env->Global();
2090   global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
2091   CHECK(global->HasRealIndexedProperty(0));
2092 }
2093
2094
2095 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2096                                                void* value) {
2097   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2098   obj->SetAlignedPointerInInternalField(0, value);
2099   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2100   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2101 }
2102
2103
2104 THREADED_TEST(InternalFieldsAlignedPointers) {
2105   LocalContext env;
2106   v8::Isolate* isolate = env->GetIsolate();
2107   v8::HandleScope scope(isolate);
2108
2109   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2110   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2111   instance_templ->SetInternalFieldCount(1);
2112   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2113   CHECK_EQ(1, obj->InternalFieldCount());
2114
2115   CheckAlignedPointerInInternalField(obj, NULL);
2116
2117   int* heap_allocated = new int[100];
2118   CheckAlignedPointerInInternalField(obj, heap_allocated);
2119   delete[] heap_allocated;
2120
2121   int stack_allocated[100];
2122   CheckAlignedPointerInInternalField(obj, stack_allocated);
2123
2124   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2125   CheckAlignedPointerInInternalField(obj, huge);
2126
2127   v8::UniquePersistent<v8::Object> persistent(isolate, obj);
2128   CHECK_EQ(1, Object::InternalFieldCount(persistent));
2129   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2130 }
2131
2132
2133 static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
2134                                               void* value) {
2135   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2136   (*env)->SetAlignedPointerInEmbedderData(index, value);
2137   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2138   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2139 }
2140
2141
2142 static void* AlignedTestPointer(int i) {
2143   return reinterpret_cast<void*>(i * 1234);
2144 }
2145
2146
2147 THREADED_TEST(EmbedderDataAlignedPointers) {
2148   LocalContext env;
2149   v8::HandleScope scope(env->GetIsolate());
2150
2151   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2152
2153   int* heap_allocated = new int[100];
2154   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2155   delete[] heap_allocated;
2156
2157   int stack_allocated[100];
2158   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2159
2160   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2161   CheckAlignedPointerInEmbedderData(&env, 3, huge);
2162
2163   // Test growing of the embedder data's backing store.
2164   for (int i = 0; i < 100; i++) {
2165     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2166   }
2167   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2168   for (int i = 0; i < 100; i++) {
2169     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2170   }
2171 }
2172
2173
2174 static void CheckEmbedderData(LocalContext* env, int index,
2175                               v8::Handle<Value> data) {
2176   (*env)->SetEmbedderData(index, data);
2177   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2178 }
2179
2180
2181 THREADED_TEST(EmbedderData) {
2182   LocalContext env;
2183   v8::Isolate* isolate = env->GetIsolate();
2184   v8::HandleScope scope(isolate);
2185
2186   CheckEmbedderData(
2187       &env, 3, v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2188   CheckEmbedderData(&env, 2,
2189                     v8::String::NewFromUtf8(isolate, "over the lazy dog."));
2190   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2191   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
2192 }
2193
2194
2195 THREADED_TEST(GetIsolate) {
2196   LocalContext env;
2197   v8::Isolate* isolate = env->GetIsolate();
2198   v8::HandleScope scope(isolate);
2199   Local<v8::Object> obj = v8::Object::New(isolate);
2200   CHECK_EQ(isolate, obj->GetIsolate());
2201   CHECK_EQ(isolate, CcTest::global()->GetIsolate());
2202 }
2203
2204
2205 THREADED_TEST(IdentityHash) {
2206   LocalContext env;
2207   v8::Isolate* isolate = env->GetIsolate();
2208   v8::HandleScope scope(isolate);
2209
2210   // Ensure that the test starts with an fresh heap to test whether the hash
2211   // code is based on the address.
2212   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2213   Local<v8::Object> obj = v8::Object::New(isolate);
2214   int hash = obj->GetIdentityHash();
2215   int hash1 = obj->GetIdentityHash();
2216   CHECK_EQ(hash, hash1);
2217   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
2218   // Since the identity hash is essentially a random number two consecutive
2219   // objects should not be assigned the same hash code. If the test below fails
2220   // the random number generator should be evaluated.
2221   CHECK_NE(hash, hash2);
2222   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2223   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
2224   // Make sure that the identity hash is not based on the initial address of
2225   // the object alone. If the test below fails the random number generator
2226   // should be evaluated.
2227   CHECK_NE(hash, hash3);
2228   int hash4 = obj->GetIdentityHash();
2229   CHECK_EQ(hash, hash4);
2230
2231   // Check identity hashes behaviour in the presence of JS accessors.
2232   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2233   {
2234     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2235     Local<v8::Object> o1 = v8::Object::New(isolate);
2236     Local<v8::Object> o2 = v8::Object::New(isolate);
2237     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2238   }
2239   {
2240     CompileRun(
2241         "function cnst() { return 42; };\n"
2242         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2243     Local<v8::Object> o1 = v8::Object::New(isolate);
2244     Local<v8::Object> o2 = v8::Object::New(isolate);
2245     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2246   }
2247 }
2248
2249
2250 THREADED_TEST(GlobalProxyIdentityHash) {
2251   LocalContext env;
2252   v8::Isolate* isolate = env->GetIsolate();
2253   v8::HandleScope scope(isolate);
2254   Handle<Object> global_proxy = env->Global();
2255   int hash1 = global_proxy->GetIdentityHash();
2256   // Hash should be retained after being detached.
2257   env->DetachGlobal();
2258   int hash2 = global_proxy->GetIdentityHash();
2259   CHECK_EQ(hash1, hash2);
2260   {
2261     // Re-attach global proxy to a new context, hash should stay the same.
2262     LocalContext env2(NULL, Handle<ObjectTemplate>(), global_proxy);
2263     int hash3 = global_proxy->GetIdentityHash();
2264     CHECK_EQ(hash1, hash3);
2265   }
2266 }
2267
2268
2269 TEST(SymbolIdentityHash) {
2270   LocalContext env;
2271   v8::Isolate* isolate = env->GetIsolate();
2272   v8::HandleScope scope(isolate);
2273
2274   {
2275     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
2276     int hash = symbol->GetIdentityHash();
2277     int hash1 = symbol->GetIdentityHash();
2278     CHECK_EQ(hash, hash1);
2279     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2280     int hash3 = symbol->GetIdentityHash();
2281     CHECK_EQ(hash, hash3);
2282   }
2283
2284   {
2285     v8::Handle<v8::Symbol> js_symbol =
2286         CompileRun("Symbol('foo')").As<v8::Symbol>();
2287     int hash = js_symbol->GetIdentityHash();
2288     int hash1 = js_symbol->GetIdentityHash();
2289     CHECK_EQ(hash, hash1);
2290     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2291     int hash3 = js_symbol->GetIdentityHash();
2292     CHECK_EQ(hash, hash3);
2293   }
2294 }
2295
2296
2297 TEST(StringIdentityHash) {
2298   LocalContext env;
2299   v8::Isolate* isolate = env->GetIsolate();
2300   v8::HandleScope scope(isolate);
2301
2302   Local<v8::String> str = v8::String::NewFromUtf8(isolate, "str1");
2303   int hash = str->GetIdentityHash();
2304   int hash1 = str->GetIdentityHash();
2305   CHECK_EQ(hash, hash1);
2306   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2307   int hash3 = str->GetIdentityHash();
2308   CHECK_EQ(hash, hash3);
2309
2310   Local<v8::String> str2 = v8::String::NewFromUtf8(isolate, "str1");
2311   int hash4 = str2->GetIdentityHash();
2312   CHECK_EQ(hash, hash4);
2313 }
2314
2315
2316 THREADED_TEST(SymbolProperties) {
2317   LocalContext env;
2318   v8::Isolate* isolate = env->GetIsolate();
2319   v8::HandleScope scope(isolate);
2320
2321   v8::Local<v8::Object> obj = v8::Object::New(isolate);
2322   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2323   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
2324   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
2325
2326   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2327
2328   // Check basic symbol functionality.
2329   CHECK(sym1->IsSymbol());
2330   CHECK(sym2->IsSymbol());
2331   CHECK(!obj->IsSymbol());
2332
2333   CHECK(sym1->Equals(sym1));
2334   CHECK(sym2->Equals(sym2));
2335   CHECK(!sym1->Equals(sym2));
2336   CHECK(!sym2->Equals(sym1));
2337   CHECK(sym1->StrictEquals(sym1));
2338   CHECK(sym2->StrictEquals(sym2));
2339   CHECK(!sym1->StrictEquals(sym2));
2340   CHECK(!sym2->StrictEquals(sym1));
2341
2342   CHECK(sym2->Name()->Equals(v8_str("my-symbol")));
2343
2344   v8::Local<v8::Value> sym_val = sym2;
2345   CHECK(sym_val->IsSymbol());
2346   CHECK(sym_val->Equals(sym2));
2347   CHECK(sym_val->StrictEquals(sym2));
2348   CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2349
2350   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2351   CHECK(sym_obj->IsSymbolObject());
2352   CHECK(!sym2->IsSymbolObject());
2353   CHECK(!obj->IsSymbolObject());
2354   CHECK(!sym_obj->Equals(sym2));
2355   CHECK(!sym_obj->StrictEquals(sym2));
2356   CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
2357   CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
2358
2359   // Make sure delete of a non-existent symbol property works.
2360   CHECK(obj->Delete(sym1));
2361   CHECK(!obj->Has(sym1));
2362
2363   CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
2364   CHECK(obj->Has(sym1));
2365   CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2366   CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
2367   CHECK(obj->Has(sym1));
2368   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2369   CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2370
2371   CHECK_EQ(0u, obj->GetOwnPropertyNames()->Length());
2372   unsigned num_props = obj->GetPropertyNames()->Length();
2373   CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2374                  v8::Integer::New(isolate, 20)));
2375   CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
2376   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2377
2378   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2379
2380   CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
2381   CHECK(obj->Get(sym3)->IsUndefined());
2382   CHECK(obj->Set(sym3, v8::Integer::New(isolate, 42)));
2383   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2384   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2385             ->Equals(v8::Integer::New(isolate, 42)));
2386
2387   // Add another property and delete it afterwards to force the object in
2388   // slow case.
2389   CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
2390   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2391   CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2392   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2393   CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
2394
2395   CHECK(obj->Has(sym1));
2396   CHECK(obj->Has(sym2));
2397   CHECK(obj->Has(sym3));
2398   CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2399   CHECK(obj->Delete(sym2));
2400   CHECK(obj->Has(sym1));
2401   CHECK(!obj->Has(sym2));
2402   CHECK(obj->Has(sym3));
2403   CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2404   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2405   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2406   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2407             ->Equals(v8::Integer::New(isolate, 42)));
2408   CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
2409
2410   // Symbol properties are inherited.
2411   v8::Local<v8::Object> child = v8::Object::New(isolate);
2412   child->SetPrototype(obj);
2413   CHECK(child->Has(sym1));
2414   CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2415   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2416   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2417             ->Equals(v8::Integer::New(isolate, 42)));
2418   CHECK_EQ(0u, child->GetOwnPropertyNames()->Length());
2419 }
2420
2421
2422 THREADED_TEST(SymbolTemplateProperties) {
2423   LocalContext env;
2424   v8::Isolate* isolate = env->GetIsolate();
2425   v8::HandleScope scope(isolate);
2426   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
2427   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
2428   CHECK(!name.IsEmpty());
2429   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
2430   v8::Local<v8::Object> new_instance = foo->InstanceTemplate()->NewInstance();
2431   CHECK(!new_instance.IsEmpty());
2432   CHECK(new_instance->Has(name));
2433 }
2434
2435
2436 THREADED_TEST(PrivateProperties) {
2437   LocalContext env;
2438   v8::Isolate* isolate = env->GetIsolate();
2439   v8::HandleScope scope(isolate);
2440
2441   v8::Local<v8::Object> obj = v8::Object::New(isolate);
2442   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2443   v8::Local<v8::Private> priv2 =
2444       v8::Private::New(isolate, v8_str("my-private"));
2445
2446   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2447
2448   CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
2449
2450   // Make sure delete of a non-existent private symbol property works.
2451   CHECK(obj->DeletePrivate(priv1));
2452   CHECK(!obj->HasPrivate(priv1));
2453
2454   CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
2455   CHECK(obj->HasPrivate(priv1));
2456   CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
2457   CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
2458   CHECK(obj->HasPrivate(priv1));
2459   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2460
2461   CHECK_EQ(0u, obj->GetOwnPropertyNames()->Length());
2462   unsigned num_props = obj->GetPropertyNames()->Length();
2463   CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2464                  v8::Integer::New(isolate, 20)));
2465   CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
2466   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2467
2468   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2469
2470   // Add another property and delete it afterwards to force the object in
2471   // slow case.
2472   CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
2473   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2474   CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
2475   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2476   CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
2477
2478   CHECK(obj->HasPrivate(priv1));
2479   CHECK(obj->HasPrivate(priv2));
2480   CHECK(obj->DeletePrivate(priv2));
2481   CHECK(obj->HasPrivate(priv1));
2482   CHECK(!obj->HasPrivate(priv2));
2483   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2484   CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
2485
2486   // Private properties are inherited (for the time being).
2487   v8::Local<v8::Object> child = v8::Object::New(isolate);
2488   child->SetPrototype(obj);
2489   CHECK(child->HasPrivate(priv1));
2490   CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
2491   CHECK_EQ(0u, child->GetOwnPropertyNames()->Length());
2492 }
2493
2494
2495 THREADED_TEST(GlobalSymbols) {
2496   LocalContext env;
2497   v8::Isolate* isolate = env->GetIsolate();
2498   v8::HandleScope scope(isolate);
2499
2500   v8::Local<String> name = v8_str("my-symbol");
2501   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
2502   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
2503   CHECK(glob2->SameValue(glob));
2504
2505   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
2506   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
2507   CHECK(glob_api2->SameValue(glob_api));
2508   CHECK(!glob_api->SameValue(glob));
2509
2510   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
2511   CHECK(!sym->SameValue(glob));
2512
2513   CompileRun("var sym2 = Symbol.for('my-symbol')");
2514   v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
2515   CHECK(sym2->SameValue(glob));
2516   CHECK(!sym2->SameValue(glob_api));
2517 }
2518
2519
2520 static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
2521                                  const char* name) {
2522   LocalContext env;
2523   v8::Isolate* isolate = env->GetIsolate();
2524   v8::HandleScope scope(isolate);
2525
2526   v8::Local<v8::Symbol> symbol = getter(isolate);
2527   std::string script = std::string("var sym = ") + name;
2528   CompileRun(script.c_str());
2529   v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
2530
2531   CHECK(!value.IsEmpty());
2532   CHECK(!symbol.IsEmpty());
2533   CHECK(value->SameValue(symbol));
2534 }
2535
2536
2537 THREADED_TEST(WellKnownSymbols) {
2538   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
2539   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
2540 }
2541
2542
2543 THREADED_TEST(GlobalPrivates) {
2544   LocalContext env;
2545   v8::Isolate* isolate = env->GetIsolate();
2546   v8::HandleScope scope(isolate);
2547
2548   v8::Local<String> name = v8_str("my-private");
2549   v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
2550   v8::Local<v8::Object> obj = v8::Object::New(isolate);
2551   CHECK(obj->SetPrivate(glob, v8::Integer::New(isolate, 3)));
2552
2553   v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
2554   CHECK(obj->HasPrivate(glob2));
2555
2556   v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
2557   CHECK(!obj->HasPrivate(priv));
2558
2559   CompileRun("var intern = %CreateGlobalPrivateSymbol('my-private')");
2560   v8::Local<Value> intern = env->Global()->Get(v8_str("intern"));
2561   CHECK(!obj->Has(intern));
2562 }
2563
2564
2565 class ScopedArrayBufferContents {
2566  public:
2567   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
2568       : contents_(contents) {}
2569   ~ScopedArrayBufferContents() { free(contents_.Data()); }
2570   void* Data() const { return contents_.Data(); }
2571   size_t ByteLength() const { return contents_.ByteLength(); }
2572
2573  private:
2574   const v8::ArrayBuffer::Contents contents_;
2575 };
2576
2577 template <typename T>
2578 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2579   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2580   for (int i = 0; i < value->InternalFieldCount(); i++) {
2581     CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2582   }
2583 }
2584
2585
2586 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
2587   LocalContext env;
2588   v8::Isolate* isolate = env->GetIsolate();
2589   v8::HandleScope handle_scope(isolate);
2590
2591   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
2592   CheckInternalFieldsAreZero(ab);
2593   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2594   CHECK(!ab->IsExternal());
2595   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2596
2597   ScopedArrayBufferContents ab_contents(ab->Externalize());
2598   CHECK(ab->IsExternal());
2599
2600   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2601   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2602   DCHECK(data != NULL);
2603   env->Global()->Set(v8_str("ab"), ab);
2604
2605   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2606   CHECK_EQ(1024, result->Int32Value());
2607
2608   result = CompileRun(
2609       "var u8 = new Uint8Array(ab);"
2610       "u8[0] = 0xFF;"
2611       "u8[1] = 0xAA;"
2612       "u8.length");
2613   CHECK_EQ(1024, result->Int32Value());
2614   CHECK_EQ(0xFF, data[0]);
2615   CHECK_EQ(0xAA, data[1]);
2616   data[0] = 0xCC;
2617   data[1] = 0x11;
2618   result = CompileRun("u8[0] + u8[1]");
2619   CHECK_EQ(0xDD, result->Int32Value());
2620 }
2621
2622
2623 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
2624   LocalContext env;
2625   v8::Isolate* isolate = env->GetIsolate();
2626   v8::HandleScope handle_scope(isolate);
2627
2628
2629   v8::Local<v8::Value> result = CompileRun(
2630       "var ab1 = new ArrayBuffer(2);"
2631       "var u8_a = new Uint8Array(ab1);"
2632       "u8_a[0] = 0xAA;"
2633       "u8_a[1] = 0xFF; u8_a.buffer");
2634   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
2635   CheckInternalFieldsAreZero(ab1);
2636   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
2637   CHECK(!ab1->IsExternal());
2638   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
2639   CHECK(ab1->IsExternal());
2640
2641   result = CompileRun("ab1.byteLength");
2642   CHECK_EQ(2, result->Int32Value());
2643   result = CompileRun("u8_a[0]");
2644   CHECK_EQ(0xAA, result->Int32Value());
2645   result = CompileRun("u8_a[1]");
2646   CHECK_EQ(0xFF, result->Int32Value());
2647   result = CompileRun(
2648       "var u8_b = new Uint8Array(ab1);"
2649       "u8_b[0] = 0xBB;"
2650       "u8_a[0]");
2651   CHECK_EQ(0xBB, result->Int32Value());
2652   result = CompileRun("u8_b[1]");
2653   CHECK_EQ(0xFF, result->Int32Value());
2654
2655   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2656   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2657   CHECK_EQ(0xBB, ab1_data[0]);
2658   CHECK_EQ(0xFF, ab1_data[1]);
2659   ab1_data[0] = 0xCC;
2660   ab1_data[1] = 0x11;
2661   result = CompileRun("u8_a[0] + u8_a[1]");
2662   CHECK_EQ(0xDD, result->Int32Value());
2663 }
2664
2665
2666 THREADED_TEST(ArrayBuffer_External) {
2667   LocalContext env;
2668   v8::Isolate* isolate = env->GetIsolate();
2669   v8::HandleScope handle_scope(isolate);
2670
2671   i::ScopedVector<uint8_t> my_data(100);
2672   memset(my_data.start(), 0, 100);
2673   Local<v8::ArrayBuffer> ab3 =
2674       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
2675   CheckInternalFieldsAreZero(ab3);
2676   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
2677   CHECK(ab3->IsExternal());
2678
2679   env->Global()->Set(v8_str("ab3"), ab3);
2680
2681   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2682   CHECK_EQ(100, result->Int32Value());
2683
2684   result = CompileRun(
2685       "var u8_b = new Uint8Array(ab3);"
2686       "u8_b[0] = 0xBB;"
2687       "u8_b[1] = 0xCC;"
2688       "u8_b.length");
2689   CHECK_EQ(100, result->Int32Value());
2690   CHECK_EQ(0xBB, my_data[0]);
2691   CHECK_EQ(0xCC, my_data[1]);
2692   my_data[0] = 0xCC;
2693   my_data[1] = 0x11;
2694   result = CompileRun("u8_b[0] + u8_b[1]");
2695   CHECK_EQ(0xDD, result->Int32Value());
2696 }
2697
2698
2699 THREADED_TEST(ArrayBuffer_DisableNeuter) {
2700   LocalContext env;
2701   v8::Isolate* isolate = env->GetIsolate();
2702   v8::HandleScope handle_scope(isolate);
2703
2704   i::ScopedVector<uint8_t> my_data(100);
2705   memset(my_data.start(), 0, 100);
2706   Local<v8::ArrayBuffer> ab =
2707       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
2708   CHECK(ab->IsNeuterable());
2709
2710   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
2711   buf->set_is_neuterable(false);
2712
2713   CHECK(!ab->IsNeuterable());
2714 }
2715
2716
2717 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
2718   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
2719   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
2720 }
2721
2722
2723 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
2724   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
2725   CHECK_EQ(0, static_cast<int>(ta->Length()));
2726   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
2727 }
2728
2729
2730 static void CheckIsTypedArrayVarNeutered(const char* name) {
2731   i::ScopedVector<char> source(1024);
2732   i::SNPrintF(source,
2733               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
2734               name, name, name);
2735   CHECK(CompileRun(source.start())->IsTrue());
2736   v8::Handle<v8::TypedArray> ta =
2737       v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
2738   CheckIsNeutered(ta);
2739 }
2740
2741
2742 template <typename TypedArray, int kElementSize>
2743 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
2744                                          int byteOffset, int length) {
2745   v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
2746   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
2747   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
2748   CHECK_EQ(length, static_cast<int>(ta->Length()));
2749   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
2750   return ta;
2751 }
2752
2753
2754 THREADED_TEST(ArrayBuffer_NeuteringApi) {
2755   LocalContext env;
2756   v8::Isolate* isolate = env->GetIsolate();
2757   v8::HandleScope handle_scope(isolate);
2758
2759   v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
2760
2761   v8::Handle<v8::Uint8Array> u8a =
2762       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
2763   v8::Handle<v8::Uint8ClampedArray> u8c =
2764       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
2765   v8::Handle<v8::Int8Array> i8a =
2766       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
2767
2768   v8::Handle<v8::Uint16Array> u16a =
2769       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
2770   v8::Handle<v8::Int16Array> i16a =
2771       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
2772
2773   v8::Handle<v8::Uint32Array> u32a =
2774       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
2775   v8::Handle<v8::Int32Array> i32a =
2776       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
2777
2778   v8::Handle<v8::Float32Array> f32a =
2779       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
2780   v8::Handle<v8::Float64Array> f64a =
2781       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
2782
2783   v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
2784   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
2785   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
2786   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
2787
2788   ScopedArrayBufferContents contents(buffer->Externalize());
2789   buffer->Neuter();
2790   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
2791   CheckIsNeutered(u8a);
2792   CheckIsNeutered(u8c);
2793   CheckIsNeutered(i8a);
2794   CheckIsNeutered(u16a);
2795   CheckIsNeutered(i16a);
2796   CheckIsNeutered(u32a);
2797   CheckIsNeutered(i32a);
2798   CheckIsNeutered(f32a);
2799   CheckIsNeutered(f64a);
2800   CheckDataViewIsNeutered(dv);
2801 }
2802
2803
2804 THREADED_TEST(ArrayBuffer_NeuteringScript) {
2805   LocalContext env;
2806   v8::Isolate* isolate = env->GetIsolate();
2807   v8::HandleScope handle_scope(isolate);
2808
2809   CompileRun(
2810       "var ab = new ArrayBuffer(1024);"
2811       "var u8a = new Uint8Array(ab, 1, 1023);"
2812       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
2813       "var i8a = new Int8Array(ab, 1, 1023);"
2814       "var u16a = new Uint16Array(ab, 2, 511);"
2815       "var i16a = new Int16Array(ab, 2, 511);"
2816       "var u32a = new Uint32Array(ab, 4, 255);"
2817       "var i32a = new Int32Array(ab, 4, 255);"
2818       "var f32a = new Float32Array(ab, 4, 255);"
2819       "var f64a = new Float64Array(ab, 8, 127);"
2820       "var dv = new DataView(ab, 1, 1023);");
2821
2822   v8::Handle<v8::ArrayBuffer> ab =
2823       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
2824
2825   v8::Handle<v8::DataView> dv =
2826       v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
2827
2828   ScopedArrayBufferContents contents(ab->Externalize());
2829   ab->Neuter();
2830   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
2831   CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
2832
2833   CheckIsTypedArrayVarNeutered("u8a");
2834   CheckIsTypedArrayVarNeutered("u8c");
2835   CheckIsTypedArrayVarNeutered("i8a");
2836   CheckIsTypedArrayVarNeutered("u16a");
2837   CheckIsTypedArrayVarNeutered("i16a");
2838   CheckIsTypedArrayVarNeutered("u32a");
2839   CheckIsTypedArrayVarNeutered("i32a");
2840   CheckIsTypedArrayVarNeutered("f32a");
2841   CheckIsTypedArrayVarNeutered("f64a");
2842
2843   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
2844   CheckDataViewIsNeutered(dv);
2845 }
2846
2847
2848 THREADED_TEST(HiddenProperties) {
2849   LocalContext env;
2850   v8::Isolate* isolate = env->GetIsolate();
2851   v8::HandleScope scope(isolate);
2852
2853   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
2854   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
2855   v8::Local<v8::String> empty = v8_str("");
2856   v8::Local<v8::String> prop_name = v8_str("prop_name");
2857
2858   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2859
2860   // Make sure delete of a non-existent hidden value works
2861   CHECK(obj->DeleteHiddenValue(key));
2862
2863   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
2864   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
2865   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
2866   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2867
2868   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2869
2870   // Make sure we do not find the hidden property.
2871   CHECK(!obj->Has(empty));
2872   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2873   CHECK(obj->Get(empty)->IsUndefined());
2874   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2875   CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
2876   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2877   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
2878
2879   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2880
2881   // Add another property and delete it afterwards to force the object in
2882   // slow case.
2883   CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
2884   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2885   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
2886   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2887   CHECK(obj->Delete(prop_name));
2888   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2889
2890   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2891
2892   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
2893   CHECK(obj->GetHiddenValue(key).IsEmpty());
2894
2895   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
2896   CHECK(obj->DeleteHiddenValue(key));
2897   CHECK(obj->GetHiddenValue(key).IsEmpty());
2898 }
2899
2900
2901 THREADED_TEST(Regress97784) {
2902   // Regression test for crbug.com/97784
2903   // Messing with the Object.prototype should not have effect on
2904   // hidden properties.
2905   LocalContext env;
2906   v8::HandleScope scope(env->GetIsolate());
2907
2908   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
2909   v8::Local<v8::String> key = v8_str("hidden");
2910
2911   CompileRun(
2912       "set_called = false;"
2913       "Object.defineProperty("
2914       "    Object.prototype,"
2915       "    'hidden',"
2916       "    {get: function() { return 45; },"
2917       "     set: function() { set_called = true; }})");
2918
2919   CHECK(obj->GetHiddenValue(key).IsEmpty());
2920   // Make sure that the getter and setter from Object.prototype is not invoked.
2921   // If it did we would have full access to the hidden properties in
2922   // the accessor.
2923   CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
2924   ExpectFalse("set_called");
2925   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
2926 }
2927
2928
2929 THREADED_TEST(External) {
2930   v8::HandleScope scope(CcTest::isolate());
2931   int x = 3;
2932   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
2933   LocalContext env;
2934   env->Global()->Set(v8_str("ext"), ext);
2935   Local<Value> reext_obj = CompileRun("this.ext");
2936   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
2937   int* ptr = static_cast<int*>(reext->Value());
2938   CHECK_EQ(x, 3);
2939   *ptr = 10;
2940   CHECK_EQ(x, 10);
2941
2942   // Make sure unaligned pointers are wrapped properly.
2943   char* data = i::StrDup("0123456789");
2944   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
2945   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
2946   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
2947   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
2948
2949   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
2950   CHECK_EQ('0', *char_ptr);
2951   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
2952   CHECK_EQ('1', *char_ptr);
2953   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
2954   CHECK_EQ('2', *char_ptr);
2955   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
2956   CHECK_EQ('3', *char_ptr);
2957   i::DeleteArray(data);
2958 }
2959
2960
2961 THREADED_TEST(GlobalHandle) {
2962   v8::Isolate* isolate = CcTest::isolate();
2963   v8::Persistent<String> global;
2964   {
2965     v8::HandleScope scope(isolate);
2966     global.Reset(isolate, v8_str("str"));
2967   }
2968   {
2969     v8::HandleScope scope(isolate);
2970     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
2971   }
2972   global.Reset();
2973   {
2974     v8::HandleScope scope(isolate);
2975     global.Reset(isolate, v8_str("str"));
2976   }
2977   {
2978     v8::HandleScope scope(isolate);
2979     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
2980   }
2981   global.Reset();
2982 }
2983
2984
2985 THREADED_TEST(ResettingGlobalHandle) {
2986   v8::Isolate* isolate = CcTest::isolate();
2987   v8::Persistent<String> global;
2988   {
2989     v8::HandleScope scope(isolate);
2990     global.Reset(isolate, v8_str("str"));
2991   }
2992   v8::internal::GlobalHandles* global_handles =
2993       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
2994   int initial_handle_count = global_handles->global_handles_count();
2995   {
2996     v8::HandleScope scope(isolate);
2997     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
2998   }
2999   {
3000     v8::HandleScope scope(isolate);
3001     global.Reset(isolate, v8_str("longer"));
3002   }
3003   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3004   {
3005     v8::HandleScope scope(isolate);
3006     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3007   }
3008   global.Reset();
3009   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3010 }
3011
3012
3013 THREADED_TEST(ResettingGlobalHandleToEmpty) {
3014   v8::Isolate* isolate = CcTest::isolate();
3015   v8::Persistent<String> global;
3016   {
3017     v8::HandleScope scope(isolate);
3018     global.Reset(isolate, v8_str("str"));
3019   }
3020   v8::internal::GlobalHandles* global_handles =
3021       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3022   int initial_handle_count = global_handles->global_handles_count();
3023   {
3024     v8::HandleScope scope(isolate);
3025     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3026   }
3027   {
3028     v8::HandleScope scope(isolate);
3029     Local<String> empty;
3030     global.Reset(isolate, empty);
3031   }
3032   CHECK(global.IsEmpty());
3033   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3034 }
3035
3036
3037 template <class T>
3038 static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
3039   return unique.Pass();
3040 }
3041
3042
3043 template <class T>
3044 static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
3045                                             const v8::Persistent<T>& global) {
3046   v8::UniquePersistent<String> unique(isolate, global);
3047   return unique.Pass();
3048 }
3049
3050
3051 THREADED_TEST(UniquePersistent) {
3052   v8::Isolate* isolate = CcTest::isolate();
3053   v8::Persistent<String> global;
3054   {
3055     v8::HandleScope scope(isolate);
3056     global.Reset(isolate, v8_str("str"));
3057   }
3058   v8::internal::GlobalHandles* global_handles =
3059       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3060   int initial_handle_count = global_handles->global_handles_count();
3061   {
3062     v8::UniquePersistent<String> unique(isolate, global);
3063     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3064     // Test assignment via Pass
3065     {
3066       v8::UniquePersistent<String> copy = unique.Pass();
3067       CHECK(unique.IsEmpty());
3068       CHECK(copy == global);
3069       CHECK_EQ(initial_handle_count + 1,
3070                global_handles->global_handles_count());
3071       unique = copy.Pass();
3072     }
3073     // Test ctor via Pass
3074     {
3075       v8::UniquePersistent<String> copy(unique.Pass());
3076       CHECK(unique.IsEmpty());
3077       CHECK(copy == global);
3078       CHECK_EQ(initial_handle_count + 1,
3079                global_handles->global_handles_count());
3080       unique = copy.Pass();
3081     }
3082     // Test pass through function call
3083     {
3084       v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
3085       CHECK(unique.IsEmpty());
3086       CHECK(copy == global);
3087       CHECK_EQ(initial_handle_count + 1,
3088                global_handles->global_handles_count());
3089       unique = copy.Pass();
3090     }
3091     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3092   }
3093   // Test pass from function call
3094   {
3095     v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
3096     CHECK(unique == global);
3097     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3098   }
3099   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3100   global.Reset();
3101 }
3102
3103
3104 template <typename K, typename V>
3105 class WeakStdMapTraits : public v8::StdMapTraits<K, V> {
3106  public:
3107   typedef typename v8::PersistentValueMap<K, V, WeakStdMapTraits<K, V>> MapType;
3108   static const v8::PersistentContainerCallbackType kCallbackType = v8::kWeak;
3109   struct WeakCallbackDataType {
3110     MapType* map;
3111     K key;
3112   };
3113   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
3114                                                      Local<V> value) {
3115     WeakCallbackDataType* data = new WeakCallbackDataType;
3116     data->map = map;
3117     data->key = key;
3118     return data;
3119   }
3120   static MapType* MapFromWeakCallbackData(
3121       const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
3122     return data.GetParameter()->map;
3123   }
3124   static K KeyFromWeakCallbackData(
3125       const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
3126     return data.GetParameter()->key;
3127   }
3128   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
3129   static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<V> value,
3130                       K key) {}
3131 };
3132
3133
3134 template <typename Map>
3135 static void TestPersistentValueMap() {
3136   LocalContext env;
3137   v8::Isolate* isolate = env->GetIsolate();
3138   Map map(isolate);
3139   v8::internal::GlobalHandles* global_handles =
3140       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3141   int initial_handle_count = global_handles->global_handles_count();
3142   CHECK_EQ(0, static_cast<int>(map.Size()));
3143   {
3144     HandleScope scope(isolate);
3145     Local<v8::Object> obj = map.Get(7);
3146     CHECK(obj.IsEmpty());
3147     Local<v8::Object> expected = v8::Object::New(isolate);
3148     map.Set(7, expected);
3149     CHECK_EQ(1, static_cast<int>(map.Size()));
3150     obj = map.Get(7);
3151     CHECK(expected->Equals(obj));
3152     {
3153       typename Map::PersistentValueReference ref = map.GetReference(7);
3154       CHECK(expected->Equals(ref.NewLocal(isolate)));
3155     }
3156     v8::UniquePersistent<v8::Object> removed = map.Remove(7);
3157     CHECK_EQ(0, static_cast<int>(map.Size()));
3158     CHECK(expected == removed);
3159     removed = map.Remove(7);
3160     CHECK(removed.IsEmpty());
3161     map.Set(8, expected);
3162     CHECK_EQ(1, static_cast<int>(map.Size()));
3163     map.Set(8, expected);
3164     CHECK_EQ(1, static_cast<int>(map.Size()));
3165     {
3166       typename Map::PersistentValueReference ref;
3167       Local<v8::Object> expected2 = v8::Object::New(isolate);
3168       removed = map.Set(8, v8::UniquePersistent<v8::Object>(isolate, expected2),
3169                         &ref);
3170       CHECK_EQ(1, static_cast<int>(map.Size()));
3171       CHECK(expected == removed);
3172       CHECK(expected2->Equals(ref.NewLocal(isolate)));
3173     }
3174   }
3175   CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3176   if (map.IsWeak()) {
3177     reinterpret_cast<v8::internal::Isolate*>(isolate)
3178         ->heap()
3179         ->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3180   } else {
3181     map.Clear();
3182   }
3183   CHECK_EQ(0, static_cast<int>(map.Size()));
3184   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3185 }
3186
3187
3188 TEST(PersistentValueMap) {
3189   // Default case, w/o weak callbacks:
3190   TestPersistentValueMap<v8::StdPersistentValueMap<int, v8::Object>>();
3191
3192   // Custom traits with weak callbacks:
3193   typedef v8::PersistentValueMap<int, v8::Object,
3194                                  WeakStdMapTraits<int, v8::Object>>
3195       WeakPersistentValueMap;
3196   TestPersistentValueMap<WeakPersistentValueMap>();
3197 }
3198
3199
3200 TEST(PersistentValueVector) {
3201   LocalContext env;
3202   v8::Isolate* isolate = env->GetIsolate();
3203   v8::internal::GlobalHandles* global_handles =
3204       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3205   int handle_count = global_handles->global_handles_count();
3206   HandleScope scope(isolate);
3207
3208   v8::PersistentValueVector<v8::Object> vector(isolate);
3209
3210   Local<v8::Object> obj1 = v8::Object::New(isolate);
3211   Local<v8::Object> obj2 = v8::Object::New(isolate);
3212   v8::UniquePersistent<v8::Object> obj3(isolate, v8::Object::New(isolate));
3213
3214   CHECK(vector.IsEmpty());
3215   CHECK_EQ(0, static_cast<int>(vector.Size()));
3216
3217   vector.ReserveCapacity(3);
3218   CHECK(vector.IsEmpty());
3219
3220   vector.Append(obj1);
3221   vector.Append(obj2);
3222   vector.Append(obj1);
3223   vector.Append(obj3.Pass());
3224   vector.Append(obj1);
3225
3226   CHECK(!vector.IsEmpty());
3227   CHECK_EQ(5, static_cast<int>(vector.Size()));
3228   CHECK(obj3.IsEmpty());
3229   CHECK(obj1->Equals(vector.Get(0)));
3230   CHECK(obj1->Equals(vector.Get(2)));
3231   CHECK(obj1->Equals(vector.Get(4)));
3232   CHECK(obj2->Equals(vector.Get(1)));
3233
3234   CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
3235
3236   vector.Clear();
3237   CHECK(vector.IsEmpty());
3238   CHECK_EQ(0, static_cast<int>(vector.Size()));
3239   CHECK_EQ(handle_count, global_handles->global_handles_count());
3240 }
3241
3242
3243 THREADED_TEST(GlobalHandleUpcast) {
3244   v8::Isolate* isolate = CcTest::isolate();
3245   v8::HandleScope scope(isolate);
3246   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
3247   v8::Persistent<String> global_string(isolate, local);
3248   v8::Persistent<Value>& global_value =
3249       v8::Persistent<Value>::Cast(global_string);
3250   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3251   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
3252   global_string.Reset();
3253 }
3254
3255
3256 THREADED_TEST(HandleEquality) {
3257   v8::Isolate* isolate = CcTest::isolate();
3258   v8::Persistent<String> global1;
3259   v8::Persistent<String> global2;
3260   {
3261     v8::HandleScope scope(isolate);
3262     global1.Reset(isolate, v8_str("str"));
3263     global2.Reset(isolate, v8_str("str2"));
3264   }
3265   CHECK_EQ(global1 == global1, true);
3266   CHECK_EQ(global1 != global1, false);
3267   {
3268     v8::HandleScope scope(isolate);
3269     Local<String> local1 = Local<String>::New(isolate, global1);
3270     Local<String> local2 = Local<String>::New(isolate, global2);
3271
3272     CHECK_EQ(global1 == local1, true);
3273     CHECK_EQ(global1 != local1, false);
3274     CHECK_EQ(local1 == global1, true);
3275     CHECK_EQ(local1 != global1, false);
3276
3277     CHECK_EQ(global1 == local2, false);
3278     CHECK_EQ(global1 != local2, true);
3279     CHECK_EQ(local2 == global1, false);
3280     CHECK_EQ(local2 != global1, true);
3281
3282     CHECK_EQ(local1 == local2, false);
3283     CHECK_EQ(local1 != local2, true);
3284
3285     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3286     CHECK_EQ(local1 == anotherLocal1, true);
3287     CHECK_EQ(local1 != anotherLocal1, false);
3288   }
3289   global1.Reset();
3290   global2.Reset();
3291 }
3292
3293
3294 THREADED_TEST(LocalHandle) {
3295   v8::HandleScope scope(CcTest::isolate());
3296   v8::Local<String> local =
3297       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
3298   CHECK_EQ(local->Length(), 3);
3299 }
3300
3301
3302 class WeakCallCounter {
3303  public:
3304   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
3305   int id() { return id_; }
3306   void increment() { number_of_weak_calls_++; }
3307   int NumberOfWeakCalls() { return number_of_weak_calls_; }
3308
3309  private:
3310   int id_;
3311   int number_of_weak_calls_;
3312 };
3313
3314
3315 template <typename T>
3316 struct WeakCallCounterAndPersistent {
3317   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3318       : counter(counter) {}
3319   WeakCallCounter* counter;
3320   v8::Persistent<T> handle;
3321 };
3322
3323
3324 template <typename T>
3325 static void WeakPointerCallback(
3326     const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T>>& data) {
3327   CHECK_EQ(1234, data.GetParameter()->counter->id());
3328   data.GetParameter()->counter->increment();
3329   data.GetParameter()->handle.Reset();
3330 }
3331
3332
3333 template <typename T>
3334 static UniqueId MakeUniqueId(const Persistent<T>& p) {
3335   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3336 }
3337
3338
3339 THREADED_TEST(ApiObjectGroups) {
3340   LocalContext env;
3341   v8::Isolate* iso = env->GetIsolate();
3342   HandleScope scope(iso);
3343
3344   WeakCallCounter counter(1234);
3345
3346   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3347   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3348   WeakCallCounterAndPersistent<Value> g1c1(&counter);
3349   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3350   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3351   WeakCallCounterAndPersistent<Value> g2c1(&counter);
3352
3353   {
3354     HandleScope scope(iso);
3355     g1s1.handle.Reset(iso, Object::New(iso));
3356     g1s2.handle.Reset(iso, Object::New(iso));
3357     g1c1.handle.Reset(iso, Object::New(iso));
3358     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3359     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3360     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3361
3362     g2s1.handle.Reset(iso, Object::New(iso));
3363     g2s2.handle.Reset(iso, Object::New(iso));
3364     g2c1.handle.Reset(iso, Object::New(iso));
3365     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3366     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3367     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3368   }
3369
3370   WeakCallCounterAndPersistent<Value> root(&counter);
3371   root.handle.Reset(iso, g1s1.handle);  // make a root.
3372
3373   // Connect group 1 and 2, make a cycle.
3374   {
3375     HandleScope scope(iso);
3376     CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
3377               ->Set(0, Local<Value>::New(iso, g2s2.handle)));
3378     CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
3379               ->Set(0, Local<Value>::New(iso, g1s1.handle)));
3380   }
3381
3382   {
3383     UniqueId id1 = MakeUniqueId(g1s1.handle);
3384     UniqueId id2 = MakeUniqueId(g2s2.handle);
3385     iso->SetObjectGroupId(g1s1.handle, id1);
3386     iso->SetObjectGroupId(g1s2.handle, id1);
3387     iso->SetReferenceFromGroup(id1, g1c1.handle);
3388     iso->SetObjectGroupId(g2s1.handle, id2);
3389     iso->SetObjectGroupId(g2s2.handle, id2);
3390     iso->SetReferenceFromGroup(id2, g2c1.handle);
3391   }
3392   // Do a single full GC, ensure incremental marking is stopped.
3393   v8::internal::Heap* heap =
3394       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3395   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3396
3397   // All object should be alive.
3398   CHECK_EQ(0, counter.NumberOfWeakCalls());
3399
3400   // Weaken the root.
3401   root.handle.SetWeak(&root, &WeakPointerCallback);
3402   // But make children strong roots---all the objects (except for children)
3403   // should be collectable now.
3404   g1c1.handle.ClearWeak();
3405   g2c1.handle.ClearWeak();
3406
3407   // Groups are deleted, rebuild groups.
3408   {
3409     UniqueId id1 = MakeUniqueId(g1s1.handle);
3410     UniqueId id2 = MakeUniqueId(g2s2.handle);
3411     iso->SetObjectGroupId(g1s1.handle, id1);
3412     iso->SetObjectGroupId(g1s2.handle, id1);
3413     iso->SetReferenceFromGroup(id1, g1c1.handle);
3414     iso->SetObjectGroupId(g2s1.handle, id2);
3415     iso->SetObjectGroupId(g2s2.handle, id2);
3416     iso->SetReferenceFromGroup(id2, g2c1.handle);
3417   }
3418
3419   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3420
3421   // All objects should be gone. 5 global handles in total.
3422   CHECK_EQ(5, counter.NumberOfWeakCalls());
3423
3424   // And now make children weak again and collect them.
3425   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3426   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3427
3428   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3429   CHECK_EQ(7, counter.NumberOfWeakCalls());
3430 }
3431
3432
3433 THREADED_TEST(ApiObjectGroupsForSubtypes) {
3434   LocalContext env;
3435   v8::Isolate* iso = env->GetIsolate();
3436   HandleScope scope(iso);
3437
3438   WeakCallCounter counter(1234);
3439
3440   WeakCallCounterAndPersistent<Object> g1s1(&counter);
3441   WeakCallCounterAndPersistent<String> g1s2(&counter);
3442   WeakCallCounterAndPersistent<String> g1c1(&counter);
3443   WeakCallCounterAndPersistent<Object> g2s1(&counter);
3444   WeakCallCounterAndPersistent<String> g2s2(&counter);
3445   WeakCallCounterAndPersistent<String> g2c1(&counter);
3446
3447   {
3448     HandleScope scope(iso);
3449     g1s1.handle.Reset(iso, Object::New(iso));
3450     g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3451     g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3452     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3453     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3454     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3455
3456     g2s1.handle.Reset(iso, Object::New(iso));
3457     g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3458     g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3459     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3460     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3461     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3462   }
3463
3464   WeakCallCounterAndPersistent<Value> root(&counter);
3465   root.handle.Reset(iso, g1s1.handle);  // make a root.
3466
3467   // Connect group 1 and 2, make a cycle.
3468   {
3469     HandleScope scope(iso);
3470     CHECK(Local<Object>::New(iso, g1s1.handle)
3471               ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3472     CHECK(Local<Object>::New(iso, g2s1.handle)
3473               ->Set(0, Local<Object>::New(iso, g1s1.handle)));
3474   }
3475
3476   {
3477     UniqueId id1 = MakeUniqueId(g1s1.handle);
3478     UniqueId id2 = MakeUniqueId(g2s2.handle);
3479     iso->SetObjectGroupId(g1s1.handle, id1);
3480     iso->SetObjectGroupId(g1s2.handle, id1);
3481     iso->SetReference(g1s1.handle, g1c1.handle);
3482     iso->SetObjectGroupId(g2s1.handle, id2);
3483     iso->SetObjectGroupId(g2s2.handle, id2);
3484     iso->SetReferenceFromGroup(id2, g2c1.handle);
3485   }
3486   // Do a single full GC, ensure incremental marking is stopped.
3487   v8::internal::Heap* heap =
3488       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3489   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3490
3491   // All object should be alive.
3492   CHECK_EQ(0, counter.NumberOfWeakCalls());
3493
3494   // Weaken the root.
3495   root.handle.SetWeak(&root, &WeakPointerCallback);
3496   // But make children strong roots---all the objects (except for children)
3497   // should be collectable now.
3498   g1c1.handle.ClearWeak();
3499   g2c1.handle.ClearWeak();
3500
3501   // Groups are deleted, rebuild groups.
3502   {
3503     UniqueId id1 = MakeUniqueId(g1s1.handle);
3504     UniqueId id2 = MakeUniqueId(g2s2.handle);
3505     iso->SetObjectGroupId(g1s1.handle, id1);
3506     iso->SetObjectGroupId(g1s2.handle, id1);
3507     iso->SetReference(g1s1.handle, g1c1.handle);
3508     iso->SetObjectGroupId(g2s1.handle, id2);
3509     iso->SetObjectGroupId(g2s2.handle, id2);
3510     iso->SetReferenceFromGroup(id2, g2c1.handle);
3511   }
3512
3513   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3514
3515   // All objects should be gone. 5 global handles in total.
3516   CHECK_EQ(5, counter.NumberOfWeakCalls());
3517
3518   // And now make children weak again and collect them.
3519   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3520   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3521
3522   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3523   CHECK_EQ(7, counter.NumberOfWeakCalls());
3524 }
3525
3526
3527 THREADED_TEST(ApiObjectGroupsCycle) {
3528   LocalContext env;
3529   v8::Isolate* iso = env->GetIsolate();
3530   HandleScope scope(iso);
3531
3532   WeakCallCounter counter(1234);
3533
3534   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3535   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3536   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3537   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3538   WeakCallCounterAndPersistent<Value> g3s1(&counter);
3539   WeakCallCounterAndPersistent<Value> g3s2(&counter);
3540   WeakCallCounterAndPersistent<Value> g4s1(&counter);
3541   WeakCallCounterAndPersistent<Value> g4s2(&counter);
3542
3543   {
3544     HandleScope scope(iso);
3545     g1s1.handle.Reset(iso, Object::New(iso));
3546     g1s2.handle.Reset(iso, Object::New(iso));
3547     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3548     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3549     CHECK(g1s1.handle.IsWeak());
3550     CHECK(g1s2.handle.IsWeak());
3551
3552     g2s1.handle.Reset(iso, Object::New(iso));
3553     g2s2.handle.Reset(iso, Object::New(iso));
3554     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3555     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3556     CHECK(g2s1.handle.IsWeak());
3557     CHECK(g2s2.handle.IsWeak());
3558
3559     g3s1.handle.Reset(iso, Object::New(iso));
3560     g3s2.handle.Reset(iso, Object::New(iso));
3561     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3562     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
3563     CHECK(g3s1.handle.IsWeak());
3564     CHECK(g3s2.handle.IsWeak());
3565
3566     g4s1.handle.Reset(iso, Object::New(iso));
3567     g4s2.handle.Reset(iso, Object::New(iso));
3568     g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
3569     g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
3570     CHECK(g4s1.handle.IsWeak());
3571     CHECK(g4s2.handle.IsWeak());
3572   }
3573
3574   WeakCallCounterAndPersistent<Value> root(&counter);
3575   root.handle.Reset(iso, g1s1.handle);  // make a root.
3576
3577   // Connect groups.  We're building the following cycle:
3578   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3579   // groups.
3580   {
3581     UniqueId id1 = MakeUniqueId(g1s1.handle);
3582     UniqueId id2 = MakeUniqueId(g2s1.handle);
3583     UniqueId id3 = MakeUniqueId(g3s1.handle);
3584     UniqueId id4 = MakeUniqueId(g4s1.handle);
3585     iso->SetObjectGroupId(g1s1.handle, id1);
3586     iso->SetObjectGroupId(g1s2.handle, id1);
3587     iso->SetReferenceFromGroup(id1, g2s1.handle);
3588     iso->SetObjectGroupId(g2s1.handle, id2);
3589     iso->SetObjectGroupId(g2s2.handle, id2);
3590     iso->SetReferenceFromGroup(id2, g3s1.handle);
3591     iso->SetObjectGroupId(g3s1.handle, id3);
3592     iso->SetObjectGroupId(g3s2.handle, id3);
3593     iso->SetReferenceFromGroup(id3, g4s1.handle);
3594     iso->SetObjectGroupId(g4s1.handle, id4);
3595     iso->SetObjectGroupId(g4s2.handle, id4);
3596     iso->SetReferenceFromGroup(id4, g1s1.handle);
3597   }
3598   // Do a single full GC
3599   v8::internal::Heap* heap =
3600       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3601   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3602
3603   // All object should be alive.
3604   CHECK_EQ(0, counter.NumberOfWeakCalls());
3605
3606   // Weaken the root.
3607   root.handle.SetWeak(&root, &WeakPointerCallback);
3608
3609   // Groups are deleted, rebuild groups.
3610   {
3611     UniqueId id1 = MakeUniqueId(g1s1.handle);
3612     UniqueId id2 = MakeUniqueId(g2s1.handle);
3613     UniqueId id3 = MakeUniqueId(g3s1.handle);
3614     UniqueId id4 = MakeUniqueId(g4s1.handle);
3615     iso->SetObjectGroupId(g1s1.handle, id1);
3616     iso->SetObjectGroupId(g1s2.handle, id1);
3617     iso->SetReferenceFromGroup(id1, g2s1.handle);
3618     iso->SetObjectGroupId(g2s1.handle, id2);
3619     iso->SetObjectGroupId(g2s2.handle, id2);
3620     iso->SetReferenceFromGroup(id2, g3s1.handle);
3621     iso->SetObjectGroupId(g3s1.handle, id3);
3622     iso->SetObjectGroupId(g3s2.handle, id3);
3623     iso->SetReferenceFromGroup(id3, g4s1.handle);
3624     iso->SetObjectGroupId(g4s1.handle, id4);
3625     iso->SetObjectGroupId(g4s2.handle, id4);
3626     iso->SetReferenceFromGroup(id4, g1s1.handle);
3627   }
3628
3629   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3630
3631   // All objects should be gone. 9 global handles in total.
3632   CHECK_EQ(9, counter.NumberOfWeakCalls());
3633 }
3634
3635
3636 THREADED_TEST(WeakRootsSurviveTwoRoundsOfGC) {
3637   LocalContext env;
3638   v8::Isolate* iso = env->GetIsolate();
3639   HandleScope scope(iso);
3640
3641   WeakCallCounter counter(1234);
3642
3643   WeakCallCounterAndPersistent<Value> weak_obj(&counter);
3644
3645   // Create a weak object that references a internalized string.
3646   {
3647     HandleScope scope(iso);
3648     weak_obj.handle.Reset(iso, Object::New(iso));
3649     weak_obj.handle.SetWeak(&weak_obj, &WeakPointerCallback);
3650     CHECK(weak_obj.handle.IsWeak());
3651     Local<Object>::New(iso, weak_obj.handle.As<Object>())
3652         ->Set(v8_str("x"), String::NewFromUtf8(iso, "magic cookie",
3653                                                String::kInternalizedString));
3654   }
3655   // Do a single full GC
3656   i::Isolate* i_iso = reinterpret_cast<v8::internal::Isolate*>(iso);
3657   i::Heap* heap = i_iso->heap();
3658   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3659
3660   // We should have received the weak callback.
3661   CHECK_EQ(1, counter.NumberOfWeakCalls());
3662
3663   // Check that the string is still alive.
3664   {
3665     HandleScope scope(iso);
3666     i::MaybeHandle<i::String> magic_string =
3667         i::StringTable::LookupStringIfExists(
3668             i_iso,
3669             v8::Utils::OpenHandle(*String::NewFromUtf8(iso, "magic cookie")));
3670     magic_string.Check();
3671   }
3672 }
3673
3674
3675 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3676 // on the buildbots, so was made non-threaded for the time being.
3677 TEST(ApiObjectGroupsCycleForScavenger) {
3678   i::FLAG_stress_compaction = false;
3679   i::FLAG_gc_global = false;
3680   LocalContext env;
3681   v8::Isolate* iso = env->GetIsolate();
3682   HandleScope scope(iso);
3683
3684   WeakCallCounter counter(1234);
3685
3686   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3687   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3688   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3689   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3690   WeakCallCounterAndPersistent<Value> g3s1(&counter);
3691   WeakCallCounterAndPersistent<Value> g3s2(&counter);
3692
3693   {
3694     HandleScope scope(iso);
3695     g1s1.handle.Reset(iso, Object::New(iso));
3696     g1s2.handle.Reset(iso, Object::New(iso));
3697     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3698     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3699
3700     g2s1.handle.Reset(iso, Object::New(iso));
3701     g2s2.handle.Reset(iso, Object::New(iso));
3702     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3703     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3704
3705     g3s1.handle.Reset(iso, Object::New(iso));
3706     g3s2.handle.Reset(iso, Object::New(iso));
3707     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3708     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
3709   }
3710
3711   // Make a root.
3712   WeakCallCounterAndPersistent<Value> root(&counter);
3713   root.handle.Reset(iso, g1s1.handle);
3714   root.handle.MarkPartiallyDependent();
3715
3716   // Connect groups.  We're building the following cycle:
3717   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3718   // groups.
3719   {
3720     HandleScope handle_scope(iso);
3721     g1s1.handle.MarkPartiallyDependent();
3722     g1s2.handle.MarkPartiallyDependent();
3723     g2s1.handle.MarkPartiallyDependent();
3724     g2s2.handle.MarkPartiallyDependent();
3725     g3s1.handle.MarkPartiallyDependent();
3726     g3s2.handle.MarkPartiallyDependent();
3727     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3728     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3729     Local<Object>::New(iso, g1s1.handle.As<Object>())
3730         ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3731     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3732     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3733     Local<Object>::New(iso, g2s1.handle.As<Object>())
3734         ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3735     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3736     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3737     Local<Object>::New(iso, g3s1.handle.As<Object>())
3738         ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
3739   }
3740
3741   v8::internal::Heap* heap =
3742       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3743   heap->CollectAllGarbage(i::Heap::kNoGCFlags);
3744
3745   // All objects should be alive.
3746   CHECK_EQ(0, counter.NumberOfWeakCalls());
3747
3748   // Weaken the root.
3749   root.handle.SetWeak(&root, &WeakPointerCallback);
3750   root.handle.MarkPartiallyDependent();
3751
3752   // Groups are deleted, rebuild groups.
3753   {
3754     HandleScope handle_scope(iso);
3755     g1s1.handle.MarkPartiallyDependent();
3756     g1s2.handle.MarkPartiallyDependent();
3757     g2s1.handle.MarkPartiallyDependent();
3758     g2s2.handle.MarkPartiallyDependent();
3759     g3s1.handle.MarkPartiallyDependent();
3760     g3s2.handle.MarkPartiallyDependent();
3761     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3762     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3763     Local<Object>::New(iso, g1s1.handle.As<Object>())
3764         ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3765     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3766     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3767     Local<Object>::New(iso, g2s1.handle.As<Object>())
3768         ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3769     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3770     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3771     Local<Object>::New(iso, g3s1.handle.As<Object>())
3772         ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
3773   }
3774
3775   heap->CollectAllGarbage(i::Heap::kNoGCFlags);
3776
3777   // All objects should be gone. 7 global handles in total.
3778   CHECK_EQ(7, counter.NumberOfWeakCalls());
3779 }
3780
3781
3782 THREADED_TEST(ScriptException) {
3783   LocalContext env;
3784   v8::HandleScope scope(env->GetIsolate());
3785   Local<Script> script = v8_compile("throw 'panama!';");
3786   v8::TryCatch try_catch;
3787   Local<Value> result = script->Run();
3788   CHECK(result.IsEmpty());
3789   CHECK(try_catch.HasCaught());
3790   String::Utf8Value exception_value(try_catch.Exception());
3791   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
3792 }
3793
3794
3795 TEST(TryCatchCustomException) {
3796   LocalContext env;
3797   v8::Isolate* isolate = env->GetIsolate();
3798   v8::HandleScope scope(isolate);
3799   v8::TryCatch try_catch;
3800   CompileRun(
3801       "function CustomError() { this.a = 'b'; }"
3802       "(function f() { throw new CustomError(); })();");
3803   CHECK(try_catch.HasCaught());
3804   CHECK(try_catch.Exception()
3805             ->ToObject(isolate)
3806             ->Get(v8_str("a"))
3807             ->Equals(v8_str("b")));
3808 }
3809
3810
3811 bool message_received;
3812
3813
3814 static void check_message_0(v8::Handle<v8::Message> message,
3815                             v8::Handle<Value> data) {
3816   CHECK_EQ(5.76, data->NumberValue());
3817   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
3818   CHECK(!message->IsSharedCrossOrigin());
3819   message_received = true;
3820 }
3821
3822
3823 THREADED_TEST(MessageHandler0) {
3824   message_received = false;
3825   v8::HandleScope scope(CcTest::isolate());
3826   CHECK(!message_received);
3827   LocalContext context;
3828   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
3829   v8::Handle<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
3830   script->Run();
3831   CHECK(message_received);
3832   // clear out the message listener
3833   v8::V8::RemoveMessageListeners(check_message_0);
3834 }
3835
3836
3837 static void check_message_1(v8::Handle<v8::Message> message,
3838                             v8::Handle<Value> data) {
3839   CHECK(data->IsNumber());
3840   CHECK_EQ(1337, data->Int32Value());
3841   CHECK(!message->IsSharedCrossOrigin());
3842   message_received = true;
3843 }
3844
3845
3846 TEST(MessageHandler1) {
3847   message_received = false;
3848   v8::HandleScope scope(CcTest::isolate());
3849   CHECK(!message_received);
3850   v8::V8::AddMessageListener(check_message_1);
3851   LocalContext context;
3852   CompileRun("throw 1337;");
3853   CHECK(message_received);
3854   // clear out the message listener
3855   v8::V8::RemoveMessageListeners(check_message_1);
3856 }
3857
3858
3859 static void check_message_2(v8::Handle<v8::Message> message,
3860                             v8::Handle<Value> data) {
3861   LocalContext context;
3862   CHECK(data->IsObject());
3863   v8::Local<v8::Value> hidden_property =
3864       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
3865   CHECK(v8_str("hidden value")->Equals(hidden_property));
3866   CHECK(!message->IsSharedCrossOrigin());
3867   message_received = true;
3868 }
3869
3870
3871 TEST(MessageHandler2) {
3872   message_received = false;
3873   v8::HandleScope scope(CcTest::isolate());
3874   CHECK(!message_received);
3875   v8::V8::AddMessageListener(check_message_2);
3876   LocalContext context;
3877   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
3878   v8::Object::Cast(*error)
3879       ->SetHiddenValue(v8_str("hidden key"), v8_str("hidden value"));
3880   context->Global()->Set(v8_str("error"), error);
3881   CompileRun("throw error;");
3882   CHECK(message_received);
3883   // clear out the message listener
3884   v8::V8::RemoveMessageListeners(check_message_2);
3885 }
3886
3887
3888 static void check_message_3(v8::Handle<v8::Message> message,
3889                             v8::Handle<Value> data) {
3890   CHECK(message->IsSharedCrossOrigin());
3891   CHECK(message->GetScriptOrigin().ResourceIsSharedCrossOrigin()->Value());
3892   CHECK(message->GetScriptOrigin().ResourceIsEmbedderDebugScript()->Value());
3893   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
3894   message_received = true;
3895 }
3896
3897
3898 TEST(MessageHandler3) {
3899   message_received = false;
3900   v8::Isolate* isolate = CcTest::isolate();
3901   v8::HandleScope scope(isolate);
3902   CHECK(!message_received);
3903   v8::V8::AddMessageListener(check_message_3);
3904   LocalContext context;
3905   v8::ScriptOrigin origin =
3906       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
3907                        v8::Integer::New(isolate, 2), v8::True(isolate),
3908                        Handle<v8::Integer>(), v8::True(isolate));
3909   v8::Handle<v8::Script> script =
3910       Script::Compile(v8_str("throw 'error'"), &origin);
3911   script->Run();
3912   CHECK(message_received);
3913   // clear out the message listener
3914   v8::V8::RemoveMessageListeners(check_message_3);
3915 }
3916
3917
3918 static void check_message_4(v8::Handle<v8::Message> message,
3919                             v8::Handle<Value> data) {
3920   CHECK(!message->IsSharedCrossOrigin());
3921   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
3922   message_received = true;
3923 }
3924
3925
3926 TEST(MessageHandler4) {
3927   message_received = false;
3928   v8::Isolate* isolate = CcTest::isolate();
3929   v8::HandleScope scope(isolate);
3930   CHECK(!message_received);
3931   v8::V8::AddMessageListener(check_message_4);
3932   LocalContext context;
3933   v8::ScriptOrigin origin =
3934       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
3935                        v8::Integer::New(isolate, 2), v8::False(isolate));
3936   v8::Handle<v8::Script> script =
3937       Script::Compile(v8_str("throw 'error'"), &origin);
3938   script->Run();
3939   CHECK(message_received);
3940   // clear out the message listener
3941   v8::V8::RemoveMessageListeners(check_message_4);
3942 }
3943
3944
3945 static void check_message_5a(v8::Handle<v8::Message> message,
3946                              v8::Handle<Value> data) {
3947   CHECK(message->IsSharedCrossOrigin());
3948   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
3949   message_received = true;
3950 }
3951
3952
3953 static void check_message_5b(v8::Handle<v8::Message> message,
3954                              v8::Handle<Value> data) {
3955   CHECK(!message->IsSharedCrossOrigin());
3956   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
3957   message_received = true;
3958 }
3959
3960
3961 TEST(MessageHandler5) {
3962   message_received = false;
3963   v8::Isolate* isolate = CcTest::isolate();
3964   v8::HandleScope scope(isolate);
3965   CHECK(!message_received);
3966   v8::V8::AddMessageListener(check_message_5a);
3967   LocalContext context;
3968   v8::ScriptOrigin origin =
3969       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
3970                        v8::Integer::New(isolate, 2), v8::True(isolate));
3971   v8::Handle<v8::Script> script =
3972       Script::Compile(v8_str("throw 'error'"), &origin);
3973   script->Run();
3974   CHECK(message_received);
3975   // clear out the message listener
3976   v8::V8::RemoveMessageListeners(check_message_5a);
3977
3978   message_received = false;
3979   v8::V8::AddMessageListener(check_message_5b);
3980   origin = v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
3981                             v8::Integer::New(isolate, 2), v8::False(isolate));
3982   script = Script::Compile(v8_str("throw 'error'"), &origin);
3983   script->Run();
3984   CHECK(message_received);
3985   // clear out the message listener
3986   v8::V8::RemoveMessageListeners(check_message_5b);
3987 }
3988
3989
3990 TEST(NativeWeakMap) {
3991   v8::Isolate* isolate = CcTest::isolate();
3992   HandleScope scope(isolate);
3993   Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
3994   CHECK(!weak_map.IsEmpty());
3995
3996   LocalContext env;
3997   Local<Object> value = v8::Object::New(isolate);
3998
3999   Local<Object> local1 = v8::Object::New(isolate);
4000   CHECK(!weak_map->Has(local1));
4001   CHECK(weak_map->Get(local1)->IsUndefined());
4002   weak_map->Set(local1, value);
4003   CHECK(weak_map->Has(local1));
4004   CHECK(value->Equals(weak_map->Get(local1)));
4005
4006   WeakCallCounter counter(1234);
4007   WeakCallCounterAndPersistent<Value> o1(&counter);
4008   WeakCallCounterAndPersistent<Value> o2(&counter);
4009   WeakCallCounterAndPersistent<Value> s1(&counter);
4010   {
4011     HandleScope scope(isolate);
4012     Local<v8::Object> obj1 = v8::Object::New(isolate);
4013     Local<v8::Object> obj2 = v8::Object::New(isolate);
4014     Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
4015
4016     weak_map->Set(obj1, value);
4017     weak_map->Set(obj2, value);
4018     weak_map->Set(sym1, value);
4019
4020     o1.handle.Reset(isolate, obj1);
4021     o2.handle.Reset(isolate, obj2);
4022     s1.handle.Reset(isolate, sym1);
4023
4024     CHECK(weak_map->Has(local1));
4025     CHECK(weak_map->Has(obj1));
4026     CHECK(weak_map->Has(obj2));
4027     CHECK(weak_map->Has(sym1));
4028
4029     CHECK(value->Equals(weak_map->Get(local1)));
4030     CHECK(value->Equals(weak_map->Get(obj1)));
4031     CHECK(value->Equals(weak_map->Get(obj2)));
4032     CHECK(value->Equals(weak_map->Get(sym1)));
4033   }
4034   CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
4035   {
4036     HandleScope scope(isolate);
4037     CHECK(value->Equals(weak_map->Get(local1)));
4038     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o1.handle))));
4039     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o2.handle))));
4040     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, s1.handle))));
4041   }
4042
4043   o1.handle.SetWeak(&o1, &WeakPointerCallback);
4044   o2.handle.SetWeak(&o2, &WeakPointerCallback);
4045   s1.handle.SetWeak(&s1, &WeakPointerCallback);
4046
4047   CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
4048   CHECK_EQ(3, counter.NumberOfWeakCalls());
4049
4050   CHECK(o1.handle.IsEmpty());
4051   CHECK(o2.handle.IsEmpty());
4052   CHECK(s1.handle.IsEmpty());
4053
4054   CHECK(value->Equals(weak_map->Get(local1)));
4055   CHECK(weak_map->Delete(local1));
4056   CHECK(!weak_map->Has(local1));
4057   CHECK(weak_map->Get(local1)->IsUndefined());
4058 }
4059
4060
4061 THREADED_TEST(GetSetProperty) {
4062   LocalContext context;
4063   v8::Isolate* isolate = context->GetIsolate();
4064   v8::HandleScope scope(isolate);
4065   context->Global()->Set(v8_str("foo"), v8_num(14));
4066   context->Global()->Set(v8_str("12"), v8_num(92));
4067   context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
4068   context->Global()->Set(v8_num(13), v8_num(56));
4069   Local<Value> foo = CompileRun("this.foo");
4070   CHECK_EQ(14, foo->Int32Value());
4071   Local<Value> twelve = CompileRun("this[12]");
4072   CHECK_EQ(92, twelve->Int32Value());
4073   Local<Value> sixteen = CompileRun("this[16]");
4074   CHECK_EQ(32, sixteen->Int32Value());
4075   Local<Value> thirteen = CompileRun("this[13]");
4076   CHECK_EQ(56, thirteen->Int32Value());
4077   CHECK_EQ(92,
4078            context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
4079   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4080   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
4081   CHECK_EQ(32,
4082            context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
4083   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4084   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
4085   CHECK_EQ(56,
4086            context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
4087   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4088   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4089 }
4090
4091
4092 THREADED_TEST(PropertyAttributes) {
4093   LocalContext context;
4094   v8::HandleScope scope(context->GetIsolate());
4095   // none
4096   Local<String> prop = v8_str("none");
4097   context->Global()->Set(prop, v8_num(7));
4098   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4099   // read-only
4100   prop = v8_str("read_only");
4101   context->Global()->ForceSet(prop, v8_num(7), v8::ReadOnly);
4102   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4103   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
4104   CompileRun("read_only = 9");
4105   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4106   context->Global()->Set(prop, v8_num(10));
4107   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4108   // dont-delete
4109   prop = v8_str("dont_delete");
4110   context->Global()->ForceSet(prop, v8_num(13), v8::DontDelete);
4111   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4112   CompileRun("delete dont_delete");
4113   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4114   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4115   // dont-enum
4116   prop = v8_str("dont_enum");
4117   context->Global()->ForceSet(prop, v8_num(28), v8::DontEnum);
4118   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4119   // absent
4120   prop = v8_str("absent");
4121   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4122   Local<Value> fake_prop = v8_num(1);
4123   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4124   // exception
4125   TryCatch try_catch;
4126   Local<Value> exception =
4127       CompileRun("({ toString: function() { throw 'exception';} })");
4128   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4129   CHECK(try_catch.HasCaught());
4130   String::Utf8Value exception_value(try_catch.Exception());
4131   CHECK_EQ(0, strcmp("exception", *exception_value));
4132   try_catch.Reset();
4133 }
4134
4135
4136 THREADED_TEST(Array) {
4137   LocalContext context;
4138   v8::HandleScope scope(context->GetIsolate());
4139   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
4140   CHECK_EQ(0u, array->Length());
4141   CHECK(array->Get(0)->IsUndefined());
4142   CHECK(!array->Has(0));
4143   CHECK(array->Get(100)->IsUndefined());
4144   CHECK(!array->Has(100));
4145   array->Set(2, v8_num(7));
4146   CHECK_EQ(3u, array->Length());
4147   CHECK(!array->Has(0));
4148   CHECK(!array->Has(1));
4149   CHECK(array->Has(2));
4150   CHECK_EQ(7, array->Get(2)->Int32Value());
4151   Local<Value> obj = CompileRun("[1, 2, 3]");
4152   Local<v8::Array> arr = obj.As<v8::Array>();
4153   CHECK_EQ(3u, arr->Length());
4154   CHECK_EQ(1, arr->Get(0)->Int32Value());
4155   CHECK_EQ(2, arr->Get(1)->Int32Value());
4156   CHECK_EQ(3, arr->Get(2)->Int32Value());
4157   array = v8::Array::New(context->GetIsolate(), 27);
4158   CHECK_EQ(27u, array->Length());
4159   array = v8::Array::New(context->GetIsolate(), -27);
4160   CHECK_EQ(0u, array->Length());
4161 }
4162
4163
4164 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
4165   v8::EscapableHandleScope scope(args.GetIsolate());
4166   ApiTestFuzzer::Fuzz();
4167   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
4168   for (int i = 0; i < args.Length(); i++) result->Set(i, args[i]);
4169   args.GetReturnValue().Set(scope.Escape(result));
4170 }
4171
4172
4173 THREADED_TEST(Vector) {
4174   v8::Isolate* isolate = CcTest::isolate();
4175   v8::HandleScope scope(isolate);
4176   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
4177   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
4178   LocalContext context(0, global);
4179
4180   const char* fun = "f()";
4181   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
4182   CHECK_EQ(0u, a0->Length());
4183
4184   const char* fun2 = "f(11)";
4185   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
4186   CHECK_EQ(1u, a1->Length());
4187   CHECK_EQ(11, a1->Get(0)->Int32Value());
4188
4189   const char* fun3 = "f(12, 13)";
4190   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
4191   CHECK_EQ(2u, a2->Length());
4192   CHECK_EQ(12, a2->Get(0)->Int32Value());
4193   CHECK_EQ(13, a2->Get(1)->Int32Value());
4194
4195   const char* fun4 = "f(14, 15, 16)";
4196   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
4197   CHECK_EQ(3u, a3->Length());
4198   CHECK_EQ(14, a3->Get(0)->Int32Value());
4199   CHECK_EQ(15, a3->Get(1)->Int32Value());
4200   CHECK_EQ(16, a3->Get(2)->Int32Value());
4201
4202   const char* fun5 = "f(17, 18, 19, 20)";
4203   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
4204   CHECK_EQ(4u, a4->Length());
4205   CHECK_EQ(17, a4->Get(0)->Int32Value());
4206   CHECK_EQ(18, a4->Get(1)->Int32Value());
4207   CHECK_EQ(19, a4->Get(2)->Int32Value());
4208   CHECK_EQ(20, a4->Get(3)->Int32Value());
4209 }
4210
4211
4212 THREADED_TEST(FunctionCall) {
4213   LocalContext context;
4214   v8::Isolate* isolate = context->GetIsolate();
4215   v8::HandleScope scope(isolate);
4216   CompileRun(
4217       "function Foo() {"
4218       "  var result = [];"
4219       "  for (var i = 0; i < arguments.length; i++) {"
4220       "    result.push(arguments[i]);"
4221       "  }"
4222       "  return result;"
4223       "}"
4224       "function ReturnThisSloppy() {"
4225       "  return this;"
4226       "}"
4227       "function ReturnThisStrict() {"
4228       "  'use strict';"
4229       "  return this;"
4230       "}");
4231   Local<Function> Foo =
4232       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4233   Local<Function> ReturnThisSloppy =
4234       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4235   Local<Function> ReturnThisStrict =
4236       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
4237
4238   v8::Handle<Value>* args0 = NULL;
4239   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4240   CHECK_EQ(0u, a0->Length());
4241
4242   v8::Handle<Value> args1[] = {v8_num(1.1)};
4243   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4244   CHECK_EQ(1u, a1->Length());
4245   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4246
4247   v8::Handle<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
4248   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4249   CHECK_EQ(2u, a2->Length());
4250   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4251   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4252
4253   v8::Handle<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
4254   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4255   CHECK_EQ(3u, a3->Length());
4256   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4257   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4258   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4259
4260   v8::Handle<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
4261                                v8_num(10.11)};
4262   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4263   CHECK_EQ(4u, a4->Length());
4264   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4265   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4266   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4267   CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4268
4269   Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4270   CHECK(r1->StrictEquals(context->Global()));
4271   Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4272   CHECK(r2->StrictEquals(context->Global()));
4273   Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4274   CHECK(r3->IsNumberObject());
4275   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4276   Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4277   CHECK(r4->IsStringObject());
4278   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4279   Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4280   CHECK(r5->IsBooleanObject());
4281   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4282
4283   Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4284   CHECK(r6->IsUndefined());
4285   Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4286   CHECK(r7->IsNull());
4287   Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4288   CHECK(r8->StrictEquals(v8_num(42)));
4289   Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4290   CHECK(r9->StrictEquals(v8_str("hello")));
4291   Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4292   CHECK(r10->StrictEquals(v8::True(isolate)));
4293 }
4294
4295
4296 THREADED_TEST(ConstructCall) {
4297   LocalContext context;
4298   v8::Isolate* isolate = context->GetIsolate();
4299   v8::HandleScope scope(isolate);
4300   CompileRun(
4301       "function Foo() {"
4302       "  var result = [];"
4303       "  for (var i = 0; i < arguments.length; i++) {"
4304       "    result.push(arguments[i]);"
4305       "  }"
4306       "  return result;"
4307       "}");
4308   Local<Function> Foo =
4309       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4310
4311   v8::Handle<Value>* args0 = NULL;
4312   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4313   CHECK_EQ(0u, a0->Length());
4314
4315   v8::Handle<Value> args1[] = {v8_num(1.1)};
4316   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4317   CHECK_EQ(1u, a1->Length());
4318   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4319
4320   v8::Handle<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
4321   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4322   CHECK_EQ(2u, a2->Length());
4323   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4324   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4325
4326   v8::Handle<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
4327   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4328   CHECK_EQ(3u, a3->Length());
4329   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4330   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4331   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4332
4333   v8::Handle<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
4334                                v8_num(10.11)};
4335   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4336   CHECK_EQ(4u, a4->Length());
4337   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4338   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4339   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4340   CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4341 }
4342
4343
4344 static void CheckUncle(v8::TryCatch* try_catch) {
4345   CHECK(try_catch->HasCaught());
4346   String::Utf8Value str_value(try_catch->Exception());
4347   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
4348   try_catch->Reset();
4349 }
4350
4351
4352 THREADED_TEST(ConversionNumber) {
4353   LocalContext env;
4354   v8::Isolate* isolate = env->GetIsolate();
4355   v8::HandleScope scope(isolate);
4356   // Very large number.
4357   CompileRun("var obj = Math.pow(2,32) * 1237;");
4358   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4359   CHECK_EQ(5312874545152.0, obj->ToNumber(isolate)->Value());
4360   CHECK_EQ(0, obj->ToInt32(isolate)->Value());
4361   CHECK(0u ==
4362         obj->ToUint32(isolate)->Value());  // NOLINT - no CHECK_EQ for unsigned.
4363   // Large number.
4364   CompileRun("var obj = -1234567890123;");
4365   obj = env->Global()->Get(v8_str("obj"));
4366   CHECK_EQ(-1234567890123.0, obj->ToNumber(isolate)->Value());
4367   CHECK_EQ(-1912276171, obj->ToInt32(isolate)->Value());
4368   CHECK(2382691125u == obj->ToUint32(isolate)->Value());  // NOLINT
4369   // Small positive integer.
4370   CompileRun("var obj = 42;");
4371   obj = env->Global()->Get(v8_str("obj"));
4372   CHECK_EQ(42.0, obj->ToNumber(isolate)->Value());
4373   CHECK_EQ(42, obj->ToInt32(isolate)->Value());
4374   CHECK(42u == obj->ToUint32(isolate)->Value());  // NOLINT
4375   // Negative integer.
4376   CompileRun("var obj = -37;");
4377   obj = env->Global()->Get(v8_str("obj"));
4378   CHECK_EQ(-37.0, obj->ToNumber(isolate)->Value());
4379   CHECK_EQ(-37, obj->ToInt32(isolate)->Value());
4380   CHECK(4294967259u == obj->ToUint32(isolate)->Value());  // NOLINT
4381   // Positive non-int32 integer.
4382   CompileRun("var obj = 0x81234567;");
4383   obj = env->Global()->Get(v8_str("obj"));
4384   CHECK_EQ(2166572391.0, obj->ToNumber(isolate)->Value());
4385   CHECK_EQ(-2128394905, obj->ToInt32(isolate)->Value());
4386   CHECK(2166572391u == obj->ToUint32(isolate)->Value());  // NOLINT
4387   // Fraction.
4388   CompileRun("var obj = 42.3;");
4389   obj = env->Global()->Get(v8_str("obj"));
4390   CHECK_EQ(42.3, obj->ToNumber(isolate)->Value());
4391   CHECK_EQ(42, obj->ToInt32(isolate)->Value());
4392   CHECK(42u == obj->ToUint32(isolate)->Value());  // NOLINT
4393   // Large negative fraction.
4394   CompileRun("var obj = -5726623061.75;");
4395   obj = env->Global()->Get(v8_str("obj"));
4396   CHECK_EQ(-5726623061.75, obj->ToNumber(isolate)->Value());
4397   CHECK_EQ(-1431655765, obj->ToInt32(isolate)->Value());
4398   CHECK(2863311531u == obj->ToUint32(isolate)->Value());  // NOLINT
4399 }
4400
4401
4402 THREADED_TEST(isNumberType) {
4403   LocalContext env;
4404   v8::HandleScope scope(env->GetIsolate());
4405   // Very large number.
4406   CompileRun("var obj = Math.pow(2,32) * 1237;");
4407   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4408   CHECK(!obj->IsInt32());
4409   CHECK(!obj->IsUint32());
4410   // Large negative number.
4411   CompileRun("var obj = -1234567890123;");
4412   obj = env->Global()->Get(v8_str("obj"));
4413   CHECK(!obj->IsInt32());
4414   CHECK(!obj->IsUint32());
4415   // Small positive integer.
4416   CompileRun("var obj = 42;");
4417   obj = env->Global()->Get(v8_str("obj"));
4418   CHECK(obj->IsInt32());
4419   CHECK(obj->IsUint32());
4420   // Negative integer.
4421   CompileRun("var obj = -37;");
4422   obj = env->Global()->Get(v8_str("obj"));
4423   CHECK(obj->IsInt32());
4424   CHECK(!obj->IsUint32());
4425   // Positive non-int32 integer.
4426   CompileRun("var obj = 0x81234567;");
4427   obj = env->Global()->Get(v8_str("obj"));
4428   CHECK(!obj->IsInt32());
4429   CHECK(obj->IsUint32());
4430   // Fraction.
4431   CompileRun("var obj = 42.3;");
4432   obj = env->Global()->Get(v8_str("obj"));
4433   CHECK(!obj->IsInt32());
4434   CHECK(!obj->IsUint32());
4435   // Large negative fraction.
4436   CompileRun("var obj = -5726623061.75;");
4437   obj = env->Global()->Get(v8_str("obj"));
4438   CHECK(!obj->IsInt32());
4439   CHECK(!obj->IsUint32());
4440   // Positive zero
4441   CompileRun("var obj = 0.0;");
4442   obj = env->Global()->Get(v8_str("obj"));
4443   CHECK(obj->IsInt32());
4444   CHECK(obj->IsUint32());
4445   // Positive zero
4446   CompileRun("var obj = -0.0;");
4447   obj = env->Global()->Get(v8_str("obj"));
4448   CHECK(!obj->IsInt32());
4449   CHECK(!obj->IsUint32());
4450 }
4451
4452
4453 THREADED_TEST(ConversionException) {
4454   LocalContext env;
4455   v8::Isolate* isolate = env->GetIsolate();
4456   v8::HandleScope scope(isolate);
4457   CompileRun(
4458       "function TestClass() { };"
4459       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4460       "var obj = new TestClass();");
4461   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4462
4463   v8::TryCatch try_catch(isolate);
4464
4465   Local<Value> to_string_result = obj->ToString(isolate);
4466   CHECK(to_string_result.IsEmpty());
4467   CheckUncle(&try_catch);
4468
4469   Local<Value> to_number_result = obj->ToNumber(isolate);
4470   CHECK(to_number_result.IsEmpty());
4471   CheckUncle(&try_catch);
4472
4473   Local<Value> to_integer_result = obj->ToInteger(isolate);
4474   CHECK(to_integer_result.IsEmpty());
4475   CheckUncle(&try_catch);
4476
4477   Local<Value> to_uint32_result = obj->ToUint32(isolate);
4478   CHECK(to_uint32_result.IsEmpty());
4479   CheckUncle(&try_catch);
4480
4481   Local<Value> to_int32_result = obj->ToInt32(isolate);
4482   CHECK(to_int32_result.IsEmpty());
4483   CheckUncle(&try_catch);
4484
4485   Local<Value> to_object_result = v8::Undefined(isolate)->ToObject(isolate);
4486   CHECK(to_object_result.IsEmpty());
4487   CHECK(try_catch.HasCaught());
4488   try_catch.Reset();
4489
4490   int32_t int32_value = obj->Int32Value();
4491   CHECK_EQ(0, int32_value);
4492   CheckUncle(&try_catch);
4493
4494   uint32_t uint32_value = obj->Uint32Value();
4495   CHECK_EQ(0u, uint32_value);
4496   CheckUncle(&try_catch);
4497
4498   double number_value = obj->NumberValue();
4499   CHECK(std::isnan(number_value));
4500   CheckUncle(&try_catch);
4501
4502   int64_t integer_value = obj->IntegerValue();
4503   CHECK_EQ(0, integer_value);
4504   CheckUncle(&try_catch);
4505 }
4506
4507
4508 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
4509   ApiTestFuzzer::Fuzz();
4510   args.GetIsolate()->ThrowException(v8_str("konto"));
4511 }
4512
4513
4514 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4515   if (args.Length() < 1) {
4516     args.GetReturnValue().Set(false);
4517     return;
4518   }
4519   v8::HandleScope scope(args.GetIsolate());
4520   v8::TryCatch try_catch;
4521   Local<Value> result = CompileRun(args[0]->ToString(args.GetIsolate()));
4522   CHECK(!try_catch.HasCaught() || result.IsEmpty());
4523   args.GetReturnValue().Set(try_catch.HasCaught());
4524 }
4525
4526
4527 THREADED_TEST(APICatch) {
4528   v8::Isolate* isolate = CcTest::isolate();
4529   v8::HandleScope scope(isolate);
4530   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4531   templ->Set(v8_str("ThrowFromC"),
4532              v8::FunctionTemplate::New(isolate, ThrowFromC));
4533   LocalContext context(0, templ);
4534   CompileRun(
4535       "var thrown = false;"
4536       "try {"
4537       "  ThrowFromC();"
4538       "} catch (e) {"
4539       "  thrown = true;"
4540       "}");
4541   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4542   CHECK(thrown->BooleanValue());
4543 }
4544
4545
4546 THREADED_TEST(APIThrowTryCatch) {
4547   v8::Isolate* isolate = CcTest::isolate();
4548   v8::HandleScope scope(isolate);
4549   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4550   templ->Set(v8_str("ThrowFromC"),
4551              v8::FunctionTemplate::New(isolate, ThrowFromC));
4552   LocalContext context(0, templ);
4553   v8::TryCatch try_catch;
4554   CompileRun("ThrowFromC();");
4555   CHECK(try_catch.HasCaught());
4556 }
4557
4558
4559 // Test that a try-finally block doesn't shadow a try-catch block
4560 // when setting up an external handler.
4561 //
4562 // BUG(271): Some of the exception propagation does not work on the
4563 // ARM simulator because the simulator separates the C++ stack and the
4564 // JS stack.  This test therefore fails on the simulator.  The test is
4565 // not threaded to allow the threading tests to run on the simulator.
4566 TEST(TryCatchInTryFinally) {
4567   v8::Isolate* isolate = CcTest::isolate();
4568   v8::HandleScope scope(isolate);
4569   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4570   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
4571   LocalContext context(0, templ);
4572   Local<Value> result = CompileRun(
4573       "try {"
4574       "  try {"
4575       "    CCatcher('throw 7;');"
4576       "  } finally {"
4577       "  }"
4578       "} catch (e) {"
4579       "}");
4580   CHECK(result->IsTrue());
4581 }
4582
4583
4584 static void check_reference_error_message(v8::Handle<v8::Message> message,
4585                                           v8::Handle<v8::Value> data) {
4586   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4587   CHECK(message->Get()->Equals(v8_str(reference_error)));
4588 }
4589
4590
4591 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
4592   ApiTestFuzzer::Fuzz();
4593   CHECK(false);
4594 }
4595
4596
4597 // Test that overwritten methods are not invoked on uncaught exception
4598 // formatting. However, they are invoked when performing normal error
4599 // string conversions.
4600 TEST(APIThrowMessageOverwrittenToString) {
4601   v8::Isolate* isolate = CcTest::isolate();
4602   v8::HandleScope scope(isolate);
4603   v8::V8::AddMessageListener(check_reference_error_message);
4604   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4605   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
4606   LocalContext context(NULL, templ);
4607   CompileRun("asdf;");
4608   CompileRun(
4609       "var limit = {};"
4610       "limit.valueOf = fail;"
4611       "Error.stackTraceLimit = limit;");
4612   CompileRun("asdf");
4613   CompileRun("Array.prototype.pop = fail;");
4614   CompileRun("Object.prototype.hasOwnProperty = fail;");
4615   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
4616   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4617   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
4618   CompileRun(
4619       "ReferenceError.prototype.toString ="
4620       "  function() { return 'Whoops' }");
4621   CompileRun("asdf;");
4622   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4623   CompileRun("asdf;");
4624   CompileRun("ReferenceError.prototype.constructor = void 0;");
4625   CompileRun("asdf;");
4626   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4627   CompileRun("asdf;");
4628   CompileRun("ReferenceError.prototype = new Object();");
4629   CompileRun("asdf;");
4630   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4631   CHECK(string->Equals(v8_str("Whoops")));
4632   CompileRun(
4633       "ReferenceError.prototype.constructor = new Object();"
4634       "ReferenceError.prototype.constructor.name = 1;"
4635       "Number.prototype.toString = function() { return 'Whoops'; };"
4636       "ReferenceError.prototype.toString = Object.prototype.toString;");
4637   CompileRun("asdf;");
4638   v8::V8::RemoveMessageListeners(check_reference_error_message);
4639 }
4640
4641
4642 static void check_custom_error_tostring(v8::Handle<v8::Message> message,
4643                                         v8::Handle<v8::Value> data) {
4644   const char* uncaught_error = "Uncaught MyError toString";
4645   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4646 }
4647
4648
4649 TEST(CustomErrorToString) {
4650   LocalContext context;
4651   v8::HandleScope scope(context->GetIsolate());
4652   v8::V8::AddMessageListener(check_custom_error_tostring);
4653   CompileRun(
4654       "function MyError(name, message) {                   "
4655       "  this.name = name;                                 "
4656       "  this.message = message;                           "
4657       "}                                                   "
4658       "MyError.prototype = Object.create(Error.prototype); "
4659       "MyError.prototype.toString = function() {           "
4660       "  return 'MyError toString';                        "
4661       "};                                                  "
4662       "throw new MyError('my name', 'my message');         ");
4663   v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4664 }
4665
4666
4667 static void check_custom_error_message(v8::Handle<v8::Message> message,
4668                                        v8::Handle<v8::Value> data) {
4669   const char* uncaught_error = "Uncaught MyError: my message";
4670   printf("%s\n", *v8::String::Utf8Value(message->Get()));
4671   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4672 }
4673
4674
4675 TEST(CustomErrorMessage) {
4676   LocalContext context;
4677   v8::HandleScope scope(context->GetIsolate());
4678   v8::V8::AddMessageListener(check_custom_error_message);
4679
4680   // Handlebars.
4681   CompileRun(
4682       "function MyError(msg) {                             "
4683       "  this.name = 'MyError';                            "
4684       "  this.message = msg;                               "
4685       "}                                                   "
4686       "MyError.prototype = new Error();                    "
4687       "throw new MyError('my message');                    ");
4688
4689   // Closure.
4690   CompileRun(
4691       "function MyError(msg) {                             "
4692       "  this.name = 'MyError';                            "
4693       "  this.message = msg;                               "
4694       "}                                                   "
4695       "inherits = function(childCtor, parentCtor) {        "
4696       "    function tempCtor() {};                         "
4697       "    tempCtor.prototype = parentCtor.prototype;      "
4698       "    childCtor.superClass_ = parentCtor.prototype;   "
4699       "    childCtor.prototype = new tempCtor();           "
4700       "    childCtor.prototype.constructor = childCtor;    "
4701       "};                                                  "
4702       "inherits(MyError, Error);                           "
4703       "throw new MyError('my message');                    ");
4704
4705   // Object.create.
4706   CompileRun(
4707       "function MyError(msg) {                             "
4708       "  this.name = 'MyError';                            "
4709       "  this.message = msg;                               "
4710       "}                                                   "
4711       "MyError.prototype = Object.create(Error.prototype); "
4712       "throw new MyError('my message');                    ");
4713
4714   v8::V8::RemoveMessageListeners(check_custom_error_message);
4715 }
4716
4717
4718 static void receive_message(v8::Handle<v8::Message> message,
4719                             v8::Handle<v8::Value> data) {
4720   message->Get();
4721   message_received = true;
4722 }
4723
4724
4725 TEST(APIThrowMessage) {
4726   message_received = false;
4727   v8::Isolate* isolate = CcTest::isolate();
4728   v8::HandleScope scope(isolate);
4729   v8::V8::AddMessageListener(receive_message);
4730   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4731   templ->Set(v8_str("ThrowFromC"),
4732              v8::FunctionTemplate::New(isolate, ThrowFromC));
4733   LocalContext context(0, templ);
4734   CompileRun("ThrowFromC();");
4735   CHECK(message_received);
4736   v8::V8::RemoveMessageListeners(receive_message);
4737 }
4738
4739
4740 TEST(APIThrowMessageAndVerboseTryCatch) {
4741   message_received = false;
4742   v8::Isolate* isolate = CcTest::isolate();
4743   v8::HandleScope scope(isolate);
4744   v8::V8::AddMessageListener(receive_message);
4745   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4746   templ->Set(v8_str("ThrowFromC"),
4747              v8::FunctionTemplate::New(isolate, ThrowFromC));
4748   LocalContext context(0, templ);
4749   v8::TryCatch try_catch;
4750   try_catch.SetVerbose(true);
4751   Local<Value> result = CompileRun("ThrowFromC();");
4752   CHECK(try_catch.HasCaught());
4753   CHECK(result.IsEmpty());
4754   CHECK(message_received);
4755   v8::V8::RemoveMessageListeners(receive_message);
4756 }
4757
4758
4759 TEST(APIStackOverflowAndVerboseTryCatch) {
4760   message_received = false;
4761   LocalContext context;
4762   v8::HandleScope scope(context->GetIsolate());
4763   v8::V8::AddMessageListener(receive_message);
4764   v8::TryCatch try_catch;
4765   try_catch.SetVerbose(true);
4766   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
4767   CHECK(try_catch.HasCaught());
4768   CHECK(result.IsEmpty());
4769   CHECK(message_received);
4770   v8::V8::RemoveMessageListeners(receive_message);
4771 }
4772
4773
4774 THREADED_TEST(ExternalScriptException) {
4775   v8::Isolate* isolate = CcTest::isolate();
4776   v8::HandleScope scope(isolate);
4777   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4778   templ->Set(v8_str("ThrowFromC"),
4779              v8::FunctionTemplate::New(isolate, ThrowFromC));
4780   LocalContext context(0, templ);
4781
4782   v8::TryCatch try_catch;
4783   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
4784   CHECK(result.IsEmpty());
4785   CHECK(try_catch.HasCaught());
4786   String::Utf8Value exception_value(try_catch.Exception());
4787   CHECK_EQ(0, strcmp("konto", *exception_value));
4788 }
4789
4790
4791 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
4792   ApiTestFuzzer::Fuzz();
4793   CHECK_EQ(4, args.Length());
4794   int count = args[0]->Int32Value();
4795   int cInterval = args[2]->Int32Value();
4796   if (count == 0) {
4797     args.GetIsolate()->ThrowException(v8_str("FromC"));
4798     return;
4799   } else {
4800     Local<v8::Object> global = args.GetIsolate()->GetCurrentContext()->Global();
4801     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
4802     v8::Handle<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
4803     if (count % cInterval == 0) {
4804       v8::TryCatch try_catch;
4805       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
4806       int expected = args[3]->Int32Value();
4807       if (try_catch.HasCaught()) {
4808         CHECK_EQ(expected, count);
4809         CHECK(result.IsEmpty());
4810         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
4811       } else {
4812         CHECK_NE(expected, count);
4813       }
4814       args.GetReturnValue().Set(result);
4815       return;
4816     } else {
4817       args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
4818       return;
4819     }
4820   }
4821 }
4822
4823
4824 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
4825   ApiTestFuzzer::Fuzz();
4826   CHECK_EQ(3, args.Length());
4827   bool equality = args[0]->BooleanValue();
4828   int count = args[1]->Int32Value();
4829   int expected = args[2]->Int32Value();
4830   if (equality) {
4831     CHECK_EQ(count, expected);
4832   } else {
4833     CHECK_NE(count, expected);
4834   }
4835 }
4836
4837
4838 THREADED_TEST(EvalInTryFinally) {
4839   LocalContext context;
4840   v8::HandleScope scope(context->GetIsolate());
4841   v8::TryCatch try_catch;
4842   CompileRun(
4843       "(function() {"
4844       "  try {"
4845       "    eval('asldkf (*&^&*^');"
4846       "  } finally {"
4847       "    return;"
4848       "  }"
4849       "})()");
4850   CHECK(!try_catch.HasCaught());
4851 }
4852
4853
4854 // This test works by making a stack of alternating JavaScript and C
4855 // activations.  These activations set up exception handlers with regular
4856 // intervals, one interval for C activations and another for JavaScript
4857 // activations.  When enough activations have been created an exception is
4858 // thrown and we check that the right activation catches the exception and that
4859 // no other activations do.  The right activation is always the topmost one with
4860 // a handler, regardless of whether it is in JavaScript or C.
4861 //
4862 // The notation used to describe a test case looks like this:
4863 //
4864 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
4865 //
4866 // Each entry is an activation, either JS or C.  The index is the count at that
4867 // level.  Stars identify activations with exception handlers, the @ identifies
4868 // the exception handler that should catch the exception.
4869 //
4870 // BUG(271): Some of the exception propagation does not work on the
4871 // ARM simulator because the simulator separates the C++ stack and the
4872 // JS stack.  This test therefore fails on the simulator.  The test is
4873 // not threaded to allow the threading tests to run on the simulator.
4874 TEST(ExceptionOrder) {
4875   v8::Isolate* isolate = CcTest::isolate();
4876   v8::HandleScope scope(isolate);
4877   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4878   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
4879   templ->Set(v8_str("CThrowCountDown"),
4880              v8::FunctionTemplate::New(isolate, CThrowCountDown));
4881   LocalContext context(0, templ);
4882   CompileRun(
4883       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
4884       "  if (count == 0) throw 'FromJS';"
4885       "  if (count % jsInterval == 0) {"
4886       "    try {"
4887       "      var value = CThrowCountDown(count - 1,"
4888       "                                  jsInterval,"
4889       "                                  cInterval,"
4890       "                                  expected);"
4891       "      check(false, count, expected);"
4892       "      return value;"
4893       "    } catch (e) {"
4894       "      check(true, count, expected);"
4895       "    }"
4896       "  } else {"
4897       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
4898       "  }"
4899       "}");
4900   Local<Function> fun =
4901       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
4902
4903   const int argc = 4;
4904   //                             count      jsInterval cInterval  expected
4905
4906   // *JS[4] *C[3] @JS[2] C[1] JS[0]
4907   v8::Handle<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
4908   fun->Call(fun, argc, a0);
4909
4910   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
4911   v8::Handle<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
4912   fun->Call(fun, argc, a1);
4913
4914   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
4915   v8::Handle<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
4916   fun->Call(fun, argc, a2);
4917
4918   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
4919   v8::Handle<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
4920   fun->Call(fun, argc, a3);
4921
4922   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
4923   v8::Handle<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
4924   fun->Call(fun, argc, a4);
4925
4926   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
4927   v8::Handle<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
4928   fun->Call(fun, argc, a5);
4929 }
4930
4931
4932 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
4933   ApiTestFuzzer::Fuzz();
4934   CHECK_EQ(1, args.Length());
4935   args.GetIsolate()->ThrowException(args[0]);
4936 }
4937
4938
4939 THREADED_TEST(ThrowValues) {
4940   v8::Isolate* isolate = CcTest::isolate();
4941   v8::HandleScope scope(isolate);
4942   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4943   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
4944   LocalContext context(0, templ);
4945   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
4946       "function Run(obj) {"
4947       "  try {"
4948       "    Throw(obj);"
4949       "  } catch (e) {"
4950       "    return e;"
4951       "  }"
4952       "  return 'no exception';"
4953       "}"
4954       "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
4955   CHECK_EQ(5u, result->Length());
4956   CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
4957   CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
4958   CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
4959   CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
4960   CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
4961   CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
4962   CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
4963 }
4964
4965
4966 THREADED_TEST(CatchZero) {
4967   LocalContext context;
4968   v8::HandleScope scope(context->GetIsolate());
4969   v8::TryCatch try_catch;
4970   CHECK(!try_catch.HasCaught());
4971   CompileRun("throw 10");
4972   CHECK(try_catch.HasCaught());
4973   CHECK_EQ(10, try_catch.Exception()->Int32Value());
4974   try_catch.Reset();
4975   CHECK(!try_catch.HasCaught());
4976   CompileRun("throw 0");
4977   CHECK(try_catch.HasCaught());
4978   CHECK_EQ(0, try_catch.Exception()->Int32Value());
4979 }
4980
4981
4982 THREADED_TEST(CatchExceptionFromWith) {
4983   LocalContext context;
4984   v8::HandleScope scope(context->GetIsolate());
4985   v8::TryCatch try_catch;
4986   CHECK(!try_catch.HasCaught());
4987   CompileRun("var o = {}; with (o) { throw 42; }");
4988   CHECK(try_catch.HasCaught());
4989 }
4990
4991
4992 THREADED_TEST(TryCatchAndFinallyHidingException) {
4993   LocalContext context;
4994   v8::HandleScope scope(context->GetIsolate());
4995   v8::TryCatch try_catch;
4996   CHECK(!try_catch.HasCaught());
4997   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
4998   CompileRun("f({toString: function() { throw 42; }});");
4999   CHECK(!try_catch.HasCaught());
5000 }
5001
5002
5003 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
5004   v8::TryCatch try_catch;
5005 }
5006
5007
5008 THREADED_TEST(TryCatchAndFinally) {
5009   LocalContext context;
5010   v8::Isolate* isolate = context->GetIsolate();
5011   v8::HandleScope scope(isolate);
5012   context->Global()->Set(
5013       v8_str("native_with_try_catch"),
5014       v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
5015   v8::TryCatch try_catch;
5016   CHECK(!try_catch.HasCaught());
5017   CompileRun(
5018       "try {\n"
5019       "  throw new Error('a');\n"
5020       "} finally {\n"
5021       "  native_with_try_catch();\n"
5022       "}\n");
5023   CHECK(try_catch.HasCaught());
5024 }
5025
5026
5027 static void TryCatchNested1Helper(int depth) {
5028   if (depth > 0) {
5029     v8::TryCatch try_catch;
5030     try_catch.SetVerbose(true);
5031     TryCatchNested1Helper(depth - 1);
5032     CHECK(try_catch.HasCaught());
5033     try_catch.ReThrow();
5034   } else {
5035     CcTest::isolate()->ThrowException(v8_str("E1"));
5036   }
5037 }
5038
5039
5040 static void TryCatchNested2Helper(int depth) {
5041   if (depth > 0) {
5042     v8::TryCatch try_catch;
5043     try_catch.SetVerbose(true);
5044     TryCatchNested2Helper(depth - 1);
5045     CHECK(try_catch.HasCaught());
5046     try_catch.ReThrow();
5047   } else {
5048     CompileRun("throw 'E2';");
5049   }
5050 }
5051
5052
5053 TEST(TryCatchNested) {
5054   v8::V8::Initialize();
5055   LocalContext context;
5056   v8::HandleScope scope(context->GetIsolate());
5057
5058   {
5059     // Test nested try-catch with a native throw in the end.
5060     v8::TryCatch try_catch;
5061     TryCatchNested1Helper(5);
5062     CHECK(try_catch.HasCaught());
5063     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
5064   }
5065
5066   {
5067     // Test nested try-catch with a JavaScript throw in the end.
5068     v8::TryCatch try_catch;
5069     TryCatchNested2Helper(5);
5070     CHECK(try_catch.HasCaught());
5071     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
5072   }
5073 }
5074
5075
5076 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5077   CHECK(try_catch->HasCaught());
5078   Handle<Message> message = try_catch->Message();
5079   Handle<Value> resource = message->GetScriptOrigin().ResourceName();
5080   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5081   CHECK_EQ(0,
5082            strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
5083   CHECK_EQ(1, message->GetLineNumber());
5084   CHECK_EQ(6, message->GetStartColumn());
5085 }
5086
5087
5088 void TryCatchMixedNestingHelper(
5089     const v8::FunctionCallbackInfo<v8::Value>& args) {
5090   ApiTestFuzzer::Fuzz();
5091   v8::TryCatch try_catch;
5092   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5093   CHECK(try_catch.HasCaught());
5094   TryCatchMixedNestingCheck(&try_catch);
5095   try_catch.ReThrow();
5096 }
5097
5098
5099 // This test ensures that an outer TryCatch in the following situation:
5100 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5101 // does not clobber the Message object generated for the inner TryCatch.
5102 // This exercises the ability of TryCatch.ReThrow() to restore the
5103 // inner pending Message before throwing the exception again.
5104 TEST(TryCatchMixedNesting) {
5105   v8::Isolate* isolate = CcTest::isolate();
5106   v8::HandleScope scope(isolate);
5107   v8::V8::Initialize();
5108   v8::TryCatch try_catch;
5109   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5110   templ->Set(v8_str("TryCatchMixedNestingHelper"),
5111              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
5112   LocalContext context(0, templ);
5113   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5114   TryCatchMixedNestingCheck(&try_catch);
5115 }
5116
5117
5118 void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
5119   ApiTestFuzzer::Fuzz();
5120   v8::TryCatch try_catch;
5121   args.GetIsolate()->ThrowException(v8_str("boom"));
5122   CHECK(try_catch.HasCaught());
5123 }
5124
5125
5126 TEST(TryCatchNative) {
5127   v8::Isolate* isolate = CcTest::isolate();
5128   v8::HandleScope scope(isolate);
5129   v8::V8::Initialize();
5130   v8::TryCatch try_catch;
5131   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5132   templ->Set(v8_str("TryCatchNativeHelper"),
5133              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
5134   LocalContext context(0, templ);
5135   CompileRun("TryCatchNativeHelper();");
5136   CHECK(!try_catch.HasCaught());
5137 }
5138
5139
5140 void TryCatchNativeResetHelper(
5141     const v8::FunctionCallbackInfo<v8::Value>& args) {
5142   ApiTestFuzzer::Fuzz();
5143   v8::TryCatch try_catch;
5144   args.GetIsolate()->ThrowException(v8_str("boom"));
5145   CHECK(try_catch.HasCaught());
5146   try_catch.Reset();
5147   CHECK(!try_catch.HasCaught());
5148 }
5149
5150
5151 TEST(TryCatchNativeReset) {
5152   v8::Isolate* isolate = CcTest::isolate();
5153   v8::HandleScope scope(isolate);
5154   v8::V8::Initialize();
5155   v8::TryCatch try_catch;
5156   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5157   templ->Set(v8_str("TryCatchNativeResetHelper"),
5158              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
5159   LocalContext context(0, templ);
5160   CompileRun("TryCatchNativeResetHelper();");
5161   CHECK(!try_catch.HasCaught());
5162 }
5163
5164
5165 THREADED_TEST(Equality) {
5166   LocalContext context;
5167   v8::Isolate* isolate = context->GetIsolate();
5168   v8::HandleScope scope(context->GetIsolate());
5169   // Check that equality works at all before relying on CHECK_EQ
5170   CHECK(v8_str("a")->Equals(v8_str("a")));
5171   CHECK(!v8_str("a")->Equals(v8_str("b")));
5172
5173   CHECK(v8_str("a")->Equals(v8_str("a")));
5174   CHECK(!v8_str("a")->Equals(v8_str("b")));
5175   CHECK(v8_num(1)->Equals(v8_num(1)));
5176   CHECK(v8_num(1.00)->Equals(v8_num(1)));
5177   CHECK(!v8_num(1)->Equals(v8_num(2)));
5178
5179   // Assume String is not internalized.
5180   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5181   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5182   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5183   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5184   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
5185   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
5186   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
5187   CHECK(!not_a_number->StrictEquals(not_a_number));
5188   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5189   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
5190
5191   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
5192   v8::Persistent<v8::Object> alias(isolate, obj);
5193   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
5194   alias.Reset();
5195
5196   CHECK(v8_str("a")->SameValue(v8_str("a")));
5197   CHECK(!v8_str("a")->SameValue(v8_str("b")));
5198   CHECK(!v8_str("5")->SameValue(v8_num(5)));
5199   CHECK(v8_num(1)->SameValue(v8_num(1)));
5200   CHECK(!v8_num(1)->SameValue(v8_num(2)));
5201   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5202   CHECK(not_a_number->SameValue(not_a_number));
5203   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5204   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
5205 }
5206
5207
5208 THREADED_TEST(MultiRun) {
5209   LocalContext context;
5210   v8::HandleScope scope(context->GetIsolate());
5211   Local<Script> script = v8_compile("x");
5212   for (int i = 0; i < 10; i++) script->Run();
5213 }
5214
5215
5216 static void GetXValue(Local<String> name,
5217                       const v8::PropertyCallbackInfo<v8::Value>& info) {
5218   ApiTestFuzzer::Fuzz();
5219   CHECK(info.Data()->Equals(v8_str("donut")));
5220   CHECK(name->Equals(v8_str("x")));
5221   info.GetReturnValue().Set(name);
5222 }
5223
5224
5225 THREADED_TEST(SimplePropertyRead) {
5226   LocalContext context;
5227   v8::Isolate* isolate = context->GetIsolate();
5228   v8::HandleScope scope(isolate);
5229   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5230   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5231   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5232   Local<Script> script = v8_compile("obj.x");
5233   for (int i = 0; i < 10; i++) {
5234     Local<Value> result = script->Run();
5235     CHECK(result->Equals(v8_str("x")));
5236   }
5237 }
5238
5239
5240 THREADED_TEST(DefinePropertyOnAPIAccessor) {
5241   LocalContext context;
5242   v8::Isolate* isolate = context->GetIsolate();
5243   v8::HandleScope scope(isolate);
5244   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5245   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5246   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5247
5248   // Uses getOwnPropertyDescriptor to check the configurable status
5249   Local<Script> script_desc = v8_compile(
5250       "var prop = Object.getOwnPropertyDescriptor( "
5251       "obj, 'x');"
5252       "prop.configurable;");
5253   Local<Value> result = script_desc->Run();
5254   CHECK_EQ(result->BooleanValue(), true);
5255
5256   // Redefine get - but still configurable
5257   Local<Script> script_define = v8_compile(
5258       "var desc = { get: function(){return 42; },"
5259       "            configurable: true };"
5260       "Object.defineProperty(obj, 'x', desc);"
5261       "obj.x");
5262   result = script_define->Run();
5263   CHECK(result->Equals(v8_num(42)));
5264
5265   // Check that the accessor is still configurable
5266   result = script_desc->Run();
5267   CHECK_EQ(result->BooleanValue(), true);
5268
5269   // Redefine to a non-configurable
5270   script_define = v8_compile(
5271       "var desc = { get: function(){return 43; },"
5272       "             configurable: false };"
5273       "Object.defineProperty(obj, 'x', desc);"
5274       "obj.x");
5275   result = script_define->Run();
5276   CHECK(result->Equals(v8_num(43)));
5277   result = script_desc->Run();
5278   CHECK_EQ(result->BooleanValue(), false);
5279
5280   // Make sure that it is not possible to redefine again
5281   v8::TryCatch try_catch;
5282   result = script_define->Run();
5283   CHECK(try_catch.HasCaught());
5284   String::Utf8Value exception_value(try_catch.Exception());
5285   CHECK_EQ(0,
5286            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5287 }
5288
5289
5290 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
5291   v8::Isolate* isolate = CcTest::isolate();
5292   v8::HandleScope scope(isolate);
5293   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5294   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5295   LocalContext context;
5296   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5297
5298   Local<Script> script_desc = v8_compile(
5299       "var prop ="
5300       "Object.getOwnPropertyDescriptor( "
5301       "obj, 'x');"
5302       "prop.configurable;");
5303   Local<Value> result = script_desc->Run();
5304   CHECK_EQ(result->BooleanValue(), true);
5305
5306   Local<Script> script_define = v8_compile(
5307       "var desc = {get: function(){return 42; },"
5308       "            configurable: true };"
5309       "Object.defineProperty(obj, 'x', desc);"
5310       "obj.x");
5311   result = script_define->Run();
5312   CHECK(result->Equals(v8_num(42)));
5313
5314
5315   result = script_desc->Run();
5316   CHECK_EQ(result->BooleanValue(), true);
5317
5318
5319   script_define = v8_compile(
5320       "var desc = {get: function(){return 43; },"
5321       "            configurable: false };"
5322       "Object.defineProperty(obj, 'x', desc);"
5323       "obj.x");
5324   result = script_define->Run();
5325   CHECK(result->Equals(v8_num(43)));
5326   result = script_desc->Run();
5327
5328   CHECK_EQ(result->BooleanValue(), false);
5329
5330   v8::TryCatch try_catch;
5331   result = script_define->Run();
5332   CHECK(try_catch.HasCaught());
5333   String::Utf8Value exception_value(try_catch.Exception());
5334   CHECK_EQ(0,
5335            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5336 }
5337
5338
5339 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5340                                                 char const* name) {
5341   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5342 }
5343
5344
5345 THREADED_TEST(DefineAPIAccessorOnObject) {
5346   v8::Isolate* isolate = CcTest::isolate();
5347   v8::HandleScope scope(isolate);
5348   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5349   LocalContext context;
5350
5351   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5352   CompileRun("var obj2 = {};");
5353
5354   CHECK(CompileRun("obj1.x")->IsUndefined());
5355   CHECK(CompileRun("obj2.x")->IsUndefined());
5356
5357   CHECK(GetGlobalProperty(&context, "obj1")
5358             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5359
5360   ExpectString("obj1.x", "x");
5361   CHECK(CompileRun("obj2.x")->IsUndefined());
5362
5363   CHECK(GetGlobalProperty(&context, "obj2")
5364             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5365
5366   ExpectString("obj1.x", "x");
5367   ExpectString("obj2.x", "x");
5368
5369   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5370   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5371
5372   CompileRun(
5373       "Object.defineProperty(obj1, 'x',"
5374       "{ get: function() { return 'y'; }, configurable: true })");
5375
5376   ExpectString("obj1.x", "y");
5377   ExpectString("obj2.x", "x");
5378
5379   CompileRun(
5380       "Object.defineProperty(obj2, 'x',"
5381       "{ get: function() { return 'y'; }, configurable: true })");
5382
5383   ExpectString("obj1.x", "y");
5384   ExpectString("obj2.x", "y");
5385
5386   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5387   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5388
5389   CHECK(GetGlobalProperty(&context, "obj1")
5390             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5391   CHECK(GetGlobalProperty(&context, "obj2")
5392             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5393
5394   ExpectString("obj1.x", "x");
5395   ExpectString("obj2.x", "x");
5396
5397   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5398   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5399
5400   // Define getters/setters, but now make them not configurable.
5401   CompileRun(
5402       "Object.defineProperty(obj1, 'x',"
5403       "{ get: function() { return 'z'; }, configurable: false })");
5404   CompileRun(
5405       "Object.defineProperty(obj2, 'x',"
5406       "{ get: function() { return 'z'; }, configurable: false })");
5407
5408   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5409   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5410
5411   ExpectString("obj1.x", "z");
5412   ExpectString("obj2.x", "z");
5413
5414   CHECK(!GetGlobalProperty(&context, "obj1")
5415              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5416   CHECK(!GetGlobalProperty(&context, "obj2")
5417              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5418
5419   ExpectString("obj1.x", "z");
5420   ExpectString("obj2.x", "z");
5421 }
5422
5423
5424 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
5425   v8::Isolate* isolate = CcTest::isolate();
5426   v8::HandleScope scope(isolate);
5427   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5428   LocalContext context;
5429
5430   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5431   CompileRun("var obj2 = {};");
5432
5433   CHECK(GetGlobalProperty(&context, "obj1")
5434             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
5435                           v8::DEFAULT, v8::DontDelete));
5436   CHECK(GetGlobalProperty(&context, "obj2")
5437             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
5438                           v8::DEFAULT, v8::DontDelete));
5439
5440   ExpectString("obj1.x", "x");
5441   ExpectString("obj2.x", "x");
5442
5443   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5444   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5445
5446   CHECK(!GetGlobalProperty(&context, "obj1")
5447              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5448   CHECK(!GetGlobalProperty(&context, "obj2")
5449              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5450
5451   {
5452     v8::TryCatch try_catch;
5453     CompileRun(
5454         "Object.defineProperty(obj1, 'x',"
5455         "{get: function() { return 'func'; }})");
5456     CHECK(try_catch.HasCaught());
5457     String::Utf8Value exception_value(try_catch.Exception());
5458     CHECK_EQ(
5459         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5460   }
5461   {
5462     v8::TryCatch try_catch;
5463     CompileRun(
5464         "Object.defineProperty(obj2, 'x',"
5465         "{get: function() { return 'func'; }})");
5466     CHECK(try_catch.HasCaught());
5467     String::Utf8Value exception_value(try_catch.Exception());
5468     CHECK_EQ(
5469         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5470   }
5471 }
5472
5473
5474 static void Get239Value(Local<String> name,
5475                         const v8::PropertyCallbackInfo<v8::Value>& info) {
5476   ApiTestFuzzer::Fuzz();
5477   CHECK(info.Data()->Equals(v8_str("donut")));
5478   CHECK(name->Equals(v8_str("239")));
5479   info.GetReturnValue().Set(name);
5480 }
5481
5482
5483 THREADED_TEST(ElementAPIAccessor) {
5484   v8::Isolate* isolate = CcTest::isolate();
5485   v8::HandleScope scope(isolate);
5486   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5487   LocalContext context;
5488
5489   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5490   CompileRun("var obj2 = {};");
5491
5492   CHECK(GetGlobalProperty(&context, "obj1")
5493             ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
5494   CHECK(GetGlobalProperty(&context, "obj2")
5495             ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
5496
5497   ExpectString("obj1[239]", "239");
5498   ExpectString("obj2[239]", "239");
5499   ExpectString("obj1['239']", "239");
5500   ExpectString("obj2['239']", "239");
5501 }
5502
5503
5504 v8::Persistent<Value> xValue;
5505
5506
5507 static void SetXValue(Local<String> name, Local<Value> value,
5508                       const v8::PropertyCallbackInfo<void>& info) {
5509   CHECK(value->Equals(v8_num(4)));
5510   CHECK(info.Data()->Equals(v8_str("donut")));
5511   CHECK(name->Equals(v8_str("x")));
5512   CHECK(xValue.IsEmpty());
5513   xValue.Reset(info.GetIsolate(), value);
5514 }
5515
5516
5517 THREADED_TEST(SimplePropertyWrite) {
5518   v8::Isolate* isolate = CcTest::isolate();
5519   v8::HandleScope scope(isolate);
5520   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5521   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5522   LocalContext context;
5523   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5524   Local<Script> script = v8_compile("obj.x = 4");
5525   for (int i = 0; i < 10; i++) {
5526     CHECK(xValue.IsEmpty());
5527     script->Run();
5528     CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
5529     xValue.Reset();
5530   }
5531 }
5532
5533
5534 THREADED_TEST(SetterOnly) {
5535   v8::Isolate* isolate = CcTest::isolate();
5536   v8::HandleScope scope(isolate);
5537   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5538   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5539   LocalContext context;
5540   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5541   Local<Script> script = v8_compile("obj.x = 4; obj.x");
5542   for (int i = 0; i < 10; i++) {
5543     CHECK(xValue.IsEmpty());
5544     script->Run();
5545     CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
5546     xValue.Reset();
5547   }
5548 }
5549
5550
5551 THREADED_TEST(NoAccessors) {
5552   v8::Isolate* isolate = CcTest::isolate();
5553   v8::HandleScope scope(isolate);
5554   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5555   templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
5556                      NULL, v8_str("donut"));
5557   LocalContext context;
5558   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5559   Local<Script> script = v8_compile("obj.x = 4; obj.x");
5560   for (int i = 0; i < 10; i++) {
5561     script->Run();
5562   }
5563 }
5564
5565
5566 THREADED_TEST(MultiContexts) {
5567   v8::Isolate* isolate = CcTest::isolate();
5568   v8::HandleScope scope(isolate);
5569   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5570   templ->Set(v8_str("dummy"),
5571              v8::FunctionTemplate::New(isolate, DummyCallHandler));
5572
5573   Local<String> password = v8_str("Password");
5574
5575   // Create an environment
5576   LocalContext context0(0, templ);
5577   context0->SetSecurityToken(password);
5578   v8::Handle<v8::Object> global0 = context0->Global();
5579   global0->Set(v8_str("custom"), v8_num(1234));
5580   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5581
5582   // Create an independent environment
5583   LocalContext context1(0, templ);
5584   context1->SetSecurityToken(password);
5585   v8::Handle<v8::Object> global1 = context1->Global();
5586   global1->Set(v8_str("custom"), v8_num(1234));
5587   CHECK(!global0->Equals(global1));
5588   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5589   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
5590
5591   // Now create a new context with the old global
5592   LocalContext context2(0, templ, global1);
5593   context2->SetSecurityToken(password);
5594   v8::Handle<v8::Object> global2 = context2->Global();
5595   CHECK(global1->Equals(global2));
5596   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
5597   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
5598 }
5599
5600
5601 THREADED_TEST(FunctionPrototypeAcrossContexts) {
5602   // Make sure that functions created by cloning boilerplates cannot
5603   // communicate through their __proto__ field.
5604
5605   v8::HandleScope scope(CcTest::isolate());
5606
5607   LocalContext env0;
5608   v8::Handle<v8::Object> global0 = env0->Global();
5609   v8::Handle<v8::Object> object0 =
5610       global0->Get(v8_str("Object")).As<v8::Object>();
5611   v8::Handle<v8::Object> tostring0 =
5612       object0->Get(v8_str("toString")).As<v8::Object>();
5613   v8::Handle<v8::Object> proto0 =
5614       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
5615   proto0->Set(v8_str("custom"), v8_num(1234));
5616
5617   LocalContext env1;
5618   v8::Handle<v8::Object> global1 = env1->Global();
5619   v8::Handle<v8::Object> object1 =
5620       global1->Get(v8_str("Object")).As<v8::Object>();
5621   v8::Handle<v8::Object> tostring1 =
5622       object1->Get(v8_str("toString")).As<v8::Object>();
5623   v8::Handle<v8::Object> proto1 =
5624       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
5625   CHECK(!proto1->Has(v8_str("custom")));
5626 }
5627
5628
5629 THREADED_TEST(Regress892105) {
5630   // Make sure that object and array literals created by cloning
5631   // boilerplates cannot communicate through their __proto__
5632   // field. This is rather difficult to check, but we try to add stuff
5633   // to Object.prototype and Array.prototype and create a new
5634   // environment. This should succeed.
5635
5636   v8::HandleScope scope(CcTest::isolate());
5637
5638   Local<String> source = v8_str(
5639       "Object.prototype.obj = 1234;"
5640       "Array.prototype.arr = 4567;"
5641       "8901");
5642
5643   LocalContext env0;
5644   Local<Script> script0 = v8_compile(source);
5645   CHECK_EQ(8901.0, script0->Run()->NumberValue());
5646
5647   LocalContext env1;
5648   Local<Script> script1 = v8_compile(source);
5649   CHECK_EQ(8901.0, script1->Run()->NumberValue());
5650 }
5651
5652
5653 THREADED_TEST(UndetectableObject) {
5654   LocalContext env;
5655   v8::HandleScope scope(env->GetIsolate());
5656
5657   Local<v8::FunctionTemplate> desc =
5658       v8::FunctionTemplate::New(env->GetIsolate());
5659   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5660
5661   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5662   env->Global()->Set(v8_str("undetectable"), obj);
5663
5664   ExpectString("undetectable.toString()", "[object Object]");
5665   ExpectString("typeof undetectable", "undefined");
5666   ExpectString("typeof(undetectable)", "undefined");
5667   ExpectBoolean("typeof undetectable == 'undefined'", true);
5668   ExpectBoolean("typeof undetectable == 'object'", false);
5669   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
5670   ExpectBoolean("!undetectable", true);
5671
5672   ExpectObject("true&&undetectable", obj);
5673   ExpectBoolean("false&&undetectable", false);
5674   ExpectBoolean("true||undetectable", true);
5675   ExpectObject("false||undetectable", obj);
5676
5677   ExpectObject("undetectable&&true", obj);
5678   ExpectObject("undetectable&&false", obj);
5679   ExpectBoolean("undetectable||true", true);
5680   ExpectBoolean("undetectable||false", false);
5681
5682   ExpectBoolean("undetectable==null", true);
5683   ExpectBoolean("null==undetectable", true);
5684   ExpectBoolean("undetectable==undefined", true);
5685   ExpectBoolean("undefined==undetectable", true);
5686   ExpectBoolean("undetectable==undetectable", true);
5687
5688
5689   ExpectBoolean("undetectable===null", false);
5690   ExpectBoolean("null===undetectable", false);
5691   ExpectBoolean("undetectable===undefined", false);
5692   ExpectBoolean("undefined===undetectable", false);
5693   ExpectBoolean("undetectable===undetectable", true);
5694 }
5695
5696
5697 THREADED_TEST(VoidLiteral) {
5698   LocalContext env;
5699   v8::Isolate* isolate = env->GetIsolate();
5700   v8::HandleScope scope(isolate);
5701
5702   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
5703   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5704
5705   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5706   env->Global()->Set(v8_str("undetectable"), obj);
5707
5708   ExpectBoolean("undefined == void 0", true);
5709   ExpectBoolean("undetectable == void 0", true);
5710   ExpectBoolean("null == void 0", true);
5711   ExpectBoolean("undefined === void 0", true);
5712   ExpectBoolean("undetectable === void 0", false);
5713   ExpectBoolean("null === void 0", false);
5714
5715   ExpectBoolean("void 0 == undefined", true);
5716   ExpectBoolean("void 0 == undetectable", true);
5717   ExpectBoolean("void 0 == null", true);
5718   ExpectBoolean("void 0 === undefined", true);
5719   ExpectBoolean("void 0 === undetectable", false);
5720   ExpectBoolean("void 0 === null", false);
5721
5722   ExpectString(
5723       "(function() {"
5724       "  try {"
5725       "    return x === void 0;"
5726       "  } catch(e) {"
5727       "    return e.toString();"
5728       "  }"
5729       "})()",
5730       "ReferenceError: x is not defined");
5731   ExpectString(
5732       "(function() {"
5733       "  try {"
5734       "    return void 0 === x;"
5735       "  } catch(e) {"
5736       "    return e.toString();"
5737       "  }"
5738       "})()",
5739       "ReferenceError: x is not defined");
5740 }
5741
5742
5743 THREADED_TEST(ExtensibleOnUndetectable) {
5744   LocalContext env;
5745   v8::Isolate* isolate = env->GetIsolate();
5746   v8::HandleScope scope(isolate);
5747
5748   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
5749   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5750
5751   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5752   env->Global()->Set(v8_str("undetectable"), obj);
5753
5754   Local<String> source = v8_str(
5755       "undetectable.x = 42;"
5756       "undetectable.x");
5757
5758   Local<Script> script = v8_compile(source);
5759
5760   CHECK(v8::Integer::New(isolate, 42)->Equals(script->Run()));
5761
5762   ExpectBoolean("Object.isExtensible(undetectable)", true);
5763
5764   source = v8_str("Object.preventExtensions(undetectable);");
5765   script = v8_compile(source);
5766   script->Run();
5767   ExpectBoolean("Object.isExtensible(undetectable)", false);
5768
5769   source = v8_str("undetectable.y = 2000;");
5770   script = v8_compile(source);
5771   script->Run();
5772   ExpectBoolean("undetectable.y == undefined", true);
5773 }
5774
5775
5776 // The point of this test is type checking. We run it only so compilers
5777 // don't complain about an unused function.
5778 TEST(PersistentHandles) {
5779   LocalContext env;
5780   v8::Isolate* isolate = CcTest::isolate();
5781   v8::HandleScope scope(isolate);
5782   Local<String> str = v8_str("foo");
5783   v8::Persistent<String> p_str(isolate, str);
5784   p_str.Reset();
5785   Local<Script> scr = v8_compile("");
5786   v8::Persistent<Script> p_scr(isolate, scr);
5787   p_scr.Reset();
5788   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5789   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
5790   p_templ.Reset();
5791 }
5792
5793
5794 static void HandleLogDelegator(
5795     const v8::FunctionCallbackInfo<v8::Value>& args) {
5796   ApiTestFuzzer::Fuzz();
5797 }
5798
5799
5800 THREADED_TEST(GlobalObjectTemplate) {
5801   v8::Isolate* isolate = CcTest::isolate();
5802   v8::HandleScope handle_scope(isolate);
5803   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
5804   global_template->Set(v8_str("JSNI_Log"),
5805                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
5806   v8::Local<Context> context = Context::New(isolate, 0, global_template);
5807   Context::Scope context_scope(context);
5808   CompileRun("JSNI_Log('LOG')");
5809 }
5810
5811
5812 static const char* kSimpleExtensionSource =
5813     "function Foo() {"
5814     "  return 4;"
5815     "}";
5816
5817
5818 TEST(SimpleExtensions) {
5819   v8::HandleScope handle_scope(CcTest::isolate());
5820   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
5821   const char* extension_names[] = {"simpletest"};
5822   v8::ExtensionConfiguration extensions(1, extension_names);
5823   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
5824   Context::Scope lock(context);
5825   v8::Handle<Value> result = CompileRun("Foo()");
5826   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
5827 }
5828
5829
5830 static const char* kStackTraceFromExtensionSource =
5831     "function foo() {"
5832     "  throw new Error();"
5833     "}"
5834     "function bar() {"
5835     "  foo();"
5836     "}";
5837
5838
5839 TEST(StackTraceInExtension) {
5840   v8::HandleScope handle_scope(CcTest::isolate());
5841   v8::RegisterExtension(
5842       new Extension("stacktracetest", kStackTraceFromExtensionSource));
5843   const char* extension_names[] = {"stacktracetest"};
5844   v8::ExtensionConfiguration extensions(1, extension_names);
5845   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
5846   Context::Scope lock(context);
5847   CompileRun(
5848       "function user() { bar(); }"
5849       "var error;"
5850       "try{ user(); } catch (e) { error = e; }");
5851   CHECK_EQ(-1, CompileRun("error.stack.indexOf('foo')")->Int32Value());
5852   CHECK_EQ(-1, CompileRun("error.stack.indexOf('bar')")->Int32Value());
5853   CHECK_NE(-1, CompileRun("error.stack.indexOf('user')")->Int32Value());
5854 }
5855
5856
5857 TEST(NullExtensions) {
5858   v8::HandleScope handle_scope(CcTest::isolate());
5859   v8::RegisterExtension(new Extension("nulltest", NULL));
5860   const char* extension_names[] = {"nulltest"};
5861   v8::ExtensionConfiguration extensions(1, extension_names);
5862   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
5863   Context::Scope lock(context);
5864   v8::Handle<Value> result = CompileRun("1+3");
5865   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
5866 }
5867
5868
5869 static const char* kEmbeddedExtensionSource =
5870     "function Ret54321(){return 54321;}~~@@$"
5871     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
5872 static const int kEmbeddedExtensionSourceValidLen = 34;
5873
5874
5875 TEST(ExtensionMissingSourceLength) {
5876   v8::HandleScope handle_scope(CcTest::isolate());
5877   v8::RegisterExtension(
5878       new Extension("srclentest_fail", kEmbeddedExtensionSource));
5879   const char* extension_names[] = {"srclentest_fail"};
5880   v8::ExtensionConfiguration extensions(1, extension_names);
5881   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
5882   CHECK(0 == *context);
5883 }
5884
5885
5886 TEST(ExtensionWithSourceLength) {
5887   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
5888        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
5889     v8::HandleScope handle_scope(CcTest::isolate());
5890     i::ScopedVector<char> extension_name(32);
5891     i::SNPrintF(extension_name, "ext #%d", source_len);
5892     v8::RegisterExtension(new Extension(
5893         extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
5894     const char* extension_names[1] = {extension_name.start()};
5895     v8::ExtensionConfiguration extensions(1, extension_names);
5896     v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
5897     if (source_len == kEmbeddedExtensionSourceValidLen) {
5898       Context::Scope lock(context);
5899       v8::Handle<Value> result = CompileRun("Ret54321()");
5900       CHECK(v8::Integer::New(CcTest::isolate(), 54321)->Equals(result));
5901     } else {
5902       // Anything but exactly the right length should fail to compile.
5903       CHECK(0 == *context);
5904     }
5905   }
5906 }
5907
5908
5909 static const char* kEvalExtensionSource1 =
5910     "function UseEval1() {"
5911     "  var x = 42;"
5912     "  return eval('x');"
5913     "}";
5914
5915
5916 static const char* kEvalExtensionSource2 =
5917     "(function() {"
5918     "  var x = 42;"
5919     "  function e() {"
5920     "    return eval('x');"
5921     "  }"
5922     "  this.UseEval2 = e;"
5923     "})()";
5924
5925
5926 TEST(UseEvalFromExtension) {
5927   v8::HandleScope handle_scope(CcTest::isolate());
5928   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
5929   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
5930   const char* extension_names[] = {"evaltest1", "evaltest2"};
5931   v8::ExtensionConfiguration extensions(2, extension_names);
5932   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
5933   Context::Scope lock(context);
5934   v8::Handle<Value> result = CompileRun("UseEval1()");
5935   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
5936   result = CompileRun("UseEval2()");
5937   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
5938 }
5939
5940
5941 static const char* kWithExtensionSource1 =
5942     "function UseWith1() {"
5943     "  var x = 42;"
5944     "  with({x:87}) { return x; }"
5945     "}";
5946
5947
5948 static const char* kWithExtensionSource2 =
5949     "(function() {"
5950     "  var x = 42;"
5951     "  function e() {"
5952     "    with ({x:87}) { return x; }"
5953     "  }"
5954     "  this.UseWith2 = e;"
5955     "})()";
5956
5957
5958 TEST(UseWithFromExtension) {
5959   v8::HandleScope handle_scope(CcTest::isolate());
5960   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
5961   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
5962   const char* extension_names[] = {"withtest1", "withtest2"};
5963   v8::ExtensionConfiguration extensions(2, extension_names);
5964   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
5965   Context::Scope lock(context);
5966   v8::Handle<Value> result = CompileRun("UseWith1()");
5967   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
5968   result = CompileRun("UseWith2()");
5969   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
5970 }
5971
5972
5973 TEST(AutoExtensions) {
5974   v8::HandleScope handle_scope(CcTest::isolate());
5975   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
5976   extension->set_auto_enable(true);
5977   v8::RegisterExtension(extension);
5978   v8::Handle<Context> context = Context::New(CcTest::isolate());
5979   Context::Scope lock(context);
5980   v8::Handle<Value> result = CompileRun("Foo()");
5981   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
5982 }
5983
5984
5985 static const char* kSyntaxErrorInExtensionSource = "[";
5986
5987
5988 // Test that a syntax error in an extension does not cause a fatal
5989 // error but results in an empty context.
5990 TEST(SyntaxErrorExtensions) {
5991   v8::HandleScope handle_scope(CcTest::isolate());
5992   v8::RegisterExtension(
5993       new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
5994   const char* extension_names[] = {"syntaxerror"};
5995   v8::ExtensionConfiguration extensions(1, extension_names);
5996   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
5997   CHECK(context.IsEmpty());
5998 }
5999
6000
6001 static const char* kExceptionInExtensionSource = "throw 42";
6002
6003
6004 // Test that an exception when installing an extension does not cause
6005 // a fatal error but results in an empty context.
6006 TEST(ExceptionExtensions) {
6007   v8::HandleScope handle_scope(CcTest::isolate());
6008   v8::RegisterExtension(
6009       new Extension("exception", kExceptionInExtensionSource));
6010   const char* extension_names[] = {"exception"};
6011   v8::ExtensionConfiguration extensions(1, extension_names);
6012   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6013   CHECK(context.IsEmpty());
6014 }
6015
6016
6017 static const char* kNativeCallInExtensionSource =
6018     "function call_runtime_last_index_of(x) {"
6019     "  return %StringLastIndexOf(x, 'bob', 10);"
6020     "}";
6021
6022
6023 static const char* kNativeCallTest =
6024     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6025
6026 // Test that a native runtime calls are supported in extensions.
6027 TEST(NativeCallInExtensions) {
6028   v8::HandleScope handle_scope(CcTest::isolate());
6029   v8::RegisterExtension(
6030       new Extension("nativecall", kNativeCallInExtensionSource));
6031   const char* extension_names[] = {"nativecall"};
6032   v8::ExtensionConfiguration extensions(1, extension_names);
6033   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6034   Context::Scope lock(context);
6035   v8::Handle<Value> result = CompileRun(kNativeCallTest);
6036   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 3)));
6037 }
6038
6039
6040 class NativeFunctionExtension : public Extension {
6041  public:
6042   NativeFunctionExtension(const char* name, const char* source,
6043                           v8::FunctionCallback fun = &Echo)
6044       : Extension(name, source), function_(fun) {}
6045
6046   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6047       v8::Isolate* isolate, v8::Handle<v8::String> name) {
6048     return v8::FunctionTemplate::New(isolate, function_);
6049   }
6050
6051   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6052     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
6053   }
6054
6055  private:
6056   v8::FunctionCallback function_;
6057 };
6058
6059
6060 TEST(NativeFunctionDeclaration) {
6061   v8::HandleScope handle_scope(CcTest::isolate());
6062   const char* name = "nativedecl";
6063   v8::RegisterExtension(
6064       new NativeFunctionExtension(name, "native function foo();"));
6065   const char* extension_names[] = {name};
6066   v8::ExtensionConfiguration extensions(1, extension_names);
6067   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6068   Context::Scope lock(context);
6069   v8::Handle<Value> result = CompileRun("foo(42);");
6070   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6071 }
6072
6073
6074 TEST(NativeFunctionDeclarationError) {
6075   v8::HandleScope handle_scope(CcTest::isolate());
6076   const char* name = "nativedeclerr";
6077   // Syntax error in extension code.
6078   v8::RegisterExtension(
6079       new NativeFunctionExtension(name, "native\nfunction foo();"));
6080   const char* extension_names[] = {name};
6081   v8::ExtensionConfiguration extensions(1, extension_names);
6082   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6083   CHECK(context.IsEmpty());
6084 }
6085
6086
6087 TEST(NativeFunctionDeclarationErrorEscape) {
6088   v8::HandleScope handle_scope(CcTest::isolate());
6089   const char* name = "nativedeclerresc";
6090   // Syntax error in extension code - escape code in "native" means that
6091   // it's not treated as a keyword.
6092   v8::RegisterExtension(
6093       new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
6094   const char* extension_names[] = {name};
6095   v8::ExtensionConfiguration extensions(1, extension_names);
6096   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6097   CHECK(context.IsEmpty());
6098 }
6099
6100
6101 static void CheckDependencies(const char* name, const char* expected) {
6102   v8::HandleScope handle_scope(CcTest::isolate());
6103   v8::ExtensionConfiguration config(1, &name);
6104   LocalContext context(&config);
6105   CHECK(String::NewFromUtf8(CcTest::isolate(), expected)
6106             ->Equals(context->Global()->Get(v8_str("loaded"))));
6107 }
6108
6109
6110 /*
6111  * Configuration:
6112  *
6113  *     /-- B <--\
6114  * A <-          -- D <-- E
6115  *     \-- C <--/
6116  */
6117 THREADED_TEST(ExtensionDependency) {
6118   static const char* kEDeps[] = {"D"};
6119   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6120   static const char* kDDeps[] = {"B", "C"};
6121   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6122   static const char* kBCDeps[] = {"A"};
6123   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6124   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6125   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6126   CheckDependencies("A", "undefinedA");
6127   CheckDependencies("B", "undefinedAB");
6128   CheckDependencies("C", "undefinedAC");
6129   CheckDependencies("D", "undefinedABCD");
6130   CheckDependencies("E", "undefinedABCDE");
6131   v8::HandleScope handle_scope(CcTest::isolate());
6132   static const char* exts[2] = {"C", "E"};
6133   v8::ExtensionConfiguration config(2, exts);
6134   LocalContext context(&config);
6135   CHECK(v8_str("undefinedACBDE")
6136             ->Equals(context->Global()->Get(v8_str("loaded"))));
6137 }
6138
6139
6140 static const char* kExtensionTestScript =
6141     "native function A();"
6142     "native function B();"
6143     "native function C();"
6144     "function Foo(i) {"
6145     "  if (i == 0) return A();"
6146     "  if (i == 1) return B();"
6147     "  if (i == 2) return C();"
6148     "}";
6149
6150
6151 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
6152   ApiTestFuzzer::Fuzz();
6153   if (args.IsConstructCall()) {
6154     args.This()->Set(v8_str("data"), args.Data());
6155     args.GetReturnValue().SetNull();
6156     return;
6157   }
6158   args.GetReturnValue().Set(args.Data());
6159 }
6160
6161
6162 class FunctionExtension : public Extension {
6163  public:
6164   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
6165   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6166       v8::Isolate* isolate, v8::Handle<String> name);
6167 };
6168
6169
6170 static int lookup_count = 0;
6171 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
6172     v8::Isolate* isolate, v8::Handle<String> name) {
6173   lookup_count++;
6174   if (name->Equals(v8_str("A"))) {
6175     return v8::FunctionTemplate::New(isolate, CallFun,
6176                                      v8::Integer::New(isolate, 8));
6177   } else if (name->Equals(v8_str("B"))) {
6178     return v8::FunctionTemplate::New(isolate, CallFun,
6179                                      v8::Integer::New(isolate, 7));
6180   } else if (name->Equals(v8_str("C"))) {
6181     return v8::FunctionTemplate::New(isolate, CallFun,
6182                                      v8::Integer::New(isolate, 6));
6183   } else {
6184     return v8::Handle<v8::FunctionTemplate>();
6185   }
6186 }
6187
6188
6189 THREADED_TEST(FunctionLookup) {
6190   v8::RegisterExtension(new FunctionExtension());
6191   v8::HandleScope handle_scope(CcTest::isolate());
6192   static const char* exts[1] = {"functiontest"};
6193   v8::ExtensionConfiguration config(1, exts);
6194   LocalContext context(&config);
6195   CHECK_EQ(3, lookup_count);
6196   CHECK(v8::Integer::New(CcTest::isolate(), 8)->Equals(CompileRun("Foo(0)")));
6197   CHECK(v8::Integer::New(CcTest::isolate(), 7)->Equals(CompileRun("Foo(1)")));
6198   CHECK(v8::Integer::New(CcTest::isolate(), 6)->Equals(CompileRun("Foo(2)")));
6199 }
6200
6201
6202 THREADED_TEST(NativeFunctionConstructCall) {
6203   v8::RegisterExtension(new FunctionExtension());
6204   v8::HandleScope handle_scope(CcTest::isolate());
6205   static const char* exts[1] = {"functiontest"};
6206   v8::ExtensionConfiguration config(1, exts);
6207   LocalContext context(&config);
6208   for (int i = 0; i < 10; i++) {
6209     // Run a few times to ensure that allocation of objects doesn't
6210     // change behavior of a constructor function.
6211     CHECK(v8::Integer::New(CcTest::isolate(), 8)
6212               ->Equals(CompileRun("(new A()).data")));
6213     CHECK(v8::Integer::New(CcTest::isolate(), 7)
6214               ->Equals(CompileRun("(new B()).data")));
6215     CHECK(v8::Integer::New(CcTest::isolate(), 6)
6216               ->Equals(CompileRun("(new C()).data")));
6217   }
6218 }
6219
6220
6221 static const char* last_location;
6222 static const char* last_message;
6223 void StoringErrorCallback(const char* location, const char* message) {
6224   if (last_location == NULL) {
6225     last_location = location;
6226     last_message = message;
6227   }
6228 }
6229
6230
6231 // ErrorReporting creates a circular extensions configuration and
6232 // tests that the fatal error handler gets called.  This renders V8
6233 // unusable and therefore this test cannot be run in parallel.
6234 TEST(ErrorReporting) {
6235   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
6236   static const char* aDeps[] = {"B"};
6237   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
6238   static const char* bDeps[] = {"A"};
6239   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
6240   last_location = NULL;
6241   v8::ExtensionConfiguration config(1, bDeps);
6242   v8::Handle<Context> context = Context::New(CcTest::isolate(), &config);
6243   CHECK(context.IsEmpty());
6244   CHECK(last_location);
6245 }
6246
6247
6248 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
6249                                              v8::Handle<Value> data) {
6250   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
6251   CHECK(v8::Undefined(CcTest::isolate())
6252             ->Equals(message->GetScriptOrigin().ResourceName()));
6253   message->GetLineNumber();
6254   message->GetSourceLine();
6255 }
6256
6257
6258 THREADED_TEST(ErrorWithMissingScriptInfo) {
6259   LocalContext context;
6260   v8::HandleScope scope(context->GetIsolate());
6261   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
6262   CompileRun("throw Error()");
6263   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
6264 }
6265
6266
6267 struct FlagAndPersistent {
6268   bool flag;
6269   v8::Persistent<v8::Object> handle;
6270 };
6271
6272
6273 static void SetFlag(const v8::PhantomCallbackData<FlagAndPersistent>& data) {
6274   data.GetParameter()->flag = true;
6275 }
6276
6277
6278 static void IndependentWeakHandle(bool global_gc, bool interlinked) {
6279   v8::Isolate* iso = CcTest::isolate();
6280   v8::HandleScope scope(iso);
6281   v8::Handle<Context> context = Context::New(iso);
6282   Context::Scope context_scope(context);
6283
6284   FlagAndPersistent object_a, object_b;
6285
6286   intptr_t big_heap_size;
6287
6288   {
6289     v8::HandleScope handle_scope(iso);
6290     Local<Object> a(v8::Object::New(iso));
6291     Local<Object> b(v8::Object::New(iso));
6292     object_a.handle.Reset(iso, a);
6293     object_b.handle.Reset(iso, b);
6294     if (interlinked) {
6295       a->Set(v8_str("x"), b);
6296       b->Set(v8_str("x"), a);
6297     }
6298     if (global_gc) {
6299       CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
6300     } else {
6301       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6302     }
6303     // We are relying on this creating a big flag array and reserving the space
6304     // up front.
6305     v8::Handle<Value> big_array = CompileRun("new Array(50000)");
6306     a->Set(v8_str("y"), big_array);
6307     big_heap_size = CcTest::heap()->SizeOfObjects();
6308   }
6309
6310   object_a.flag = false;
6311   object_b.flag = false;
6312   object_a.handle.SetPhantom(&object_a, &SetFlag);
6313   object_b.handle.SetPhantom(&object_b, &SetFlag);
6314   CHECK(!object_b.handle.IsIndependent());
6315   object_a.handle.MarkIndependent();
6316   object_b.handle.MarkIndependent();
6317   CHECK(object_b.handle.IsIndependent());
6318   if (global_gc) {
6319     CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
6320   } else {
6321     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6322   }
6323   // A single GC should be enough to reclaim the memory, since we are using
6324   // phantom handles.
6325   CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 200000);
6326   CHECK(object_a.flag);
6327   CHECK(object_b.flag);
6328 }
6329
6330
6331 THREADED_TEST(IndependentWeakHandle) {
6332   IndependentWeakHandle(false, false);
6333   IndependentWeakHandle(false, true);
6334   IndependentWeakHandle(true, false);
6335   IndependentWeakHandle(true, true);
6336 }
6337
6338
6339 class Trivial {
6340  public:
6341   explicit Trivial(int x) : x_(x) {}
6342
6343   int x() { return x_; }
6344   void set_x(int x) { x_ = x; }
6345
6346  private:
6347   int x_;
6348 };
6349
6350
6351 class Trivial2 {
6352  public:
6353   Trivial2(int x, int y) : y_(y), x_(x) {}
6354
6355   int x() { return x_; }
6356   void set_x(int x) { x_ = x; }
6357
6358   int y() { return y_; }
6359   void set_y(int y) { y_ = y; }
6360
6361  private:
6362   int y_;
6363   int x_;
6364 };
6365
6366
6367 void CheckInternalFields(
6368     const v8::PhantomCallbackData<v8::Persistent<v8::Object>>& data) {
6369   v8::Persistent<v8::Object>* handle = data.GetParameter();
6370   handle->Reset();
6371   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField1());
6372   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField2());
6373   CHECK_EQ(42, t1->x());
6374   CHECK_EQ(103, t2->x());
6375   t1->set_x(1729);
6376   t2->set_x(33550336);
6377 }
6378
6379
6380 void InternalFieldCallback(bool global_gc) {
6381   LocalContext env;
6382   v8::Isolate* isolate = env->GetIsolate();
6383   v8::HandleScope scope(isolate);
6384
6385   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
6386   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
6387   Trivial* t1;
6388   Trivial2* t2;
6389   instance_templ->SetInternalFieldCount(2);
6390   {
6391     v8::HandleScope scope(isolate);
6392     Local<v8::Object> obj = templ->GetFunction()->NewInstance();
6393     v8::Persistent<v8::Object> handle(isolate, obj);
6394     CHECK_EQ(2, obj->InternalFieldCount());
6395     CHECK(obj->GetInternalField(0)->IsUndefined());
6396     t1 = new Trivial(42);
6397     t2 = new Trivial2(103, 9);
6398
6399     obj->SetAlignedPointerInInternalField(0, t1);
6400     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
6401     CHECK_EQ(42, t1->x());
6402
6403     obj->SetAlignedPointerInInternalField(1, t2);
6404     t2 =
6405         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
6406     CHECK_EQ(103, t2->x());
6407
6408     handle.SetPhantom<v8::Persistent<v8::Object>>(&handle, CheckInternalFields,
6409                                                   0, 1);
6410     if (!global_gc) {
6411       handle.MarkIndependent();
6412     }
6413   }
6414   if (global_gc) {
6415     CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags);
6416   } else {
6417     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6418   }
6419
6420   CHECK_EQ(1729, t1->x());
6421   CHECK_EQ(33550336, t2->x());
6422
6423   delete t1;
6424   delete t2;
6425 }
6426
6427
6428 THREADED_TEST(InternalFieldCallback) {
6429   InternalFieldCallback(false);
6430   InternalFieldCallback(true);
6431 }
6432
6433
6434 static void ResetUseValueAndSetFlag(
6435     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
6436   // Blink will reset the handle, and then use the other handle, so they
6437   // can't use the same backing slot.
6438   data.GetParameter()->handle.Reset();
6439   data.GetValue()->IsBoolean();  // Make sure the handle still works.
6440   data.GetParameter()->flag = true;
6441 }
6442
6443
6444 static void ResetWeakHandle(bool global_gc) {
6445   v8::Isolate* iso = CcTest::isolate();
6446   v8::HandleScope scope(iso);
6447   v8::Handle<Context> context = Context::New(iso);
6448   Context::Scope context_scope(context);
6449
6450   FlagAndPersistent object_a, object_b;
6451
6452   {
6453     v8::HandleScope handle_scope(iso);
6454     Local<Object> a(v8::Object::New(iso));
6455     Local<Object> b(v8::Object::New(iso));
6456     object_a.handle.Reset(iso, a);
6457     object_b.handle.Reset(iso, b);
6458     if (global_gc) {
6459       CcTest::heap()->CollectAllGarbage(
6460           TestHeap::Heap::kAbortIncrementalMarkingMask);
6461     } else {
6462       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6463     }
6464   }
6465
6466   object_a.flag = false;
6467   object_b.flag = false;
6468   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag);
6469   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag);
6470   if (!global_gc) {
6471     object_a.handle.MarkIndependent();
6472     object_b.handle.MarkIndependent();
6473     CHECK(object_b.handle.IsIndependent());
6474   }
6475   if (global_gc) {
6476     CcTest::heap()->CollectAllGarbage(
6477         TestHeap::Heap::kAbortIncrementalMarkingMask);
6478   } else {
6479     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6480   }
6481   CHECK(object_a.flag);
6482   CHECK(object_b.flag);
6483 }
6484
6485
6486 THREADED_TEST(ResetWeakHandle) {
6487   ResetWeakHandle(false);
6488   ResetWeakHandle(true);
6489 }
6490
6491
6492 static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
6493
6494
6495 static void InvokeMarkSweep() {
6496   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
6497 }
6498
6499
6500 static void ForceScavenge(
6501     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
6502   data.GetParameter()->handle.Reset();
6503   data.GetParameter()->flag = true;
6504   InvokeScavenge();
6505 }
6506
6507
6508 static void ForceMarkSweep(
6509     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
6510   data.GetParameter()->handle.Reset();
6511   data.GetParameter()->flag = true;
6512   InvokeMarkSweep();
6513 }
6514
6515
6516 THREADED_TEST(GCFromWeakCallbacks) {
6517   v8::Isolate* isolate = CcTest::isolate();
6518   v8::HandleScope scope(isolate);
6519   v8::Handle<Context> context = Context::New(isolate);
6520   Context::Scope context_scope(context);
6521
6522   static const int kNumberOfGCTypes = 2;
6523   typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
6524       Callback;
6525   Callback gc_forcing_callback[kNumberOfGCTypes] =
6526       {&ForceScavenge, &ForceMarkSweep};
6527
6528   typedef void (*GCInvoker)();
6529   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
6530
6531   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
6532     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
6533       FlagAndPersistent object;
6534       {
6535         v8::HandleScope handle_scope(isolate);
6536         object.handle.Reset(isolate, v8::Object::New(isolate));
6537       }
6538       object.flag = false;
6539       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
6540       object.handle.MarkIndependent();
6541       invoke_gc[outer_gc]();
6542       CHECK(object.flag);
6543     }
6544   }
6545 }
6546
6547
6548 static void RevivingCallback(
6549     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
6550   data.GetParameter()->handle.ClearWeak();
6551   data.GetParameter()->flag = true;
6552 }
6553
6554
6555 THREADED_TEST(IndependentHandleRevival) {
6556   v8::Isolate* isolate = CcTest::isolate();
6557   v8::HandleScope scope(isolate);
6558   v8::Handle<Context> context = Context::New(isolate);
6559   Context::Scope context_scope(context);
6560
6561   FlagAndPersistent object;
6562   {
6563     v8::HandleScope handle_scope(isolate);
6564     v8::Local<v8::Object> o = v8::Object::New(isolate);
6565     object.handle.Reset(isolate, o);
6566     o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
6567     v8::Local<String> y_str = v8_str("y");
6568     o->Set(y_str, y_str);
6569   }
6570   object.flag = false;
6571   object.handle.SetWeak(&object, &RevivingCallback);
6572   object.handle.MarkIndependent();
6573   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6574   CHECK(object.flag);
6575   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
6576   {
6577     v8::HandleScope handle_scope(isolate);
6578     v8::Local<v8::Object> o =
6579         v8::Local<v8::Object>::New(isolate, object.handle);
6580     v8::Local<String> y_str = v8_str("y");
6581     CHECK(v8::Integer::New(isolate, 1)->Equals(o->Get(v8_str("x"))));
6582     CHECK(o->Get(y_str)->Equals(y_str));
6583   }
6584 }
6585
6586
6587 v8::Handle<Function> args_fun;
6588
6589
6590 static void ArgumentsTestCallback(
6591     const v8::FunctionCallbackInfo<v8::Value>& args) {
6592   ApiTestFuzzer::Fuzz();
6593   v8::Isolate* isolate = args.GetIsolate();
6594   CHECK(args_fun->Equals(args.Callee()));
6595   CHECK_EQ(3, args.Length());
6596   CHECK(v8::Integer::New(isolate, 1)->Equals(args[0]));
6597   CHECK(v8::Integer::New(isolate, 2)->Equals(args[1]));
6598   CHECK(v8::Integer::New(isolate, 3)->Equals(args[2]));
6599   CHECK(v8::Undefined(isolate)->Equals(args[3]));
6600   v8::HandleScope scope(args.GetIsolate());
6601   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
6602 }
6603
6604
6605 THREADED_TEST(Arguments) {
6606   v8::Isolate* isolate = CcTest::isolate();
6607   v8::HandleScope scope(isolate);
6608   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
6609   global->Set(v8_str("f"),
6610               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
6611   LocalContext context(NULL, global);
6612   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
6613   v8_compile("f(1, 2, 3)")->Run();
6614 }
6615
6616
6617 static int p_getter_count;
6618 static int p_getter_count2;
6619
6620
6621 static void PGetter(Local<String> name,
6622                     const v8::PropertyCallbackInfo<v8::Value>& info) {
6623   ApiTestFuzzer::Fuzz();
6624   p_getter_count++;
6625   v8::Handle<v8::Object> global =
6626       info.GetIsolate()->GetCurrentContext()->Global();
6627   CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
6628   if (name->Equals(v8_str("p1"))) {
6629     CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
6630   } else if (name->Equals(v8_str("p2"))) {
6631     CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
6632   } else if (name->Equals(v8_str("p3"))) {
6633     CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
6634   } else if (name->Equals(v8_str("p4"))) {
6635     CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
6636   }
6637 }
6638
6639
6640 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
6641   ApiTestFuzzer::Fuzz();
6642   LocalContext context;
6643   context->Global()->Set(v8_str("o1"), obj->NewInstance());
6644   CompileRun(
6645     "o1.__proto__ = { };"
6646     "var o2 = { __proto__: o1 };"
6647     "var o3 = { __proto__: o2 };"
6648     "var o4 = { __proto__: o3 };"
6649     "for (var i = 0; i < 10; i++) o4.p4;"
6650     "for (var i = 0; i < 10; i++) o3.p3;"
6651     "for (var i = 0; i < 10; i++) o2.p2;"
6652     "for (var i = 0; i < 10; i++) o1.p1;");
6653 }
6654
6655
6656 static void PGetter2(Local<Name> name,
6657                      const v8::PropertyCallbackInfo<v8::Value>& info) {
6658   ApiTestFuzzer::Fuzz();
6659   p_getter_count2++;
6660   v8::Handle<v8::Object> global =
6661       info.GetIsolate()->GetCurrentContext()->Global();
6662   CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
6663   if (name->Equals(v8_str("p1"))) {
6664     CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
6665   } else if (name->Equals(v8_str("p2"))) {
6666     CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
6667   } else if (name->Equals(v8_str("p3"))) {
6668     CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
6669   } else if (name->Equals(v8_str("p4"))) {
6670     CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
6671   }
6672 }
6673
6674
6675 THREADED_TEST(GetterHolders) {
6676   v8::Isolate* isolate = CcTest::isolate();
6677   v8::HandleScope scope(isolate);
6678   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
6679   obj->SetAccessor(v8_str("p1"), PGetter);
6680   obj->SetAccessor(v8_str("p2"), PGetter);
6681   obj->SetAccessor(v8_str("p3"), PGetter);
6682   obj->SetAccessor(v8_str("p4"), PGetter);
6683   p_getter_count = 0;
6684   RunHolderTest(obj);
6685   CHECK_EQ(40, p_getter_count);
6686 }
6687
6688
6689 THREADED_TEST(PreInterceptorHolders) {
6690   v8::Isolate* isolate = CcTest::isolate();
6691   v8::HandleScope scope(isolate);
6692   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
6693   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
6694   p_getter_count2 = 0;
6695   RunHolderTest(obj);
6696   CHECK_EQ(40, p_getter_count2);
6697 }
6698
6699
6700 THREADED_TEST(ObjectInstantiation) {
6701   v8::Isolate* isolate = CcTest::isolate();
6702   v8::HandleScope scope(isolate);
6703   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
6704   templ->SetAccessor(v8_str("t"), PGetter2);
6705   LocalContext context;
6706   context->Global()->Set(v8_str("o"), templ->NewInstance());
6707   for (int i = 0; i < 100; i++) {
6708     v8::HandleScope inner_scope(CcTest::isolate());
6709     v8::Handle<v8::Object> obj = templ->NewInstance();
6710     CHECK(!obj->Equals(context->Global()->Get(v8_str("o"))));
6711     context->Global()->Set(v8_str("o2"), obj);
6712     v8::Handle<Value> value =
6713         CompileRun("o.__proto__ === o2.__proto__");
6714     CHECK(v8::True(isolate)->Equals(value));
6715     context->Global()->Set(v8_str("o"), obj);
6716   }
6717 }
6718
6719
6720 static int StrCmp16(uint16_t* a, uint16_t* b) {
6721   while (true) {
6722     if (*a == 0 && *b == 0) return 0;
6723     if (*a != *b) return 0 + *a - *b;
6724     a++;
6725     b++;
6726   }
6727 }
6728
6729
6730 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
6731   while (true) {
6732     if (n-- == 0) return 0;
6733     if (*a == 0 && *b == 0) return 0;
6734     if (*a != *b) return 0 + *a - *b;
6735     a++;
6736     b++;
6737   }
6738 }
6739
6740
6741 int GetUtf8Length(Handle<String> str) {
6742   int len = str->Utf8Length();
6743   if (len < 0) {
6744     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
6745     i::String::Flatten(istr);
6746     len = str->Utf8Length();
6747   }
6748   return len;
6749 }
6750
6751
6752 THREADED_TEST(StringWrite) {
6753   LocalContext context;
6754   v8::HandleScope scope(context->GetIsolate());
6755   v8::Handle<String> str = v8_str("abcde");
6756   // abc<Icelandic eth><Unicode snowman>.
6757   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
6758   v8::Handle<String> str3 = v8::String::NewFromUtf8(
6759       context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
6760   // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
6761   uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
6762   v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
6763       context->GetIsolate(), orphans, v8::String::kNormalString, 8);
6764   // single lead surrogate
6765   uint16_t lead[1] = { 0xd800 };
6766   v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
6767       context->GetIsolate(), lead, v8::String::kNormalString, 1);
6768   // single trail surrogate
6769   uint16_t trail[1] = { 0xdc00 };
6770   v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
6771       context->GetIsolate(), trail, v8::String::kNormalString, 1);
6772   // surrogate pair
6773   uint16_t pair[2] = { 0xd800,  0xdc00 };
6774   v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
6775       context->GetIsolate(), pair, v8::String::kNormalString, 2);
6776   const int kStride = 4;  // Must match stride in for loops in JS below.
6777   CompileRun(
6778       "var left = '';"
6779       "for (var i = 0; i < 0xd800; i += 4) {"
6780       "  left = left + String.fromCharCode(i);"
6781       "}");
6782   CompileRun(
6783       "var right = '';"
6784       "for (var i = 0; i < 0xd800; i += 4) {"
6785       "  right = String.fromCharCode(i) + right;"
6786       "}");
6787   v8::Handle<v8::Object> global = context->Global();
6788   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
6789   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
6790
6791   CHECK_EQ(5, str2->Length());
6792   CHECK_EQ(0xd800 / kStride, left_tree->Length());
6793   CHECK_EQ(0xd800 / kStride, right_tree->Length());
6794
6795   char buf[100];
6796   char utf8buf[0xd800 * 3];
6797   uint16_t wbuf[100];
6798   int len;
6799   int charlen;
6800
6801   memset(utf8buf, 0x1, 1000);
6802   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
6803   CHECK_EQ(9, len);
6804   CHECK_EQ(5, charlen);
6805   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
6806
6807   memset(utf8buf, 0x1, 1000);
6808   len = str2->WriteUtf8(utf8buf, 8, &charlen);
6809   CHECK_EQ(8, len);
6810   CHECK_EQ(5, charlen);
6811   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
6812
6813   memset(utf8buf, 0x1, 1000);
6814   len = str2->WriteUtf8(utf8buf, 7, &charlen);
6815   CHECK_EQ(5, len);
6816   CHECK_EQ(4, charlen);
6817   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
6818
6819   memset(utf8buf, 0x1, 1000);
6820   len = str2->WriteUtf8(utf8buf, 6, &charlen);
6821   CHECK_EQ(5, len);
6822   CHECK_EQ(4, charlen);
6823   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
6824
6825   memset(utf8buf, 0x1, 1000);
6826   len = str2->WriteUtf8(utf8buf, 5, &charlen);
6827   CHECK_EQ(5, len);
6828   CHECK_EQ(4, charlen);
6829   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
6830
6831   memset(utf8buf, 0x1, 1000);
6832   len = str2->WriteUtf8(utf8buf, 4, &charlen);
6833   CHECK_EQ(3, len);
6834   CHECK_EQ(3, charlen);
6835   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
6836
6837   memset(utf8buf, 0x1, 1000);
6838   len = str2->WriteUtf8(utf8buf, 3, &charlen);
6839   CHECK_EQ(3, len);
6840   CHECK_EQ(3, charlen);
6841   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
6842
6843   memset(utf8buf, 0x1, 1000);
6844   len = str2->WriteUtf8(utf8buf, 2, &charlen);
6845   CHECK_EQ(2, len);
6846   CHECK_EQ(2, charlen);
6847   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
6848
6849   // allow orphan surrogates by default
6850   memset(utf8buf, 0x1, 1000);
6851   len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
6852   CHECK_EQ(13, len);
6853   CHECK_EQ(8, charlen);
6854   CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
6855
6856   // replace orphan surrogates with unicode replacement character
6857   memset(utf8buf, 0x1, 1000);
6858   len = orphans_str->WriteUtf8(utf8buf,
6859                                sizeof(utf8buf),
6860                                &charlen,
6861                                String::REPLACE_INVALID_UTF8);
6862   CHECK_EQ(13, len);
6863   CHECK_EQ(8, charlen);
6864   CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
6865
6866   // replace single lead surrogate with unicode replacement character
6867   memset(utf8buf, 0x1, 1000);
6868   len = lead_str->WriteUtf8(utf8buf,
6869                             sizeof(utf8buf),
6870                             &charlen,
6871                             String::REPLACE_INVALID_UTF8);
6872   CHECK_EQ(4, len);
6873   CHECK_EQ(1, charlen);
6874   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
6875
6876   // replace single trail surrogate with unicode replacement character
6877   memset(utf8buf, 0x1, 1000);
6878   len = trail_str->WriteUtf8(utf8buf,
6879                              sizeof(utf8buf),
6880                              &charlen,
6881                              String::REPLACE_INVALID_UTF8);
6882   CHECK_EQ(4, len);
6883   CHECK_EQ(1, charlen);
6884   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
6885
6886   // do not replace / write anything if surrogate pair does not fit the buffer
6887   // space
6888   memset(utf8buf, 0x1, 1000);
6889   len = pair_str->WriteUtf8(utf8buf,
6890                              3,
6891                              &charlen,
6892                              String::REPLACE_INVALID_UTF8);
6893   CHECK_EQ(0, len);
6894   CHECK_EQ(0, charlen);
6895
6896   memset(utf8buf, 0x1, sizeof(utf8buf));
6897   len = GetUtf8Length(left_tree);
6898   int utf8_expected =
6899       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
6900   CHECK_EQ(utf8_expected, len);
6901   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
6902   CHECK_EQ(utf8_expected, len);
6903   CHECK_EQ(0xd800 / kStride, charlen);
6904   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
6905   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
6906   CHECK_EQ(0xc0 - kStride,
6907            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
6908   CHECK_EQ(1, utf8buf[utf8_expected]);
6909
6910   memset(utf8buf, 0x1, sizeof(utf8buf));
6911   len = GetUtf8Length(right_tree);
6912   CHECK_EQ(utf8_expected, len);
6913   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
6914   CHECK_EQ(utf8_expected, len);
6915   CHECK_EQ(0xd800 / kStride, charlen);
6916   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
6917   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
6918   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
6919   CHECK_EQ(1, utf8buf[utf8_expected]);
6920
6921   memset(buf, 0x1, sizeof(buf));
6922   memset(wbuf, 0x1, sizeof(wbuf));
6923   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
6924   CHECK_EQ(5, len);
6925   len = str->Write(wbuf);
6926   CHECK_EQ(5, len);
6927   CHECK_EQ(0, strcmp("abcde", buf));
6928   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
6929   CHECK_EQ(0, StrCmp16(answer1, wbuf));
6930
6931   memset(buf, 0x1, sizeof(buf));
6932   memset(wbuf, 0x1, sizeof(wbuf));
6933   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
6934   CHECK_EQ(4, len);
6935   len = str->Write(wbuf, 0, 4);
6936   CHECK_EQ(4, len);
6937   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
6938   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
6939   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
6940
6941   memset(buf, 0x1, sizeof(buf));
6942   memset(wbuf, 0x1, sizeof(wbuf));
6943   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
6944   CHECK_EQ(5, len);
6945   len = str->Write(wbuf, 0, 5);
6946   CHECK_EQ(5, len);
6947   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
6948   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
6949   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
6950
6951   memset(buf, 0x1, sizeof(buf));
6952   memset(wbuf, 0x1, sizeof(wbuf));
6953   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
6954   CHECK_EQ(5, len);
6955   len = str->Write(wbuf, 0, 6);
6956   CHECK_EQ(5, len);
6957   CHECK_EQ(0, strcmp("abcde", buf));
6958   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
6959   CHECK_EQ(0, StrCmp16(answer4, wbuf));
6960
6961   memset(buf, 0x1, sizeof(buf));
6962   memset(wbuf, 0x1, sizeof(wbuf));
6963   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
6964   CHECK_EQ(1, len);
6965   len = str->Write(wbuf, 4, -1);
6966   CHECK_EQ(1, len);
6967   CHECK_EQ(0, strcmp("e", buf));
6968   uint16_t answer5[] = {'e', '\0'};
6969   CHECK_EQ(0, StrCmp16(answer5, wbuf));
6970
6971   memset(buf, 0x1, sizeof(buf));
6972   memset(wbuf, 0x1, sizeof(wbuf));
6973   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
6974   CHECK_EQ(1, len);
6975   len = str->Write(wbuf, 4, 6);
6976   CHECK_EQ(1, len);
6977   CHECK_EQ(0, strcmp("e", buf));
6978   CHECK_EQ(0, StrCmp16(answer5, wbuf));
6979
6980   memset(buf, 0x1, sizeof(buf));
6981   memset(wbuf, 0x1, sizeof(wbuf));
6982   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
6983   CHECK_EQ(1, len);
6984   len = str->Write(wbuf, 4, 1);
6985   CHECK_EQ(1, len);
6986   CHECK_EQ(0, strncmp("e\1", buf, 2));
6987   uint16_t answer6[] = {'e', 0x101};
6988   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
6989
6990   memset(buf, 0x1, sizeof(buf));
6991   memset(wbuf, 0x1, sizeof(wbuf));
6992   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
6993   CHECK_EQ(1, len);
6994   len = str->Write(wbuf, 3, 1);
6995   CHECK_EQ(1, len);
6996   CHECK_EQ(0, strncmp("d\1", buf, 2));
6997   uint16_t answer7[] = {'d', 0x101};
6998   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
6999
7000   memset(wbuf, 0x1, sizeof(wbuf));
7001   wbuf[5] = 'X';
7002   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7003   CHECK_EQ(5, len);
7004   CHECK_EQ('X', wbuf[5]);
7005   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7006   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7007   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7008   CHECK_NE(0, StrCmp16(answer8b, wbuf));
7009   wbuf[5] = '\0';
7010   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7011
7012   memset(buf, 0x1, sizeof(buf));
7013   buf[5] = 'X';
7014   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7015                           0,
7016                           6,
7017                           String::NO_NULL_TERMINATION);
7018   CHECK_EQ(5, len);
7019   CHECK_EQ('X', buf[5]);
7020   CHECK_EQ(0, strncmp("abcde", buf, 5));
7021   CHECK_NE(0, strcmp("abcde", buf));
7022   buf[5] = '\0';
7023   CHECK_EQ(0, strcmp("abcde", buf));
7024
7025   memset(utf8buf, 0x1, sizeof(utf8buf));
7026   utf8buf[8] = 'X';
7027   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7028                         String::NO_NULL_TERMINATION);
7029   CHECK_EQ(8, len);
7030   CHECK_EQ('X', utf8buf[8]);
7031   CHECK_EQ(5, charlen);
7032   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7033   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7034   utf8buf[8] = '\0';
7035   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7036
7037   memset(utf8buf, 0x1, sizeof(utf8buf));
7038   utf8buf[5] = 'X';
7039   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7040                         String::NO_NULL_TERMINATION);
7041   CHECK_EQ(5, len);
7042   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
7043   CHECK_EQ(5, charlen);
7044   utf8buf[5] = '\0';
7045   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7046
7047   memset(buf, 0x1, sizeof(buf));
7048   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7049   CHECK_EQ(7, len);
7050   CHECK_EQ(0, strcmp("abc", buf));
7051   CHECK_EQ(0, buf[3]);
7052   CHECK_EQ(0, strcmp("def", buf + 4));
7053
7054   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
7055   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7056   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
7057 }
7058
7059
7060 static void Utf16Helper(
7061     LocalContext& context,  // NOLINT
7062     const char* name,
7063     const char* lengths_name,
7064     int len) {
7065   Local<v8::Array> a =
7066       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7067   Local<v8::Array> alens =
7068       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7069   for (int i = 0; i < len; i++) {
7070     Local<v8::String> string =
7071       Local<v8::String>::Cast(a->Get(i));
7072     Local<v8::Number> expected_len =
7073       Local<v8::Number>::Cast(alens->Get(i));
7074     int length = GetUtf8Length(string);
7075     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7076   }
7077 }
7078
7079
7080 static uint16_t StringGet(Handle<String> str, int index) {
7081   i::Handle<i::String> istring =
7082       v8::Utils::OpenHandle(String::Cast(*str));
7083   return istring->Get(index);
7084 }
7085
7086
7087 static void WriteUtf8Helper(
7088     LocalContext& context,  // NOLINT
7089     const char* name,
7090     const char* lengths_name,
7091     int len) {
7092   Local<v8::Array> b =
7093       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7094   Local<v8::Array> alens =
7095       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7096   char buffer[1000];
7097   char buffer2[1000];
7098   for (int i = 0; i < len; i++) {
7099     Local<v8::String> string =
7100       Local<v8::String>::Cast(b->Get(i));
7101     Local<v8::Number> expected_len =
7102       Local<v8::Number>::Cast(alens->Get(i));
7103     int utf8_length = static_cast<int>(expected_len->Value());
7104     for (int j = utf8_length + 1; j >= 0; j--) {
7105       memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
7106       memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
7107       int nchars;
7108       int utf8_written =
7109           string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
7110       int utf8_written2 =
7111           string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
7112       CHECK_GE(utf8_length + 1, utf8_written);
7113       CHECK_GE(utf8_length, utf8_written2);
7114       for (int k = 0; k < utf8_written2; k++) {
7115         CHECK_EQ(buffer[k], buffer2[k]);
7116       }
7117       CHECK(nchars * 3 >= utf8_written - 1);
7118       CHECK(nchars <= utf8_written);
7119       if (j == utf8_length + 1) {
7120         CHECK_EQ(utf8_written2, utf8_length);
7121         CHECK_EQ(utf8_written2 + 1, utf8_written);
7122       }
7123       CHECK_EQ(buffer[utf8_written], 42);
7124       if (j > utf8_length) {
7125         if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
7126         if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
7127         Handle<String> roundtrip = v8_str(buffer);
7128         CHECK(roundtrip->Equals(string));
7129       } else {
7130         if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7131       }
7132       if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7133       if (nchars >= 2) {
7134         uint16_t trail = StringGet(string, nchars - 1);
7135         uint16_t lead = StringGet(string, nchars - 2);
7136         if (((lead & 0xfc00) == 0xd800) &&
7137             ((trail & 0xfc00) == 0xdc00)) {
7138           unsigned u1 = buffer2[utf8_written2 - 4];
7139           unsigned u2 = buffer2[utf8_written2 - 3];
7140           unsigned u3 = buffer2[utf8_written2 - 2];
7141           unsigned u4 = buffer2[utf8_written2 - 1];
7142           CHECK_EQ((u1 & 0xf8), 0xf0u);
7143           CHECK_EQ((u2 & 0xc0), 0x80u);
7144           CHECK_EQ((u3 & 0xc0), 0x80u);
7145           CHECK_EQ((u4 & 0xc0), 0x80u);
7146           uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
7147           CHECK_EQ((u4 & 0x3f), (c & 0x3f));
7148           CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
7149           CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
7150           CHECK_EQ((u1 & 0x3), c >> 18);
7151         }
7152       }
7153     }
7154   }
7155 }
7156
7157
7158 THREADED_TEST(Utf16) {
7159   LocalContext context;
7160   v8::HandleScope scope(context->GetIsolate());
7161   CompileRun(
7162       "var pad = '01234567890123456789';"
7163       "var p = [];"
7164       "var plens = [20, 3, 3];"
7165       "p.push('01234567890123456789');"
7166       "var lead = 0xd800;"
7167       "var trail = 0xdc00;"
7168       "p.push(String.fromCharCode(0xd800));"
7169       "p.push(String.fromCharCode(0xdc00));"
7170       "var a = [];"
7171       "var b = [];"
7172       "var c = [];"
7173       "var alens = [];"
7174       "for (var i = 0; i < 3; i++) {"
7175       "  p[1] = String.fromCharCode(lead++);"
7176       "  for (var j = 0; j < 3; j++) {"
7177       "    p[2] = String.fromCharCode(trail++);"
7178       "    a.push(p[i] + p[j]);"
7179       "    b.push(p[i] + p[j]);"
7180       "    c.push(p[i] + p[j]);"
7181       "    alens.push(plens[i] + plens[j]);"
7182       "  }"
7183       "}"
7184       "alens[5] -= 2;"  // Here the surrogate pairs match up.
7185       "var a2 = [];"
7186       "var b2 = [];"
7187       "var c2 = [];"
7188       "var a2lens = [];"
7189       "for (var m = 0; m < 9; m++) {"
7190       "  for (var n = 0; n < 9; n++) {"
7191       "    a2.push(a[m] + a[n]);"
7192       "    b2.push(b[m] + b[n]);"
7193       "    var newc = 'x' + c[m] + c[n] + 'y';"
7194       "    c2.push(newc.substring(1, newc.length - 1));"
7195       "    var utf = alens[m] + alens[n];"  // And here.
7196            // The 'n's that start with 0xdc.. are 6-8
7197            // The 'm's that end with 0xd8.. are 1, 4 and 7
7198       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
7199       "    a2lens.push(utf);"
7200       "  }"
7201       "}");
7202   Utf16Helper(context, "a", "alens", 9);
7203   Utf16Helper(context, "a2", "a2lens", 81);
7204   WriteUtf8Helper(context, "b", "alens", 9);
7205   WriteUtf8Helper(context, "b2", "a2lens", 81);
7206   WriteUtf8Helper(context, "c2", "a2lens", 81);
7207 }
7208
7209
7210 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
7211   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
7212   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
7213   return *is1 == *is2;
7214 }
7215
7216 static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
7217                              const char* b) {
7218   Handle<String> symbol1 =
7219       v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
7220   Handle<String> symbol2 =
7221       v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
7222   CHECK(SameSymbol(symbol1, symbol2));
7223 }
7224
7225
7226 THREADED_TEST(Utf16Symbol) {
7227   LocalContext context;
7228   v8::HandleScope scope(context->GetIsolate());
7229
7230   Handle<String> symbol1 = v8::String::NewFromUtf8(
7231       context->GetIsolate(), "abc", v8::String::kInternalizedString);
7232   Handle<String> symbol2 = v8::String::NewFromUtf8(
7233       context->GetIsolate(), "abc", v8::String::kInternalizedString);
7234   CHECK(SameSymbol(symbol1, symbol2));
7235
7236   SameSymbolHelper(context->GetIsolate(),
7237                    "\360\220\220\205",  // 4 byte encoding.
7238                    "\355\240\201\355\260\205");  // 2 3-byte surrogates.
7239   SameSymbolHelper(context->GetIsolate(),
7240                    "\355\240\201\355\260\206",  // 2 3-byte surrogates.
7241                    "\360\220\220\206");  // 4 byte encoding.
7242   SameSymbolHelper(context->GetIsolate(),
7243                    "x\360\220\220\205",  // 4 byte encoding.
7244                    "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
7245   SameSymbolHelper(context->GetIsolate(),
7246                    "x\355\240\201\355\260\206",  // 2 3-byte surrogates.
7247                    "x\360\220\220\206");  // 4 byte encoding.
7248   CompileRun(
7249       "var sym0 = 'benedictus';"
7250       "var sym0b = 'S\303\270ren';"
7251       "var sym1 = '\355\240\201\355\260\207';"
7252       "var sym2 = '\360\220\220\210';"
7253       "var sym3 = 'x\355\240\201\355\260\207';"
7254       "var sym4 = 'x\360\220\220\210';"
7255       "if (sym1.length != 2) throw sym1;"
7256       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
7257       "if (sym2.length != 2) throw sym2;"
7258       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
7259       "if (sym3.length != 3) throw sym3;"
7260       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
7261       "if (sym4.length != 3) throw sym4;"
7262       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
7263   Handle<String> sym0 = v8::String::NewFromUtf8(
7264       context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
7265   Handle<String> sym0b = v8::String::NewFromUtf8(
7266       context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
7267   Handle<String> sym1 =
7268       v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
7269                               v8::String::kInternalizedString);
7270   Handle<String> sym2 =
7271       v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
7272                               v8::String::kInternalizedString);
7273   Handle<String> sym3 = v8::String::NewFromUtf8(
7274       context->GetIsolate(), "x\355\240\201\355\260\207",
7275       v8::String::kInternalizedString);
7276   Handle<String> sym4 =
7277       v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
7278                               v8::String::kInternalizedString);
7279   v8::Local<v8::Object> global = context->Global();
7280   Local<Value> s0 = global->Get(v8_str("sym0"));
7281   Local<Value> s0b = global->Get(v8_str("sym0b"));
7282   Local<Value> s1 = global->Get(v8_str("sym1"));
7283   Local<Value> s2 = global->Get(v8_str("sym2"));
7284   Local<Value> s3 = global->Get(v8_str("sym3"));
7285   Local<Value> s4 = global->Get(v8_str("sym4"));
7286   CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
7287   CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
7288   CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
7289   CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
7290   CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
7291   CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
7292 }
7293
7294
7295 THREADED_TEST(ToArrayIndex) {
7296   LocalContext context;
7297   v8::Isolate* isolate = context->GetIsolate();
7298   v8::HandleScope scope(isolate);
7299
7300   v8::Handle<String> str = v8_str("42");
7301   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
7302   CHECK(!index.IsEmpty());
7303   CHECK_EQ(42.0, index->Uint32Value());
7304   str = v8_str("42asdf");
7305   index = str->ToArrayIndex();
7306   CHECK(index.IsEmpty());
7307   str = v8_str("-42");
7308   index = str->ToArrayIndex();
7309   CHECK(index.IsEmpty());
7310   str = v8_str("4294967295");
7311   index = str->ToArrayIndex();
7312   CHECK(!index.IsEmpty());
7313   CHECK_EQ(4294967295.0, index->Uint32Value());
7314   v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
7315   index = num->ToArrayIndex();
7316   CHECK(!index.IsEmpty());
7317   CHECK_EQ(1.0, index->Uint32Value());
7318   num = v8::Number::New(isolate, -1);
7319   index = num->ToArrayIndex();
7320   CHECK(index.IsEmpty());
7321   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
7322   index = obj->ToArrayIndex();
7323   CHECK(index.IsEmpty());
7324 }
7325
7326
7327 THREADED_TEST(ErrorConstruction) {
7328   LocalContext context;
7329   v8::HandleScope scope(context->GetIsolate());
7330
7331   v8::Handle<String> foo = v8_str("foo");
7332   v8::Handle<String> message = v8_str("message");
7333   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
7334   CHECK(range_error->IsObject());
7335   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
7336   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
7337   CHECK(reference_error->IsObject());
7338   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
7339   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
7340   CHECK(syntax_error->IsObject());
7341   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
7342   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
7343   CHECK(type_error->IsObject());
7344   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
7345   v8::Handle<Value> error = v8::Exception::Error(foo);
7346   CHECK(error->IsObject());
7347   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7348 }
7349
7350
7351 static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
7352   ApiTestFuzzer::Fuzz();
7353   v8::Handle<String> foo = v8_str("foo");
7354   v8::Handle<String> message = v8_str("message");
7355   v8::Handle<Value> error = v8::Exception::Error(foo);
7356   CHECK(error->IsObject());
7357   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7358   info.GetIsolate()->ThrowException(error);
7359   info.GetReturnValue().SetUndefined();
7360 }
7361
7362
7363 THREADED_TEST(ExceptionCreateMessage) {
7364   LocalContext context;
7365   v8::HandleScope scope(context->GetIsolate());
7366   v8::Handle<String> foo_str = v8_str("foo");
7367   v8::Handle<String> message_str = v8_str("message");
7368
7369   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
7370
7371   Local<v8::FunctionTemplate> fun =
7372       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
7373   v8::Local<v8::Object> global = context->Global();
7374   global->Set(v8_str("throwV8Exception"), fun->GetFunction());
7375
7376   TryCatch try_catch;
7377   CompileRun(
7378       "function f1() {\n"
7379       "  throwV8Exception();\n"
7380       "};\n"
7381       "f1();");
7382   CHECK(try_catch.HasCaught());
7383
7384   v8::Handle<v8::Value> error = try_catch.Exception();
7385   CHECK(error->IsObject());
7386   CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
7387
7388   v8::Handle<v8::Message> message = v8::Exception::CreateMessage(error);
7389   CHECK(!message.IsEmpty());
7390   CHECK_EQ(2, message->GetLineNumber());
7391   CHECK_EQ(2, message->GetStartColumn());
7392
7393   v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace();
7394   CHECK(!stackTrace.IsEmpty());
7395   CHECK_EQ(2, stackTrace->GetFrameCount());
7396
7397   stackTrace = v8::Exception::GetStackTrace(error);
7398   CHECK(!stackTrace.IsEmpty());
7399   CHECK_EQ(2, stackTrace->GetFrameCount());
7400
7401   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
7402
7403   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
7404   // is false.
7405   try_catch.Reset();
7406
7407   CompileRun(
7408       "function f2() {\n"
7409       "  return throwV8Exception();\n"
7410       "};\n"
7411       "f2();");
7412   CHECK(try_catch.HasCaught());
7413
7414   error = try_catch.Exception();
7415   CHECK(error->IsObject());
7416   CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
7417
7418   message = v8::Exception::CreateMessage(error);
7419   CHECK(!message.IsEmpty());
7420   CHECK_EQ(2, message->GetLineNumber());
7421   CHECK_EQ(9, message->GetStartColumn());
7422
7423   // Should be empty stack trace.
7424   stackTrace = message->GetStackTrace();
7425   CHECK(stackTrace.IsEmpty());
7426   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
7427 }
7428
7429
7430 static void YGetter(Local<String> name,
7431                     const v8::PropertyCallbackInfo<v8::Value>& info) {
7432   ApiTestFuzzer::Fuzz();
7433   info.GetReturnValue().Set(v8_num(10));
7434 }
7435
7436
7437 static void YSetter(Local<String> name,
7438                     Local<Value> value,
7439                     const v8::PropertyCallbackInfo<void>& info) {
7440   Local<Object> this_obj = Local<Object>::Cast(info.This());
7441   if (this_obj->Has(name)) this_obj->Delete(name);
7442   this_obj->Set(name, value);
7443 }
7444
7445
7446 THREADED_TEST(DeleteAccessor) {
7447   v8::Isolate* isolate = CcTest::isolate();
7448   v8::HandleScope scope(isolate);
7449   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7450   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
7451   LocalContext context;
7452   v8::Handle<v8::Object> holder = obj->NewInstance();
7453   context->Global()->Set(v8_str("holder"), holder);
7454   v8::Handle<Value> result = CompileRun(
7455       "holder.y = 11; holder.y = 12; holder.y");
7456   CHECK_EQ(12u, result->Uint32Value());
7457 }
7458
7459
7460 THREADED_TEST(TypeSwitch) {
7461   v8::Isolate* isolate = CcTest::isolate();
7462   v8::HandleScope scope(isolate);
7463   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
7464   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
7465   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
7466   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
7467   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
7468   LocalContext context;
7469   v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
7470   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
7471   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
7472   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
7473   for (int i = 0; i < 10; i++) {
7474     CHECK_EQ(0, type_switch->match(obj0));
7475     CHECK_EQ(1, type_switch->match(obj1));
7476     CHECK_EQ(2, type_switch->match(obj2));
7477     CHECK_EQ(3, type_switch->match(obj3));
7478     CHECK_EQ(3, type_switch->match(obj3));
7479     CHECK_EQ(2, type_switch->match(obj2));
7480     CHECK_EQ(1, type_switch->match(obj1));
7481     CHECK_EQ(0, type_switch->match(obj0));
7482   }
7483 }
7484
7485
7486 static int trouble_nesting = 0;
7487 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
7488   ApiTestFuzzer::Fuzz();
7489   trouble_nesting++;
7490
7491   // Call a JS function that throws an uncaught exception.
7492   Local<v8::Object> arg_this =
7493       args.GetIsolate()->GetCurrentContext()->Global();
7494   Local<Value> trouble_callee = (trouble_nesting == 3) ?
7495     arg_this->Get(v8_str("trouble_callee")) :
7496     arg_this->Get(v8_str("trouble_caller"));
7497   CHECK(trouble_callee->IsFunction());
7498   args.GetReturnValue().Set(
7499       Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
7500 }
7501
7502
7503 static int report_count = 0;
7504 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
7505                                              v8::Handle<Value>) {
7506   report_count++;
7507 }
7508
7509
7510 // Counts uncaught exceptions, but other tests running in parallel
7511 // also have uncaught exceptions.
7512 TEST(ApiUncaughtException) {
7513   report_count = 0;
7514   LocalContext env;
7515   v8::Isolate* isolate = env->GetIsolate();
7516   v8::HandleScope scope(isolate);
7517   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7518
7519   Local<v8::FunctionTemplate> fun =
7520       v8::FunctionTemplate::New(isolate, TroubleCallback);
7521   v8::Local<v8::Object> global = env->Global();
7522   global->Set(v8_str("trouble"), fun->GetFunction());
7523
7524   CompileRun(
7525       "function trouble_callee() {"
7526       "  var x = null;"
7527       "  return x.foo;"
7528       "};"
7529       "function trouble_caller() {"
7530       "  trouble();"
7531       "};");
7532   Local<Value> trouble = global->Get(v8_str("trouble"));
7533   CHECK(trouble->IsFunction());
7534   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
7535   CHECK(trouble_callee->IsFunction());
7536   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
7537   CHECK(trouble_caller->IsFunction());
7538   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
7539   CHECK_EQ(1, report_count);
7540   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7541 }
7542
7543
7544 TEST(ApiUncaughtExceptionInObjectObserve) {
7545   v8::internal::FLAG_stack_size = 150;
7546   report_count = 0;
7547   LocalContext env;
7548   v8::Isolate* isolate = env->GetIsolate();
7549   v8::HandleScope scope(isolate);
7550   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7551   CompileRun(
7552       "var obj = {};"
7553       "var observe_count = 0;"
7554       "function observer1() { ++observe_count; };"
7555       "function observer2() { ++observe_count; };"
7556       "function observer_throws() { throw new Error(); };"
7557       "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
7558       "Object.observe(obj, observer_throws.bind());"
7559       "Object.observe(obj, observer1);"
7560       "Object.observe(obj, stack_overflow);"
7561       "Object.observe(obj, observer2);"
7562       "Object.observe(obj, observer_throws.bind());"
7563       "obj.foo = 'bar';");
7564   CHECK_EQ(3, report_count);
7565   ExpectInt32("observe_count", 2);
7566   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7567 }
7568
7569
7570 static const char* script_resource_name = "ExceptionInNativeScript.js";
7571 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
7572                                                 v8::Handle<Value>) {
7573   v8::Handle<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
7574   CHECK(!name_val.IsEmpty() && name_val->IsString());
7575   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
7576   CHECK_EQ(0, strcmp(script_resource_name, *name));
7577   CHECK_EQ(3, message->GetLineNumber());
7578   v8::String::Utf8Value source_line(message->GetSourceLine());
7579   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
7580 }
7581
7582
7583 TEST(ExceptionInNativeScript) {
7584   LocalContext env;
7585   v8::Isolate* isolate = env->GetIsolate();
7586   v8::HandleScope scope(isolate);
7587   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
7588
7589   Local<v8::FunctionTemplate> fun =
7590       v8::FunctionTemplate::New(isolate, TroubleCallback);
7591   v8::Local<v8::Object> global = env->Global();
7592   global->Set(v8_str("trouble"), fun->GetFunction());
7593
7594   CompileRunWithOrigin(
7595       "function trouble() {\n"
7596       "  var o = {};\n"
7597       "  new o.foo();\n"
7598       "};",
7599       script_resource_name);
7600   Local<Value> trouble = global->Get(v8_str("trouble"));
7601   CHECK(trouble->IsFunction());
7602   Function::Cast(*trouble)->Call(global, 0, NULL);
7603   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
7604 }
7605
7606
7607 TEST(CompilationErrorUsingTryCatchHandler) {
7608   LocalContext env;
7609   v8::HandleScope scope(env->GetIsolate());
7610   v8::TryCatch try_catch;
7611   v8_compile("This doesn't &*&@#$&*^ compile.");
7612   CHECK(*try_catch.Exception());
7613   CHECK(try_catch.HasCaught());
7614 }
7615
7616
7617 TEST(TryCatchFinallyUsingTryCatchHandler) {
7618   LocalContext env;
7619   v8::HandleScope scope(env->GetIsolate());
7620   v8::TryCatch try_catch;
7621   CompileRun("try { throw ''; } catch (e) {}");
7622   CHECK(!try_catch.HasCaught());
7623   CompileRun("try { throw ''; } finally {}");
7624   CHECK(try_catch.HasCaught());
7625   try_catch.Reset();
7626   CompileRun(
7627       "(function() {"
7628       "try { throw ''; } finally { return; }"
7629       "})()");
7630   CHECK(!try_catch.HasCaught());
7631   CompileRun(
7632       "(function()"
7633       "  { try { throw ''; } finally { throw 0; }"
7634       "})()");
7635   CHECK(try_catch.HasCaught());
7636 }
7637
7638
7639 void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
7640   v8::HandleScope scope(args.GetIsolate());
7641   CompileRun(args[0]->ToString(args.GetIsolate()));
7642 }
7643
7644
7645 TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
7646   v8::Isolate* isolate = CcTest::isolate();
7647   v8::HandleScope scope(isolate);
7648   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
7649   templ->Set(v8_str("CEvaluate"),
7650              v8::FunctionTemplate::New(isolate, CEvaluate));
7651   LocalContext context(0, templ);
7652   v8::TryCatch try_catch;
7653   CompileRun("try {"
7654              "  CEvaluate('throw 1;');"
7655              "} finally {"
7656              "}");
7657   CHECK(try_catch.HasCaught());
7658   CHECK(!try_catch.Message().IsEmpty());
7659   String::Utf8Value exception_value(try_catch.Exception());
7660   CHECK_EQ(0, strcmp(*exception_value, "1"));
7661   try_catch.Reset();
7662   CompileRun("try {"
7663              "  CEvaluate('throw 1;');"
7664              "} finally {"
7665              "  throw 2;"
7666              "}");
7667   CHECK(try_catch.HasCaught());
7668   CHECK(!try_catch.Message().IsEmpty());
7669   String::Utf8Value finally_exception_value(try_catch.Exception());
7670   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
7671 }
7672
7673
7674 // For use within the TestSecurityHandler() test.
7675 static bool g_security_callback_result = false;
7676 static bool NamedSecurityTestCallback(Local<v8::Object> global,
7677                                       Local<Value> name,
7678                                       v8::AccessType type,
7679                                       Local<Value> data) {
7680   printf("a\n");
7681   // Always allow read access.
7682   if (type == v8::ACCESS_GET)
7683     return true;
7684
7685   // Sometimes allow other access.
7686   return g_security_callback_result;
7687 }
7688
7689
7690 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
7691                                         uint32_t key,
7692                                         v8::AccessType type,
7693                                         Local<Value> data) {
7694   printf("b\n");
7695   // Always allow read access.
7696   if (type == v8::ACCESS_GET)
7697     return true;
7698
7699   // Sometimes allow other access.
7700   return g_security_callback_result;
7701 }
7702
7703
7704 // SecurityHandler can't be run twice
7705 TEST(SecurityHandler) {
7706   v8::Isolate* isolate = CcTest::isolate();
7707   v8::HandleScope scope0(isolate);
7708   v8::Handle<v8::ObjectTemplate> global_template =
7709       v8::ObjectTemplate::New(isolate);
7710   global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
7711                                            IndexedSecurityTestCallback);
7712   // Create an environment
7713   v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
7714   context0->Enter();
7715
7716   v8::Handle<v8::Object> global0 = context0->Global();
7717   v8::Handle<Script> script0 = v8_compile("foo = 111");
7718   script0->Run();
7719   global0->Set(v8_str("0"), v8_num(999));
7720   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
7721   CHECK_EQ(111, foo0->Int32Value());
7722   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
7723   CHECK_EQ(999, z0->Int32Value());
7724
7725   // Create another environment, should fail security checks.
7726   v8::HandleScope scope1(isolate);
7727
7728   v8::Handle<Context> context1 =
7729     Context::New(isolate, NULL, global_template);
7730   context1->Enter();
7731
7732   v8::Handle<v8::Object> global1 = context1->Global();
7733   global1->Set(v8_str("othercontext"), global0);
7734   // This set will fail the security check.
7735   v8::Handle<Script> script1 =
7736     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
7737   script1->Run();
7738   // This read will pass the security check.
7739   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
7740   CHECK_EQ(111, foo1->Int32Value());
7741   // This read will pass the security check.
7742   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
7743   CHECK_EQ(999, z1->Int32Value());
7744
7745   // Create another environment, should pass security checks.
7746   { g_security_callback_result = true;  // allow security handler to pass.
7747     v8::HandleScope scope2(isolate);
7748     LocalContext context2;
7749     v8::Handle<v8::Object> global2 = context2->Global();
7750     global2->Set(v8_str("othercontext"), global0);
7751     v8::Handle<Script> script2 =
7752         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
7753     script2->Run();
7754     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
7755     CHECK_EQ(333, foo2->Int32Value());
7756     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
7757     CHECK_EQ(888, z2->Int32Value());
7758   }
7759
7760   context1->Exit();
7761   context0->Exit();
7762 }
7763
7764
7765 THREADED_TEST(SecurityChecks) {
7766   LocalContext env1;
7767   v8::HandleScope handle_scope(env1->GetIsolate());
7768   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
7769
7770   Local<Value> foo = v8_str("foo");
7771   Local<Value> bar = v8_str("bar");
7772
7773   // Set to the same domain.
7774   env1->SetSecurityToken(foo);
7775
7776   // Create a function in env1.
7777   CompileRun("spy=function(){return spy;}");
7778   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
7779   CHECK(spy->IsFunction());
7780
7781   // Create another function accessing global objects.
7782   CompileRun("spy2=function(){return new this.Array();}");
7783   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
7784   CHECK(spy2->IsFunction());
7785
7786   // Switch to env2 in the same domain and invoke spy on env2.
7787   {
7788     env2->SetSecurityToken(foo);
7789     // Enter env2
7790     Context::Scope scope_env2(env2);
7791     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
7792     CHECK(result->IsFunction());
7793   }
7794
7795   {
7796     env2->SetSecurityToken(bar);
7797     Context::Scope scope_env2(env2);
7798
7799     // Call cross_domain_call, it should throw an exception
7800     v8::TryCatch try_catch;
7801     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
7802     CHECK(try_catch.HasCaught());
7803   }
7804 }
7805
7806
7807 // Regression test case for issue 1183439.
7808 THREADED_TEST(SecurityChecksForPrototypeChain) {
7809   LocalContext current;
7810   v8::HandleScope scope(current->GetIsolate());
7811   v8::Handle<Context> other = Context::New(current->GetIsolate());
7812
7813   // Change context to be able to get to the Object function in the
7814   // other context without hitting the security checks.
7815   v8::Local<Value> other_object;
7816   { Context::Scope scope(other);
7817     other_object = other->Global()->Get(v8_str("Object"));
7818     other->Global()->Set(v8_num(42), v8_num(87));
7819   }
7820
7821   current->Global()->Set(v8_str("other"), other->Global());
7822   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
7823
7824   // Make sure the security check fails here and we get an undefined
7825   // result instead of getting the Object function. Repeat in a loop
7826   // to make sure to exercise the IC code.
7827   v8::Local<Script> access_other0 = v8_compile("other.Object");
7828   v8::Local<Script> access_other1 = v8_compile("other[42]");
7829   for (int i = 0; i < 5; i++) {
7830     CHECK(access_other0->Run().IsEmpty());
7831     CHECK(access_other1->Run().IsEmpty());
7832   }
7833
7834   // Create an object that has 'other' in its prototype chain and make
7835   // sure we cannot access the Object function indirectly through
7836   // that. Repeat in a loop to make sure to exercise the IC code.
7837   v8_compile("function F() { };"
7838              "F.prototype = other;"
7839              "var f = new F();")->Run();
7840   v8::Local<Script> access_f0 = v8_compile("f.Object");
7841   v8::Local<Script> access_f1 = v8_compile("f[42]");
7842   for (int j = 0; j < 5; j++) {
7843     CHECK(access_f0->Run().IsEmpty());
7844     CHECK(access_f1->Run().IsEmpty());
7845   }
7846
7847   // Now it gets hairy: Set the prototype for the other global object
7848   // to be the current global object. The prototype chain for 'f' now
7849   // goes through 'other' but ends up in the current global object.
7850   { Context::Scope scope(other);
7851     other->Global()->Set(v8_str("__proto__"), current->Global());
7852   }
7853   // Set a named and an index property on the current global
7854   // object. To force the lookup to go through the other global object,
7855   // the properties must not exist in the other global object.
7856   current->Global()->Set(v8_str("foo"), v8_num(100));
7857   current->Global()->Set(v8_num(99), v8_num(101));
7858   // Try to read the properties from f and make sure that the access
7859   // gets stopped by the security checks on the other global object.
7860   Local<Script> access_f2 = v8_compile("f.foo");
7861   Local<Script> access_f3 = v8_compile("f[99]");
7862   for (int k = 0; k < 5; k++) {
7863     CHECK(access_f2->Run().IsEmpty());
7864     CHECK(access_f3->Run().IsEmpty());
7865   }
7866 }
7867
7868
7869 static bool named_security_check_with_gc_called;
7870
7871 static bool NamedSecurityCallbackWithGC(Local<v8::Object> global,
7872                                         Local<Value> name,
7873                                         v8::AccessType type,
7874                                         Local<Value> data) {
7875   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
7876   named_security_check_with_gc_called = true;
7877   return true;
7878 }
7879
7880
7881 static bool indexed_security_check_with_gc_called;
7882
7883 static bool IndexedSecurityTestCallbackWithGC(Local<v8::Object> global,
7884                                               uint32_t key,
7885                                               v8::AccessType type,
7886                                               Local<Value> data) {
7887   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
7888   indexed_security_check_with_gc_called = true;
7889   return true;
7890 }
7891
7892
7893 TEST(SecurityTestGCAllowed) {
7894   v8::Isolate* isolate = CcTest::isolate();
7895   v8::HandleScope handle_scope(isolate);
7896   v8::Handle<v8::ObjectTemplate> object_template =
7897       v8::ObjectTemplate::New(isolate);
7898   object_template->SetAccessCheckCallbacks(NamedSecurityCallbackWithGC,
7899                                            IndexedSecurityTestCallbackWithGC);
7900
7901   v8::Handle<Context> context = Context::New(isolate);
7902   v8::Context::Scope context_scope(context);
7903
7904   context->Global()->Set(v8_str("obj"), object_template->NewInstance());
7905
7906   named_security_check_with_gc_called = false;
7907   CompileRun("obj.foo = new String(1001);");
7908   CHECK(named_security_check_with_gc_called);
7909
7910   indexed_security_check_with_gc_called = false;
7911   CompileRun("obj[0] = new String(1002);");
7912   CHECK(indexed_security_check_with_gc_called);
7913
7914   named_security_check_with_gc_called = false;
7915   CHECK(CompileRun("obj.foo")->ToString(isolate)->Equals(v8_str("1001")));
7916   CHECK(named_security_check_with_gc_called);
7917
7918   indexed_security_check_with_gc_called = false;
7919   CHECK(CompileRun("obj[0]")->ToString(isolate)->Equals(v8_str("1002")));
7920   CHECK(indexed_security_check_with_gc_called);
7921 }
7922
7923
7924 THREADED_TEST(CrossDomainDelete) {
7925   LocalContext env1;
7926   v8::HandleScope handle_scope(env1->GetIsolate());
7927   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
7928
7929   Local<Value> foo = v8_str("foo");
7930   Local<Value> bar = v8_str("bar");
7931
7932   // Set to the same domain.
7933   env1->SetSecurityToken(foo);
7934   env2->SetSecurityToken(foo);
7935
7936   env1->Global()->Set(v8_str("prop"), v8_num(3));
7937   env2->Global()->Set(v8_str("env1"), env1->Global());
7938
7939   // Change env2 to a different domain and delete env1.prop.
7940   env2->SetSecurityToken(bar);
7941   {
7942     Context::Scope scope_env2(env2);
7943     Local<Value> result =
7944         CompileRun("delete env1.prop");
7945     CHECK(result.IsEmpty());
7946   }
7947
7948   // Check that env1.prop still exists.
7949   Local<Value> v = env1->Global()->Get(v8_str("prop"));
7950   CHECK(v->IsNumber());
7951   CHECK_EQ(3, v->Int32Value());
7952 }
7953
7954
7955 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
7956   LocalContext env1;
7957   v8::HandleScope handle_scope(env1->GetIsolate());
7958   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
7959
7960   Local<Value> foo = v8_str("foo");
7961   Local<Value> bar = v8_str("bar");
7962
7963   // Set to the same domain.
7964   env1->SetSecurityToken(foo);
7965   env2->SetSecurityToken(foo);
7966
7967   env1->Global()->Set(v8_str("prop"), v8_num(3));
7968   env2->Global()->Set(v8_str("env1"), env1->Global());
7969
7970   // env1.prop is enumerable in env2.
7971   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
7972   {
7973     Context::Scope scope_env2(env2);
7974     Local<Value> result = CompileRun(test);
7975     CHECK(result->IsTrue());
7976   }
7977
7978   // Change env2 to a different domain and test again.
7979   env2->SetSecurityToken(bar);
7980   {
7981     Context::Scope scope_env2(env2);
7982     Local<Value> result = CompileRun(test);
7983     CHECK(result.IsEmpty());
7984   }
7985 }
7986
7987
7988 THREADED_TEST(CrossDomainForIn) {
7989   LocalContext env1;
7990   v8::HandleScope handle_scope(env1->GetIsolate());
7991   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
7992
7993   Local<Value> foo = v8_str("foo");
7994   Local<Value> bar = v8_str("bar");
7995
7996   // Set to the same domain.
7997   env1->SetSecurityToken(foo);
7998   env2->SetSecurityToken(foo);
7999
8000   env1->Global()->Set(v8_str("prop"), v8_num(3));
8001   env2->Global()->Set(v8_str("env1"), env1->Global());
8002
8003   // Change env2 to a different domain and set env1's global object
8004   // as the __proto__ of an object in env2 and enumerate properties
8005   // in for-in. It shouldn't enumerate properties on env1's global
8006   // object.
8007   env2->SetSecurityToken(bar);
8008   {
8009     Context::Scope scope_env2(env2);
8010     Local<Value> result = CompileRun(
8011         "(function() {"
8012         "  var obj = { '__proto__': env1 };"
8013         "  try {"
8014         "    for (var p in obj) {"
8015         "      if (p == 'prop') return false;"
8016         "    }"
8017         "    return false;"
8018         "  } catch (e) {"
8019         "    return true;"
8020         "  }"
8021         "})()");
8022     CHECK(result->IsTrue());
8023   }
8024 }
8025
8026
8027 TEST(ContextDetachGlobal) {
8028   LocalContext env1;
8029   v8::HandleScope handle_scope(env1->GetIsolate());
8030   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8031
8032   Local<v8::Object> global1 = env1->Global();
8033
8034   Local<Value> foo = v8_str("foo");
8035
8036   // Set to the same domain.
8037   env1->SetSecurityToken(foo);
8038   env2->SetSecurityToken(foo);
8039
8040   // Enter env2
8041   env2->Enter();
8042
8043   // Create a function in env2 and add a reference to it in env1.
8044   Local<v8::Object> global2 = env2->Global();
8045   global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
8046   CompileRun("function getProp() {return prop;}");
8047
8048   env1->Global()->Set(v8_str("getProp"),
8049                       global2->Get(v8_str("getProp")));
8050
8051   // Detach env2's global, and reuse the global object of env2
8052   env2->Exit();
8053   env2->DetachGlobal();
8054
8055   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8056                                           0,
8057                                           v8::Handle<v8::ObjectTemplate>(),
8058                                           global2);
8059   env3->SetSecurityToken(v8_str("bar"));
8060   env3->Enter();
8061
8062   Local<v8::Object> global3 = env3->Global();
8063   CHECK(global2->Equals(global3));
8064   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8065   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
8066   global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8067   global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
8068   env3->Exit();
8069
8070   // Call getProp in env1, and it should return the value 1
8071   {
8072     Local<Value> get_prop = global1->Get(v8_str("getProp"));
8073     CHECK(get_prop->IsFunction());
8074     v8::TryCatch try_catch;
8075     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8076     CHECK(!try_catch.HasCaught());
8077     CHECK_EQ(1, r->Int32Value());
8078   }
8079
8080   // Check that env3 is not accessible from env1
8081   {
8082     Local<Value> r = global3->Get(v8_str("prop2"));
8083     CHECK(r.IsEmpty());
8084   }
8085 }
8086
8087
8088 TEST(DetachGlobal) {
8089   LocalContext env1;
8090   v8::HandleScope scope(env1->GetIsolate());
8091
8092   // Create second environment.
8093   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8094
8095   Local<Value> foo = v8_str("foo");
8096
8097   // Set same security token for env1 and env2.
8098   env1->SetSecurityToken(foo);
8099   env2->SetSecurityToken(foo);
8100
8101   // Create a property on the global object in env2.
8102   {
8103     v8::Context::Scope scope(env2);
8104     env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
8105   }
8106
8107   // Create a reference to env2 global from env1 global.
8108   env1->Global()->Set(v8_str("other"), env2->Global());
8109
8110   // Check that we have access to other.p in env2 from env1.
8111   Local<Value> result = CompileRun("other.p");
8112   CHECK(result->IsInt32());
8113   CHECK_EQ(42, result->Int32Value());
8114
8115   // Hold on to global from env2 and detach global from env2.
8116   Local<v8::Object> global2 = env2->Global();
8117   env2->DetachGlobal();
8118
8119   // Check that the global has been detached. No other.p property can
8120   // be found.
8121   result = CompileRun("other.p");
8122   CHECK(result.IsEmpty());
8123
8124   // Reuse global2 for env3.
8125   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8126                                           0,
8127                                           v8::Handle<v8::ObjectTemplate>(),
8128                                           global2);
8129   CHECK(global2->Equals(env3->Global()));
8130
8131   // Start by using the same security token for env3 as for env1 and env2.
8132   env3->SetSecurityToken(foo);
8133
8134   // Create a property on the global object in env3.
8135   {
8136     v8::Context::Scope scope(env3);
8137     env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
8138   }
8139
8140   // Check that other.p is now the property in env3 and that we have access.
8141   result = CompileRun("other.p");
8142   CHECK(result->IsInt32());
8143   CHECK_EQ(24, result->Int32Value());
8144
8145   // Change security token for env3 to something different from env1 and env2.
8146   env3->SetSecurityToken(v8_str("bar"));
8147
8148   // Check that we do not have access to other.p in env1. |other| is now
8149   // the global object for env3 which has a different security token,
8150   // so access should be blocked.
8151   result = CompileRun("other.p");
8152   CHECK(result.IsEmpty());
8153 }
8154
8155
8156 void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
8157   info.GetReturnValue().Set(
8158       info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8159 }
8160
8161
8162 TEST(DetachedAccesses) {
8163   LocalContext env1;
8164   v8::HandleScope scope(env1->GetIsolate());
8165
8166   // Create second environment.
8167   Local<ObjectTemplate> inner_global_template =
8168       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8169   inner_global_template ->SetAccessorProperty(
8170       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8171   v8::Local<Context> env2 =
8172       Context::New(env1->GetIsolate(), NULL, inner_global_template);
8173
8174   Local<Value> foo = v8_str("foo");
8175
8176   // Set same security token for env1 and env2.
8177   env1->SetSecurityToken(foo);
8178   env2->SetSecurityToken(foo);
8179
8180   env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8181
8182   {
8183     v8::Context::Scope scope(env2);
8184     env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
8185     CompileRun(
8186         "function bound_x() { return x; }"
8187         "function get_x()   { return this.x; }"
8188         "function get_x_w() { return (function() {return this.x;})(); }");
8189     env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
8190     env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8191     env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
8192     env1->Global()->Set(
8193         v8_str("this_x"),
8194         CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
8195   }
8196
8197   Local<Object> env2_global = env2->Global();
8198   env2_global->TurnOnAccessCheck();
8199   env2->DetachGlobal();
8200
8201   Local<Value> result;
8202   result = CompileRun("bound_x()");
8203   CHECK(v8_str("env2_x")->Equals(result));
8204   result = CompileRun("get_x()");
8205   CHECK(result.IsEmpty());
8206   result = CompileRun("get_x_w()");
8207   CHECK(result.IsEmpty());
8208   result = CompileRun("this_x()");
8209   CHECK(v8_str("env2_x")->Equals(result));
8210
8211   // Reattach env2's proxy
8212   env2 = Context::New(env1->GetIsolate(),
8213                       0,
8214                       v8::Handle<v8::ObjectTemplate>(),
8215                       env2_global);
8216   env2->SetSecurityToken(foo);
8217   {
8218     v8::Context::Scope scope(env2);
8219     env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8220     env2->Global()->Set(v8_str("env1"), env1->Global());
8221     result = CompileRun(
8222         "results = [];"
8223         "for (var i = 0; i < 4; i++ ) {"
8224         "  results.push(env1.bound_x());"
8225         "  results.push(env1.get_x());"
8226         "  results.push(env1.get_x_w());"
8227         "  results.push(env1.this_x());"
8228         "}"
8229         "results");
8230     Local<v8::Array> results = Local<v8::Array>::Cast(result);
8231     CHECK_EQ(16u, results->Length());
8232     for (int i = 0; i < 16; i += 4) {
8233       CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8234       CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
8235       CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8236       CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8237     }
8238   }
8239
8240   result = CompileRun(
8241       "results = [];"
8242       "for (var i = 0; i < 4; i++ ) {"
8243       "  results.push(bound_x());"
8244       "  results.push(get_x());"
8245       "  results.push(get_x_w());"
8246       "  results.push(this_x());"
8247       "}"
8248       "results");
8249   Local<v8::Array> results = Local<v8::Array>::Cast(result);
8250   CHECK_EQ(16u, results->Length());
8251   for (int i = 0; i < 16; i += 4) {
8252     CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8253     CHECK(v8_str("env3_x")->Equals(results->Get(i + 1)));
8254     CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8255     CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8256   }
8257
8258   result = CompileRun(
8259       "results = [];"
8260       "for (var i = 0; i < 4; i++ ) {"
8261       "  results.push(this.bound_x());"
8262       "  results.push(this.get_x());"
8263       "  results.push(this.get_x_w());"
8264       "  results.push(this.this_x());"
8265       "}"
8266       "results");
8267   results = Local<v8::Array>::Cast(result);
8268   CHECK_EQ(16u, results->Length());
8269   for (int i = 0; i < 16; i += 4) {
8270     CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8271     CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
8272     CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8273     CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8274   }
8275 }
8276
8277
8278 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
8279 static bool NamedAccessBlocker(Local<v8::Object> global,
8280                                Local<Value> name,
8281                                v8::AccessType type,
8282                                Local<Value> data) {
8283   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
8284       allowed_access_type[type];
8285 }
8286
8287
8288 static bool IndexedAccessBlocker(Local<v8::Object> global,
8289                                  uint32_t key,
8290                                  v8::AccessType type,
8291                                  Local<Value> data) {
8292   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
8293       allowed_access_type[type];
8294 }
8295
8296
8297 static int g_echo_value = -1;
8298
8299
8300 static void EchoGetter(
8301     Local<String> name,
8302     const v8::PropertyCallbackInfo<v8::Value>& info) {
8303   info.GetReturnValue().Set(v8_num(g_echo_value));
8304 }
8305
8306
8307 static void EchoSetter(Local<String> name,
8308                        Local<Value> value,
8309                        const v8::PropertyCallbackInfo<void>&) {
8310   if (value->IsNumber())
8311     g_echo_value = value->Int32Value();
8312 }
8313
8314
8315 static void UnreachableGetter(
8316     Local<String> name,
8317     const v8::PropertyCallbackInfo<v8::Value>& info) {
8318   CHECK(false);  // This function should not be called..
8319 }
8320
8321
8322 static void UnreachableSetter(Local<String>,
8323                               Local<Value>,
8324                               const v8::PropertyCallbackInfo<void>&) {
8325   CHECK(false);  // This function should nto be called.
8326 }
8327
8328
8329 static void UnreachableFunction(
8330     const v8::FunctionCallbackInfo<v8::Value>& info) {
8331   CHECK(false);  // This function should not be called..
8332 }
8333
8334
8335 TEST(AccessControl) {
8336   v8::Isolate* isolate = CcTest::isolate();
8337   v8::HandleScope handle_scope(isolate);
8338   v8::Handle<v8::ObjectTemplate> global_template =
8339       v8::ObjectTemplate::New(isolate);
8340
8341   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8342                                            IndexedAccessBlocker);
8343
8344   // Add an accessor accessible by cross-domain JS code.
8345   global_template->SetAccessor(
8346       v8_str("accessible_prop"),
8347       EchoGetter, EchoSetter,
8348       v8::Handle<Value>(),
8349       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8350
8351
8352   // Add an accessor that is not accessible by cross-domain JS code.
8353   global_template->SetAccessor(v8_str("blocked_prop"),
8354                                UnreachableGetter, UnreachableSetter,
8355                                v8::Handle<Value>(),
8356                                v8::DEFAULT);
8357
8358   global_template->SetAccessorProperty(
8359       v8_str("blocked_js_prop"),
8360       v8::FunctionTemplate::New(isolate, UnreachableFunction),
8361       v8::FunctionTemplate::New(isolate, UnreachableFunction),
8362       v8::None,
8363       v8::DEFAULT);
8364
8365   // Create an environment
8366   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8367   context0->Enter();
8368
8369   v8::Handle<v8::Object> global0 = context0->Global();
8370
8371   // Define a property with JS getter and setter.
8372   CompileRun(
8373       "function getter() { return 'getter'; };\n"
8374       "function setter() { return 'setter'; }\n"
8375       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8376
8377   Local<Value> getter = global0->Get(v8_str("getter"));
8378   Local<Value> setter = global0->Get(v8_str("setter"));
8379
8380   // And define normal element.
8381   global0->Set(239, v8_str("239"));
8382
8383   // Define an element with JS getter and setter.
8384   CompileRun(
8385       "function el_getter() { return 'el_getter'; };\n"
8386       "function el_setter() { return 'el_setter'; };\n"
8387       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
8388
8389   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
8390   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
8391
8392   v8::HandleScope scope1(isolate);
8393
8394   v8::Local<Context> context1 = Context::New(isolate);
8395   context1->Enter();
8396
8397   v8::Handle<v8::Object> global1 = context1->Global();
8398   global1->Set(v8_str("other"), global0);
8399
8400   // Access blocked property.
8401   CompileRun("other.blocked_prop = 1");
8402
8403   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8404   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
8405             .IsEmpty());
8406   CHECK(
8407       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
8408
8409   // Access blocked element.
8410   CHECK(CompileRun("other[239] = 1").IsEmpty());
8411
8412   CHECK(CompileRun("other[239]").IsEmpty());
8413   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
8414   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
8415
8416   // Enable ACCESS_HAS
8417   allowed_access_type[v8::ACCESS_HAS] = true;
8418   CHECK(CompileRun("other[239]").IsEmpty());
8419   // ... and now we can get the descriptor...
8420   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239').value")
8421             .IsEmpty());
8422   // ... and enumerate the property.
8423   ExpectTrue("propertyIsEnumerable.call(other, '239')");
8424   allowed_access_type[v8::ACCESS_HAS] = false;
8425
8426   // Access a property with JS accessor.
8427   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
8428
8429   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
8430   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
8431             .IsEmpty());
8432
8433   // Enable both ACCESS_HAS and ACCESS_GET.
8434   allowed_access_type[v8::ACCESS_HAS] = true;
8435   allowed_access_type[v8::ACCESS_GET] = true;
8436
8437   ExpectString("other.js_accessor_p", "getter");
8438   ExpectObject(
8439       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
8440   ExpectObject(
8441       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
8442   ExpectUndefined(
8443       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8444
8445   allowed_access_type[v8::ACCESS_HAS] = false;
8446   allowed_access_type[v8::ACCESS_GET] = false;
8447
8448   // Access an element with JS accessor.
8449   CHECK(CompileRun("other[42] = 2").IsEmpty());
8450
8451   CHECK(CompileRun("other[42]").IsEmpty());
8452   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
8453
8454   // Enable both ACCESS_HAS and ACCESS_GET.
8455   allowed_access_type[v8::ACCESS_HAS] = true;
8456   allowed_access_type[v8::ACCESS_GET] = true;
8457
8458   ExpectString("other[42]", "el_getter");
8459   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
8460   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
8461   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8462
8463   allowed_access_type[v8::ACCESS_HAS] = false;
8464   allowed_access_type[v8::ACCESS_GET] = false;
8465
8466   v8::Handle<Value> value;
8467
8468   // Access accessible property
8469   value = CompileRun("other.accessible_prop = 3");
8470   CHECK(value->IsNumber());
8471   CHECK_EQ(3, value->Int32Value());
8472   CHECK_EQ(3, g_echo_value);
8473
8474   value = CompileRun("other.accessible_prop");
8475   CHECK(value->IsNumber());
8476   CHECK_EQ(3, value->Int32Value());
8477
8478   value = CompileRun(
8479       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
8480   CHECK(value->IsNumber());
8481   CHECK_EQ(3, value->Int32Value());
8482
8483   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
8484   CHECK(value->IsTrue());
8485
8486   // Enumeration doesn't enumerate accessors from inaccessible objects in
8487   // the prototype chain even if the accessors are in themselves accessible.
8488   value = CompileRun(
8489       "(function() {"
8490       "  var obj = { '__proto__': other };"
8491       "  try {"
8492       "    for (var p in obj) {"
8493       "      if (p == 'accessible_prop' ||"
8494       "          p == 'blocked_js_prop' ||"
8495       "          p == 'blocked_js_prop') {"
8496       "        return false;"
8497       "      }"
8498       "    }"
8499       "    return false;"
8500       "  } catch (e) {"
8501       "    return true;"
8502       "  }"
8503       "})()");
8504   CHECK(value->IsTrue());
8505
8506   context1->Exit();
8507   context0->Exit();
8508 }
8509
8510
8511 TEST(AccessControlES5) {
8512   v8::Isolate* isolate = CcTest::isolate();
8513   v8::HandleScope handle_scope(isolate);
8514   v8::Handle<v8::ObjectTemplate> global_template =
8515       v8::ObjectTemplate::New(isolate);
8516
8517   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8518                                            IndexedAccessBlocker);
8519
8520   // Add accessible accessor.
8521   global_template->SetAccessor(
8522       v8_str("accessible_prop"),
8523       EchoGetter, EchoSetter,
8524       v8::Handle<Value>(),
8525       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8526
8527
8528   // Add an accessor that is not accessible by cross-domain JS code.
8529   global_template->SetAccessor(v8_str("blocked_prop"),
8530                                UnreachableGetter, UnreachableSetter,
8531                                v8::Handle<Value>(),
8532                                v8::DEFAULT);
8533
8534   // Create an environment
8535   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8536   context0->Enter();
8537
8538   v8::Handle<v8::Object> global0 = context0->Global();
8539
8540   v8::Local<Context> context1 = Context::New(isolate);
8541   context1->Enter();
8542   v8::Handle<v8::Object> global1 = context1->Global();
8543   global1->Set(v8_str("other"), global0);
8544
8545   // Regression test for issue 1154.
8546   CHECK(CompileRun("Object.keys(other)").IsEmpty());
8547   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8548
8549   // Regression test for issue 1027.
8550   CompileRun("Object.defineProperty(\n"
8551              "  other, 'blocked_prop', {configurable: false})");
8552   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8553   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
8554             .IsEmpty());
8555
8556   // Regression test for issue 1171.
8557   ExpectTrue("Object.isExtensible(other)");
8558   CompileRun("Object.preventExtensions(other)");
8559   ExpectTrue("Object.isExtensible(other)");
8560
8561   // Object.seal and Object.freeze.
8562   CompileRun("Object.freeze(other)");
8563   ExpectTrue("Object.isExtensible(other)");
8564
8565   CompileRun("Object.seal(other)");
8566   ExpectTrue("Object.isExtensible(other)");
8567
8568   // Regression test for issue 1250.
8569   // Make sure that we can set the accessible accessors value using normal
8570   // assignment.
8571   CompileRun("other.accessible_prop = 42");
8572   CHECK_EQ(42, g_echo_value);
8573
8574   v8::Handle<Value> value;
8575   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
8576   value = CompileRun("other.accessible_prop == 42");
8577   CHECK(value->IsTrue());
8578 }
8579
8580
8581 static bool BlockEverythingNamed(Local<v8::Object> object, Local<Value> name,
8582                                  v8::AccessType type, Local<Value> data) {
8583   return false;
8584 }
8585
8586
8587 static bool BlockEverythingIndexed(Local<v8::Object> object, uint32_t key,
8588                                    v8::AccessType type, Local<Value> data) {
8589   return false;
8590 }
8591
8592
8593 THREADED_TEST(AccessControlGetOwnPropertyNames) {
8594   v8::Isolate* isolate = CcTest::isolate();
8595   v8::HandleScope handle_scope(isolate);
8596   v8::Handle<v8::ObjectTemplate> obj_template =
8597       v8::ObjectTemplate::New(isolate);
8598
8599   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
8600   obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
8601                                         BlockEverythingIndexed);
8602
8603   // Create an environment
8604   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
8605   context0->Enter();
8606
8607   v8::Handle<v8::Object> global0 = context0->Global();
8608
8609   v8::HandleScope scope1(CcTest::isolate());
8610
8611   v8::Local<Context> context1 = Context::New(isolate);
8612   context1->Enter();
8613
8614   v8::Handle<v8::Object> global1 = context1->Global();
8615   global1->Set(v8_str("other"), global0);
8616   global1->Set(v8_str("object"), obj_template->NewInstance());
8617
8618   v8::Handle<Value> value;
8619
8620   // Attempt to get the property names of the other global object and
8621   // of an object that requires access checks.  Accessing the other
8622   // global object should be blocked by access checks on the global
8623   // proxy object.  Accessing the object that requires access checks
8624   // is blocked by the access checks on the object itself.
8625   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
8626   CHECK(value.IsEmpty());
8627
8628   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
8629   CHECK(value.IsEmpty());
8630
8631   context1->Exit();
8632   context0->Exit();
8633 }
8634
8635
8636 TEST(SuperAccessControl) {
8637   i::FLAG_allow_natives_syntax = true;
8638   i::FLAG_harmony_classes = true;
8639   i::FLAG_harmony_object_literals = true;
8640   v8::Isolate* isolate = CcTest::isolate();
8641   v8::HandleScope handle_scope(isolate);
8642   v8::Handle<v8::ObjectTemplate> obj_template =
8643       v8::ObjectTemplate::New(isolate);
8644   obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
8645                                         BlockEverythingIndexed);
8646   LocalContext env;
8647   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
8648
8649   {
8650     v8::TryCatch try_catch;
8651     CompileRun(
8652         "var f = { m() { return super.hasOwnProperty; } }.m;"
8653         "var m = %ToMethod(f, prohibited);"
8654         "m();");
8655     CHECK(try_catch.HasCaught());
8656   }
8657
8658   {
8659     v8::TryCatch try_catch;
8660     CompileRun(
8661         "var f = {m() { return super[42]; } }.m;"
8662         "var m = %ToMethod(f, prohibited);"
8663         "m();");
8664     CHECK(try_catch.HasCaught());
8665   }
8666
8667   {
8668     v8::TryCatch try_catch;
8669     CompileRun(
8670         "var f = {m() { super.hasOwnProperty = function () {}; } }.m;"
8671         "var m = %ToMethod(f, prohibited);"
8672         "m();");
8673     CHECK(try_catch.HasCaught());
8674   }
8675
8676   {
8677     v8::TryCatch try_catch;
8678     CompileRun(
8679         "Object.defineProperty(Object.prototype, 'x', { set : function(){}});"
8680         "var f = {"
8681         "  m() { "
8682         "    'use strict';"
8683         "    super.x = function () {};"
8684         "  }"
8685         "}.m;"
8686         "var m = %ToMethod(f, prohibited);"
8687         "m();");
8688     CHECK(try_catch.HasCaught());
8689   }
8690 }
8691
8692
8693 static void ConstTenGetter(Local<String> name,
8694                            const v8::PropertyCallbackInfo<v8::Value>& info) {
8695   info.GetReturnValue().Set(v8_num(10));
8696 }
8697
8698
8699 THREADED_TEST(CrossDomainAccessors) {
8700   v8::Isolate* isolate = CcTest::isolate();
8701   v8::HandleScope handle_scope(isolate);
8702
8703   v8::Handle<v8::FunctionTemplate> func_template =
8704       v8::FunctionTemplate::New(isolate);
8705
8706   v8::Handle<v8::ObjectTemplate> global_template =
8707       func_template->InstanceTemplate();
8708
8709   v8::Handle<v8::ObjectTemplate> proto_template =
8710       func_template->PrototypeTemplate();
8711
8712   // Add an accessor to proto that's accessible by cross-domain JS code.
8713   proto_template->SetAccessor(v8_str("accessible"),
8714                               ConstTenGetter, 0,
8715                               v8::Handle<Value>(),
8716                               v8::ALL_CAN_READ);
8717
8718   // Add an accessor that is not accessible by cross-domain JS code.
8719   global_template->SetAccessor(v8_str("unreachable"),
8720                                UnreachableGetter, 0,
8721                                v8::Handle<Value>(),
8722                                v8::DEFAULT);
8723
8724   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8725   context0->Enter();
8726
8727   Local<v8::Object> global = context0->Global();
8728   // Add a normal property that shadows 'accessible'
8729   global->Set(v8_str("accessible"), v8_num(11));
8730
8731   // Enter a new context.
8732   v8::HandleScope scope1(CcTest::isolate());
8733   v8::Local<Context> context1 = Context::New(isolate);
8734   context1->Enter();
8735
8736   v8::Handle<v8::Object> global1 = context1->Global();
8737   global1->Set(v8_str("other"), global);
8738
8739   // Should return 10, instead of 11
8740   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
8741   CHECK(value->IsNumber());
8742   CHECK_EQ(10, value->Int32Value());
8743
8744   value = v8_compile("other.unreachable")->Run();
8745   CHECK(value.IsEmpty());
8746
8747   context1->Exit();
8748   context0->Exit();
8749 }
8750
8751
8752 static int named_access_count = 0;
8753 static int indexed_access_count = 0;
8754
8755 static bool NamedAccessCounter(Local<v8::Object> global,
8756                                Local<Value> name,
8757                                v8::AccessType type,
8758                                Local<Value> data) {
8759   named_access_count++;
8760   return true;
8761 }
8762
8763
8764 static bool IndexedAccessCounter(Local<v8::Object> global,
8765                                  uint32_t key,
8766                                  v8::AccessType type,
8767                                  Local<Value> data) {
8768   indexed_access_count++;
8769   return true;
8770 }
8771
8772
8773 // This one is too easily disturbed by other tests.
8774 TEST(AccessControlIC) {
8775   named_access_count = 0;
8776   indexed_access_count = 0;
8777
8778   v8::Isolate* isolate = CcTest::isolate();
8779   v8::HandleScope handle_scope(isolate);
8780
8781   // Create an environment.
8782   v8::Local<Context> context0 = Context::New(isolate);
8783   context0->Enter();
8784
8785   // Create an object that requires access-check functions to be
8786   // called for cross-domain access.
8787   v8::Handle<v8::ObjectTemplate> object_template =
8788       v8::ObjectTemplate::New(isolate);
8789   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
8790                                            IndexedAccessCounter);
8791   Local<v8::Object> object = object_template->NewInstance();
8792
8793   v8::HandleScope scope1(isolate);
8794
8795   // Create another environment.
8796   v8::Local<Context> context1 = Context::New(isolate);
8797   context1->Enter();
8798
8799   // Make easy access to the object from the other environment.
8800   v8::Handle<v8::Object> global1 = context1->Global();
8801   global1->Set(v8_str("obj"), object);
8802
8803   v8::Handle<Value> value;
8804
8805   // Check that the named access-control function is called every time.
8806   CompileRun("function testProp(obj) {"
8807              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
8808              "  for (var j = 0; j < 10; j++) obj.prop;"
8809              "  return obj.prop"
8810              "}");
8811   value = CompileRun("testProp(obj)");
8812   CHECK(value->IsNumber());
8813   CHECK_EQ(1, value->Int32Value());
8814   CHECK_EQ(21, named_access_count);
8815
8816   // Check that the named access-control function is called every time.
8817   CompileRun("var p = 'prop';"
8818              "function testKeyed(obj) {"
8819              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
8820              "  for (var j = 0; j < 10; j++) obj[p];"
8821              "  return obj[p];"
8822              "}");
8823   // Use obj which requires access checks.  No inline caching is used
8824   // in that case.
8825   value = CompileRun("testKeyed(obj)");
8826   CHECK(value->IsNumber());
8827   CHECK_EQ(1, value->Int32Value());
8828   CHECK_EQ(42, named_access_count);
8829   // Force the inline caches into generic state and try again.
8830   CompileRun("testKeyed({ a: 0 })");
8831   CompileRun("testKeyed({ b: 0 })");
8832   value = CompileRun("testKeyed(obj)");
8833   CHECK(value->IsNumber());
8834   CHECK_EQ(1, value->Int32Value());
8835   CHECK_EQ(63, named_access_count);
8836
8837   // Check that the indexed access-control function is called every time.
8838   CompileRun("function testIndexed(obj) {"
8839              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
8840              "  for (var j = 0; j < 10; j++) obj[0];"
8841              "  return obj[0]"
8842              "}");
8843   value = CompileRun("testIndexed(obj)");
8844   CHECK(value->IsNumber());
8845   CHECK_EQ(1, value->Int32Value());
8846   CHECK_EQ(21, indexed_access_count);
8847   // Force the inline caches into generic state.
8848   CompileRun("testIndexed(new Array(1))");
8849   // Test that the indexed access check is called.
8850   value = CompileRun("testIndexed(obj)");
8851   CHECK(value->IsNumber());
8852   CHECK_EQ(1, value->Int32Value());
8853   CHECK_EQ(42, indexed_access_count);
8854
8855   // Check that the named access check is called when invoking
8856   // functions on an object that requires access checks.
8857   CompileRun("obj.f = function() {}");
8858   CompileRun("function testCallNormal(obj) {"
8859              "  for (var i = 0; i < 10; i++) obj.f();"
8860              "}");
8861   CompileRun("testCallNormal(obj)");
8862   CHECK_EQ(74, named_access_count);
8863
8864   // Force obj into slow case.
8865   value = CompileRun("delete obj.prop");
8866   CHECK(value->BooleanValue());
8867   // Force inline caches into dictionary probing mode.
8868   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
8869   // Test that the named access check is called.
8870   value = CompileRun("testProp(obj);");
8871   CHECK(value->IsNumber());
8872   CHECK_EQ(1, value->Int32Value());
8873   CHECK_EQ(96, named_access_count);
8874
8875   // Force the call inline cache into dictionary probing mode.
8876   CompileRun("o.f = function() {}; testCallNormal(o)");
8877   // Test that the named access check is still called for each
8878   // invocation of the function.
8879   value = CompileRun("testCallNormal(obj)");
8880   CHECK_EQ(106, named_access_count);
8881
8882   context1->Exit();
8883   context0->Exit();
8884 }
8885
8886
8887 static bool NamedAccessFlatten(Local<v8::Object> global,
8888                                Local<Value> name,
8889                                v8::AccessType type,
8890                                Local<Value> data) {
8891   char buf[100];
8892   int len;
8893
8894   CHECK(name->IsString());
8895
8896   memset(buf, 0x1, sizeof(buf));
8897   len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
8898   CHECK_EQ(4, len);
8899
8900   uint16_t buf2[100];
8901
8902   memset(buf, 0x1, sizeof(buf));
8903   len = name.As<String>()->Write(buf2);
8904   CHECK_EQ(4, len);
8905
8906   return true;
8907 }
8908
8909
8910 static bool IndexedAccessFlatten(Local<v8::Object> global,
8911                                  uint32_t key,
8912                                  v8::AccessType type,
8913                                  Local<Value> data) {
8914   return true;
8915 }
8916
8917
8918 // Regression test.  In access checks, operations that may cause
8919 // garbage collection are not allowed.  It used to be the case that
8920 // using the Write operation on a string could cause a garbage
8921 // collection due to flattening of the string.  This is no longer the
8922 // case.
8923 THREADED_TEST(AccessControlFlatten) {
8924   named_access_count = 0;
8925   indexed_access_count = 0;
8926
8927   v8::Isolate* isolate = CcTest::isolate();
8928   v8::HandleScope handle_scope(isolate);
8929
8930   // Create an environment.
8931   v8::Local<Context> context0 = Context::New(isolate);
8932   context0->Enter();
8933
8934   // Create an object that requires access-check functions to be
8935   // called for cross-domain access.
8936   v8::Handle<v8::ObjectTemplate> object_template =
8937       v8::ObjectTemplate::New(isolate);
8938   object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
8939                                            IndexedAccessFlatten);
8940   Local<v8::Object> object = object_template->NewInstance();
8941
8942   v8::HandleScope scope1(isolate);
8943
8944   // Create another environment.
8945   v8::Local<Context> context1 = Context::New(isolate);
8946   context1->Enter();
8947
8948   // Make easy access to the object from the other environment.
8949   v8::Handle<v8::Object> global1 = context1->Global();
8950   global1->Set(v8_str("obj"), object);
8951
8952   v8::Handle<Value> value;
8953
8954   value = v8_compile("var p = 'as' + 'df';")->Run();
8955   value = v8_compile("obj[p];")->Run();
8956
8957   context1->Exit();
8958   context0->Exit();
8959 }
8960
8961
8962 THREADED_TEST(Version) { v8::V8::GetVersion(); }
8963
8964
8965 static void InstanceFunctionCallback(
8966     const v8::FunctionCallbackInfo<v8::Value>& args) {
8967   ApiTestFuzzer::Fuzz();
8968   args.GetReturnValue().Set(v8_num(12));
8969 }
8970
8971
8972 THREADED_TEST(InstanceProperties) {
8973   LocalContext context;
8974   v8::Isolate* isolate = context->GetIsolate();
8975   v8::HandleScope handle_scope(isolate);
8976
8977   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
8978   Local<ObjectTemplate> instance = t->InstanceTemplate();
8979
8980   instance->Set(v8_str("x"), v8_num(42));
8981   instance->Set(v8_str("f"),
8982                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
8983
8984   Local<Value> o = t->GetFunction()->NewInstance();
8985
8986   context->Global()->Set(v8_str("i"), o);
8987   Local<Value> value = CompileRun("i.x");
8988   CHECK_EQ(42, value->Int32Value());
8989
8990   value = CompileRun("i.f()");
8991   CHECK_EQ(12, value->Int32Value());
8992 }
8993
8994
8995 static void GlobalObjectInstancePropertiesGet(
8996     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
8997   ApiTestFuzzer::Fuzz();
8998 }
8999
9000
9001 THREADED_TEST(GlobalObjectInstanceProperties) {
9002   v8::Isolate* isolate = CcTest::isolate();
9003   v8::HandleScope handle_scope(isolate);
9004
9005   Local<Value> global_object;
9006
9007   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9008   t->InstanceTemplate()->SetHandler(
9009       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
9010   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9011   instance_template->Set(v8_str("x"), v8_num(42));
9012   instance_template->Set(v8_str("f"),
9013                          v8::FunctionTemplate::New(isolate,
9014                                                    InstanceFunctionCallback));
9015
9016   // The script to check how Crankshaft compiles missing global function
9017   // invocations.  function g is not defined and should throw on call.
9018   const char* script =
9019       "function wrapper(call) {"
9020       "  var x = 0, y = 1;"
9021       "  for (var i = 0; i < 1000; i++) {"
9022       "    x += i * 100;"
9023       "    y += i * 100;"
9024       "  }"
9025       "  if (call) g();"
9026       "}"
9027       "for (var i = 0; i < 17; i++) wrapper(false);"
9028       "var thrown = 0;"
9029       "try { wrapper(true); } catch (e) { thrown = 1; };"
9030       "thrown";
9031
9032   {
9033     LocalContext env(NULL, instance_template);
9034     // Hold on to the global object so it can be used again in another
9035     // environment initialization.
9036     global_object = env->Global();
9037
9038     Local<Value> value = CompileRun("x");
9039     CHECK_EQ(42, value->Int32Value());
9040     value = CompileRun("f()");
9041     CHECK_EQ(12, value->Int32Value());
9042     value = CompileRun(script);
9043     CHECK_EQ(1, value->Int32Value());
9044   }
9045
9046   {
9047     // Create new environment reusing the global object.
9048     LocalContext env(NULL, instance_template, global_object);
9049     Local<Value> value = CompileRun("x");
9050     CHECK_EQ(42, value->Int32Value());
9051     value = CompileRun("f()");
9052     CHECK_EQ(12, value->Int32Value());
9053     value = CompileRun(script);
9054     CHECK_EQ(1, value->Int32Value());
9055   }
9056 }
9057
9058
9059 THREADED_TEST(CallKnownGlobalReceiver) {
9060   v8::Isolate* isolate = CcTest::isolate();
9061   v8::HandleScope handle_scope(isolate);
9062
9063   Local<Value> global_object;
9064
9065   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9066   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9067
9068   // The script to check that we leave global object not
9069   // global object proxy on stack when we deoptimize from inside
9070   // arguments evaluation.
9071   // To provoke error we need to both force deoptimization
9072   // from arguments evaluation and to force CallIC to take
9073   // CallIC_Miss code path that can't cope with global proxy.
9074   const char* script =
9075       "function bar(x, y) { try { } finally { } }"
9076       "function baz(x) { try { } finally { } }"
9077       "function bom(x) { try { } finally { } }"
9078       "function foo(x) { bar([x], bom(2)); }"
9079       "for (var i = 0; i < 10000; i++) foo(1);"
9080       "foo";
9081
9082   Local<Value> foo;
9083   {
9084     LocalContext env(NULL, instance_template);
9085     // Hold on to the global object so it can be used again in another
9086     // environment initialization.
9087     global_object = env->Global();
9088     foo = CompileRun(script);
9089   }
9090
9091   {
9092     // Create new environment reusing the global object.
9093     LocalContext env(NULL, instance_template, global_object);
9094     env->Global()->Set(v8_str("foo"), foo);
9095     CompileRun("foo()");
9096   }
9097 }
9098
9099
9100 static void ShadowFunctionCallback(
9101     const v8::FunctionCallbackInfo<v8::Value>& args) {
9102   ApiTestFuzzer::Fuzz();
9103   args.GetReturnValue().Set(v8_num(42));
9104 }
9105
9106
9107 static int shadow_y;
9108 static int shadow_y_setter_call_count;
9109 static int shadow_y_getter_call_count;
9110
9111
9112 static void ShadowYSetter(Local<String>,
9113                           Local<Value>,
9114                           const v8::PropertyCallbackInfo<void>&) {
9115   shadow_y_setter_call_count++;
9116   shadow_y = 42;
9117 }
9118
9119
9120 static void ShadowYGetter(Local<String> name,
9121                           const v8::PropertyCallbackInfo<v8::Value>& info) {
9122   ApiTestFuzzer::Fuzz();
9123   shadow_y_getter_call_count++;
9124   info.GetReturnValue().Set(v8_num(shadow_y));
9125 }
9126
9127
9128 static void ShadowIndexedGet(uint32_t index,
9129                              const v8::PropertyCallbackInfo<v8::Value>&) {
9130 }
9131
9132
9133 static void ShadowNamedGet(Local<Name> key,
9134                            const v8::PropertyCallbackInfo<v8::Value>&) {}
9135
9136
9137 THREADED_TEST(ShadowObject) {
9138   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
9139   v8::Isolate* isolate = CcTest::isolate();
9140   v8::HandleScope handle_scope(isolate);
9141
9142   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
9143   LocalContext context(NULL, global_template);
9144
9145   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9146   t->InstanceTemplate()->SetHandler(
9147       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
9148   t->InstanceTemplate()->SetHandler(
9149       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
9150   Local<ObjectTemplate> proto = t->PrototypeTemplate();
9151   Local<ObjectTemplate> instance = t->InstanceTemplate();
9152
9153   proto->Set(v8_str("f"),
9154              v8::FunctionTemplate::New(isolate,
9155                                        ShadowFunctionCallback,
9156                                        Local<Value>()));
9157   proto->Set(v8_str("x"), v8_num(12));
9158
9159   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9160
9161   Local<Value> o = t->GetFunction()->NewInstance();
9162   context->Global()->Set(v8_str("__proto__"), o);
9163
9164   Local<Value> value =
9165       CompileRun("this.propertyIsEnumerable(0)");
9166   CHECK(value->IsBoolean());
9167   CHECK(!value->BooleanValue());
9168
9169   value = CompileRun("x");
9170   CHECK_EQ(12, value->Int32Value());
9171
9172   value = CompileRun("f()");
9173   CHECK_EQ(42, value->Int32Value());
9174
9175   CompileRun("y = 43");
9176   CHECK_EQ(1, shadow_y_setter_call_count);
9177   value = CompileRun("y");
9178   CHECK_EQ(1, shadow_y_getter_call_count);
9179   CHECK_EQ(42, value->Int32Value());
9180 }
9181
9182
9183 THREADED_TEST(HiddenPrototype) {
9184   LocalContext context;
9185   v8::Isolate* isolate = context->GetIsolate();
9186   v8::HandleScope handle_scope(isolate);
9187
9188   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9189   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9190   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9191   t1->SetHiddenPrototype(true);
9192   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9193   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9194   t2->SetHiddenPrototype(true);
9195   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9196   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9197   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9198
9199   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9200   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9201   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9202   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9203
9204   // Setting the prototype on an object skips hidden prototypes.
9205   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9206   o0->Set(v8_str("__proto__"), o1);
9207   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9208   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9209   o0->Set(v8_str("__proto__"), o2);
9210   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9211   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9212   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9213   o0->Set(v8_str("__proto__"), o3);
9214   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9215   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9216   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9217   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9218
9219   // Getting the prototype of o0 should get the first visible one
9220   // which is o3.  Therefore, z should not be defined on the prototype
9221   // object.
9222   Local<Value> proto = o0->Get(v8_str("__proto__"));
9223   CHECK(proto->IsObject());
9224   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
9225 }
9226
9227
9228 THREADED_TEST(HiddenPrototypeSet) {
9229   LocalContext context;
9230   v8::Isolate* isolate = context->GetIsolate();
9231   v8::HandleScope handle_scope(isolate);
9232
9233   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
9234   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
9235   ht->SetHiddenPrototype(true);
9236   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
9237   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9238
9239   Local<v8::Object> o = ot->GetFunction()->NewInstance();
9240   Local<v8::Object> h = ht->GetFunction()->NewInstance();
9241   Local<v8::Object> p = pt->GetFunction()->NewInstance();
9242   o->Set(v8_str("__proto__"), h);
9243   h->Set(v8_str("__proto__"), p);
9244
9245   // Setting a property that exists on the hidden prototype goes there.
9246   o->Set(v8_str("x"), v8_num(7));
9247   CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
9248   CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
9249   CHECK(p->Get(v8_str("x"))->IsUndefined());
9250
9251   // Setting a new property should not be forwarded to the hidden prototype.
9252   o->Set(v8_str("y"), v8_num(6));
9253   CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
9254   CHECK(h->Get(v8_str("y"))->IsUndefined());
9255   CHECK(p->Get(v8_str("y"))->IsUndefined());
9256
9257   // Setting a property that only exists on a prototype of the hidden prototype
9258   // is treated normally again.
9259   p->Set(v8_str("z"), v8_num(8));
9260   CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
9261   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9262   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9263   o->Set(v8_str("z"), v8_num(9));
9264   CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
9265   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9266   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9267 }
9268
9269
9270 // Regression test for issue 2457.
9271 THREADED_TEST(HiddenPrototypeIdentityHash) {
9272   LocalContext context;
9273   v8::HandleScope handle_scope(context->GetIsolate());
9274
9275   Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
9276   t->SetHiddenPrototype(true);
9277   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
9278   Handle<Object> p = t->GetFunction()->NewInstance();
9279   Handle<Object> o = Object::New(context->GetIsolate());
9280   o->SetPrototype(p);
9281
9282   int hash = o->GetIdentityHash();
9283   USE(hash);
9284   o->Set(v8_str("foo"), v8_num(42));
9285   DCHECK_EQ(hash, o->GetIdentityHash());
9286 }
9287
9288
9289 THREADED_TEST(SetPrototype) {
9290   LocalContext context;
9291   v8::Isolate* isolate = context->GetIsolate();
9292   v8::HandleScope handle_scope(isolate);
9293
9294   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9295   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9296   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9297   t1->SetHiddenPrototype(true);
9298   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9299   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9300   t2->SetHiddenPrototype(true);
9301   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9302   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9303   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9304
9305   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9306   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9307   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9308   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9309
9310   // Setting the prototype on an object does not skip hidden prototypes.
9311   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9312   CHECK(o0->SetPrototype(o1));
9313   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9314   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9315   CHECK(o1->SetPrototype(o2));
9316   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9317   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9318   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9319   CHECK(o2->SetPrototype(o3));
9320   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9321   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9322   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9323   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9324
9325   // Getting the prototype of o0 should get the first visible one
9326   // which is o3.  Therefore, z should not be defined on the prototype
9327   // object.
9328   Local<Value> proto = o0->Get(v8_str("__proto__"));
9329   CHECK(proto->IsObject());
9330   CHECK(proto.As<v8::Object>()->Equals(o3));
9331
9332   // However, Object::GetPrototype ignores hidden prototype.
9333   Local<Value> proto0 = o0->GetPrototype();
9334   CHECK(proto0->IsObject());
9335   CHECK(proto0.As<v8::Object>()->Equals(o1));
9336
9337   Local<Value> proto1 = o1->GetPrototype();
9338   CHECK(proto1->IsObject());
9339   CHECK(proto1.As<v8::Object>()->Equals(o2));
9340
9341   Local<Value> proto2 = o2->GetPrototype();
9342   CHECK(proto2->IsObject());
9343   CHECK(proto2.As<v8::Object>()->Equals(o3));
9344 }
9345
9346
9347 // Getting property names of an object with a prototype chain that
9348 // triggers dictionary elements in GetOwnPropertyNames() shouldn't
9349 // crash the runtime.
9350 THREADED_TEST(Regress91517) {
9351   i::FLAG_allow_natives_syntax = true;
9352   LocalContext context;
9353   v8::Isolate* isolate = context->GetIsolate();
9354   v8::HandleScope handle_scope(isolate);
9355
9356   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9357   t1->SetHiddenPrototype(true);
9358   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
9359   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9360   t2->SetHiddenPrototype(true);
9361   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
9362   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
9363   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
9364   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9365   t3->SetHiddenPrototype(true);
9366   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
9367   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
9368   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
9369
9370   // Force dictionary-based properties.
9371   i::ScopedVector<char> name_buf(1024);
9372   for (int i = 1; i <= 1000; i++) {
9373     i::SNPrintF(name_buf, "sdf%d", i);
9374     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
9375   }
9376
9377   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9378   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9379   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9380   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
9381
9382   // Create prototype chain of hidden prototypes.
9383   CHECK(o4->SetPrototype(o3));
9384   CHECK(o3->SetPrototype(o2));
9385   CHECK(o2->SetPrototype(o1));
9386
9387   // Call the runtime version of GetOwnPropertyNames() on the natively
9388   // created object through JavaScript.
9389   context->Global()->Set(v8_str("obj"), o4);
9390   // PROPERTY_ATTRIBUTES_NONE = 0
9391   CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
9392
9393   ExpectInt32("names.length", 1006);
9394   ExpectTrue("names.indexOf(\"baz\") >= 0");
9395   ExpectTrue("names.indexOf(\"boo\") >= 0");
9396   ExpectTrue("names.indexOf(\"foo\") >= 0");
9397   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
9398   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
9399   ExpectFalse("names[1005] == undefined");
9400 }
9401
9402
9403 // Getting property names of an object with a hidden and inherited
9404 // prototype should not duplicate the accessor properties inherited.
9405 THREADED_TEST(Regress269562) {
9406   i::FLAG_allow_natives_syntax = true;
9407   LocalContext context;
9408   v8::HandleScope handle_scope(context->GetIsolate());
9409
9410   Local<v8::FunctionTemplate> t1 =
9411       v8::FunctionTemplate::New(context->GetIsolate());
9412   t1->SetHiddenPrototype(true);
9413
9414   Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
9415   i1->SetAccessor(v8_str("foo"),
9416                   SimpleAccessorGetter, SimpleAccessorSetter);
9417   i1->SetAccessor(v8_str("bar"),
9418                   SimpleAccessorGetter, SimpleAccessorSetter);
9419   i1->SetAccessor(v8_str("baz"),
9420                   SimpleAccessorGetter, SimpleAccessorSetter);
9421   i1->Set(v8_str("n1"), v8_num(1));
9422   i1->Set(v8_str("n2"), v8_num(2));
9423
9424   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9425   Local<v8::FunctionTemplate> t2 =
9426       v8::FunctionTemplate::New(context->GetIsolate());
9427   t2->SetHiddenPrototype(true);
9428
9429   // Inherit from t1 and mark prototype as hidden.
9430   t2->Inherit(t1);
9431   t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
9432
9433   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9434   CHECK(o2->SetPrototype(o1));
9435
9436   v8::Local<v8::Symbol> sym =
9437       v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
9438   o1->Set(sym, v8_num(3));
9439   o1->SetHiddenValue(
9440       v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
9441
9442   // Call the runtime version of GetOwnPropertyNames() on
9443   // the natively created object through JavaScript.
9444   context->Global()->Set(v8_str("obj"), o2);
9445   context->Global()->Set(v8_str("sym"), sym);
9446   // PROPERTY_ATTRIBUTES_NONE = 0
9447   CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
9448
9449   ExpectInt32("names.length", 7);
9450   ExpectTrue("names.indexOf(\"foo\") >= 0");
9451   ExpectTrue("names.indexOf(\"bar\") >= 0");
9452   ExpectTrue("names.indexOf(\"baz\") >= 0");
9453   ExpectTrue("names.indexOf(\"n1\") >= 0");
9454   ExpectTrue("names.indexOf(\"n2\") >= 0");
9455   ExpectTrue("names.indexOf(sym) >= 0");
9456   ExpectTrue("names.indexOf(\"mine\") >= 0");
9457 }
9458
9459
9460 THREADED_TEST(FunctionReadOnlyPrototype) {
9461   LocalContext context;
9462   v8::Isolate* isolate = context->GetIsolate();
9463   v8::HandleScope handle_scope(isolate);
9464
9465   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9466   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9467   t1->ReadOnlyPrototype();
9468   context->Global()->Set(v8_str("func1"), t1->GetFunction());
9469   // Configured value of ReadOnly flag.
9470   CHECK(CompileRun(
9471       "(function() {"
9472       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
9473       "  return (descriptor['writable'] == false);"
9474       "})()")->BooleanValue());
9475   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
9476   CHECK_EQ(42,
9477            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
9478
9479   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9480   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9481   context->Global()->Set(v8_str("func2"), t2->GetFunction());
9482   // Default value of ReadOnly flag.
9483   CHECK(CompileRun(
9484       "(function() {"
9485       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
9486       "  return (descriptor['writable'] == true);"
9487       "})()")->BooleanValue());
9488   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
9489 }
9490
9491
9492 THREADED_TEST(SetPrototypeThrows) {
9493   LocalContext context;
9494   v8::Isolate* isolate = context->GetIsolate();
9495   v8::HandleScope handle_scope(isolate);
9496
9497   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9498
9499   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
9500   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
9501
9502   CHECK(o0->SetPrototype(o1));
9503   // If setting the prototype leads to the cycle, SetPrototype should
9504   // return false and keep VM in sane state.
9505   v8::TryCatch try_catch;
9506   CHECK(!o1->SetPrototype(o0));
9507   CHECK(!try_catch.HasCaught());
9508   DCHECK(!CcTest::i_isolate()->has_pending_exception());
9509
9510   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
9511 }
9512
9513
9514 THREADED_TEST(FunctionRemovePrototype) {
9515   LocalContext context;
9516   v8::Isolate* isolate = context->GetIsolate();
9517   v8::HandleScope handle_scope(isolate);
9518
9519   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9520   t1->RemovePrototype();
9521   Local<v8::Function> fun = t1->GetFunction();
9522   context->Global()->Set(v8_str("fun"), fun);
9523   CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
9524
9525   v8::TryCatch try_catch;
9526   CompileRun("new fun()");
9527   CHECK(try_catch.HasCaught());
9528
9529   try_catch.Reset();
9530   fun->NewInstance();
9531   CHECK(try_catch.HasCaught());
9532 }
9533
9534
9535 THREADED_TEST(GetterSetterExceptions) {
9536   LocalContext context;
9537   v8::Isolate* isolate = context->GetIsolate();
9538   v8::HandleScope handle_scope(isolate);
9539   CompileRun(
9540       "function Foo() { };"
9541       "function Throw() { throw 5; };"
9542       "var x = { };"
9543       "x.__defineSetter__('set', Throw);"
9544       "x.__defineGetter__('get', Throw);");
9545   Local<v8::Object> x =
9546       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
9547   v8::TryCatch try_catch;
9548   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9549   x->Get(v8_str("get"));
9550   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9551   x->Get(v8_str("get"));
9552   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9553   x->Get(v8_str("get"));
9554   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9555   x->Get(v8_str("get"));
9556 }
9557
9558
9559 THREADED_TEST(Constructor) {
9560   LocalContext context;
9561   v8::Isolate* isolate = context->GetIsolate();
9562   v8::HandleScope handle_scope(isolate);
9563   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
9564   templ->SetClassName(v8_str("Fun"));
9565   Local<Function> cons = templ->GetFunction();
9566   context->Global()->Set(v8_str("Fun"), cons);
9567   Local<v8::Object> inst = cons->NewInstance();
9568   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
9569   CHECK(obj->IsJSObject());
9570   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
9571   CHECK(value->BooleanValue());
9572 }
9573
9574
9575 static void ConstructorCallback(
9576     const v8::FunctionCallbackInfo<v8::Value>& args) {
9577   ApiTestFuzzer::Fuzz();
9578   Local<Object> This;
9579
9580   if (args.IsConstructCall()) {
9581     Local<Object> Holder = args.Holder();
9582     This = Object::New(args.GetIsolate());
9583     Local<Value> proto = Holder->GetPrototype();
9584     if (proto->IsObject()) {
9585       This->SetPrototype(proto);
9586     }
9587   } else {
9588     This = args.This();
9589   }
9590
9591   This->Set(v8_str("a"), args[0]);
9592   args.GetReturnValue().Set(This);
9593 }
9594
9595
9596 static void FakeConstructorCallback(
9597     const v8::FunctionCallbackInfo<v8::Value>& args) {
9598   ApiTestFuzzer::Fuzz();
9599   args.GetReturnValue().Set(args[0]);
9600 }
9601
9602
9603 THREADED_TEST(ConstructorForObject) {
9604   LocalContext context;
9605   v8::Isolate* isolate = context->GetIsolate();
9606   v8::HandleScope handle_scope(isolate);
9607
9608   {
9609     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9610     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
9611     Local<Object> instance = instance_template->NewInstance();
9612     context->Global()->Set(v8_str("obj"), instance);
9613     v8::TryCatch try_catch;
9614     Local<Value> value;
9615     CHECK(!try_catch.HasCaught());
9616
9617     // Call the Object's constructor with a 32-bit signed integer.
9618     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
9619     CHECK(!try_catch.HasCaught());
9620     CHECK(value->IsInt32());
9621     CHECK_EQ(28, value->Int32Value());
9622
9623     Local<Value> args1[] = {v8_num(28)};
9624     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
9625     CHECK(value_obj1->IsObject());
9626     Local<Object> object1 = Local<Object>::Cast(value_obj1);
9627     value = object1->Get(v8_str("a"));
9628     CHECK(value->IsInt32());
9629     CHECK(!try_catch.HasCaught());
9630     CHECK_EQ(28, value->Int32Value());
9631
9632     // Call the Object's constructor with a String.
9633     value =
9634         CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
9635     CHECK(!try_catch.HasCaught());
9636     CHECK(value->IsString());
9637     String::Utf8Value string_value1(value->ToString(isolate));
9638     CHECK_EQ(0, strcmp("tipli", *string_value1));
9639
9640     Local<Value> args2[] = {v8_str("tipli")};
9641     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
9642     CHECK(value_obj2->IsObject());
9643     Local<Object> object2 = Local<Object>::Cast(value_obj2);
9644     value = object2->Get(v8_str("a"));
9645     CHECK(!try_catch.HasCaught());
9646     CHECK(value->IsString());
9647     String::Utf8Value string_value2(value->ToString(isolate));
9648     CHECK_EQ(0, strcmp("tipli", *string_value2));
9649
9650     // Call the Object's constructor with a Boolean.
9651     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
9652     CHECK(!try_catch.HasCaught());
9653     CHECK(value->IsBoolean());
9654     CHECK_EQ(true, value->BooleanValue());
9655
9656     Handle<Value> args3[] = {v8::True(isolate)};
9657     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
9658     CHECK(value_obj3->IsObject());
9659     Local<Object> object3 = Local<Object>::Cast(value_obj3);
9660     value = object3->Get(v8_str("a"));
9661     CHECK(!try_catch.HasCaught());
9662     CHECK(value->IsBoolean());
9663     CHECK_EQ(true, value->BooleanValue());
9664
9665     // Call the Object's constructor with undefined.
9666     Handle<Value> args4[] = {v8::Undefined(isolate)};
9667     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
9668     CHECK(value_obj4->IsObject());
9669     Local<Object> object4 = Local<Object>::Cast(value_obj4);
9670     value = object4->Get(v8_str("a"));
9671     CHECK(!try_catch.HasCaught());
9672     CHECK(value->IsUndefined());
9673
9674     // Call the Object's constructor with null.
9675     Handle<Value> args5[] = {v8::Null(isolate)};
9676     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
9677     CHECK(value_obj5->IsObject());
9678     Local<Object> object5 = Local<Object>::Cast(value_obj5);
9679     value = object5->Get(v8_str("a"));
9680     CHECK(!try_catch.HasCaught());
9681     CHECK(value->IsNull());
9682   }
9683
9684   // Check exception handling when there is no constructor set for the Object.
9685   {
9686     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9687     Local<Object> instance = instance_template->NewInstance();
9688     context->Global()->Set(v8_str("obj2"), instance);
9689     v8::TryCatch try_catch;
9690     Local<Value> value;
9691     CHECK(!try_catch.HasCaught());
9692
9693     value = CompileRun("new obj2(28)");
9694     CHECK(try_catch.HasCaught());
9695     String::Utf8Value exception_value1(try_catch.Exception());
9696     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
9697     try_catch.Reset();
9698
9699     Local<Value> args[] = {v8_num(29)};
9700     value = instance->CallAsConstructor(1, args);
9701     CHECK(try_catch.HasCaught());
9702     String::Utf8Value exception_value2(try_catch.Exception());
9703     CHECK_EQ(
9704         0, strcmp("TypeError: #<Object> is not a function", *exception_value2));
9705     try_catch.Reset();
9706   }
9707
9708   // Check the case when constructor throws exception.
9709   {
9710     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9711     instance_template->SetCallAsFunctionHandler(ThrowValue);
9712     Local<Object> instance = instance_template->NewInstance();
9713     context->Global()->Set(v8_str("obj3"), instance);
9714     v8::TryCatch try_catch;
9715     Local<Value> value;
9716     CHECK(!try_catch.HasCaught());
9717
9718     value = CompileRun("new obj3(22)");
9719     CHECK(try_catch.HasCaught());
9720     String::Utf8Value exception_value1(try_catch.Exception());
9721     CHECK_EQ(0, strcmp("22", *exception_value1));
9722     try_catch.Reset();
9723
9724     Local<Value> args[] = {v8_num(23)};
9725     value = instance->CallAsConstructor(1, args);
9726     CHECK(try_catch.HasCaught());
9727     String::Utf8Value exception_value2(try_catch.Exception());
9728     CHECK_EQ(0, strcmp("23", *exception_value2));
9729     try_catch.Reset();
9730   }
9731
9732   // Check whether constructor returns with an object or non-object.
9733   {
9734     Local<FunctionTemplate> function_template =
9735         FunctionTemplate::New(isolate, FakeConstructorCallback);
9736     Local<Function> function = function_template->GetFunction();
9737     Local<Object> instance1 = function;
9738     context->Global()->Set(v8_str("obj4"), instance1);
9739     v8::TryCatch try_catch;
9740     Local<Value> value;
9741     CHECK(!try_catch.HasCaught());
9742
9743     CHECK(instance1->IsObject());
9744     CHECK(instance1->IsFunction());
9745
9746     value = CompileRun("new obj4(28)");
9747     CHECK(!try_catch.HasCaught());
9748     CHECK(value->IsObject());
9749
9750     Local<Value> args1[] = {v8_num(28)};
9751     value = instance1->CallAsConstructor(1, args1);
9752     CHECK(!try_catch.HasCaught());
9753     CHECK(value->IsObject());
9754
9755     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9756     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
9757     Local<Object> instance2 = instance_template->NewInstance();
9758     context->Global()->Set(v8_str("obj5"), instance2);
9759     CHECK(!try_catch.HasCaught());
9760
9761     CHECK(instance2->IsObject());
9762     CHECK(!instance2->IsFunction());
9763
9764     value = CompileRun("new obj5(28)");
9765     CHECK(!try_catch.HasCaught());
9766     CHECK(!value->IsObject());
9767
9768     Local<Value> args2[] = {v8_num(28)};
9769     value = instance2->CallAsConstructor(1, args2);
9770     CHECK(!try_catch.HasCaught());
9771     CHECK(!value->IsObject());
9772   }
9773 }
9774
9775
9776 THREADED_TEST(FunctionDescriptorException) {
9777   LocalContext context;
9778   v8::Isolate* isolate = context->GetIsolate();
9779   v8::HandleScope handle_scope(isolate);
9780   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
9781   templ->SetClassName(v8_str("Fun"));
9782   Local<Function> cons = templ->GetFunction();
9783   context->Global()->Set(v8_str("Fun"), cons);
9784   Local<Value> value = CompileRun(
9785       "function test() {"
9786       "  try {"
9787       "    (new Fun()).blah()"
9788       "  } catch (e) {"
9789       "    var str = String(e);"
9790       // "    if (str.indexOf('TypeError') == -1) return 1;"
9791       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
9792       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
9793       "    return 0;"
9794       "  }"
9795       "  return 4;"
9796       "}"
9797       "test();");
9798   CHECK_EQ(0, value->Int32Value());
9799 }
9800
9801
9802 THREADED_TEST(EvalAliasedDynamic) {
9803   LocalContext current;
9804   v8::HandleScope scope(current->GetIsolate());
9805
9806   // Tests where aliased eval can only be resolved dynamically.
9807   Local<Script> script = v8_compile(
9808       "function f(x) { "
9809       "  var foo = 2;"
9810       "  with (x) { return eval('foo'); }"
9811       "}"
9812       "foo = 0;"
9813       "result1 = f(new Object());"
9814       "result2 = f(this);"
9815       "var x = new Object();"
9816       "x.eval = function(x) { return 1; };"
9817       "result3 = f(x);");
9818   script->Run();
9819   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
9820   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
9821   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
9822
9823   v8::TryCatch try_catch;
9824   script = v8_compile(
9825       "function f(x) { "
9826       "  var bar = 2;"
9827       "  with (x) { return eval('bar'); }"
9828       "}"
9829       "result4 = f(this)");
9830   script->Run();
9831   CHECK(!try_catch.HasCaught());
9832   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
9833
9834   try_catch.Reset();
9835 }
9836
9837
9838 THREADED_TEST(CrossEval) {
9839   v8::HandleScope scope(CcTest::isolate());
9840   LocalContext other;
9841   LocalContext current;
9842
9843   Local<String> token = v8_str("<security token>");
9844   other->SetSecurityToken(token);
9845   current->SetSecurityToken(token);
9846
9847   // Set up reference from current to other.
9848   current->Global()->Set(v8_str("other"), other->Global());
9849
9850   // Check that new variables are introduced in other context.
9851   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
9852   script->Run();
9853   Local<Value> foo = other->Global()->Get(v8_str("foo"));
9854   CHECK_EQ(1234, foo->Int32Value());
9855   CHECK(!current->Global()->Has(v8_str("foo")));
9856
9857   // Check that writing to non-existing properties introduces them in
9858   // the other context.
9859   script = v8_compile("other.eval('na = 1234')");
9860   script->Run();
9861   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
9862   CHECK(!current->Global()->Has(v8_str("na")));
9863
9864   // Check that global variables in current context are not visible in other
9865   // context.
9866   v8::TryCatch try_catch;
9867   script = v8_compile("var bar = 42; other.eval('bar');");
9868   Local<Value> result = script->Run();
9869   CHECK(try_catch.HasCaught());
9870   try_catch.Reset();
9871
9872   // Check that local variables in current context are not visible in other
9873   // context.
9874   script = v8_compile(
9875       "(function() { "
9876       "  var baz = 87;"
9877       "  return other.eval('baz');"
9878       "})();");
9879   result = script->Run();
9880   CHECK(try_catch.HasCaught());
9881   try_catch.Reset();
9882
9883   // Check that global variables in the other environment are visible
9884   // when evaluting code.
9885   other->Global()->Set(v8_str("bis"), v8_num(1234));
9886   script = v8_compile("other.eval('bis')");
9887   CHECK_EQ(1234, script->Run()->Int32Value());
9888   CHECK(!try_catch.HasCaught());
9889
9890   // Check that the 'this' pointer points to the global object evaluating
9891   // code.
9892   other->Global()->Set(v8_str("t"), other->Global());
9893   script = v8_compile("other.eval('this == t')");
9894   result = script->Run();
9895   CHECK(result->IsTrue());
9896   CHECK(!try_catch.HasCaught());
9897
9898   // Check that variables introduced in with-statement are not visible in
9899   // other context.
9900   script = v8_compile("with({x:2}){other.eval('x')}");
9901   result = script->Run();
9902   CHECK(try_catch.HasCaught());
9903   try_catch.Reset();
9904
9905   // Check that you cannot use 'eval.call' with another object than the
9906   // current global object.
9907   script = v8_compile("other.y = 1; eval.call(other, 'y')");
9908   result = script->Run();
9909   CHECK(try_catch.HasCaught());
9910 }
9911
9912
9913 // Test that calling eval in a context which has been detached from
9914 // its global proxy works.
9915 THREADED_TEST(EvalInDetachedGlobal) {
9916   v8::Isolate* isolate = CcTest::isolate();
9917   v8::HandleScope scope(isolate);
9918
9919   v8::Local<Context> context0 = Context::New(isolate);
9920   v8::Local<Context> context1 = Context::New(isolate);
9921
9922   // Set up function in context0 that uses eval from context0.
9923   context0->Enter();
9924   v8::Handle<v8::Value> fun = CompileRun(
9925       "var x = 42;"
9926       "(function() {"
9927       "  var e = eval;"
9928       "  return function(s) { return e(s); }"
9929       "})()");
9930   context0->Exit();
9931
9932   // Put the function into context1 and call it before and after
9933   // detaching the global.  Before detaching, the call succeeds and
9934   // after detaching and exception is thrown.
9935   context1->Enter();
9936   context1->Global()->Set(v8_str("fun"), fun);
9937   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
9938   CHECK_EQ(42, x_value->Int32Value());
9939   context0->DetachGlobal();
9940   v8::TryCatch catcher;
9941   x_value = CompileRun("fun('x')");
9942   CHECK_EQ(42, x_value->Int32Value());
9943   context1->Exit();
9944 }
9945
9946
9947 THREADED_TEST(CrossLazyLoad) {
9948   v8::HandleScope scope(CcTest::isolate());
9949   LocalContext other;
9950   LocalContext current;
9951
9952   Local<String> token = v8_str("<security token>");
9953   other->SetSecurityToken(token);
9954   current->SetSecurityToken(token);
9955
9956   // Set up reference from current to other.
9957   current->Global()->Set(v8_str("other"), other->Global());
9958
9959   // Trigger lazy loading in other context.
9960   Local<Script> script = v8_compile("other.eval('new Date(42)')");
9961   Local<Value> value = script->Run();
9962   CHECK_EQ(42.0, value->NumberValue());
9963 }
9964
9965
9966 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
9967   ApiTestFuzzer::Fuzz();
9968   if (args.IsConstructCall()) {
9969     if (args[0]->IsInt32()) {
9970       args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
9971       return;
9972     }
9973   }
9974
9975   args.GetReturnValue().Set(args[0]);
9976 }
9977
9978
9979 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
9980   args.GetReturnValue().Set(args.This());
9981 }
9982
9983
9984 // Test that a call handler can be set for objects which will allow
9985 // non-function objects created through the API to be called as
9986 // functions.
9987 THREADED_TEST(CallAsFunction) {
9988   LocalContext context;
9989   v8::Isolate* isolate = context->GetIsolate();
9990   v8::HandleScope scope(isolate);
9991
9992   {
9993     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9994     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9995     instance_template->SetCallAsFunctionHandler(call_as_function);
9996     Local<v8::Object> instance = t->GetFunction()->NewInstance();
9997     context->Global()->Set(v8_str("obj"), instance);
9998     v8::TryCatch try_catch;
9999     Local<Value> value;
10000     CHECK(!try_catch.HasCaught());
10001
10002     value = CompileRun("obj(42)");
10003     CHECK(!try_catch.HasCaught());
10004     CHECK_EQ(42, value->Int32Value());
10005
10006     value = CompileRun("(function(o){return o(49)})(obj)");
10007     CHECK(!try_catch.HasCaught());
10008     CHECK_EQ(49, value->Int32Value());
10009
10010     // test special case of call as function
10011     value = CompileRun("[obj]['0'](45)");
10012     CHECK(!try_catch.HasCaught());
10013     CHECK_EQ(45, value->Int32Value());
10014
10015     value = CompileRun(
10016         "obj.call = Function.prototype.call;"
10017         "obj.call(null, 87)");
10018     CHECK(!try_catch.HasCaught());
10019     CHECK_EQ(87, value->Int32Value());
10020
10021     // Regression tests for bug #1116356: Calling call through call/apply
10022     // must work for non-function receivers.
10023     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10024     value = CompileRun(apply_99);
10025     CHECK(!try_catch.HasCaught());
10026     CHECK_EQ(99, value->Int32Value());
10027
10028     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10029     value = CompileRun(call_17);
10030     CHECK(!try_catch.HasCaught());
10031     CHECK_EQ(17, value->Int32Value());
10032
10033     // Check that the call-as-function handler can be called through
10034     // new.
10035     value = CompileRun("new obj(43)");
10036     CHECK(!try_catch.HasCaught());
10037     CHECK_EQ(-43, value->Int32Value());
10038
10039     // Check that the call-as-function handler can be called through
10040     // the API.
10041     v8::Handle<Value> args[] = {v8_num(28)};
10042     value = instance->CallAsFunction(instance, 1, args);
10043     CHECK(!try_catch.HasCaught());
10044     CHECK_EQ(28, value->Int32Value());
10045   }
10046
10047   {
10048     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10049     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
10050     USE(instance_template);
10051     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10052     context->Global()->Set(v8_str("obj2"), instance);
10053     v8::TryCatch try_catch;
10054     Local<Value> value;
10055     CHECK(!try_catch.HasCaught());
10056
10057     // Call an object without call-as-function handler through the JS
10058     value = CompileRun("obj2(28)");
10059     CHECK(value.IsEmpty());
10060     CHECK(try_catch.HasCaught());
10061     String::Utf8Value exception_value1(try_catch.Exception());
10062     // TODO(verwaest): Better message
10063     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
10064     try_catch.Reset();
10065
10066     // Call an object without call-as-function handler through the API
10067     value = CompileRun("obj2(28)");
10068     v8::Handle<Value> args[] = {v8_num(28)};
10069     value = instance->CallAsFunction(instance, 1, args);
10070     CHECK(value.IsEmpty());
10071     CHECK(try_catch.HasCaught());
10072     String::Utf8Value exception_value2(try_catch.Exception());
10073     CHECK_EQ(0, strcmp("TypeError: [object Object] is not a function",
10074                        *exception_value2));
10075     try_catch.Reset();
10076   }
10077
10078   {
10079     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10080     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10081     instance_template->SetCallAsFunctionHandler(ThrowValue);
10082     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10083     context->Global()->Set(v8_str("obj3"), instance);
10084     v8::TryCatch try_catch;
10085     Local<Value> value;
10086     CHECK(!try_catch.HasCaught());
10087
10088     // Catch the exception which is thrown by call-as-function handler
10089     value = CompileRun("obj3(22)");
10090     CHECK(try_catch.HasCaught());
10091     String::Utf8Value exception_value1(try_catch.Exception());
10092     CHECK_EQ(0, strcmp("22", *exception_value1));
10093     try_catch.Reset();
10094
10095     v8::Handle<Value> args[] = {v8_num(23)};
10096     value = instance->CallAsFunction(instance, 1, args);
10097     CHECK(try_catch.HasCaught());
10098     String::Utf8Value exception_value2(try_catch.Exception());
10099     CHECK_EQ(0, strcmp("23", *exception_value2));
10100     try_catch.Reset();
10101   }
10102
10103   {
10104     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10105     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10106     instance_template->SetCallAsFunctionHandler(ReturnThis);
10107     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10108
10109     Local<v8::Value> a1 =
10110         instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10111     CHECK(a1->StrictEquals(instance));
10112     Local<v8::Value> a2 = instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10113     CHECK(a2->StrictEquals(instance));
10114     Local<v8::Value> a3 = instance->CallAsFunction(v8_num(42), 0, NULL);
10115     CHECK(a3->StrictEquals(instance));
10116     Local<v8::Value> a4 = instance->CallAsFunction(v8_str("hello"), 0, NULL);
10117     CHECK(a4->StrictEquals(instance));
10118     Local<v8::Value> a5 = instance->CallAsFunction(v8::True(isolate), 0, NULL);
10119     CHECK(a5->StrictEquals(instance));
10120   }
10121
10122   {
10123     CompileRun(
10124         "function ReturnThisSloppy() {"
10125         "  return this;"
10126         "}"
10127         "function ReturnThisStrict() {"
10128         "  'use strict';"
10129         "  return this;"
10130         "}");
10131     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
10132         context->Global()->Get(v8_str("ReturnThisSloppy")));
10133     Local<Function> ReturnThisStrict = Local<Function>::Cast(
10134         context->Global()->Get(v8_str("ReturnThisStrict")));
10135
10136     Local<v8::Value> a1 =
10137         ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10138     CHECK(a1->StrictEquals(context->Global()));
10139     Local<v8::Value> a2 =
10140         ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10141     CHECK(a2->StrictEquals(context->Global()));
10142     Local<v8::Value> a3 = ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10143     CHECK(a3->IsNumberObject());
10144     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10145     Local<v8::Value> a4 =
10146         ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10147     CHECK(a4->IsStringObject());
10148     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10149     Local<v8::Value> a5 =
10150         ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10151     CHECK(a5->IsBooleanObject());
10152     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10153
10154     Local<v8::Value> a6 =
10155         ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10156     CHECK(a6->IsUndefined());
10157     Local<v8::Value> a7 =
10158         ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10159     CHECK(a7->IsNull());
10160     Local<v8::Value> a8 = ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10161     CHECK(a8->StrictEquals(v8_num(42)));
10162     Local<v8::Value> a9 =
10163         ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10164     CHECK(a9->StrictEquals(v8_str("hello")));
10165     Local<v8::Value> a10 =
10166         ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10167     CHECK(a10->StrictEquals(v8::True(isolate)));
10168   }
10169 }
10170
10171
10172 // Check whether a non-function object is callable.
10173 THREADED_TEST(CallableObject) {
10174   LocalContext context;
10175   v8::Isolate* isolate = context->GetIsolate();
10176   v8::HandleScope scope(isolate);
10177
10178   {
10179     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10180     instance_template->SetCallAsFunctionHandler(call_as_function);
10181     Local<Object> instance = instance_template->NewInstance();
10182     v8::TryCatch try_catch;
10183
10184     CHECK(instance->IsCallable());
10185     CHECK(!try_catch.HasCaught());
10186   }
10187
10188   {
10189     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10190     Local<Object> instance = instance_template->NewInstance();
10191     v8::TryCatch try_catch;
10192
10193     CHECK(!instance->IsCallable());
10194     CHECK(!try_catch.HasCaught());
10195   }
10196
10197   {
10198     Local<FunctionTemplate> function_template =
10199         FunctionTemplate::New(isolate, call_as_function);
10200     Local<Function> function = function_template->GetFunction();
10201     Local<Object> instance = function;
10202     v8::TryCatch try_catch;
10203
10204     CHECK(instance->IsCallable());
10205     CHECK(!try_catch.HasCaught());
10206   }
10207
10208   {
10209     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
10210     Local<Function> function = function_template->GetFunction();
10211     Local<Object> instance = function;
10212     v8::TryCatch try_catch;
10213
10214     CHECK(instance->IsCallable());
10215     CHECK(!try_catch.HasCaught());
10216   }
10217 }
10218
10219
10220 static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
10221   v8::HandleScope scope(isolate);
10222   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
10223   for (int i = 0; i < iterations; i++) {
10224     Local<v8::Number> n(v8::Integer::New(isolate, 42));
10225   }
10226   return Recurse(isolate, depth - 1, iterations);
10227 }
10228
10229
10230 THREADED_TEST(HandleIteration) {
10231   static const int kIterations = 500;
10232   static const int kNesting = 200;
10233   LocalContext context;
10234   v8::Isolate* isolate = context->GetIsolate();
10235   v8::HandleScope scope0(isolate);
10236   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10237   {
10238     v8::HandleScope scope1(isolate);
10239     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10240     for (int i = 0; i < kIterations; i++) {
10241       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
10242       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
10243     }
10244
10245     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
10246     {
10247       v8::HandleScope scope2(CcTest::isolate());
10248       for (int j = 0; j < kIterations; j++) {
10249         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
10250         CHECK_EQ(j + 1 + kIterations,
10251                  v8::HandleScope::NumberOfHandles(isolate));
10252       }
10253     }
10254     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
10255   }
10256   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10257   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
10258 }
10259
10260
10261 static void InterceptorCallICFastApi(
10262     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
10263   ApiTestFuzzer::Fuzz();
10264   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
10265   int* call_count =
10266       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
10267   ++(*call_count);
10268   if ((*call_count) % 20 == 0) {
10269     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
10270   }
10271 }
10272
10273 static void FastApiCallback_TrivialSignature(
10274     const v8::FunctionCallbackInfo<v8::Value>& args) {
10275   ApiTestFuzzer::Fuzz();
10276   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
10277   v8::Isolate* isolate = CcTest::isolate();
10278   CHECK_EQ(isolate, args.GetIsolate());
10279   CHECK(args.This()->Equals(args.Holder()));
10280   CHECK(args.Data()->Equals(v8_str("method_data")));
10281   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
10282 }
10283
10284 static void FastApiCallback_SimpleSignature(
10285     const v8::FunctionCallbackInfo<v8::Value>& args) {
10286   ApiTestFuzzer::Fuzz();
10287   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
10288   v8::Isolate* isolate = CcTest::isolate();
10289   CHECK_EQ(isolate, args.GetIsolate());
10290   CHECK(args.This()->GetPrototype()->Equals(args.Holder()));
10291   CHECK(args.Data()->Equals(v8_str("method_data")));
10292   // Note, we're using HasRealNamedProperty instead of Has to avoid
10293   // invoking the interceptor again.
10294   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
10295   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
10296 }
10297
10298
10299 // Helper to maximize the odds of object moving.
10300 static void GenerateSomeGarbage() {
10301   CompileRun(
10302       "var garbage;"
10303       "for (var i = 0; i < 1000; i++) {"
10304       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
10305       "}"
10306       "garbage = undefined;");
10307 }
10308
10309
10310 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
10311   static int count = 0;
10312   if (count++ % 3 == 0) {
10313     CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
10314         // This should move the stub
10315     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
10316   }
10317 }
10318
10319
10320 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
10321   LocalContext context;
10322   v8::Isolate* isolate = context->GetIsolate();
10323   v8::HandleScope scope(isolate);
10324   v8::Handle<v8::ObjectTemplate> nativeobject_templ =
10325       v8::ObjectTemplate::New(isolate);
10326   nativeobject_templ->Set(isolate, "callback",
10327                           v8::FunctionTemplate::New(isolate,
10328                                                     DirectApiCallback));
10329   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10330   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10331   // call the api function multiple times to ensure direct call stub creation.
10332   CompileRun(
10333         "function f() {"
10334         "  for (var i = 1; i <= 30; i++) {"
10335         "    nativeobject.callback();"
10336         "  }"
10337         "}"
10338         "f();");
10339 }
10340
10341
10342 void ThrowingDirectApiCallback(
10343     const v8::FunctionCallbackInfo<v8::Value>& args) {
10344   args.GetIsolate()->ThrowException(v8_str("g"));
10345 }
10346
10347
10348 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
10349   LocalContext context;
10350   v8::Isolate* isolate = context->GetIsolate();
10351   v8::HandleScope scope(isolate);
10352   v8::Handle<v8::ObjectTemplate> nativeobject_templ =
10353       v8::ObjectTemplate::New(isolate);
10354   nativeobject_templ->Set(isolate, "callback",
10355                           v8::FunctionTemplate::New(isolate,
10356                                                     ThrowingDirectApiCallback));
10357   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10358   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10359   // call the api function multiple times to ensure direct call stub creation.
10360   v8::Handle<Value> result = CompileRun(
10361       "var result = '';"
10362       "function f() {"
10363       "  for (var i = 1; i <= 5; i++) {"
10364       "    try { nativeobject.callback(); } catch (e) { result += e; }"
10365       "  }"
10366       "}"
10367       "f(); result;");
10368   CHECK(v8_str("ggggg")->Equals(result));
10369 }
10370
10371
10372 static int p_getter_count_3;
10373
10374
10375 static Handle<Value> DoDirectGetter() {
10376   if (++p_getter_count_3 % 3 == 0) {
10377     CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
10378     GenerateSomeGarbage();
10379   }
10380   return v8_str("Direct Getter Result");
10381 }
10382
10383
10384 static void DirectGetterCallback(
10385     Local<String> name,
10386     const v8::PropertyCallbackInfo<v8::Value>& info) {
10387   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
10388   info.GetReturnValue().Set(DoDirectGetter());
10389 }
10390
10391
10392 template<typename Accessor>
10393 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
10394   LocalContext context;
10395   v8::Isolate* isolate = context->GetIsolate();
10396   v8::HandleScope scope(isolate);
10397   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
10398   obj->SetAccessor(v8_str("p1"), accessor);
10399   context->Global()->Set(v8_str("o1"), obj->NewInstance());
10400   p_getter_count_3 = 0;
10401   v8::Handle<v8::Value> result = CompileRun(
10402       "function f() {"
10403       "  for (var i = 0; i < 30; i++) o1.p1;"
10404       "  return o1.p1"
10405       "}"
10406       "f();");
10407   CHECK(v8_str("Direct Getter Result")->Equals(result));
10408   CHECK_EQ(31, p_getter_count_3);
10409 }
10410
10411
10412 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
10413   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
10414 }
10415
10416
10417 void ThrowingDirectGetterCallback(
10418     Local<String> name,
10419     const v8::PropertyCallbackInfo<v8::Value>& info) {
10420   info.GetIsolate()->ThrowException(v8_str("g"));
10421 }
10422
10423
10424 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
10425   LocalContext context;
10426   v8::Isolate* isolate = context->GetIsolate();
10427   v8::HandleScope scope(isolate);
10428   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
10429   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
10430   context->Global()->Set(v8_str("o1"), obj->NewInstance());
10431   v8::Handle<Value> result = CompileRun(
10432       "var result = '';"
10433       "for (var i = 0; i < 5; i++) {"
10434       "    try { o1.p1; } catch (e) { result += e; }"
10435       "}"
10436       "result;");
10437   CHECK(v8_str("ggggg")->Equals(result));
10438 }
10439
10440
10441 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
10442   int interceptor_call_count = 0;
10443   v8::Isolate* isolate = CcTest::isolate();
10444   v8::HandleScope scope(isolate);
10445   v8::Handle<v8::FunctionTemplate> fun_templ =
10446       v8::FunctionTemplate::New(isolate);
10447   v8::Handle<v8::FunctionTemplate> method_templ =
10448       v8::FunctionTemplate::New(isolate,
10449                                 FastApiCallback_TrivialSignature,
10450                                 v8_str("method_data"),
10451                                 v8::Handle<v8::Signature>());
10452   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10453   proto_templ->Set(v8_str("method"), method_templ);
10454   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10455   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10456       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10457       v8::External::New(isolate, &interceptor_call_count)));
10458   LocalContext context;
10459   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10460   GenerateSomeGarbage();
10461   context->Global()->Set(v8_str("o"), fun->NewInstance());
10462   CompileRun(
10463       "var result = 0;"
10464       "for (var i = 0; i < 100; i++) {"
10465       "  result = o.method(41);"
10466       "}");
10467   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10468   CHECK_EQ(100, interceptor_call_count);
10469 }
10470
10471
10472 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
10473   int interceptor_call_count = 0;
10474   v8::Isolate* isolate = CcTest::isolate();
10475   v8::HandleScope scope(isolate);
10476   v8::Handle<v8::FunctionTemplate> fun_templ =
10477       v8::FunctionTemplate::New(isolate);
10478   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10479       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10480       v8::Signature::New(isolate, fun_templ));
10481   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10482   proto_templ->Set(v8_str("method"), method_templ);
10483   fun_templ->SetHiddenPrototype(true);
10484   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10485   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10486       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10487       v8::External::New(isolate, &interceptor_call_count)));
10488   LocalContext context;
10489   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10490   GenerateSomeGarbage();
10491   context->Global()->Set(v8_str("o"), fun->NewInstance());
10492   CompileRun(
10493       "o.foo = 17;"
10494       "var receiver = {};"
10495       "receiver.__proto__ = o;"
10496       "var result = 0;"
10497       "for (var i = 0; i < 100; i++) {"
10498       "  result = receiver.method(41);"
10499       "}");
10500   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10501   CHECK_EQ(100, interceptor_call_count);
10502 }
10503
10504
10505 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
10506   int interceptor_call_count = 0;
10507   v8::Isolate* isolate = CcTest::isolate();
10508   v8::HandleScope scope(isolate);
10509   v8::Handle<v8::FunctionTemplate> fun_templ =
10510       v8::FunctionTemplate::New(isolate);
10511   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10512       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10513       v8::Signature::New(isolate, fun_templ));
10514   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10515   proto_templ->Set(v8_str("method"), method_templ);
10516   fun_templ->SetHiddenPrototype(true);
10517   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10518   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10519       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10520       v8::External::New(isolate, &interceptor_call_count)));
10521   LocalContext context;
10522   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10523   GenerateSomeGarbage();
10524   context->Global()->Set(v8_str("o"), fun->NewInstance());
10525   CompileRun(
10526       "o.foo = 17;"
10527       "var receiver = {};"
10528       "receiver.__proto__ = o;"
10529       "var result = 0;"
10530       "var saved_result = 0;"
10531       "for (var i = 0; i < 100; i++) {"
10532       "  result = receiver.method(41);"
10533       "  if (i == 50) {"
10534       "    saved_result = result;"
10535       "    receiver = {method: function(x) { return x - 1 }};"
10536       "  }"
10537       "}");
10538   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10539   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10540   CHECK_GE(interceptor_call_count, 50);
10541 }
10542
10543
10544 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
10545   int interceptor_call_count = 0;
10546   v8::Isolate* isolate = CcTest::isolate();
10547   v8::HandleScope scope(isolate);
10548   v8::Handle<v8::FunctionTemplate> fun_templ =
10549       v8::FunctionTemplate::New(isolate);
10550   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10551       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10552       v8::Signature::New(isolate, fun_templ));
10553   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10554   proto_templ->Set(v8_str("method"), method_templ);
10555   fun_templ->SetHiddenPrototype(true);
10556   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10557   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10558       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10559       v8::External::New(isolate, &interceptor_call_count)));
10560   LocalContext context;
10561   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10562   GenerateSomeGarbage();
10563   context->Global()->Set(v8_str("o"), fun->NewInstance());
10564   CompileRun(
10565       "o.foo = 17;"
10566       "var receiver = {};"
10567       "receiver.__proto__ = o;"
10568       "var result = 0;"
10569       "var saved_result = 0;"
10570       "for (var i = 0; i < 100; i++) {"
10571       "  result = receiver.method(41);"
10572       "  if (i == 50) {"
10573       "    saved_result = result;"
10574       "    o.method = function(x) { return x - 1 };"
10575       "  }"
10576       "}");
10577   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10578   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10579   CHECK_GE(interceptor_call_count, 50);
10580 }
10581
10582
10583 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
10584   int interceptor_call_count = 0;
10585   v8::Isolate* isolate = CcTest::isolate();
10586   v8::HandleScope scope(isolate);
10587   v8::Handle<v8::FunctionTemplate> fun_templ =
10588       v8::FunctionTemplate::New(isolate);
10589   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10590       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10591       v8::Signature::New(isolate, fun_templ));
10592   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10593   proto_templ->Set(v8_str("method"), method_templ);
10594   fun_templ->SetHiddenPrototype(true);
10595   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10596   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10597       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10598       v8::External::New(isolate, &interceptor_call_count)));
10599   LocalContext context;
10600   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10601   GenerateSomeGarbage();
10602   context->Global()->Set(v8_str("o"), fun->NewInstance());
10603   v8::TryCatch try_catch;
10604   CompileRun(
10605       "o.foo = 17;"
10606       "var receiver = {};"
10607       "receiver.__proto__ = o;"
10608       "var result = 0;"
10609       "var saved_result = 0;"
10610       "for (var i = 0; i < 100; i++) {"
10611       "  result = receiver.method(41);"
10612       "  if (i == 50) {"
10613       "    saved_result = result;"
10614       "    receiver = 333;"
10615       "  }"
10616       "}");
10617   CHECK(try_catch.HasCaught());
10618   // TODO(verwaest): Adjust message.
10619   CHECK(v8_str("TypeError: receiver.method is not a function")
10620             ->Equals(try_catch.Exception()->ToString(isolate)));
10621   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10622   CHECK_GE(interceptor_call_count, 50);
10623 }
10624
10625
10626 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
10627   int interceptor_call_count = 0;
10628   v8::Isolate* isolate = CcTest::isolate();
10629   v8::HandleScope scope(isolate);
10630   v8::Handle<v8::FunctionTemplate> fun_templ =
10631       v8::FunctionTemplate::New(isolate);
10632   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10633       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10634       v8::Signature::New(isolate, fun_templ));
10635   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10636   proto_templ->Set(v8_str("method"), method_templ);
10637   fun_templ->SetHiddenPrototype(true);
10638   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10639   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10640       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10641       v8::External::New(isolate, &interceptor_call_count)));
10642   LocalContext context;
10643   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10644   GenerateSomeGarbage();
10645   context->Global()->Set(v8_str("o"), fun->NewInstance());
10646   v8::TryCatch try_catch;
10647   CompileRun(
10648       "o.foo = 17;"
10649       "var receiver = {};"
10650       "receiver.__proto__ = o;"
10651       "var result = 0;"
10652       "var saved_result = 0;"
10653       "for (var i = 0; i < 100; i++) {"
10654       "  result = receiver.method(41);"
10655       "  if (i == 50) {"
10656       "    saved_result = result;"
10657       "    receiver = {method: receiver.method};"
10658       "  }"
10659       "}");
10660   CHECK(try_catch.HasCaught());
10661   CHECK(v8_str("TypeError: Illegal invocation")
10662             ->Equals(try_catch.Exception()->ToString(isolate)));
10663   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10664   CHECK_GE(interceptor_call_count, 50);
10665 }
10666
10667
10668 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
10669   v8::Isolate* isolate = CcTest::isolate();
10670   v8::HandleScope scope(isolate);
10671   v8::Handle<v8::FunctionTemplate> fun_templ =
10672       v8::FunctionTemplate::New(isolate);
10673   v8::Handle<v8::FunctionTemplate> method_templ =
10674       v8::FunctionTemplate::New(isolate,
10675                                 FastApiCallback_TrivialSignature,
10676                                 v8_str("method_data"),
10677                                 v8::Handle<v8::Signature>());
10678   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10679   proto_templ->Set(v8_str("method"), method_templ);
10680   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10681   USE(templ);
10682   LocalContext context;
10683   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10684   GenerateSomeGarbage();
10685   context->Global()->Set(v8_str("o"), fun->NewInstance());
10686   CompileRun(
10687       "var result = 0;"
10688       "for (var i = 0; i < 100; i++) {"
10689       "  result = o.method(41);"
10690       "}");
10691
10692   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10693 }
10694
10695
10696 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
10697   v8::Isolate* isolate = CcTest::isolate();
10698   v8::HandleScope scope(isolate);
10699   v8::Handle<v8::FunctionTemplate> fun_templ =
10700       v8::FunctionTemplate::New(isolate);
10701   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10702       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10703       v8::Signature::New(isolate, fun_templ));
10704   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10705   proto_templ->Set(v8_str("method"), method_templ);
10706   fun_templ->SetHiddenPrototype(true);
10707   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10708   CHECK(!templ.IsEmpty());
10709   LocalContext context;
10710   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10711   GenerateSomeGarbage();
10712   context->Global()->Set(v8_str("o"), fun->NewInstance());
10713   CompileRun(
10714       "o.foo = 17;"
10715       "var receiver = {};"
10716       "receiver.__proto__ = o;"
10717       "var result = 0;"
10718       "for (var i = 0; i < 100; i++) {"
10719       "  result = receiver.method(41);"
10720       "}");
10721
10722   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10723 }
10724
10725
10726 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
10727   v8::Isolate* isolate = CcTest::isolate();
10728   v8::HandleScope scope(isolate);
10729   v8::Handle<v8::FunctionTemplate> fun_templ =
10730       v8::FunctionTemplate::New(isolate);
10731   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10732       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10733       v8::Signature::New(isolate, fun_templ));
10734   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10735   proto_templ->Set(v8_str("method"), method_templ);
10736   fun_templ->SetHiddenPrototype(true);
10737   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10738   CHECK(!templ.IsEmpty());
10739   LocalContext context;
10740   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10741   GenerateSomeGarbage();
10742   context->Global()->Set(v8_str("o"), fun->NewInstance());
10743   CompileRun(
10744       "o.foo = 17;"
10745       "var receiver = {};"
10746       "receiver.__proto__ = o;"
10747       "var result = 0;"
10748       "var saved_result = 0;"
10749       "for (var i = 0; i < 100; i++) {"
10750       "  result = receiver.method(41);"
10751       "  if (i == 50) {"
10752       "    saved_result = result;"
10753       "    receiver = {method: function(x) { return x - 1 }};"
10754       "  }"
10755       "}");
10756   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10757   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10758 }
10759
10760
10761 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
10762   v8::Isolate* isolate = CcTest::isolate();
10763   v8::HandleScope scope(isolate);
10764   v8::Handle<v8::FunctionTemplate> fun_templ =
10765       v8::FunctionTemplate::New(isolate);
10766   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10767       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10768       v8::Signature::New(isolate, fun_templ));
10769   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10770   proto_templ->Set(v8_str("method"), method_templ);
10771   fun_templ->SetHiddenPrototype(true);
10772   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10773   CHECK(!templ.IsEmpty());
10774   LocalContext context;
10775   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10776   GenerateSomeGarbage();
10777   context->Global()->Set(v8_str("o"), fun->NewInstance());
10778   v8::TryCatch try_catch;
10779   CompileRun(
10780       "o.foo = 17;"
10781       "var receiver = {};"
10782       "receiver.__proto__ = o;"
10783       "var result = 0;"
10784       "var saved_result = 0;"
10785       "for (var i = 0; i < 100; i++) {"
10786       "  result = receiver.method(41);"
10787       "  if (i == 50) {"
10788       "    saved_result = result;"
10789       "    receiver = 333;"
10790       "  }"
10791       "}");
10792   CHECK(try_catch.HasCaught());
10793   // TODO(verwaest): Adjust message.
10794   CHECK(v8_str("TypeError: receiver.method is not a function")
10795             ->Equals(try_catch.Exception()->ToString(isolate)));
10796   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10797 }
10798
10799
10800 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
10801   v8::Isolate* isolate = CcTest::isolate();
10802   v8::HandleScope scope(isolate);
10803   v8::Handle<v8::FunctionTemplate> fun_templ =
10804       v8::FunctionTemplate::New(isolate);
10805   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10806       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10807       v8::Signature::New(isolate, fun_templ));
10808   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10809   proto_templ->Set(v8_str("method"), method_templ);
10810   fun_templ->SetHiddenPrototype(true);
10811   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10812   CHECK(!templ.IsEmpty());
10813   LocalContext context;
10814   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10815   GenerateSomeGarbage();
10816   context->Global()->Set(v8_str("o"), fun->NewInstance());
10817   v8::TryCatch try_catch;
10818   CompileRun(
10819       "o.foo = 17;"
10820       "var receiver = {};"
10821       "receiver.__proto__ = o;"
10822       "var result = 0;"
10823       "var saved_result = 0;"
10824       "for (var i = 0; i < 100; i++) {"
10825       "  result = receiver.method(41);"
10826       "  if (i == 50) {"
10827       "    saved_result = result;"
10828       "    receiver = Object.create(receiver);"
10829       "  }"
10830       "}");
10831   CHECK(try_catch.HasCaught());
10832   CHECK(v8_str("TypeError: Illegal invocation")
10833             ->Equals(try_catch.Exception()->ToString(isolate)));
10834   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10835 }
10836
10837
10838 static void ThrowingGetter(Local<String> name,
10839                            const v8::PropertyCallbackInfo<v8::Value>& info) {
10840   ApiTestFuzzer::Fuzz();
10841   info.GetIsolate()->ThrowException(Handle<Value>());
10842   info.GetReturnValue().SetUndefined();
10843 }
10844
10845
10846 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
10847   LocalContext context;
10848   HandleScope scope(context->GetIsolate());
10849
10850   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
10851   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
10852   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
10853
10854   Local<Object> instance = templ->GetFunction()->NewInstance();
10855
10856   Local<Object> another = Object::New(context->GetIsolate());
10857   another->SetPrototype(instance);
10858
10859   Local<Object> with_js_getter = CompileRun(
10860       "o = {};\n"
10861       "o.__defineGetter__('f', function() { throw undefined; });\n"
10862       "o\n").As<Object>();
10863   CHECK(!with_js_getter.IsEmpty());
10864
10865   TryCatch try_catch;
10866
10867   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
10868   CHECK(try_catch.HasCaught());
10869   try_catch.Reset();
10870   CHECK(result.IsEmpty());
10871
10872   result = another->GetRealNamedProperty(v8_str("f"));
10873   CHECK(try_catch.HasCaught());
10874   try_catch.Reset();
10875   CHECK(result.IsEmpty());
10876
10877   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
10878   CHECK(try_catch.HasCaught());
10879   try_catch.Reset();
10880   CHECK(result.IsEmpty());
10881
10882   result = another->Get(v8_str("f"));
10883   CHECK(try_catch.HasCaught());
10884   try_catch.Reset();
10885   CHECK(result.IsEmpty());
10886
10887   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
10888   CHECK(try_catch.HasCaught());
10889   try_catch.Reset();
10890   CHECK(result.IsEmpty());
10891
10892   result = with_js_getter->Get(v8_str("f"));
10893   CHECK(try_catch.HasCaught());
10894   try_catch.Reset();
10895   CHECK(result.IsEmpty());
10896 }
10897
10898
10899 static void ThrowingCallbackWithTryCatch(
10900     const v8::FunctionCallbackInfo<v8::Value>& args) {
10901   TryCatch try_catch;
10902   // Verboseness is important: it triggers message delivery which can call into
10903   // external code.
10904   try_catch.SetVerbose(true);
10905   CompileRun("throw 'from JS';");
10906   CHECK(try_catch.HasCaught());
10907   CHECK(!CcTest::i_isolate()->has_pending_exception());
10908   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
10909 }
10910
10911
10912 static int call_depth;
10913
10914
10915 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
10916   TryCatch try_catch;
10917 }
10918
10919
10920 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
10921   if (--call_depth) CompileRun("throw 'ThrowInJS';");
10922 }
10923
10924
10925 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
10926   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
10927 }
10928
10929
10930 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
10931   Handle<String> errorMessageString = message->Get();
10932   CHECK(!errorMessageString.IsEmpty());
10933   message->GetStackTrace();
10934   message->GetScriptOrigin().ResourceName();
10935 }
10936
10937
10938 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
10939   LocalContext context;
10940   v8::Isolate* isolate = context->GetIsolate();
10941   HandleScope scope(isolate);
10942
10943   Local<Function> func =
10944       FunctionTemplate::New(isolate,
10945                             ThrowingCallbackWithTryCatch)->GetFunction();
10946   context->Global()->Set(v8_str("func"), func);
10947
10948   MessageCallback callbacks[] =
10949       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
10950   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
10951     MessageCallback callback = callbacks[i];
10952     if (callback != NULL) {
10953       V8::AddMessageListener(callback);
10954     }
10955     // Some small number to control number of times message handler should
10956     // throw an exception.
10957     call_depth = 5;
10958     ExpectFalse(
10959         "var thrown = false;\n"
10960         "try { func(); } catch(e) { thrown = true; }\n"
10961         "thrown\n");
10962     if (callback != NULL) {
10963       V8::RemoveMessageListeners(callback);
10964     }
10965   }
10966 }
10967
10968
10969 static void ParentGetter(Local<String> name,
10970                          const v8::PropertyCallbackInfo<v8::Value>& info) {
10971   ApiTestFuzzer::Fuzz();
10972   info.GetReturnValue().Set(v8_num(1));
10973 }
10974
10975
10976 static void ChildGetter(Local<String> name,
10977                         const v8::PropertyCallbackInfo<v8::Value>& info) {
10978   ApiTestFuzzer::Fuzz();
10979   info.GetReturnValue().Set(v8_num(42));
10980 }
10981
10982
10983 THREADED_TEST(Overriding) {
10984   LocalContext context;
10985   v8::Isolate* isolate = context->GetIsolate();
10986   v8::HandleScope scope(isolate);
10987
10988   // Parent template.
10989   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
10990   Local<ObjectTemplate> parent_instance_templ =
10991       parent_templ->InstanceTemplate();
10992   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
10993
10994   // Template that inherits from the parent template.
10995   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
10996   Local<ObjectTemplate> child_instance_templ =
10997       child_templ->InstanceTemplate();
10998   child_templ->Inherit(parent_templ);
10999   // Override 'f'.  The child version of 'f' should get called for child
11000   // instances.
11001   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
11002   // Add 'g' twice.  The 'g' added last should get called for instances.
11003   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
11004   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
11005
11006   // Add 'h' as an accessor to the proto template with ReadOnly attributes
11007   // so 'h' can be shadowed on the instance object.
11008   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
11009   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
11010       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
11011
11012   // Add 'i' as an accessor to the instance template with ReadOnly attributes
11013   // but the attribute does not have effect because it is duplicated with
11014   // NULL setter.
11015   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
11016       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
11017
11018
11019
11020   // Instantiate the child template.
11021   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
11022
11023   // Check that the child function overrides the parent one.
11024   context->Global()->Set(v8_str("o"), instance);
11025   Local<Value> value = v8_compile("o.f")->Run();
11026   // Check that the 'g' that was added last is hit.
11027   CHECK_EQ(42, value->Int32Value());
11028   value = v8_compile("o.g")->Run();
11029   CHECK_EQ(42, value->Int32Value());
11030
11031   // Check that 'h' cannot be shadowed.
11032   value = v8_compile("o.h = 3; o.h")->Run();
11033   CHECK_EQ(1, value->Int32Value());
11034
11035   // Check that 'i' cannot be shadowed or changed.
11036   value = v8_compile("o.i = 3; o.i")->Run();
11037   CHECK_EQ(42, value->Int32Value());
11038 }
11039
11040
11041 static void IsConstructHandler(
11042     const v8::FunctionCallbackInfo<v8::Value>& args) {
11043   ApiTestFuzzer::Fuzz();
11044   args.GetReturnValue().Set(args.IsConstructCall());
11045 }
11046
11047
11048 THREADED_TEST(IsConstructCall) {
11049   v8::Isolate* isolate = CcTest::isolate();
11050   v8::HandleScope scope(isolate);
11051
11052   // Function template with call handler.
11053   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11054   templ->SetCallHandler(IsConstructHandler);
11055
11056   LocalContext context;
11057
11058   context->Global()->Set(v8_str("f"), templ->GetFunction());
11059   Local<Value> value = v8_compile("f()")->Run();
11060   CHECK(!value->BooleanValue());
11061   value = v8_compile("new f()")->Run();
11062   CHECK(value->BooleanValue());
11063 }
11064
11065
11066 THREADED_TEST(ObjectProtoToString) {
11067   v8::Isolate* isolate = CcTest::isolate();
11068   v8::HandleScope scope(isolate);
11069   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11070   templ->SetClassName(v8_str("MyClass"));
11071
11072   LocalContext context;
11073
11074   Local<String> customized_tostring = v8_str("customized toString");
11075
11076   // Replace Object.prototype.toString
11077   v8_compile("Object.prototype.toString = function() {"
11078                   "  return 'customized toString';"
11079                   "}")->Run();
11080
11081   // Normal ToString call should call replaced Object.prototype.toString
11082   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
11083   Local<String> value = instance->ToString(isolate);
11084   CHECK(value->IsString() && value->Equals(customized_tostring));
11085
11086   // ObjectProtoToString should not call replace toString function.
11087   value = instance->ObjectProtoToString();
11088   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
11089
11090   // Check global
11091   value = context->Global()->ObjectProtoToString();
11092   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
11093
11094   // Check ordinary object
11095   Local<Value> object = v8_compile("new Object()")->Run();
11096   value = object.As<v8::Object>()->ObjectProtoToString();
11097   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11098 }
11099
11100
11101 TEST(ObjectProtoToStringES6) {
11102   // TODO(dslomov, caitp): merge into ObjectProtoToString test once shipped.
11103   i::FLAG_harmony_tostring = true;
11104   LocalContext context;
11105   v8::Isolate* isolate = CcTest::isolate();
11106   v8::HandleScope scope(isolate);
11107   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11108   templ->SetClassName(v8_str("MyClass"));
11109
11110   Local<String> customized_tostring = v8_str("customized toString");
11111
11112   // Replace Object.prototype.toString
11113   CompileRun(
11114       "Object.prototype.toString = function() {"
11115       "  return 'customized toString';"
11116       "}");
11117
11118   // Normal ToString call should call replaced Object.prototype.toString
11119   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
11120   Local<String> value = instance->ToString(isolate);
11121   CHECK(value->IsString() && value->Equals(customized_tostring));
11122
11123   // ObjectProtoToString should not call replace toString function.
11124   value = instance->ObjectProtoToString();
11125   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
11126
11127   // Check global
11128   value = context->Global()->ObjectProtoToString();
11129   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
11130
11131   // Check ordinary object
11132   Local<Value> object = CompileRun("new Object()");
11133   value = object.As<v8::Object>()->ObjectProtoToString();
11134   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11135
11136   // Check that ES6 semantics using @@toStringTag work
11137   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
11138
11139 #define TEST_TOSTRINGTAG(type, tag, expected)                \
11140   do {                                                       \
11141     object = CompileRun("new " #type "()");                  \
11142     object.As<v8::Object>()->Set(toStringTag, v8_str(#tag)); \
11143     value = object.As<v8::Object>()->ObjectProtoToString();  \
11144     CHECK(value->IsString() &&                               \
11145           value->Equals(v8_str("[object " #expected "]")));  \
11146   } while (0)
11147
11148   TEST_TOSTRINGTAG(Array, Object, Object);
11149   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
11150   TEST_TOSTRINGTAG(Object, Array, Array);
11151   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
11152   TEST_TOSTRINGTAG(Object, Date, Date);
11153   TEST_TOSTRINGTAG(Object, Error, Error);
11154   TEST_TOSTRINGTAG(Object, Function, Function);
11155   TEST_TOSTRINGTAG(Object, Number, Number);
11156   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
11157   TEST_TOSTRINGTAG(Object, String, String);
11158   TEST_TOSTRINGTAG(Object, Foo, Foo);
11159
11160 #undef TEST_TOSTRINGTAG
11161
11162   Local<v8::RegExp> valueRegExp = v8::RegExp::New(v8_str("^$"),
11163                                                   v8::RegExp::kNone);
11164   Local<Value> valueNumber = v8_num(123);
11165   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
11166   Local<v8::Function> valueFunction =
11167       CompileRun("(function fn() {})").As<v8::Function>();
11168   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
11169   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
11170   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
11171
11172 #define TEST_TOSTRINGTAG(type, tagValue, expected)          \
11173   do {                                                      \
11174     object = CompileRun("new " #type "()");                 \
11175     object.As<v8::Object>()->Set(toStringTag, tagValue);    \
11176     value = object.As<v8::Object>()->ObjectProtoToString(); \
11177     CHECK(value->IsString() &&                              \
11178           value->Equals(v8_str("[object " #expected "]"))); \
11179   } while (0)
11180
11181 #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
11182   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
11183   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
11184   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
11185   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
11186   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
11187   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
11188
11189   // Test non-String-valued @@toStringTag
11190   TEST_TOSTRINGTAG_TYPES(valueRegExp);
11191   TEST_TOSTRINGTAG_TYPES(valueNumber);
11192   TEST_TOSTRINGTAG_TYPES(valueSymbol);
11193   TEST_TOSTRINGTAG_TYPES(valueFunction);
11194   TEST_TOSTRINGTAG_TYPES(valueObject);
11195   TEST_TOSTRINGTAG_TYPES(valueNull);
11196   TEST_TOSTRINGTAG_TYPES(valueUndef);
11197
11198 #undef TEST_TOSTRINGTAG
11199 #undef TEST_TOSTRINGTAG_TYPES
11200
11201   // @@toStringTag getter throws
11202   Local<Value> obj = v8::Object::New(isolate);
11203   obj.As<v8::Object>()->SetAccessor(toStringTag, ThrowingSymbolAccessorGetter);
11204   {
11205     TryCatch try_catch;
11206     value = obj.As<v8::Object>()->ObjectProtoToString();
11207     CHECK(value.IsEmpty());
11208     CHECK(try_catch.HasCaught());
11209   }
11210
11211   // @@toStringTag getter does not throw
11212   obj = v8::Object::New(isolate);
11213   obj.As<v8::Object>()->SetAccessor(
11214       toStringTag, SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"));
11215   {
11216     TryCatch try_catch;
11217     value = obj.As<v8::Object>()->ObjectProtoToString();
11218     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11219     CHECK(!try_catch.HasCaught());
11220   }
11221
11222   // JS @@toStringTag value
11223   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
11224   {
11225     TryCatch try_catch;
11226     value = obj.As<v8::Object>()->ObjectProtoToString();
11227     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11228     CHECK(!try_catch.HasCaught());
11229   }
11230
11231   // JS @@toStringTag getter throws
11232   obj = CompileRun(
11233       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
11234       "  get: function() { throw 'Test'; }"
11235       "}); obj");
11236   {
11237     TryCatch try_catch;
11238     value = obj.As<v8::Object>()->ObjectProtoToString();
11239     CHECK(value.IsEmpty());
11240     CHECK(try_catch.HasCaught());
11241   }
11242
11243   // JS @@toStringTag getter does not throw
11244   obj = CompileRun(
11245       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
11246       "  get: function() { return 'Test'; }"
11247       "}); obj");
11248   {
11249     TryCatch try_catch;
11250     value = obj.As<v8::Object>()->ObjectProtoToString();
11251     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11252     CHECK(!try_catch.HasCaught());
11253   }
11254 }
11255
11256
11257 THREADED_TEST(ObjectGetConstructorName) {
11258   v8::Isolate* isolate = CcTest::isolate();
11259   LocalContext context;
11260   v8::HandleScope scope(isolate);
11261   v8_compile("function Parent() {};"
11262              "function Child() {};"
11263              "Child.prototype = new Parent();"
11264              "var outer = { inner: function() { } };"
11265              "var p = new Parent();"
11266              "var c = new Child();"
11267              "var x = new outer.inner();")->Run();
11268
11269   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
11270   CHECK(p->IsObject() &&
11271         p->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Parent")));
11272
11273   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
11274   CHECK(c->IsObject() &&
11275         c->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Child")));
11276
11277   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
11278   CHECK(x->IsObject() &&
11279         x->ToObject(isolate)->GetConstructorName()->Equals(
11280             v8_str("outer.inner")));
11281 }
11282
11283
11284 bool ApiTestFuzzer::fuzzing_ = false;
11285 v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
11286 int ApiTestFuzzer::active_tests_;
11287 int ApiTestFuzzer::tests_being_run_;
11288 int ApiTestFuzzer::current_;
11289
11290
11291 // We are in a callback and want to switch to another thread (if we
11292 // are currently running the thread fuzzing test).
11293 void ApiTestFuzzer::Fuzz() {
11294   if (!fuzzing_) return;
11295   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
11296   test->ContextSwitch();
11297 }
11298
11299
11300 // Let the next thread go.  Since it is also waiting on the V8 lock it may
11301 // not start immediately.
11302 bool ApiTestFuzzer::NextThread() {
11303   int test_position = GetNextTestNumber();
11304   const char* test_name = RegisterThreadedTest::nth(current_)->name();
11305   if (test_position == current_) {
11306     if (kLogThreading)
11307       printf("Stay with %s\n", test_name);
11308     return false;
11309   }
11310   if (kLogThreading) {
11311     printf("Switch from %s to %s\n",
11312            test_name,
11313            RegisterThreadedTest::nth(test_position)->name());
11314   }
11315   current_ = test_position;
11316   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
11317   return true;
11318 }
11319
11320
11321 void ApiTestFuzzer::Run() {
11322   // When it is our turn...
11323   gate_.Wait();
11324   {
11325     // ... get the V8 lock and start running the test.
11326     v8::Locker locker(CcTest::isolate());
11327     CallTest();
11328   }
11329   // This test finished.
11330   active_ = false;
11331   active_tests_--;
11332   // If it was the last then signal that fact.
11333   if (active_tests_ == 0) {
11334     all_tests_done_.Signal();
11335   } else {
11336     // Otherwise select a new test and start that.
11337     NextThread();
11338   }
11339 }
11340
11341
11342 static unsigned linear_congruential_generator;
11343
11344
11345 void ApiTestFuzzer::SetUp(PartOfTest part) {
11346   linear_congruential_generator = i::FLAG_testing_prng_seed;
11347   fuzzing_ = true;
11348   int count = RegisterThreadedTest::count();
11349   int start =  count * part / (LAST_PART + 1);
11350   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
11351   active_tests_ = tests_being_run_ = end - start + 1;
11352   for (int i = 0; i < tests_being_run_; i++) {
11353     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
11354   }
11355   for (int i = 0; i < active_tests_; i++) {
11356     RegisterThreadedTest::nth(i)->fuzzer_->Start();
11357   }
11358 }
11359
11360
11361 static void CallTestNumber(int test_number) {
11362   (RegisterThreadedTest::nth(test_number)->callback())();
11363 }
11364
11365
11366 void ApiTestFuzzer::RunAllTests() {
11367   // Set off the first test.
11368   current_ = -1;
11369   NextThread();
11370   // Wait till they are all done.
11371   all_tests_done_.Wait();
11372 }
11373
11374
11375 int ApiTestFuzzer::GetNextTestNumber() {
11376   int next_test;
11377   do {
11378     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
11379     linear_congruential_generator *= 1664525u;
11380     linear_congruential_generator += 1013904223u;
11381   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
11382   return next_test;
11383 }
11384
11385
11386 void ApiTestFuzzer::ContextSwitch() {
11387   // If the new thread is the same as the current thread there is nothing to do.
11388   if (NextThread()) {
11389     // Now it can start.
11390     v8::Unlocker unlocker(CcTest::isolate());
11391     // Wait till someone starts us again.
11392     gate_.Wait();
11393     // And we're off.
11394   }
11395 }
11396
11397
11398 void ApiTestFuzzer::TearDown() {
11399   fuzzing_ = false;
11400   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
11401     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
11402     if (fuzzer != NULL) fuzzer->Join();
11403   }
11404 }
11405
11406
11407 // Lets not be needlessly self-referential.
11408 TEST(Threading1) {
11409   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
11410   ApiTestFuzzer::RunAllTests();
11411   ApiTestFuzzer::TearDown();
11412 }
11413
11414
11415 TEST(Threading2) {
11416   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
11417   ApiTestFuzzer::RunAllTests();
11418   ApiTestFuzzer::TearDown();
11419 }
11420
11421
11422 TEST(Threading3) {
11423   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
11424   ApiTestFuzzer::RunAllTests();
11425   ApiTestFuzzer::TearDown();
11426 }
11427
11428
11429 TEST(Threading4) {
11430   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
11431   ApiTestFuzzer::RunAllTests();
11432   ApiTestFuzzer::TearDown();
11433 }
11434
11435
11436 void ApiTestFuzzer::CallTest() {
11437   v8::Isolate::Scope scope(CcTest::isolate());
11438   if (kLogThreading)
11439     printf("Start test %d\n", test_number_);
11440   CallTestNumber(test_number_);
11441   if (kLogThreading)
11442     printf("End test %d\n", test_number_);
11443 }
11444
11445
11446 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
11447   v8::Isolate* isolate = args.GetIsolate();
11448   CHECK(v8::Locker::IsLocked(isolate));
11449   ApiTestFuzzer::Fuzz();
11450   v8::Unlocker unlocker(isolate);
11451   const char* code = "throw 7;";
11452   {
11453     v8::Locker nested_locker(isolate);
11454     v8::HandleScope scope(isolate);
11455     v8::Handle<Value> exception;
11456     { v8::TryCatch try_catch;
11457       v8::Handle<Value> value = CompileRun(code);
11458       CHECK(value.IsEmpty());
11459       CHECK(try_catch.HasCaught());
11460       // Make sure to wrap the exception in a new handle because
11461       // the handle returned from the TryCatch is destroyed
11462       // when the TryCatch is destroyed.
11463       exception = Local<Value>::New(isolate, try_catch.Exception());
11464     }
11465     args.GetIsolate()->ThrowException(exception);
11466   }
11467 }
11468
11469
11470 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
11471   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
11472   ApiTestFuzzer::Fuzz();
11473   v8::Unlocker unlocker(CcTest::isolate());
11474   const char* code = "throw 7;";
11475   {
11476     v8::Locker nested_locker(CcTest::isolate());
11477     v8::HandleScope scope(args.GetIsolate());
11478     v8::Handle<Value> value = CompileRun(code);
11479     CHECK(value.IsEmpty());
11480     args.GetReturnValue().Set(v8_str("foo"));
11481   }
11482 }
11483
11484
11485 // These are locking tests that don't need to be run again
11486 // as part of the locking aggregation tests.
11487 TEST(NestedLockers) {
11488   v8::Isolate* isolate = CcTest::isolate();
11489   v8::Locker locker(isolate);
11490   CHECK(v8::Locker::IsLocked(isolate));
11491   LocalContext env;
11492   v8::HandleScope scope(env->GetIsolate());
11493   Local<v8::FunctionTemplate> fun_templ =
11494       v8::FunctionTemplate::New(isolate, ThrowInJS);
11495   Local<Function> fun = fun_templ->GetFunction();
11496   env->Global()->Set(v8_str("throw_in_js"), fun);
11497   Local<Script> script = v8_compile("(function () {"
11498                                     "  try {"
11499                                     "    throw_in_js();"
11500                                     "    return 42;"
11501                                     "  } catch (e) {"
11502                                     "    return e * 13;"
11503                                     "  }"
11504                                     "})();");
11505   CHECK_EQ(91, script->Run()->Int32Value());
11506 }
11507
11508
11509 // These are locking tests that don't need to be run again
11510 // as part of the locking aggregation tests.
11511 TEST(NestedLockersNoTryCatch) {
11512   v8::Locker locker(CcTest::isolate());
11513   LocalContext env;
11514   v8::HandleScope scope(env->GetIsolate());
11515   Local<v8::FunctionTemplate> fun_templ =
11516       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
11517   Local<Function> fun = fun_templ->GetFunction();
11518   env->Global()->Set(v8_str("throw_in_js"), fun);
11519   Local<Script> script = v8_compile("(function () {"
11520                                     "  try {"
11521                                     "    throw_in_js();"
11522                                     "    return 42;"
11523                                     "  } catch (e) {"
11524                                     "    return e * 13;"
11525                                     "  }"
11526                                     "})();");
11527   CHECK_EQ(91, script->Run()->Int32Value());
11528 }
11529
11530
11531 THREADED_TEST(RecursiveLocking) {
11532   v8::Locker locker(CcTest::isolate());
11533   {
11534     v8::Locker locker2(CcTest::isolate());
11535     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
11536   }
11537 }
11538
11539
11540 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
11541   ApiTestFuzzer::Fuzz();
11542   v8::Unlocker unlocker(CcTest::isolate());
11543 }
11544
11545
11546 THREADED_TEST(LockUnlockLock) {
11547   {
11548     v8::Locker locker(CcTest::isolate());
11549     v8::HandleScope scope(CcTest::isolate());
11550     LocalContext env;
11551     Local<v8::FunctionTemplate> fun_templ =
11552         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
11553     Local<Function> fun = fun_templ->GetFunction();
11554     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11555     Local<Script> script = v8_compile("(function () {"
11556                                       "  unlock_for_a_moment();"
11557                                       "  return 42;"
11558                                       "})();");
11559     CHECK_EQ(42, script->Run()->Int32Value());
11560   }
11561   {
11562     v8::Locker locker(CcTest::isolate());
11563     v8::HandleScope scope(CcTest::isolate());
11564     LocalContext env;
11565     Local<v8::FunctionTemplate> fun_templ =
11566         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
11567     Local<Function> fun = fun_templ->GetFunction();
11568     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11569     Local<Script> script = v8_compile("(function () {"
11570                                       "  unlock_for_a_moment();"
11571                                       "  return 42;"
11572                                       "})();");
11573     CHECK_EQ(42, script->Run()->Int32Value());
11574   }
11575 }
11576
11577
11578 static int GetGlobalObjectsCount() {
11579   int count = 0;
11580   i::HeapIterator it(CcTest::heap());
11581   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
11582     if (object->IsJSGlobalObject()) count++;
11583   return count;
11584 }
11585
11586
11587 static void CheckSurvivingGlobalObjectsCount(int expected) {
11588   // We need to collect all garbage twice to be sure that everything
11589   // has been collected.  This is because inline caches are cleared in
11590   // the first garbage collection but some of the maps have already
11591   // been marked at that point.  Therefore some of the maps are not
11592   // collected until the second garbage collection.
11593   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
11594   CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
11595   int count = GetGlobalObjectsCount();
11596 #ifdef DEBUG
11597   if (count != expected) CcTest::heap()->TracePathToGlobal();
11598 #endif
11599   CHECK_EQ(expected, count);
11600 }
11601
11602
11603 TEST(DontLeakGlobalObjects) {
11604   // Regression test for issues 1139850 and 1174891.
11605
11606   i::FLAG_expose_gc = true;
11607   v8::V8::Initialize();
11608
11609   for (int i = 0; i < 5; i++) {
11610     { v8::HandleScope scope(CcTest::isolate());
11611       LocalContext context;
11612     }
11613     CcTest::isolate()->ContextDisposedNotification();
11614     CheckSurvivingGlobalObjectsCount(0);
11615
11616     { v8::HandleScope scope(CcTest::isolate());
11617       LocalContext context;
11618       v8_compile("Date")->Run();
11619     }
11620     CcTest::isolate()->ContextDisposedNotification();
11621     CheckSurvivingGlobalObjectsCount(0);
11622
11623     { v8::HandleScope scope(CcTest::isolate());
11624       LocalContext context;
11625       v8_compile("/aaa/")->Run();
11626     }
11627     CcTest::isolate()->ContextDisposedNotification();
11628     CheckSurvivingGlobalObjectsCount(0);
11629
11630     { v8::HandleScope scope(CcTest::isolate());
11631       const char* extension_list[] = { "v8/gc" };
11632       v8::ExtensionConfiguration extensions(1, extension_list);
11633       LocalContext context(&extensions);
11634       v8_compile("gc();")->Run();
11635     }
11636     CcTest::isolate()->ContextDisposedNotification();
11637     CheckSurvivingGlobalObjectsCount(0);
11638   }
11639 }
11640
11641
11642 TEST(CopyablePersistent) {
11643   LocalContext context;
11644   v8::Isolate* isolate = context->GetIsolate();
11645   i::GlobalHandles* globals =
11646       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
11647   int initial_handles = globals->global_handles_count();
11648   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
11649       CopyableObject;
11650   {
11651     CopyableObject handle1;
11652     {
11653       v8::HandleScope scope(isolate);
11654       handle1.Reset(isolate, v8::Object::New(isolate));
11655     }
11656     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
11657     CopyableObject  handle2;
11658     handle2 = handle1;
11659     CHECK(handle1 == handle2);
11660     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
11661     CopyableObject handle3(handle2);
11662     CHECK(handle1 == handle3);
11663     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
11664   }
11665   // Verify autodispose
11666   CHECK_EQ(initial_handles, globals->global_handles_count());
11667 }
11668
11669
11670 static void WeakApiCallback(
11671     const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
11672   Local<Value> value = data.GetValue()->Get(v8_str("key"));
11673   CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
11674   data.GetParameter()->Reset();
11675   delete data.GetParameter();
11676 }
11677
11678
11679 TEST(WeakCallbackApi) {
11680   LocalContext context;
11681   v8::Isolate* isolate = context->GetIsolate();
11682   i::GlobalHandles* globals =
11683       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
11684   int initial_handles = globals->global_handles_count();
11685   {
11686     v8::HandleScope scope(isolate);
11687     v8::Local<v8::Object> obj = v8::Object::New(isolate);
11688     obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
11689     v8::Persistent<v8::Object>* handle =
11690         new v8::Persistent<v8::Object>(isolate, obj);
11691     handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
11692                                                              WeakApiCallback);
11693   }
11694   reinterpret_cast<i::Isolate*>(isolate)->heap()->
11695       CollectAllGarbage(i::Heap::kNoGCFlags);
11696   // Verify disposed.
11697   CHECK_EQ(initial_handles, globals->global_handles_count());
11698 }
11699
11700
11701 v8::Persistent<v8::Object> some_object;
11702 v8::Persistent<v8::Object> bad_handle;
11703
11704 void NewPersistentHandleCallback(
11705     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
11706   v8::HandleScope scope(data.GetIsolate());
11707   bad_handle.Reset(data.GetIsolate(), some_object);
11708   data.GetParameter()->Reset();
11709 }
11710
11711
11712 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
11713   LocalContext context;
11714   v8::Isolate* isolate = context->GetIsolate();
11715
11716   v8::Persistent<v8::Object> handle1, handle2;
11717   {
11718     v8::HandleScope scope(isolate);
11719     some_object.Reset(isolate, v8::Object::New(isolate));
11720     handle1.Reset(isolate, v8::Object::New(isolate));
11721     handle2.Reset(isolate, v8::Object::New(isolate));
11722   }
11723   // Note: order is implementation dependent alas: currently
11724   // global handle nodes are processed by PostGarbageCollectionProcessing
11725   // in reverse allocation order, so if second allocated handle is deleted,
11726   // weak callback of the first handle would be able to 'reallocate' it.
11727   handle1.SetWeak(&handle1, NewPersistentHandleCallback);
11728   handle2.Reset();
11729   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
11730 }
11731
11732
11733 v8::Persistent<v8::Object> to_be_disposed;
11734
11735 void DisposeAndForceGcCallback(
11736     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
11737   to_be_disposed.Reset();
11738   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
11739   data.GetParameter()->Reset();
11740 }
11741
11742
11743 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
11744   LocalContext context;
11745   v8::Isolate* isolate = context->GetIsolate();
11746
11747   v8::Persistent<v8::Object> handle1, handle2;
11748   {
11749     v8::HandleScope scope(isolate);
11750     handle1.Reset(isolate, v8::Object::New(isolate));
11751     handle2.Reset(isolate, v8::Object::New(isolate));
11752   }
11753   handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
11754   to_be_disposed.Reset(isolate, handle2);
11755   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
11756 }
11757
11758 void DisposingCallback(
11759     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
11760   data.GetParameter()->Reset();
11761 }
11762
11763 void HandleCreatingCallback(
11764     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
11765   v8::HandleScope scope(data.GetIsolate());
11766   v8::Persistent<v8::Object>(data.GetIsolate(),
11767                              v8::Object::New(data.GetIsolate()));
11768   data.GetParameter()->Reset();
11769 }
11770
11771
11772 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
11773   LocalContext context;
11774   v8::Isolate* isolate = context->GetIsolate();
11775
11776   v8::Persistent<v8::Object> handle1, handle2, handle3;
11777   {
11778     v8::HandleScope scope(isolate);
11779     handle3.Reset(isolate, v8::Object::New(isolate));
11780     handle2.Reset(isolate, v8::Object::New(isolate));
11781     handle1.Reset(isolate, v8::Object::New(isolate));
11782   }
11783   handle2.SetWeak(&handle2, DisposingCallback);
11784   handle3.SetWeak(&handle3, HandleCreatingCallback);
11785   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
11786 }
11787
11788
11789 THREADED_TEST(CheckForCrossContextObjectLiterals) {
11790   v8::V8::Initialize();
11791
11792   const int nof = 2;
11793   const char* sources[nof] = {
11794     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
11795     "Object()"
11796   };
11797
11798   for (int i = 0; i < nof; i++) {
11799     const char* source = sources[i];
11800     { v8::HandleScope scope(CcTest::isolate());
11801       LocalContext context;
11802       CompileRun(source);
11803     }
11804     { v8::HandleScope scope(CcTest::isolate());
11805       LocalContext context;
11806       CompileRun(source);
11807     }
11808   }
11809 }
11810
11811
11812 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
11813   v8::EscapableHandleScope inner(env->GetIsolate());
11814   env->Enter();
11815   v8::Local<Value> three = v8_num(3);
11816   v8::Local<Value> value = inner.Escape(three);
11817   env->Exit();
11818   return value;
11819 }
11820
11821
11822 THREADED_TEST(NestedHandleScopeAndContexts) {
11823   v8::Isolate* isolate = CcTest::isolate();
11824   v8::HandleScope outer(isolate);
11825   v8::Local<Context> env = Context::New(isolate);
11826   env->Enter();
11827   v8::Handle<Value> value = NestedScope(env);
11828   v8::Handle<String> str(value->ToString(isolate));
11829   CHECK(!str.IsEmpty());
11830   env->Exit();
11831 }
11832
11833
11834 static bool MatchPointers(void* key1, void* key2) {
11835   return key1 == key2;
11836 }
11837
11838
11839 struct SymbolInfo {
11840   size_t id;
11841   size_t size;
11842   std::string name;
11843 };
11844
11845
11846 class SetFunctionEntryHookTest {
11847  public:
11848   SetFunctionEntryHookTest() {
11849     CHECK(instance_ == NULL);
11850     instance_ = this;
11851   }
11852   ~SetFunctionEntryHookTest() {
11853     CHECK(instance_ == this);
11854     instance_ = NULL;
11855   }
11856   void Reset() {
11857     symbols_.clear();
11858     symbol_locations_.clear();
11859     invocations_.clear();
11860   }
11861   void RunTest();
11862   void OnJitEvent(const v8::JitCodeEvent* event);
11863   static void JitEvent(const v8::JitCodeEvent* event) {
11864     CHECK(instance_ != NULL);
11865     instance_->OnJitEvent(event);
11866   }
11867
11868   void OnEntryHook(uintptr_t function,
11869                    uintptr_t return_addr_location);
11870   static void EntryHook(uintptr_t function,
11871                         uintptr_t return_addr_location) {
11872     CHECK(instance_ != NULL);
11873     instance_->OnEntryHook(function, return_addr_location);
11874   }
11875
11876   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
11877     CHECK(instance_ != NULL);
11878     args.GetReturnValue().Set(v8_num(42));
11879   }
11880   void RunLoopInNewEnv(v8::Isolate* isolate);
11881
11882   // Records addr as location of symbol.
11883   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
11884
11885   // Finds the symbol containing addr
11886   SymbolInfo* FindSymbolForAddr(i::Address addr);
11887   // Returns the number of invocations where the caller name contains
11888   // \p caller_name and the function name contains \p function_name.
11889   int CountInvocations(const char* caller_name,
11890                        const char* function_name);
11891
11892   i::Handle<i::JSFunction> foo_func_;
11893   i::Handle<i::JSFunction> bar_func_;
11894
11895   typedef std::map<size_t, SymbolInfo> SymbolMap;
11896   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
11897   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
11898   SymbolMap symbols_;
11899   SymbolLocationMap symbol_locations_;
11900   InvocationMap invocations_;
11901
11902   static SetFunctionEntryHookTest* instance_;
11903 };
11904 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
11905
11906
11907 // Returns true if addr is in the range [start, start+len).
11908 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
11909   if (start <= addr && start + len > addr)
11910     return true;
11911
11912   return false;
11913 }
11914
11915 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
11916                                               SymbolInfo* symbol) {
11917   // Insert the symbol at the new location.
11918   SymbolLocationMap::iterator it =
11919       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
11920   // Now erase symbols to the left and right that overlap this one.
11921   while (it != symbol_locations_.begin()) {
11922     SymbolLocationMap::iterator left = it;
11923     --left;
11924     if (!Overlaps(left->first, left->second->size, addr))
11925       break;
11926     symbol_locations_.erase(left);
11927   }
11928
11929   // Now erase symbols to the left and right that overlap this one.
11930   while (true) {
11931     SymbolLocationMap::iterator right = it;
11932     ++right;
11933     if (right == symbol_locations_.end())
11934         break;
11935     if (!Overlaps(addr, symbol->size, right->first))
11936       break;
11937     symbol_locations_.erase(right);
11938   }
11939 }
11940
11941
11942 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
11943   switch (event->type) {
11944     case v8::JitCodeEvent::CODE_ADDED: {
11945         CHECK(event->code_start != NULL);
11946         CHECK_NE(0, static_cast<int>(event->code_len));
11947         CHECK(event->name.str != NULL);
11948         size_t symbol_id = symbols_.size();
11949
11950         // Record the new symbol.
11951         SymbolInfo& info = symbols_[symbol_id];
11952         info.id = symbol_id;
11953         info.size = event->code_len;
11954         info.name.assign(event->name.str, event->name.str + event->name.len);
11955
11956         // And record it's location.
11957         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
11958       }
11959       break;
11960
11961     case v8::JitCodeEvent::CODE_MOVED: {
11962         // We would like to never see code move that we haven't seen before,
11963         // but the code creation event does not happen until the line endings
11964         // have been calculated (this is so that we can report the line in the
11965         // script at which the function source is found, see
11966         // Compiler::RecordFunctionCompilation) and the line endings
11967         // calculations can cause a GC, which can move the newly created code
11968         // before its existence can be logged.
11969         SymbolLocationMap::iterator it(
11970             symbol_locations_.find(
11971                 reinterpret_cast<i::Address>(event->code_start)));
11972         if (it != symbol_locations_.end()) {
11973           // Found a symbol at this location, move it.
11974           SymbolInfo* info = it->second;
11975           symbol_locations_.erase(it);
11976           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
11977                          info);
11978         }
11979       }
11980     default:
11981       break;
11982   }
11983 }
11984
11985 void SetFunctionEntryHookTest::OnEntryHook(
11986     uintptr_t function, uintptr_t return_addr_location) {
11987   // Get the function's code object.
11988   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
11989       reinterpret_cast<i::Address>(function));
11990   CHECK(function_code != NULL);
11991
11992   // Then try and look up the caller's code object.
11993   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
11994
11995   // Count the invocation.
11996   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
11997   SymbolInfo* function_symbol =
11998       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
11999   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
12000
12001   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
12002     // Check that we have a symbol for the "bar" function at the right location.
12003     SymbolLocationMap::iterator it(
12004         symbol_locations_.find(function_code->instruction_start()));
12005     CHECK(it != symbol_locations_.end());
12006   }
12007
12008   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
12009     // Check that we have a symbol for "foo" at the right location.
12010     SymbolLocationMap::iterator it(
12011         symbol_locations_.find(function_code->instruction_start()));
12012     CHECK(it != symbol_locations_.end());
12013   }
12014 }
12015
12016
12017 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
12018   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
12019   // Do we have a direct hit on a symbol?
12020   if (it != symbol_locations_.end()) {
12021     if (it->first == addr)
12022       return it->second;
12023   }
12024
12025   // If not a direct hit, it'll have to be the previous symbol.
12026   if (it == symbol_locations_.begin())
12027     return NULL;
12028
12029   --it;
12030   size_t offs = addr - it->first;
12031   if (offs < it->second->size)
12032     return it->second;
12033
12034   return NULL;
12035 }
12036
12037
12038 int SetFunctionEntryHookTest::CountInvocations(
12039     const char* caller_name, const char* function_name) {
12040   InvocationMap::iterator it(invocations_.begin());
12041   int invocations = 0;
12042   for (; it != invocations_.end(); ++it) {
12043     SymbolInfo* caller = it->first.first;
12044     SymbolInfo* function = it->first.second;
12045
12046     // Filter out non-matching functions.
12047     if (function_name != NULL) {
12048       if (function->name.find(function_name) == std::string::npos)
12049         continue;
12050     }
12051
12052     // Filter out non-matching callers.
12053     if (caller_name != NULL) {
12054       if (caller == NULL)
12055         continue;
12056       if (caller->name.find(caller_name) == std::string::npos)
12057         continue;
12058     }
12059
12060     // It matches add the invocation count to the tally.
12061     invocations += it->second;
12062   }
12063
12064   return invocations;
12065 }
12066
12067
12068 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
12069   v8::HandleScope outer(isolate);
12070   v8::Local<Context> env = Context::New(isolate);
12071   env->Enter();
12072
12073   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
12074   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
12075   env->Global()->Set(v8_str("obj"), t->NewInstance());
12076
12077   const char* script =
12078       "function bar() {\n"
12079       "  var sum = 0;\n"
12080       "  for (i = 0; i < 100; ++i)\n"
12081       "    sum = foo(i);\n"
12082       "  return sum;\n"
12083       "}\n"
12084       "function foo(i) { return i * i; }\n"
12085       "// Invoke on the runtime function.\n"
12086       "obj.asdf()";
12087   CompileRun(script);
12088   bar_func_ = i::Handle<i::JSFunction>::cast(
12089           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
12090   DCHECK(!bar_func_.is_null());
12091
12092   foo_func_ =
12093       i::Handle<i::JSFunction>::cast(
12094            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
12095   DCHECK(!foo_func_.is_null());
12096
12097   v8::Handle<v8::Value> value = CompileRun("bar();");
12098   CHECK(value->IsNumber());
12099   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
12100
12101   // Test the optimized codegen path.
12102   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
12103                      "bar();");
12104   CHECK(value->IsNumber());
12105   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
12106
12107   env->Exit();
12108 }
12109
12110
12111 void SetFunctionEntryHookTest::RunTest() {
12112   // Work in a new isolate throughout.
12113   v8::Isolate::CreateParams create_params;
12114   create_params.entry_hook = EntryHook;
12115   create_params.code_event_handler = JitEvent;
12116   v8::Isolate* isolate = v8::Isolate::New(create_params);
12117
12118   {
12119     v8::Isolate::Scope scope(isolate);
12120
12121     RunLoopInNewEnv(isolate);
12122
12123     // Check the exepected invocation counts.
12124     CHECK_EQ(2, CountInvocations(NULL, "bar"));
12125     CHECK_EQ(200, CountInvocations("bar", "foo"));
12126     CHECK_EQ(200, CountInvocations(NULL, "foo"));
12127
12128     // Verify that we have an entry hook on some specific stubs.
12129     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
12130     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
12131     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
12132   }
12133   isolate->Dispose();
12134
12135   Reset();
12136
12137   // Make sure a second isolate is unaffected by the previous entry hook.
12138   isolate = v8::Isolate::New();
12139   {
12140     v8::Isolate::Scope scope(isolate);
12141
12142     // Reset the entry count to zero and set the entry hook.
12143     RunLoopInNewEnv(isolate);
12144
12145     // We should record no invocations in this isolate.
12146     CHECK_EQ(0, static_cast<int>(invocations_.size()));
12147   }
12148
12149   isolate->Dispose();
12150 }
12151
12152
12153 TEST(SetFunctionEntryHook) {
12154   // FunctionEntryHook does not work well with experimental natives.
12155   // Experimental natives are compiled during snapshot deserialization.
12156   // This test breaks because InstallGetter (function from snapshot that
12157   // only gets called from experimental natives) is compiled with entry hooks.
12158   i::FLAG_allow_natives_syntax = true;
12159   i::FLAG_use_inlining = false;
12160
12161   SetFunctionEntryHookTest test;
12162   test.RunTest();
12163 }
12164
12165
12166 static i::HashMap* code_map = NULL;
12167 static i::HashMap* jitcode_line_info = NULL;
12168 static int saw_bar = 0;
12169 static int move_events = 0;
12170
12171
12172 static bool FunctionNameIs(const char* expected,
12173                            const v8::JitCodeEvent* event) {
12174   // Log lines for functions are of the general form:
12175   // "LazyCompile:<type><function_name>", where the type is one of
12176   // "*", "~" or "".
12177   static const char kPreamble[] = "LazyCompile:";
12178   static size_t kPreambleLen = sizeof(kPreamble) - 1;
12179
12180   if (event->name.len < sizeof(kPreamble) - 1 ||
12181       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
12182     return false;
12183   }
12184
12185   const char* tail = event->name.str + kPreambleLen;
12186   size_t tail_len = event->name.len - kPreambleLen;
12187   size_t expected_len = strlen(expected);
12188   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
12189     --tail_len;
12190     ++tail;
12191   }
12192
12193   // Check for tails like 'bar :1'.
12194   if (tail_len > expected_len + 2 &&
12195       tail[expected_len] == ' ' &&
12196       tail[expected_len + 1] == ':' &&
12197       tail[expected_len + 2] &&
12198       !strncmp(tail, expected, expected_len)) {
12199     return true;
12200   }
12201
12202   if (tail_len != expected_len)
12203     return false;
12204
12205   return strncmp(tail, expected, expected_len) == 0;
12206 }
12207
12208
12209 static void event_handler(const v8::JitCodeEvent* event) {
12210   CHECK(event != NULL);
12211   CHECK(code_map != NULL);
12212   CHECK(jitcode_line_info != NULL);
12213
12214   class DummyJitCodeLineInfo {
12215   };
12216
12217   switch (event->type) {
12218     case v8::JitCodeEvent::CODE_ADDED: {
12219         CHECK(event->code_start != NULL);
12220         CHECK_NE(0, static_cast<int>(event->code_len));
12221         CHECK(event->name.str != NULL);
12222         i::HashMap::Entry* entry =
12223             code_map->Lookup(event->code_start,
12224                              i::ComputePointerHash(event->code_start),
12225                              true);
12226         entry->value = reinterpret_cast<void*>(event->code_len);
12227
12228         if (FunctionNameIs("bar", event)) {
12229           ++saw_bar;
12230         }
12231       }
12232       break;
12233
12234     case v8::JitCodeEvent::CODE_MOVED: {
12235         uint32_t hash = i::ComputePointerHash(event->code_start);
12236         // We would like to never see code move that we haven't seen before,
12237         // but the code creation event does not happen until the line endings
12238         // have been calculated (this is so that we can report the line in the
12239         // script at which the function source is found, see
12240         // Compiler::RecordFunctionCompilation) and the line endings
12241         // calculations can cause a GC, which can move the newly created code
12242         // before its existence can be logged.
12243         i::HashMap::Entry* entry =
12244             code_map->Lookup(event->code_start, hash, false);
12245         if (entry != NULL) {
12246           ++move_events;
12247
12248           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
12249           code_map->Remove(event->code_start, hash);
12250
12251           entry = code_map->Lookup(event->new_code_start,
12252                                    i::ComputePointerHash(event->new_code_start),
12253                                    true);
12254           CHECK(entry != NULL);
12255           entry->value = reinterpret_cast<void*>(event->code_len);
12256         }
12257       }
12258       break;
12259
12260     case v8::JitCodeEvent::CODE_REMOVED:
12261       // Object/code removal events are currently not dispatched from the GC.
12262       CHECK(false);
12263       break;
12264
12265     // For CODE_START_LINE_INFO_RECORDING event, we will create one
12266     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
12267     // record it in jitcode_line_info.
12268     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
12269         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
12270         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
12271         temp_event->user_data = line_info;
12272         i::HashMap::Entry* entry =
12273             jitcode_line_info->Lookup(line_info,
12274                                       i::ComputePointerHash(line_info),
12275                                       true);
12276         entry->value = reinterpret_cast<void*>(line_info);
12277       }
12278       break;
12279     // For these two events, we will check whether the event->user_data
12280     // data structure is created before during CODE_START_LINE_INFO_RECORDING
12281     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
12282     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
12283         CHECK(event->user_data != NULL);
12284         uint32_t hash = i::ComputePointerHash(event->user_data);
12285         i::HashMap::Entry* entry =
12286             jitcode_line_info->Lookup(event->user_data, hash, false);
12287         CHECK(entry != NULL);
12288         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
12289       }
12290       break;
12291
12292     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
12293         CHECK(event->user_data != NULL);
12294         uint32_t hash = i::ComputePointerHash(event->user_data);
12295         i::HashMap::Entry* entry =
12296             jitcode_line_info->Lookup(event->user_data, hash, false);
12297         CHECK(entry != NULL);
12298       }
12299       break;
12300
12301     default:
12302       // Impossible event.
12303       CHECK(false);
12304       break;
12305   }
12306 }
12307
12308
12309 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
12310   i::FLAG_stress_compaction = true;
12311   i::FLAG_incremental_marking = false;
12312   if (i::FLAG_never_compact) return;
12313   const char* script =
12314       "function bar() {"
12315       "  var sum = 0;"
12316       "  for (i = 0; i < 10; ++i)"
12317       "    sum = foo(i);"
12318       "  return sum;"
12319       "}"
12320       "function foo(i) { return i; };"
12321       "bar();";
12322
12323   // Run this test in a new isolate to make sure we don't
12324   // have remnants of state from other code.
12325   v8::Isolate* isolate = v8::Isolate::New();
12326   isolate->Enter();
12327   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
12328   i::Heap* heap = i_isolate->heap();
12329
12330   // Start with a clean slate.
12331   heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
12332
12333   {
12334     v8::HandleScope scope(isolate);
12335     i::HashMap code(MatchPointers);
12336     code_map = &code;
12337
12338     i::HashMap lineinfo(MatchPointers);
12339     jitcode_line_info = &lineinfo;
12340
12341     saw_bar = 0;
12342     move_events = 0;
12343
12344     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
12345
12346     // Generate new code objects sparsely distributed across several
12347     // different fragmented code-space pages.
12348     const int kIterations = 10;
12349     for (int i = 0; i < kIterations; ++i) {
12350       LocalContext env(isolate);
12351       i::AlwaysAllocateScope always_allocate(i_isolate);
12352       SimulateFullSpace(heap->code_space());
12353       CompileRun(script);
12354
12355       // Keep a strong reference to the code object in the handle scope.
12356       i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
12357           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
12358       i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
12359           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
12360
12361       // Clear the compilation cache to get more wastage.
12362       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
12363     }
12364
12365     // Force code movement.
12366     heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
12367
12368     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
12369
12370     CHECK_LE(kIterations, saw_bar);
12371     CHECK_LT(0, move_events);
12372
12373     code_map = NULL;
12374     jitcode_line_info = NULL;
12375   }
12376
12377   isolate->Exit();
12378   isolate->Dispose();
12379
12380   // Do this in a new isolate.
12381   isolate = v8::Isolate::New();
12382   isolate->Enter();
12383
12384   // Verify that we get callbacks for existing code objects when we
12385   // request enumeration of existing code.
12386   {
12387     v8::HandleScope scope(isolate);
12388     LocalContext env(isolate);
12389     CompileRun(script);
12390
12391     // Now get code through initial iteration.
12392     i::HashMap code(MatchPointers);
12393     code_map = &code;
12394
12395     i::HashMap lineinfo(MatchPointers);
12396     jitcode_line_info = &lineinfo;
12397
12398     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
12399                                     event_handler);
12400     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
12401
12402     jitcode_line_info = NULL;
12403     // We expect that we got some events. Note that if we could get code removal
12404     // notifications, we could compare two collections, one created by listening
12405     // from the time of creation of an isolate, and the other by subscribing
12406     // with EnumExisting.
12407     CHECK_LT(0u, code.occupancy());
12408
12409     code_map = NULL;
12410   }
12411
12412   isolate->Exit();
12413   isolate->Dispose();
12414 }
12415
12416
12417 THREADED_TEST(ExternalAllocatedMemory) {
12418   v8::Isolate* isolate = CcTest::isolate();
12419   v8::HandleScope outer(isolate);
12420   v8::Local<Context> env(Context::New(isolate));
12421   CHECK(!env.IsEmpty());
12422   const int64_t kSize = 1024*1024;
12423   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
12424   CHECK_EQ(baseline + kSize,
12425            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
12426   CHECK_EQ(baseline,
12427            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
12428   const int64_t kTriggerGCSize =
12429       v8::internal::Internals::kExternalAllocationLimit + 1;
12430   CHECK_EQ(baseline + kTriggerGCSize,
12431            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
12432   CHECK_EQ(baseline,
12433            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
12434 }
12435
12436
12437 // Regression test for issue 54, object templates with internal fields
12438 // but no accessors or interceptors did not get their internal field
12439 // count set on instances.
12440 THREADED_TEST(Regress54) {
12441   LocalContext context;
12442   v8::Isolate* isolate = context->GetIsolate();
12443   v8::HandleScope outer(isolate);
12444   static v8::Persistent<v8::ObjectTemplate> templ;
12445   if (templ.IsEmpty()) {
12446     v8::EscapableHandleScope inner(isolate);
12447     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
12448     local->SetInternalFieldCount(1);
12449     templ.Reset(isolate, inner.Escape(local));
12450   }
12451   v8::Handle<v8::Object> result =
12452       v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
12453   CHECK_EQ(1, result->InternalFieldCount());
12454 }
12455
12456
12457 // If part of the threaded tests, this test makes ThreadingTest fail
12458 // on mac.
12459 TEST(CatchStackOverflow) {
12460   LocalContext context;
12461   v8::HandleScope scope(context->GetIsolate());
12462   v8::TryCatch try_catch;
12463   v8::Handle<v8::Value> result = CompileRun(
12464     "function f() {"
12465     "  return f();"
12466     "}"
12467     ""
12468     "f();");
12469   CHECK(result.IsEmpty());
12470 }
12471
12472
12473 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
12474                                     const char* resource_name,
12475                                     int line_offset) {
12476   v8::HandleScope scope(CcTest::isolate());
12477   v8::TryCatch try_catch;
12478   v8::Handle<v8::Value> result = script->Run();
12479   CHECK(result.IsEmpty());
12480   CHECK(try_catch.HasCaught());
12481   v8::Handle<v8::Message> message = try_catch.Message();
12482   CHECK(!message.IsEmpty());
12483   CHECK_EQ(10 + line_offset, message->GetLineNumber());
12484   CHECK_EQ(91, message->GetStartPosition());
12485   CHECK_EQ(92, message->GetEndPosition());
12486   CHECK_EQ(2, message->GetStartColumn());
12487   CHECK_EQ(3, message->GetEndColumn());
12488   v8::String::Utf8Value line(message->GetSourceLine());
12489   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
12490   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
12491   CHECK_EQ(0, strcmp(resource_name, *name));
12492 }
12493
12494
12495 THREADED_TEST(TryCatchSourceInfo) {
12496   LocalContext context;
12497   v8::HandleScope scope(context->GetIsolate());
12498   v8::Local<v8::String> source = v8_str(
12499       "function Foo() {\n"
12500       "  return Bar();\n"
12501       "}\n"
12502       "\n"
12503       "function Bar() {\n"
12504       "  return Baz();\n"
12505       "}\n"
12506       "\n"
12507       "function Baz() {\n"
12508       "  throw 'nirk';\n"
12509       "}\n"
12510       "\n"
12511       "Foo();\n");
12512
12513   const char* resource_name;
12514   v8::Handle<v8::Script> script;
12515   resource_name = "test.js";
12516   script = CompileWithOrigin(source, resource_name);
12517   CheckTryCatchSourceInfo(script, resource_name, 0);
12518
12519   resource_name = "test1.js";
12520   v8::ScriptOrigin origin1(
12521       v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
12522   script = v8::Script::Compile(source, &origin1);
12523   CheckTryCatchSourceInfo(script, resource_name, 0);
12524
12525   resource_name = "test2.js";
12526   v8::ScriptOrigin origin2(
12527       v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
12528       v8::Integer::New(context->GetIsolate(), 7));
12529   script = v8::Script::Compile(source, &origin2);
12530   CheckTryCatchSourceInfo(script, resource_name, 7);
12531 }
12532
12533
12534 THREADED_TEST(CompilationCache) {
12535   LocalContext context;
12536   v8::HandleScope scope(context->GetIsolate());
12537   v8::Handle<v8::String> source0 =
12538       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
12539   v8::Handle<v8::String> source1 =
12540       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
12541   v8::Handle<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
12542   v8::Handle<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
12543   v8::Handle<v8::Script> script2 =
12544       v8::Script::Compile(source0);  // different origin
12545   CHECK_EQ(1234, script0->Run()->Int32Value());
12546   CHECK_EQ(1234, script1->Run()->Int32Value());
12547   CHECK_EQ(1234, script2->Run()->Int32Value());
12548 }
12549
12550
12551 static void FunctionNameCallback(
12552     const v8::FunctionCallbackInfo<v8::Value>& args) {
12553   ApiTestFuzzer::Fuzz();
12554   args.GetReturnValue().Set(v8_num(42));
12555 }
12556
12557
12558 THREADED_TEST(CallbackFunctionName) {
12559   LocalContext context;
12560   v8::Isolate* isolate = context->GetIsolate();
12561   v8::HandleScope scope(isolate);
12562   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
12563   t->Set(v8_str("asdf"),
12564          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
12565   context->Global()->Set(v8_str("obj"), t->NewInstance());
12566   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
12567   CHECK(value->IsString());
12568   v8::String::Utf8Value name(value);
12569   CHECK_EQ(0, strcmp("asdf", *name));
12570 }
12571
12572
12573 THREADED_TEST(DateAccess) {
12574   LocalContext context;
12575   v8::HandleScope scope(context->GetIsolate());
12576   v8::Handle<v8::Value> date =
12577       v8::Date::New(context->GetIsolate(), 1224744689038.0);
12578   CHECK(date->IsDate());
12579   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
12580 }
12581
12582
12583 void CheckProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
12584                      unsigned elmc, const char* elmv[]) {
12585   v8::Handle<v8::Object> obj = val.As<v8::Object>();
12586   v8::Handle<v8::Array> props = obj->GetPropertyNames();
12587   CHECK_EQ(elmc, props->Length());
12588   for (unsigned i = 0; i < elmc; i++) {
12589     v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
12590     CHECK_EQ(0, strcmp(elmv[i], *elm));
12591   }
12592 }
12593
12594
12595 void CheckOwnProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
12596                         unsigned elmc, const char* elmv[]) {
12597   v8::Handle<v8::Object> obj = val.As<v8::Object>();
12598   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
12599   CHECK_EQ(elmc, props->Length());
12600   for (unsigned i = 0; i < elmc; i++) {
12601     v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
12602     CHECK_EQ(0, strcmp(elmv[i], *elm));
12603   }
12604 }
12605
12606
12607 THREADED_TEST(PropertyEnumeration) {
12608   LocalContext context;
12609   v8::Isolate* isolate = context->GetIsolate();
12610   v8::HandleScope scope(isolate);
12611   v8::Handle<v8::Value> obj = CompileRun(
12612       "var result = [];"
12613       "result[0] = {};"
12614       "result[1] = {a: 1, b: 2};"
12615       "result[2] = [1, 2, 3];"
12616       "var proto = {x: 1, y: 2, z: 3};"
12617       "var x = { __proto__: proto, w: 0, z: 1 };"
12618       "result[3] = x;"
12619       "result;");
12620   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12621   CHECK_EQ(4u, elms->Length());
12622   int elmc0 = 0;
12623   const char** elmv0 = NULL;
12624   CheckProperties(
12625       isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12626   CheckOwnProperties(
12627       isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12628   int elmc1 = 2;
12629   const char* elmv1[] = {"a", "b"};
12630   CheckProperties(
12631       isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
12632   CheckOwnProperties(
12633       isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
12634   int elmc2 = 3;
12635   const char* elmv2[] = {"0", "1", "2"};
12636   CheckProperties(
12637       isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
12638   CheckOwnProperties(
12639       isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
12640   int elmc3 = 4;
12641   const char* elmv3[] = {"w", "z", "x", "y"};
12642   CheckProperties(
12643       isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
12644   int elmc4 = 2;
12645   const char* elmv4[] = {"w", "z"};
12646   CheckOwnProperties(
12647       isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
12648 }
12649
12650
12651 THREADED_TEST(PropertyEnumeration2) {
12652   LocalContext context;
12653   v8::Isolate* isolate = context->GetIsolate();
12654   v8::HandleScope scope(isolate);
12655   v8::Handle<v8::Value> obj = CompileRun(
12656       "var result = [];"
12657       "result[0] = {};"
12658       "result[1] = {a: 1, b: 2};"
12659       "result[2] = [1, 2, 3];"
12660       "var proto = {x: 1, y: 2, z: 3};"
12661       "var x = { __proto__: proto, w: 0, z: 1 };"
12662       "result[3] = x;"
12663       "result;");
12664   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12665   CHECK_EQ(4u, elms->Length());
12666   int elmc0 = 0;
12667   const char** elmv0 = NULL;
12668   CheckProperties(isolate,
12669                   elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12670
12671   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
12672   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
12673   CHECK_EQ(0u, props->Length());
12674   for (uint32_t i = 0; i < props->Length(); i++) {
12675     printf("p[%u]\n", i);
12676   }
12677 }
12678
12679 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
12680                                   Local<Value> name,
12681                                   v8::AccessType type,
12682                                   Local<Value> data) {
12683   return type != v8::ACCESS_SET;
12684 }
12685
12686
12687 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
12688                                     uint32_t key,
12689                                     v8::AccessType type,
12690                                     Local<Value> data) {
12691   return type != v8::ACCESS_SET;
12692 }
12693
12694
12695 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
12696   LocalContext context;
12697   v8::Isolate* isolate = context->GetIsolate();
12698   v8::HandleScope scope(isolate);
12699   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
12700   templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
12701                                  IndexedSetAccessBlocker);
12702   templ->Set(v8_str("x"), v8::True(isolate));
12703   Local<v8::Object> instance = templ->NewInstance();
12704   context->Global()->Set(v8_str("obj"), instance);
12705   Local<Value> value = CompileRun("obj.x");
12706   CHECK(value->BooleanValue());
12707 }
12708
12709
12710 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
12711                                   Local<Value> name,
12712                                   v8::AccessType type,
12713                                   Local<Value> data) {
12714   return false;
12715 }
12716
12717
12718 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
12719                                     uint32_t key,
12720                                     v8::AccessType type,
12721                                     Local<Value> data) {
12722   return false;
12723 }
12724
12725
12726
12727 THREADED_TEST(AccessChecksReenabledCorrectly) {
12728   LocalContext context;
12729   v8::Isolate* isolate = context->GetIsolate();
12730   v8::HandleScope scope(isolate);
12731   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
12732   templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
12733                                  IndexedGetAccessBlocker);
12734   templ->Set(v8_str("a"), v8_str("a"));
12735   // Add more than 8 (see kMaxFastProperties) properties
12736   // so that the constructor will force copying map.
12737   // Cannot sprintf, gcc complains unsafety.
12738   char buf[4];
12739   for (char i = '0'; i <= '9' ; i++) {
12740     buf[0] = i;
12741     for (char j = '0'; j <= '9'; j++) {
12742       buf[1] = j;
12743       for (char k = '0'; k <= '9'; k++) {
12744         buf[2] = k;
12745         buf[3] = 0;
12746         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
12747       }
12748     }
12749   }
12750
12751   Local<v8::Object> instance_1 = templ->NewInstance();
12752   context->Global()->Set(v8_str("obj_1"), instance_1);
12753
12754   Local<Value> value_1 = CompileRun("obj_1.a");
12755   CHECK(value_1.IsEmpty());
12756
12757   Local<v8::Object> instance_2 = templ->NewInstance();
12758   context->Global()->Set(v8_str("obj_2"), instance_2);
12759
12760   Local<Value> value_2 = CompileRun("obj_2.a");
12761   CHECK(value_2.IsEmpty());
12762 }
12763
12764
12765 // This tests that access check information remains on the global
12766 // object template when creating contexts.
12767 THREADED_TEST(AccessControlRepeatedContextCreation) {
12768   v8::Isolate* isolate = CcTest::isolate();
12769   v8::HandleScope handle_scope(isolate);
12770   v8::Handle<v8::ObjectTemplate> global_template =
12771       v8::ObjectTemplate::New(isolate);
12772   global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
12773                                            IndexedSetAccessBlocker);
12774   i::Handle<i::ObjectTemplateInfo> internal_template =
12775       v8::Utils::OpenHandle(*global_template);
12776   CHECK(!internal_template->constructor()->IsUndefined());
12777   i::Handle<i::FunctionTemplateInfo> constructor(
12778       i::FunctionTemplateInfo::cast(internal_template->constructor()));
12779   CHECK(!constructor->access_check_info()->IsUndefined());
12780   v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
12781   CHECK(!context0.IsEmpty());
12782   CHECK(!constructor->access_check_info()->IsUndefined());
12783 }
12784
12785
12786 THREADED_TEST(TurnOnAccessCheck) {
12787   v8::Isolate* isolate = CcTest::isolate();
12788   v8::HandleScope handle_scope(isolate);
12789
12790   // Create an environment with access check to the global object disabled by
12791   // default.
12792   v8::Handle<v8::ObjectTemplate> global_template =
12793       v8::ObjectTemplate::New(isolate);
12794   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
12795                                            IndexedGetAccessBlocker,
12796                                            v8::Handle<v8::Value>(),
12797                                            false);
12798   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
12799   Context::Scope context_scope(context);
12800
12801   // Set up a property and a number of functions.
12802   context->Global()->Set(v8_str("a"), v8_num(1));
12803   CompileRun("function f1() {return a;}"
12804              "function f2() {return a;}"
12805              "function g1() {return h();}"
12806              "function g2() {return h();}"
12807              "function h() {return 1;}");
12808   Local<Function> f1 =
12809       Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
12810   Local<Function> f2 =
12811       Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
12812   Local<Function> g1 =
12813       Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
12814   Local<Function> g2 =
12815       Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
12816   Local<Function> h =
12817       Local<Function>::Cast(context->Global()->Get(v8_str("h")));
12818
12819   // Get the global object.
12820   v8::Handle<v8::Object> global = context->Global();
12821
12822   // Call f1 one time and f2 a number of times. This will ensure that f1 still
12823   // uses the runtime system to retreive property a whereas f2 uses global load
12824   // inline cache.
12825   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
12826   for (int i = 0; i < 4; i++) {
12827     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
12828   }
12829
12830   // Same for g1 and g2.
12831   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
12832   for (int i = 0; i < 4; i++) {
12833     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
12834   }
12835
12836   // Detach the global and turn on access check.
12837   Local<Object> hidden_global = Local<Object>::Cast(
12838       context->Global()->GetPrototype());
12839   context->DetachGlobal();
12840   hidden_global->TurnOnAccessCheck();
12841
12842   // Failing access check results in exception.
12843   CHECK(f1->Call(global, 0, NULL).IsEmpty());
12844   CHECK(f2->Call(global, 0, NULL).IsEmpty());
12845   CHECK(g1->Call(global, 0, NULL).IsEmpty());
12846   CHECK(g2->Call(global, 0, NULL).IsEmpty());
12847
12848   // No failing access check when just returning a constant.
12849   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
12850 }
12851
12852
12853 static const char* kPropertyA = "a";
12854 static const char* kPropertyH = "h";
12855
12856 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
12857                                        Local<Value> name,
12858                                        v8::AccessType type,
12859                                        Local<Value> data) {
12860   if (!name->IsString()) return false;
12861   i::Handle<i::String> name_handle =
12862       v8::Utils::OpenHandle(String::Cast(*name));
12863   return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
12864       && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
12865 }
12866
12867
12868 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
12869   v8::Isolate* isolate = CcTest::isolate();
12870   v8::HandleScope handle_scope(isolate);
12871
12872   // Create an environment with access check to the global object disabled by
12873   // default. When the registered access checker will block access to properties
12874   // a and h.
12875   v8::Handle<v8::ObjectTemplate> global_template =
12876      v8::ObjectTemplate::New(isolate);
12877   global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
12878                                            IndexedGetAccessBlocker,
12879                                            v8::Handle<v8::Value>(),
12880                                            false);
12881   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
12882   Context::Scope context_scope(context);
12883
12884   // Set up a property and a number of functions.
12885   context->Global()->Set(v8_str("a"), v8_num(1));
12886   static const char* source = "function f1() {return a;}"
12887                               "function f2() {return a;}"
12888                               "function g1() {return h();}"
12889                               "function g2() {return h();}"
12890                               "function h() {return 1;}";
12891
12892   CompileRun(source);
12893   Local<Function> f1;
12894   Local<Function> f2;
12895   Local<Function> g1;
12896   Local<Function> g2;
12897   Local<Function> h;
12898   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
12899   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
12900   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
12901   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
12902   h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
12903
12904   // Get the global object.
12905   v8::Handle<v8::Object> global = context->Global();
12906
12907   // Call f1 one time and f2 a number of times. This will ensure that f1 still
12908   // uses the runtime system to retreive property a whereas f2 uses global load
12909   // inline cache.
12910   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
12911   for (int i = 0; i < 4; i++) {
12912     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
12913   }
12914
12915   // Same for g1 and g2.
12916   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
12917   for (int i = 0; i < 4; i++) {
12918     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
12919   }
12920
12921   // Detach the global and turn on access check now blocking access to property
12922   // a and function h.
12923   Local<Object> hidden_global = Local<Object>::Cast(
12924       context->Global()->GetPrototype());
12925   context->DetachGlobal();
12926   hidden_global->TurnOnAccessCheck();
12927
12928   // Failing access check results in exception.
12929   CHECK(f1->Call(global, 0, NULL).IsEmpty());
12930   CHECK(f2->Call(global, 0, NULL).IsEmpty());
12931   CHECK(g1->Call(global, 0, NULL).IsEmpty());
12932   CHECK(g2->Call(global, 0, NULL).IsEmpty());
12933
12934   // No failing access check when just returning a constant.
12935   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
12936
12937   // Now compile the source again. And get the newly compiled functions, except
12938   // for h for which access is blocked.
12939   CompileRun(source);
12940   f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
12941   f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
12942   g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
12943   g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
12944   CHECK(hidden_global->Get(v8_str("h")).IsEmpty());
12945
12946   // Failing access check results in exception.
12947   v8::Local<v8::Value> result = f1->Call(global, 0, NULL);
12948   CHECK(result.IsEmpty());
12949   CHECK(f1->Call(global, 0, NULL).IsEmpty());
12950   CHECK(f2->Call(global, 0, NULL).IsEmpty());
12951   CHECK(g1->Call(global, 0, NULL).IsEmpty());
12952   CHECK(g2->Call(global, 0, NULL).IsEmpty());
12953 }
12954
12955
12956 // Tests that ScriptData can be serialized and deserialized.
12957 TEST(PreCompileSerialization) {
12958   v8::V8::Initialize();
12959   LocalContext env;
12960   v8::Isolate* isolate = env->GetIsolate();
12961   HandleScope handle_scope(isolate);
12962
12963   i::FLAG_min_preparse_length = 0;
12964   const char* script = "function foo(a) { return a+1; }";
12965   v8::ScriptCompiler::Source source(v8_str(script));
12966   v8::ScriptCompiler::Compile(isolate, &source,
12967                               v8::ScriptCompiler::kProduceParserCache);
12968   // Serialize.
12969   const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
12970   i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
12971   i::MemCopy(serialized_data, cd->data, cd->length);
12972
12973   // Deserialize.
12974   i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
12975
12976   // Verify that the original is the same as the deserialized.
12977   CHECK_EQ(cd->length, deserialized->length());
12978   CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
12979
12980   delete deserialized;
12981   i::DeleteArray(serialized_data);
12982 }
12983
12984
12985 // This tests that we do not allow dictionary load/call inline caches
12986 // to use functions that have not yet been compiled.  The potential
12987 // problem of loading a function that has not yet been compiled can
12988 // arise because we share code between contexts via the compilation
12989 // cache.
12990 THREADED_TEST(DictionaryICLoadedFunction) {
12991   v8::HandleScope scope(CcTest::isolate());
12992   // Test LoadIC.
12993   for (int i = 0; i < 2; i++) {
12994     LocalContext context;
12995     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
12996     context->Global()->Delete(v8_str("tmp"));
12997     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
12998   }
12999   // Test CallIC.
13000   for (int i = 0; i < 2; i++) {
13001     LocalContext context;
13002     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
13003     context->Global()->Delete(v8_str("tmp"));
13004     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
13005   }
13006 }
13007
13008
13009 // Test that cross-context new calls use the context of the callee to
13010 // create the new JavaScript object.
13011 THREADED_TEST(CrossContextNew) {
13012   v8::Isolate* isolate = CcTest::isolate();
13013   v8::HandleScope scope(isolate);
13014   v8::Local<Context> context0 = Context::New(isolate);
13015   v8::Local<Context> context1 = Context::New(isolate);
13016
13017   // Allow cross-domain access.
13018   Local<String> token = v8_str("<security token>");
13019   context0->SetSecurityToken(token);
13020   context1->SetSecurityToken(token);
13021
13022   // Set an 'x' property on the Object prototype and define a
13023   // constructor function in context0.
13024   context0->Enter();
13025   CompileRun("Object.prototype.x = 42; function C() {};");
13026   context0->Exit();
13027
13028   // Call the constructor function from context0 and check that the
13029   // result has the 'x' property.
13030   context1->Enter();
13031   context1->Global()->Set(v8_str("other"), context0->Global());
13032   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
13033   CHECK(value->IsInt32());
13034   CHECK_EQ(42, value->Int32Value());
13035   context1->Exit();
13036 }
13037
13038
13039 // Verify that we can clone an object
13040 TEST(ObjectClone) {
13041   LocalContext env;
13042   v8::Isolate* isolate = env->GetIsolate();
13043   v8::HandleScope scope(isolate);
13044
13045   const char* sample =
13046     "var rv = {};"      \
13047     "rv.alpha = 'hello';" \
13048     "rv.beta = 123;"     \
13049     "rv;";
13050
13051   // Create an object, verify basics.
13052   Local<Value> val = CompileRun(sample);
13053   CHECK(val->IsObject());
13054   Local<v8::Object> obj = val.As<v8::Object>();
13055   obj->Set(v8_str("gamma"), v8_str("cloneme"));
13056
13057   CHECK(v8_str("hello")->Equals(obj->Get(v8_str("alpha"))));
13058   CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
13059   CHECK(v8_str("cloneme")->Equals(obj->Get(v8_str("gamma"))));
13060
13061   // Clone it.
13062   Local<v8::Object> clone = obj->Clone();
13063   CHECK(v8_str("hello")->Equals(clone->Get(v8_str("alpha"))));
13064   CHECK(v8::Integer::New(isolate, 123)->Equals(clone->Get(v8_str("beta"))));
13065   CHECK(v8_str("cloneme")->Equals(clone->Get(v8_str("gamma"))));
13066
13067   // Set a property on the clone, verify each object.
13068   clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
13069   CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
13070   CHECK(v8::Integer::New(isolate, 456)->Equals(clone->Get(v8_str("beta"))));
13071 }
13072
13073
13074 class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
13075  public:
13076   explicit OneByteVectorResource(i::Vector<const char> vector)
13077       : data_(vector) {}
13078   virtual ~OneByteVectorResource() {}
13079   virtual size_t length() const { return data_.length(); }
13080   virtual const char* data() const { return data_.start(); }
13081  private:
13082   i::Vector<const char> data_;
13083 };
13084
13085
13086 class UC16VectorResource : public v8::String::ExternalStringResource {
13087  public:
13088   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
13089       : data_(vector) {}
13090   virtual ~UC16VectorResource() {}
13091   virtual size_t length() const { return data_.length(); }
13092   virtual const i::uc16* data() const { return data_.start(); }
13093  private:
13094   i::Vector<const i::uc16> data_;
13095 };
13096
13097
13098 static void MorphAString(i::String* string,
13099                          OneByteVectorResource* one_byte_resource,
13100                          UC16VectorResource* uc16_resource) {
13101   CHECK(i::StringShape(string).IsExternal());
13102   if (string->IsOneByteRepresentation()) {
13103     // Check old map is not internalized or long.
13104     CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
13105     // Morph external string to be TwoByte string.
13106     string->set_map(CcTest::heap()->external_string_map());
13107     i::ExternalTwoByteString* morphed =
13108          i::ExternalTwoByteString::cast(string);
13109     morphed->set_resource(uc16_resource);
13110   } else {
13111     // Check old map is not internalized or long.
13112     CHECK(string->map() == CcTest::heap()->external_string_map());
13113     // Morph external string to be one-byte string.
13114     string->set_map(CcTest::heap()->external_one_byte_string_map());
13115     i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
13116     morphed->set_resource(one_byte_resource);
13117   }
13118 }
13119
13120
13121 // Test that we can still flatten a string if the components it is built up
13122 // from have been turned into 16 bit strings in the mean time.
13123 THREADED_TEST(MorphCompositeStringTest) {
13124   char utf_buffer[129];
13125   const char* c_string = "Now is the time for all good men"
13126                          " to come to the aid of the party";
13127   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
13128   {
13129     LocalContext env;
13130     i::Factory* factory = CcTest::i_isolate()->factory();
13131     v8::HandleScope scope(env->GetIsolate());
13132     OneByteVectorResource one_byte_resource(
13133         i::Vector<const char>(c_string, i::StrLength(c_string)));
13134     UC16VectorResource uc16_resource(
13135         i::Vector<const uint16_t>(two_byte_string,
13136                                   i::StrLength(c_string)));
13137
13138     Local<String> lhs(
13139         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
13140                                         &one_byte_resource).ToHandleChecked()));
13141     Local<String> rhs(
13142         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
13143                                         &one_byte_resource).ToHandleChecked()));
13144
13145     env->Global()->Set(v8_str("lhs"), lhs);
13146     env->Global()->Set(v8_str("rhs"), rhs);
13147
13148     CompileRun(
13149         "var cons = lhs + rhs;"
13150         "var slice = lhs.substring(1, lhs.length - 1);"
13151         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
13152
13153     CHECK(lhs->IsOneByte());
13154     CHECK(rhs->IsOneByte());
13155
13156     MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
13157                  &uc16_resource);
13158     MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
13159                  &uc16_resource);
13160
13161     // This should UTF-8 without flattening, since everything is ASCII.
13162     Handle<String> cons = v8_compile("cons")->Run().As<String>();
13163     CHECK_EQ(128, cons->Utf8Length());
13164     int nchars = -1;
13165     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
13166     CHECK_EQ(128, nchars);
13167     CHECK_EQ(0, strcmp(
13168         utf_buffer,
13169         "Now is the time for all good men to come to the aid of the party"
13170         "Now is the time for all good men to come to the aid of the party"));
13171
13172     // Now do some stuff to make sure the strings are flattened, etc.
13173     CompileRun(
13174         "/[^a-z]/.test(cons);"
13175         "/[^a-z]/.test(slice);"
13176         "/[^a-z]/.test(slice_on_cons);");
13177     const char* expected_cons =
13178         "Now is the time for all good men to come to the aid of the party"
13179         "Now is the time for all good men to come to the aid of the party";
13180     const char* expected_slice =
13181         "ow is the time for all good men to come to the aid of the part";
13182     const char* expected_slice_on_cons =
13183         "ow is the time for all good men to come to the aid of the party"
13184         "Now is the time for all good men to come to the aid of the part";
13185     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_cons)
13186               ->Equals(env->Global()->Get(v8_str("cons"))));
13187     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice)
13188               ->Equals(env->Global()->Get(v8_str("slice"))));
13189     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons)
13190               ->Equals(env->Global()->Get(v8_str("slice_on_cons"))));
13191   }
13192   i::DeleteArray(two_byte_string);
13193 }
13194
13195
13196 TEST(CompileExternalTwoByteSource) {
13197   LocalContext context;
13198   v8::HandleScope scope(context->GetIsolate());
13199
13200   // This is a very short list of sources, which currently is to check for a
13201   // regression caused by r2703.
13202   const char* one_byte_sources[] = {
13203       "0.5",
13204       "-0.5",   // This mainly testes PushBack in the Scanner.
13205       "--0.5",  // This mainly testes PushBack in the Scanner.
13206       NULL};
13207
13208   // Compile the sources as external two byte strings.
13209   for (int i = 0; one_byte_sources[i] != NULL; i++) {
13210     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
13211     TestResource* uc16_resource = new TestResource(two_byte_string);
13212     v8::Local<v8::String> source =
13213         v8::String::NewExternal(context->GetIsolate(), uc16_resource);
13214     v8::Script::Compile(source);
13215   }
13216 }
13217
13218
13219 #ifndef V8_INTERPRETED_REGEXP
13220
13221 struct RegExpInterruptionData {
13222   v8::base::Atomic32 loop_count;
13223   UC16VectorResource* string_resource;
13224   v8::Persistent<v8::String> string;
13225 } regexp_interruption_data;
13226
13227
13228 class RegExpInterruptionThread : public v8::base::Thread {
13229  public:
13230   explicit RegExpInterruptionThread(v8::Isolate* isolate)
13231       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
13232
13233   virtual void Run() {
13234     for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
13235          v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
13236          v8::base::NoBarrier_AtomicIncrement(
13237              &regexp_interruption_data.loop_count, 1)) {
13238       v8::base::OS::Sleep(50);  // Wait a bit before requesting GC.
13239       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
13240     }
13241     v8::base::OS::Sleep(50);  // Wait a bit before terminating.
13242     v8::V8::TerminateExecution(isolate_);
13243   }
13244
13245  private:
13246   v8::Isolate* isolate_;
13247 };
13248
13249
13250 void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
13251   if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
13252     return;
13253   }
13254   v8::HandleScope scope(CcTest::isolate());
13255   v8::Local<v8::String> string = v8::Local<v8::String>::New(
13256       CcTest::isolate(), regexp_interruption_data.string);
13257   string->MakeExternal(regexp_interruption_data.string_resource);
13258 }
13259
13260
13261 // Test that RegExp execution can be interrupted.  Specifically, we test
13262 // * interrupting with GC
13263 // * turn the subject string from one-byte internal to two-byte external string
13264 // * force termination
13265 TEST(RegExpInterruption) {
13266   v8::HandleScope scope(CcTest::isolate());
13267   LocalContext env;
13268
13269   RegExpInterruptionThread timeout_thread(CcTest::isolate());
13270
13271   v8::V8::AddGCPrologueCallback(RunBeforeGC);
13272   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
13273   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
13274   v8::Local<v8::String> string = v8_str(one_byte_content);
13275
13276   CcTest::global()->Set(v8_str("a"), string);
13277   regexp_interruption_data.string.Reset(CcTest::isolate(), string);
13278   regexp_interruption_data.string_resource = new UC16VectorResource(
13279       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
13280
13281   v8::TryCatch try_catch;
13282   timeout_thread.Start();
13283
13284   CompileRun("/((a*)*)*b/.exec(a)");
13285   CHECK(try_catch.HasTerminated());
13286
13287   timeout_thread.Join();
13288
13289   regexp_interruption_data.string.Reset();
13290   i::DeleteArray(uc16_content);
13291 }
13292
13293 #endif  // V8_INTERPRETED_REGEXP
13294
13295
13296 // Test that we cannot set a property on the global object if there
13297 // is a read-only property in the prototype chain.
13298 TEST(ReadOnlyPropertyInGlobalProto) {
13299   v8::Isolate* isolate = CcTest::isolate();
13300   v8::HandleScope scope(isolate);
13301   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13302   LocalContext context(0, templ);
13303   v8::Handle<v8::Object> global = context->Global();
13304   v8::Handle<v8::Object> global_proto =
13305       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
13306   global_proto->ForceSet(v8_str("x"), v8::Integer::New(isolate, 0),
13307                          v8::ReadOnly);
13308   global_proto->ForceSet(v8_str("y"), v8::Integer::New(isolate, 0),
13309                          v8::ReadOnly);
13310   // Check without 'eval' or 'with'.
13311   v8::Handle<v8::Value> res =
13312       CompileRun("function f() { x = 42; return x; }; f()");
13313   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13314   // Check with 'eval'.
13315   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
13316   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13317   // Check with 'with'.
13318   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
13319   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13320 }
13321
13322 static int force_set_set_count = 0;
13323 static int force_set_get_count = 0;
13324 bool pass_on_get = false;
13325
13326 static void ForceSetGetter(v8::Local<v8::String> name,
13327                            const v8::PropertyCallbackInfo<v8::Value>& info) {
13328   force_set_get_count++;
13329   if (pass_on_get) {
13330     return;
13331   }
13332   info.GetReturnValue().Set(3);
13333 }
13334
13335 static void ForceSetSetter(v8::Local<v8::String> name,
13336                            v8::Local<v8::Value> value,
13337                            const v8::PropertyCallbackInfo<void>& info) {
13338   force_set_set_count++;
13339 }
13340
13341 static void ForceSetInterceptGetter(
13342     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
13343   CHECK(name->IsString());
13344   ForceSetGetter(Local<String>::Cast(name), info);
13345 }
13346
13347 static void ForceSetInterceptSetter(
13348     v8::Local<v8::Name> name, v8::Local<v8::Value> value,
13349     const v8::PropertyCallbackInfo<v8::Value>& info) {
13350   force_set_set_count++;
13351   info.GetReturnValue().SetUndefined();
13352 }
13353
13354
13355 TEST(ForceSet) {
13356   force_set_get_count = 0;
13357   force_set_set_count = 0;
13358   pass_on_get = false;
13359
13360   v8::Isolate* isolate = CcTest::isolate();
13361   v8::HandleScope scope(isolate);
13362   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13363   v8::Handle<v8::String> access_property =
13364       v8::String::NewFromUtf8(isolate, "a");
13365   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
13366   LocalContext context(NULL, templ);
13367   v8::Handle<v8::Object> global = context->Global();
13368
13369   // Ordinary properties
13370   v8::Handle<v8::String> simple_property =
13371       v8::String::NewFromUtf8(isolate, "p");
13372   global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
13373   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13374   // This should fail because the property is read-only
13375   global->Set(simple_property, v8::Int32::New(isolate, 5));
13376   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13377   // This should succeed even though the property is read-only
13378   global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
13379   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
13380
13381   // Accessors
13382   CHECK_EQ(0, force_set_set_count);
13383   CHECK_EQ(0, force_set_get_count);
13384   CHECK_EQ(3, global->Get(access_property)->Int32Value());
13385   // CHECK_EQ the property shouldn't override it, just call the setter
13386   // which in this case does nothing.
13387   global->Set(access_property, v8::Int32::New(isolate, 7));
13388   CHECK_EQ(3, global->Get(access_property)->Int32Value());
13389   CHECK_EQ(1, force_set_set_count);
13390   CHECK_EQ(2, force_set_get_count);
13391   // Forcing the property to be set should override the accessor without
13392   // calling it
13393   global->ForceSet(access_property, v8::Int32::New(isolate, 8));
13394   CHECK_EQ(8, global->Get(access_property)->Int32Value());
13395   CHECK_EQ(1, force_set_set_count);
13396   CHECK_EQ(2, force_set_get_count);
13397 }
13398
13399
13400 TEST(ForceSetWithInterceptor) {
13401   force_set_get_count = 0;
13402   force_set_set_count = 0;
13403   pass_on_get = false;
13404
13405   v8::Isolate* isolate = CcTest::isolate();
13406   v8::HandleScope scope(isolate);
13407   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13408   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
13409       ForceSetInterceptGetter, ForceSetInterceptSetter));
13410   LocalContext context(NULL, templ);
13411   v8::Handle<v8::Object> global = context->Global();
13412
13413   v8::Handle<v8::String> some_property =
13414       v8::String::NewFromUtf8(isolate, "a");
13415   CHECK_EQ(0, force_set_set_count);
13416   CHECK_EQ(0, force_set_get_count);
13417   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13418   // Setting the property shouldn't override it, just call the setter
13419   // which in this case does nothing.
13420   global->Set(some_property, v8::Int32::New(isolate, 7));
13421   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13422   CHECK_EQ(1, force_set_set_count);
13423   CHECK_EQ(2, force_set_get_count);
13424   // Getting the property when the interceptor returns an empty handle
13425   // should yield undefined, since the property isn't present on the
13426   // object itself yet.
13427   pass_on_get = true;
13428   CHECK(global->Get(some_property)->IsUndefined());
13429   CHECK_EQ(1, force_set_set_count);
13430   CHECK_EQ(3, force_set_get_count);
13431   // Forcing the property to be set should cause the value to be
13432   // set locally without calling the interceptor.
13433   global->ForceSet(some_property, v8::Int32::New(isolate, 8));
13434   CHECK_EQ(8, global->Get(some_property)->Int32Value());
13435   CHECK_EQ(1, force_set_set_count);
13436   CHECK_EQ(4, force_set_get_count);
13437   // Reenabling the interceptor should cause it to take precedence over
13438   // the property
13439   pass_on_get = false;
13440   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13441   CHECK_EQ(1, force_set_set_count);
13442   CHECK_EQ(5, force_set_get_count);
13443   // The interceptor should also work for other properties
13444   CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
13445                   ->Int32Value());
13446   CHECK_EQ(1, force_set_set_count);
13447   CHECK_EQ(6, force_set_get_count);
13448 }
13449
13450
13451 static v8::Local<Context> calling_context0;
13452 static v8::Local<Context> calling_context1;
13453 static v8::Local<Context> calling_context2;
13454
13455
13456 // Check that the call to the callback is initiated in
13457 // calling_context2, the directly calling context is calling_context1
13458 // and the callback itself is in calling_context0.
13459 static void GetCallingContextCallback(
13460     const v8::FunctionCallbackInfo<v8::Value>& args) {
13461   ApiTestFuzzer::Fuzz();
13462   CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
13463   CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
13464   CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
13465   args.GetReturnValue().Set(42);
13466 }
13467
13468
13469 THREADED_TEST(GetCurrentContextWhenNotInContext) {
13470   i::Isolate* isolate = CcTest::i_isolate();
13471   CHECK(isolate != NULL);
13472   CHECK(isolate->context() == NULL);
13473   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
13474   v8::HandleScope scope(v8_isolate);
13475   // The following should not crash, but return an empty handle.
13476   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
13477   CHECK(current.IsEmpty());
13478 }
13479
13480
13481 THREADED_TEST(GetCallingContext) {
13482   v8::Isolate* isolate = CcTest::isolate();
13483   v8::HandleScope scope(isolate);
13484
13485   Local<Context> calling_context0(Context::New(isolate));
13486   Local<Context> calling_context1(Context::New(isolate));
13487   Local<Context> calling_context2(Context::New(isolate));
13488   ::calling_context0 = calling_context0;
13489   ::calling_context1 = calling_context1;
13490   ::calling_context2 = calling_context2;
13491
13492   // Allow cross-domain access.
13493   Local<String> token = v8_str("<security token>");
13494   calling_context0->SetSecurityToken(token);
13495   calling_context1->SetSecurityToken(token);
13496   calling_context2->SetSecurityToken(token);
13497
13498   // Create an object with a C++ callback in context0.
13499   calling_context0->Enter();
13500   Local<v8::FunctionTemplate> callback_templ =
13501       v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
13502   calling_context0->Global()->Set(v8_str("callback"),
13503                                   callback_templ->GetFunction());
13504   calling_context0->Exit();
13505
13506   // Expose context0 in context1 and set up a function that calls the
13507   // callback function.
13508   calling_context1->Enter();
13509   calling_context1->Global()->Set(v8_str("context0"),
13510                                   calling_context0->Global());
13511   CompileRun("function f() { context0.callback() }");
13512   calling_context1->Exit();
13513
13514   // Expose context1 in context2 and call the callback function in
13515   // context0 indirectly through f in context1.
13516   calling_context2->Enter();
13517   calling_context2->Global()->Set(v8_str("context1"),
13518                                   calling_context1->Global());
13519   CompileRun("context1.f()");
13520   calling_context2->Exit();
13521   ::calling_context0.Clear();
13522   ::calling_context1.Clear();
13523   ::calling_context2.Clear();
13524 }
13525
13526
13527 // Check that a variable declaration with no explicit initialization
13528 // value does shadow an existing property in the prototype chain.
13529 THREADED_TEST(InitGlobalVarInProtoChain) {
13530   LocalContext context;
13531   v8::HandleScope scope(context->GetIsolate());
13532   // Introduce a variable in the prototype chain.
13533   CompileRun("__proto__.x = 42");
13534   v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
13535   CHECK(!result->IsUndefined());
13536   CHECK_EQ(43, result->Int32Value());
13537 }
13538
13539
13540 // Regression test for issue 398.
13541 // If a function is added to an object, creating a constant function
13542 // field, and the result is cloned, replacing the constant function on the
13543 // original should not affect the clone.
13544 // See http://code.google.com/p/v8/issues/detail?id=398
13545 THREADED_TEST(ReplaceConstantFunction) {
13546   LocalContext context;
13547   v8::Isolate* isolate = context->GetIsolate();
13548   v8::HandleScope scope(isolate);
13549   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
13550   v8::Handle<v8::FunctionTemplate> func_templ =
13551       v8::FunctionTemplate::New(isolate);
13552   v8::Handle<v8::String> foo_string =
13553       v8::String::NewFromUtf8(isolate, "foo");
13554   obj->Set(foo_string, func_templ->GetFunction());
13555   v8::Handle<v8::Object> obj_clone = obj->Clone();
13556   obj_clone->Set(foo_string,
13557                  v8::String::NewFromUtf8(isolate, "Hello"));
13558   CHECK(!obj->Get(foo_string)->IsUndefined());
13559 }
13560
13561
13562 static void CheckElementValue(i::Isolate* isolate,
13563                               int expected,
13564                               i::Handle<i::Object> obj,
13565                               int offset) {
13566   i::Object* element =
13567       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
13568   CHECK_EQ(expected, i::Smi::cast(element)->value());
13569 }
13570
13571
13572 THREADED_TEST(PixelArray) {
13573   LocalContext context;
13574   i::Isolate* isolate = CcTest::i_isolate();
13575   i::Factory* factory = isolate->factory();
13576   v8::HandleScope scope(context->GetIsolate());
13577   const int kElementCount = 260;
13578   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
13579   i::Handle<i::ExternalUint8ClampedArray> pixels =
13580       i::Handle<i::ExternalUint8ClampedArray>::cast(
13581           factory->NewExternalArray(kElementCount,
13582                                     v8::kExternalUint8ClampedArray,
13583                                     pixel_data));
13584   // Force GC to trigger verification.
13585   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13586   for (int i = 0; i < kElementCount; i++) {
13587     pixels->set(i, i % 256);
13588   }
13589   // Force GC to trigger verification.
13590   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13591   for (int i = 0; i < kElementCount; i++) {
13592     CHECK_EQ(i % 256, pixels->get_scalar(i));
13593     CHECK_EQ(i % 256, pixel_data[i]);
13594   }
13595
13596   v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
13597   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
13598   // Set the elements to be the pixels.
13599   // jsobj->set_elements(*pixels);
13600   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
13601   CheckElementValue(isolate, 1, jsobj, 1);
13602   obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
13603   context->Global()->Set(v8_str("pixels"), obj);
13604   v8::Handle<v8::Value> result = CompileRun("pixels.field");
13605   CHECK_EQ(1503, result->Int32Value());
13606   result = CompileRun("pixels[1]");
13607   CHECK_EQ(1, result->Int32Value());
13608
13609   result = CompileRun("var sum = 0;"
13610                       "for (var i = 0; i < 8; i++) {"
13611                       "  sum += pixels[i] = pixels[i] = -i;"
13612                       "}"
13613                       "sum;");
13614   CHECK_EQ(-28, result->Int32Value());
13615
13616   result = CompileRun("var sum = 0;"
13617                       "for (var i = 0; i < 8; i++) {"
13618                       "  sum += pixels[i] = pixels[i] = 0;"
13619                       "}"
13620                       "sum;");
13621   CHECK_EQ(0, result->Int32Value());
13622
13623   result = CompileRun("var sum = 0;"
13624                       "for (var i = 0; i < 8; i++) {"
13625                       "  sum += pixels[i] = pixels[i] = 255;"
13626                       "}"
13627                       "sum;");
13628   CHECK_EQ(8 * 255, result->Int32Value());
13629
13630   result = CompileRun("var sum = 0;"
13631                       "for (var i = 0; i < 8; i++) {"
13632                       "  sum += pixels[i] = pixels[i] = 256 + i;"
13633                       "}"
13634                       "sum;");
13635   CHECK_EQ(2076, result->Int32Value());
13636
13637   result = CompileRun("var sum = 0;"
13638                       "for (var i = 0; i < 8; i++) {"
13639                       "  sum += pixels[i] = pixels[i] = i;"
13640                       "}"
13641                       "sum;");
13642   CHECK_EQ(28, result->Int32Value());
13643
13644   result = CompileRun("var sum = 0;"
13645                       "for (var i = 0; i < 8; i++) {"
13646                       "  sum += pixels[i];"
13647                       "}"
13648                       "sum;");
13649   CHECK_EQ(28, result->Int32Value());
13650
13651   i::Handle<i::Smi> value(i::Smi::FromInt(2),
13652                           reinterpret_cast<i::Isolate*>(context->GetIsolate()));
13653   i::Handle<i::Object> no_failure;
13654   no_failure = i::JSObject::SetElement(
13655       jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
13656   DCHECK(!no_failure.is_null());
13657   USE(no_failure);
13658   CheckElementValue(isolate, 2, jsobj, 1);
13659   *value.location() = i::Smi::FromInt(256);
13660   no_failure = i::JSObject::SetElement(
13661       jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
13662   DCHECK(!no_failure.is_null());
13663   USE(no_failure);
13664   CheckElementValue(isolate, 255, jsobj, 1);
13665   *value.location() = i::Smi::FromInt(-1);
13666   no_failure = i::JSObject::SetElement(
13667       jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
13668   DCHECK(!no_failure.is_null());
13669   USE(no_failure);
13670   CheckElementValue(isolate, 0, jsobj, 1);
13671
13672   result = CompileRun("for (var i = 0; i < 8; i++) {"
13673                       "  pixels[i] = (i * 65) - 109;"
13674                       "}"
13675                       "pixels[1] + pixels[6];");
13676   CHECK_EQ(255, result->Int32Value());
13677   CheckElementValue(isolate, 0, jsobj, 0);
13678   CheckElementValue(isolate, 0, jsobj, 1);
13679   CheckElementValue(isolate, 21, jsobj, 2);
13680   CheckElementValue(isolate, 86, jsobj, 3);
13681   CheckElementValue(isolate, 151, jsobj, 4);
13682   CheckElementValue(isolate, 216, jsobj, 5);
13683   CheckElementValue(isolate, 255, jsobj, 6);
13684   CheckElementValue(isolate, 255, jsobj, 7);
13685   result = CompileRun("var sum = 0;"
13686                       "for (var i = 0; i < 8; i++) {"
13687                       "  sum += pixels[i];"
13688                       "}"
13689                       "sum;");
13690   CHECK_EQ(984, result->Int32Value());
13691
13692   result = CompileRun("for (var i = 0; i < 8; i++) {"
13693                       "  pixels[i] = (i * 1.1);"
13694                       "}"
13695                       "pixels[1] + pixels[6];");
13696   CHECK_EQ(8, result->Int32Value());
13697   CheckElementValue(isolate, 0, jsobj, 0);
13698   CheckElementValue(isolate, 1, jsobj, 1);
13699   CheckElementValue(isolate, 2, jsobj, 2);
13700   CheckElementValue(isolate, 3, jsobj, 3);
13701   CheckElementValue(isolate, 4, jsobj, 4);
13702   CheckElementValue(isolate, 6, jsobj, 5);
13703   CheckElementValue(isolate, 7, jsobj, 6);
13704   CheckElementValue(isolate, 8, jsobj, 7);
13705
13706   result = CompileRun("for (var i = 0; i < 8; i++) {"
13707                       "  pixels[7] = undefined;"
13708                       "}"
13709                       "pixels[7];");
13710   CHECK_EQ(0, result->Int32Value());
13711   CheckElementValue(isolate, 0, jsobj, 7);
13712
13713   result = CompileRun("for (var i = 0; i < 8; i++) {"
13714                       "  pixels[6] = '2.3';"
13715                       "}"
13716                       "pixels[6];");
13717   CHECK_EQ(2, result->Int32Value());
13718   CheckElementValue(isolate, 2, jsobj, 6);
13719
13720   result = CompileRun("for (var i = 0; i < 8; i++) {"
13721                       "  pixels[5] = NaN;"
13722                       "}"
13723                       "pixels[5];");
13724   CHECK_EQ(0, result->Int32Value());
13725   CheckElementValue(isolate, 0, jsobj, 5);
13726
13727   result = CompileRun("for (var i = 0; i < 8; i++) {"
13728                       "  pixels[8] = Infinity;"
13729                       "}"
13730                       "pixels[8];");
13731   CHECK_EQ(255, result->Int32Value());
13732   CheckElementValue(isolate, 255, jsobj, 8);
13733
13734   result = CompileRun("for (var i = 0; i < 8; i++) {"
13735                       "  pixels[9] = -Infinity;"
13736                       "}"
13737                       "pixels[9];");
13738   CHECK_EQ(0, result->Int32Value());
13739   CheckElementValue(isolate, 0, jsobj, 9);
13740
13741   result = CompileRun("pixels[3] = 33;"
13742                       "delete pixels[3];"
13743                       "pixels[3];");
13744   CHECK_EQ(33, result->Int32Value());
13745
13746   result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
13747                       "pixels[2] = 12; pixels[3] = 13;"
13748                       "pixels.__defineGetter__('2',"
13749                       "function() { return 120; });"
13750                       "pixels[2];");
13751   CHECK_EQ(12, result->Int32Value());
13752
13753   result = CompileRun("var js_array = new Array(40);"
13754                       "js_array[0] = 77;"
13755                       "js_array;");
13756   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13757
13758   result = CompileRun("pixels[1] = 23;"
13759                       "pixels.__proto__ = [];"
13760                       "js_array.__proto__ = pixels;"
13761                       "js_array.concat(pixels);");
13762   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13763   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
13764
13765   result = CompileRun("pixels[1] = 23;");
13766   CHECK_EQ(23, result->Int32Value());
13767
13768   // Test for index greater than 255.  Regression test for:
13769   // http://code.google.com/p/chromium/issues/detail?id=26337.
13770   result = CompileRun("pixels[256] = 255;");
13771   CHECK_EQ(255, result->Int32Value());
13772   result = CompileRun("var i = 0;"
13773                       "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
13774                       "i");
13775   CHECK_EQ(255, result->Int32Value());
13776
13777   // Make sure that pixel array ICs recognize when a non-pixel array
13778   // is passed to it.
13779   result = CompileRun("function pa_load(p) {"
13780                       "  var sum = 0;"
13781                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
13782                       "  return sum;"
13783                       "}"
13784                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13785                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
13786                       "just_ints = new Object();"
13787                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13788                       "for (var i = 0; i < 10; ++i) {"
13789                       "  result = pa_load(just_ints);"
13790                       "}"
13791                       "result");
13792   CHECK_EQ(32640, result->Int32Value());
13793
13794   // Make sure that pixel array ICs recognize out-of-bound accesses.
13795   result = CompileRun("function pa_load(p, start) {"
13796                       "  var sum = 0;"
13797                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
13798                       "  return sum;"
13799                       "}"
13800                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13801                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
13802                       "for (var i = 0; i < 10; ++i) {"
13803                       "  result = pa_load(pixels,-10);"
13804                       "}"
13805                       "result");
13806   CHECK_EQ(0, result->Int32Value());
13807
13808   // Make sure that generic ICs properly handles a pixel array.
13809   result = CompileRun("function pa_load(p) {"
13810                       "  var sum = 0;"
13811                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
13812                       "  return sum;"
13813                       "}"
13814                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13815                       "just_ints = new Object();"
13816                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13817                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
13818                       "for (var i = 0; i < 10; ++i) {"
13819                       "  result = pa_load(pixels);"
13820                       "}"
13821                       "result");
13822   CHECK_EQ(32640, result->Int32Value());
13823
13824   // Make sure that generic load ICs recognize out-of-bound accesses in
13825   // pixel arrays.
13826   result = CompileRun("function pa_load(p, start) {"
13827                       "  var sum = 0;"
13828                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
13829                       "  return sum;"
13830                       "}"
13831                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13832                       "just_ints = new Object();"
13833                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13834                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
13835                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
13836                       "for (var i = 0; i < 10; ++i) {"
13837                       "  result = pa_load(pixels,-10);"
13838                       "}"
13839                       "result");
13840   CHECK_EQ(0, result->Int32Value());
13841
13842   // Make sure that generic ICs properly handles other types than pixel
13843   // arrays (that the inlined fast pixel array test leaves the right information
13844   // in the right registers).
13845   result = CompileRun("function pa_load(p) {"
13846                       "  var sum = 0;"
13847                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
13848                       "  return sum;"
13849                       "}"
13850                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13851                       "just_ints = new Object();"
13852                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13853                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
13854                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
13855                       "sparse_array = new Object();"
13856                       "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
13857                       "sparse_array[1000000] = 3;"
13858                       "for (var i = 0; i < 10; ++i) {"
13859                       "  result = pa_load(sparse_array);"
13860                       "}"
13861                       "result");
13862   CHECK_EQ(32640, result->Int32Value());
13863
13864   // Make sure that pixel array store ICs clamp values correctly.
13865   result = CompileRun("function pa_store(p) {"
13866                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
13867                       "}"
13868                       "pa_store(pixels);"
13869                       "var sum = 0;"
13870                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13871                       "sum");
13872   CHECK_EQ(48896, result->Int32Value());
13873
13874   // Make sure that pixel array stores correctly handle accesses outside
13875   // of the pixel array..
13876   result = CompileRun("function pa_store(p,start) {"
13877                       "  for (var j = 0; j < 256; j++) {"
13878                       "    p[j+start] = j * 2;"
13879                       "  }"
13880                       "}"
13881                       "pa_store(pixels,0);"
13882                       "pa_store(pixels,-128);"
13883                       "var sum = 0;"
13884                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13885                       "sum");
13886   CHECK_EQ(65280, result->Int32Value());
13887
13888   // Make sure that the generic store stub correctly handle accesses outside
13889   // of the pixel array..
13890   result = CompileRun("function pa_store(p,start) {"
13891                       "  for (var j = 0; j < 256; j++) {"
13892                       "    p[j+start] = j * 2;"
13893                       "  }"
13894                       "}"
13895                       "pa_store(pixels,0);"
13896                       "just_ints = new Object();"
13897                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13898                       "pa_store(just_ints, 0);"
13899                       "pa_store(pixels,-128);"
13900                       "var sum = 0;"
13901                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13902                       "sum");
13903   CHECK_EQ(65280, result->Int32Value());
13904
13905   // Make sure that the generic keyed store stub clamps pixel array values
13906   // correctly.
13907   result = CompileRun("function pa_store(p) {"
13908                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
13909                       "}"
13910                       "pa_store(pixels);"
13911                       "just_ints = new Object();"
13912                       "pa_store(just_ints);"
13913                       "pa_store(pixels);"
13914                       "var sum = 0;"
13915                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13916                       "sum");
13917   CHECK_EQ(48896, result->Int32Value());
13918
13919   // Make sure that pixel array loads are optimized by crankshaft.
13920   result = CompileRun("function pa_load(p) {"
13921                       "  var sum = 0;"
13922                       "  for (var i=0; i<256; ++i) {"
13923                       "    sum += p[i];"
13924                       "  }"
13925                       "  return sum; "
13926                       "}"
13927                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13928                       "for (var i = 0; i < 5000; ++i) {"
13929                       "  result = pa_load(pixels);"
13930                       "}"
13931                       "result");
13932   CHECK_EQ(32640, result->Int32Value());
13933
13934   // Make sure that pixel array stores are optimized by crankshaft.
13935   result = CompileRun("function pa_init(p) {"
13936                       "for (var i = 0; i < 256; ++i) { p[i] = i; }"
13937                       "}"
13938                       "function pa_load(p) {"
13939                       "  var sum = 0;"
13940                       "  for (var i=0; i<256; ++i) {"
13941                       "    sum += p[i];"
13942                       "  }"
13943                       "  return sum; "
13944                       "}"
13945                       "for (var i = 0; i < 5000; ++i) {"
13946                       "  pa_init(pixels);"
13947                       "}"
13948                       "result = pa_load(pixels);"
13949                       "result");
13950   CHECK_EQ(32640, result->Int32Value());
13951
13952   free(pixel_data);
13953 }
13954
13955
13956 THREADED_TEST(PixelArrayInfo) {
13957   LocalContext context;
13958   v8::HandleScope scope(context->GetIsolate());
13959   for (int size = 0; size < 100; size += 10) {
13960     uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
13961     v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
13962     obj->SetIndexedPropertiesToPixelData(pixel_data, size);
13963     CHECK(obj->HasIndexedPropertiesInPixelData());
13964     CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
13965     CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
13966     free(pixel_data);
13967   }
13968 }
13969
13970
13971 static void NotHandledIndexedPropertyGetter(
13972     uint32_t index,
13973     const v8::PropertyCallbackInfo<v8::Value>& info) {
13974   ApiTestFuzzer::Fuzz();
13975 }
13976
13977
13978 static void NotHandledIndexedPropertySetter(
13979     uint32_t index,
13980     Local<Value> value,
13981     const v8::PropertyCallbackInfo<v8::Value>& info) {
13982   ApiTestFuzzer::Fuzz();
13983 }
13984
13985
13986 THREADED_TEST(PixelArrayWithInterceptor) {
13987   LocalContext context;
13988   i::Factory* factory = CcTest::i_isolate()->factory();
13989   v8::Isolate* isolate = context->GetIsolate();
13990   v8::HandleScope scope(isolate);
13991   const int kElementCount = 260;
13992   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
13993   i::Handle<i::ExternalUint8ClampedArray> pixels =
13994       i::Handle<i::ExternalUint8ClampedArray>::cast(
13995           factory->NewExternalArray(kElementCount,
13996                                     v8::kExternalUint8ClampedArray,
13997                                     pixel_data));
13998   for (int i = 0; i < kElementCount; i++) {
13999     pixels->set(i, i % 256);
14000   }
14001   v8::Handle<v8::ObjectTemplate> templ =
14002       v8::ObjectTemplate::New(context->GetIsolate());
14003   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
14004       NotHandledIndexedPropertyGetter, NotHandledIndexedPropertySetter));
14005   v8::Handle<v8::Object> obj = templ->NewInstance();
14006   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
14007   context->Global()->Set(v8_str("pixels"), obj);
14008   v8::Handle<v8::Value> result = CompileRun("pixels[1]");
14009   CHECK_EQ(1, result->Int32Value());
14010   result = CompileRun("var sum = 0;"
14011                       "for (var i = 0; i < 8; i++) {"
14012                       "  sum += pixels[i] = pixels[i] = -i;"
14013                       "}"
14014                       "sum;");
14015   CHECK_EQ(-28, result->Int32Value());
14016   result = CompileRun("pixels.hasOwnProperty('1')");
14017   CHECK(result->BooleanValue());
14018   free(pixel_data);
14019 }
14020
14021
14022 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
14023   switch (array_type) {
14024     case v8::kExternalInt8Array:
14025     case v8::kExternalUint8Array:
14026     case v8::kExternalUint8ClampedArray:
14027       return 1;
14028       break;
14029     case v8::kExternalInt16Array:
14030     case v8::kExternalUint16Array:
14031       return 2;
14032       break;
14033     case v8::kExternalInt32Array:
14034     case v8::kExternalUint32Array:
14035     case v8::kExternalFloat32Array:
14036       return 4;
14037       break;
14038     case v8::kExternalFloat64Array:
14039       return 8;
14040       break;
14041     default:
14042       UNREACHABLE();
14043       return -1;
14044   }
14045   UNREACHABLE();
14046   return -1;
14047 }
14048
14049
14050 template <class ExternalArrayClass, class ElementType>
14051 static void ObjectWithExternalArrayTestHelper(
14052     Handle<Context> context,
14053     v8::Handle<Object> obj,
14054     int element_count,
14055     v8::ExternalArrayType array_type,
14056     int64_t low, int64_t high) {
14057   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
14058   i::Isolate* isolate = jsobj->GetIsolate();
14059   obj->Set(v8_str("field"),
14060            v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
14061   context->Global()->Set(v8_str("ext_array"), obj);
14062   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
14063   CHECK_EQ(1503, result->Int32Value());
14064   result = CompileRun("ext_array[1]");
14065   CHECK_EQ(1, result->Int32Value());
14066
14067   // Check assigned smis
14068   result = CompileRun("for (var i = 0; i < 8; i++) {"
14069                       "  ext_array[i] = i;"
14070                       "}"
14071                       "var sum = 0;"
14072                       "for (var i = 0; i < 8; i++) {"
14073                       "  sum += ext_array[i];"
14074                       "}"
14075                       "sum;");
14076
14077   CHECK_EQ(28, result->Int32Value());
14078   // Check pass through of assigned smis
14079   result = CompileRun("var sum = 0;"
14080                       "for (var i = 0; i < 8; i++) {"
14081                       "  sum += ext_array[i] = ext_array[i] = -i;"
14082                       "}"
14083                       "sum;");
14084   CHECK_EQ(-28, result->Int32Value());
14085
14086
14087   // Check assigned smis in reverse order
14088   result = CompileRun("for (var i = 8; --i >= 0; ) {"
14089                       "  ext_array[i] = i;"
14090                       "}"
14091                       "var sum = 0;"
14092                       "for (var i = 0; i < 8; i++) {"
14093                       "  sum += ext_array[i];"
14094                       "}"
14095                       "sum;");
14096   CHECK_EQ(28, result->Int32Value());
14097
14098   // Check pass through of assigned HeapNumbers
14099   result = CompileRun("var sum = 0;"
14100                       "for (var i = 0; i < 16; i+=2) {"
14101                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
14102                       "}"
14103                       "sum;");
14104   CHECK_EQ(-28, result->Int32Value());
14105
14106   // Check assigned HeapNumbers
14107   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
14108                       "  ext_array[i] = (i * 0.5);"
14109                       "}"
14110                       "var sum = 0;"
14111                       "for (var i = 0; i < 16; i+=2) {"
14112                       "  sum += ext_array[i];"
14113                       "}"
14114                       "sum;");
14115   CHECK_EQ(28, result->Int32Value());
14116
14117   // Check assigned HeapNumbers in reverse order
14118   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
14119                       "  ext_array[i] = (i * 0.5);"
14120                       "}"
14121                       "var sum = 0;"
14122                       "for (var i = 0; i < 16; i+=2) {"
14123                       "  sum += ext_array[i];"
14124                       "}"
14125                       "sum;");
14126   CHECK_EQ(28, result->Int32Value());
14127
14128   i::ScopedVector<char> test_buf(1024);
14129
14130   // Check legal boundary conditions.
14131   // The repeated loads and stores ensure the ICs are exercised.
14132   const char* boundary_program =
14133       "var res = 0;"
14134       "for (var i = 0; i < 16; i++) {"
14135       "  ext_array[i] = %lld;"
14136       "  if (i > 8) {"
14137       "    res = ext_array[i];"
14138       "  }"
14139       "}"
14140       "res;";
14141   i::SNPrintF(test_buf,
14142               boundary_program,
14143               low);
14144   result = CompileRun(test_buf.start());
14145   CHECK_EQ(low, result->IntegerValue());
14146
14147   i::SNPrintF(test_buf,
14148               boundary_program,
14149               high);
14150   result = CompileRun(test_buf.start());
14151   CHECK_EQ(high, result->IntegerValue());
14152
14153   // Check misprediction of type in IC.
14154   result = CompileRun("var tmp_array = ext_array;"
14155                       "var sum = 0;"
14156                       "for (var i = 0; i < 8; i++) {"
14157                       "  tmp_array[i] = i;"
14158                       "  sum += tmp_array[i];"
14159                       "  if (i == 4) {"
14160                       "    tmp_array = {};"
14161                       "  }"
14162                       "}"
14163                       "sum;");
14164   // Force GC to trigger verification.
14165   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
14166   CHECK_EQ(28, result->Int32Value());
14167
14168   // Make sure out-of-range loads do not throw.
14169   i::SNPrintF(test_buf,
14170               "var caught_exception = false;"
14171               "try {"
14172               "  ext_array[%d];"
14173               "} catch (e) {"
14174               "  caught_exception = true;"
14175               "}"
14176               "caught_exception;",
14177               element_count);
14178   result = CompileRun(test_buf.start());
14179   CHECK_EQ(false, result->BooleanValue());
14180
14181   // Make sure out-of-range stores do not throw.
14182   i::SNPrintF(test_buf,
14183               "var caught_exception = false;"
14184               "try {"
14185               "  ext_array[%d] = 1;"
14186               "} catch (e) {"
14187               "  caught_exception = true;"
14188               "}"
14189               "caught_exception;",
14190               element_count);
14191   result = CompileRun(test_buf.start());
14192   CHECK_EQ(false, result->BooleanValue());
14193
14194   // Check other boundary conditions, values and operations.
14195   result = CompileRun("for (var i = 0; i < 8; i++) {"
14196                       "  ext_array[7] = undefined;"
14197                       "}"
14198                       "ext_array[7];");
14199   CHECK_EQ(0, result->Int32Value());
14200   if (array_type == v8::kExternalFloat64Array ||
14201       array_type == v8::kExternalFloat32Array) {
14202     CHECK(std::isnan(
14203         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
14204   } else {
14205     CheckElementValue(isolate, 0, jsobj, 7);
14206   }
14207
14208   result = CompileRun("for (var i = 0; i < 8; i++) {"
14209                       "  ext_array[6] = '2.3';"
14210                       "}"
14211                       "ext_array[6];");
14212   CHECK_EQ(2, result->Int32Value());
14213   CHECK_EQ(2,
14214            static_cast<int>(
14215                i::Object::GetElement(
14216                    isolate, jsobj, 6).ToHandleChecked()->Number()));
14217
14218   if (array_type != v8::kExternalFloat32Array &&
14219       array_type != v8::kExternalFloat64Array) {
14220     // Though the specification doesn't state it, be explicit about
14221     // converting NaNs and +/-Infinity to zero.
14222     result = CompileRun("for (var i = 0; i < 8; i++) {"
14223                         "  ext_array[i] = 5;"
14224                         "}"
14225                         "for (var i = 0; i < 8; i++) {"
14226                         "  ext_array[i] = NaN;"
14227                         "}"
14228                         "ext_array[5];");
14229     CHECK_EQ(0, result->Int32Value());
14230     CheckElementValue(isolate, 0, jsobj, 5);
14231
14232     result = CompileRun("for (var i = 0; i < 8; i++) {"
14233                         "  ext_array[i] = 5;"
14234                         "}"
14235                         "for (var i = 0; i < 8; i++) {"
14236                         "  ext_array[i] = Infinity;"
14237                         "}"
14238                         "ext_array[5];");
14239     int expected_value =
14240         (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
14241     CHECK_EQ(expected_value, result->Int32Value());
14242     CheckElementValue(isolate, expected_value, jsobj, 5);
14243
14244     result = CompileRun("for (var i = 0; i < 8; i++) {"
14245                         "  ext_array[i] = 5;"
14246                         "}"
14247                         "for (var i = 0; i < 8; i++) {"
14248                         "  ext_array[i] = -Infinity;"
14249                         "}"
14250                         "ext_array[5];");
14251     CHECK_EQ(0, result->Int32Value());
14252     CheckElementValue(isolate, 0, jsobj, 5);
14253
14254     // Check truncation behavior of integral arrays.
14255     const char* unsigned_data =
14256         "var source_data = [0.6, 10.6];"
14257         "var expected_results = [0, 10];";
14258     const char* signed_data =
14259         "var source_data = [0.6, 10.6, -0.6, -10.6];"
14260         "var expected_results = [0, 10, 0, -10];";
14261     const char* pixel_data =
14262         "var source_data = [0.6, 10.6];"
14263         "var expected_results = [1, 11];";
14264     bool is_unsigned =
14265         (array_type == v8::kExternalUint8Array ||
14266          array_type == v8::kExternalUint16Array ||
14267          array_type == v8::kExternalUint32Array);
14268     bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
14269
14270     i::SNPrintF(test_buf,
14271                 "%s"
14272                 "var all_passed = true;"
14273                 "for (var i = 0; i < source_data.length; i++) {"
14274                 "  for (var j = 0; j < 8; j++) {"
14275                 "    ext_array[j] = source_data[i];"
14276                 "  }"
14277                 "  all_passed = all_passed &&"
14278                 "               (ext_array[5] == expected_results[i]);"
14279                 "}"
14280                 "all_passed;",
14281                 (is_unsigned ?
14282                      unsigned_data :
14283                      (is_pixel_data ? pixel_data : signed_data)));
14284     result = CompileRun(test_buf.start());
14285     CHECK_EQ(true, result->BooleanValue());
14286   }
14287
14288   i::Handle<ExternalArrayClass> array(
14289       ExternalArrayClass::cast(jsobj->elements()));
14290   for (int i = 0; i < element_count; i++) {
14291     array->set(i, static_cast<ElementType>(i));
14292   }
14293
14294   // Test complex assignments
14295   result = CompileRun("function ee_op_test_complex_func(sum) {"
14296                       " for (var i = 0; i < 40; ++i) {"
14297                       "   sum += (ext_array[i] += 1);"
14298                       "   sum += (ext_array[i] -= 1);"
14299                       " } "
14300                       " return sum;"
14301                       "}"
14302                       "sum=0;"
14303                       "for (var i=0;i<10000;++i) {"
14304                       "  sum=ee_op_test_complex_func(sum);"
14305                       "}"
14306                       "sum;");
14307   CHECK_EQ(16000000, result->Int32Value());
14308
14309   // Test count operations
14310   result = CompileRun("function ee_op_test_count_func(sum) {"
14311                       " for (var i = 0; i < 40; ++i) {"
14312                       "   sum += (++ext_array[i]);"
14313                       "   sum += (--ext_array[i]);"
14314                       " } "
14315                       " return sum;"
14316                       "}"
14317                       "sum=0;"
14318                       "for (var i=0;i<10000;++i) {"
14319                       "  sum=ee_op_test_count_func(sum);"
14320                       "}"
14321                       "sum;");
14322   CHECK_EQ(16000000, result->Int32Value());
14323
14324   result = CompileRun("ext_array[3] = 33;"
14325                       "delete ext_array[3];"
14326                       "ext_array[3];");
14327   CHECK_EQ(33, result->Int32Value());
14328
14329   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
14330                       "ext_array[2] = 12; ext_array[3] = 13;"
14331                       "ext_array.__defineGetter__('2',"
14332                       "function() { return 120; });"
14333                       "ext_array[2];");
14334   CHECK_EQ(12, result->Int32Value());
14335
14336   result = CompileRun("var js_array = new Array(40);"
14337                       "js_array[0] = 77;"
14338                       "js_array;");
14339   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
14340
14341   result = CompileRun("ext_array[1] = 23;"
14342                       "ext_array.__proto__ = [];"
14343                       "js_array.__proto__ = ext_array;"
14344                       "js_array.concat(ext_array);");
14345   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
14346   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
14347
14348   result = CompileRun("ext_array[1] = 23;");
14349   CHECK_EQ(23, result->Int32Value());
14350 }
14351
14352
14353 template <class FixedTypedArrayClass,
14354           i::ElementsKind elements_kind,
14355           class ElementType>
14356 static void FixedTypedArrayTestHelper(
14357     v8::ExternalArrayType array_type,
14358     ElementType low,
14359     ElementType high) {
14360   i::FLAG_allow_natives_syntax = true;
14361   LocalContext context;
14362   i::Isolate* isolate = CcTest::i_isolate();
14363   i::Factory* factory = isolate->factory();
14364   v8::HandleScope scope(context->GetIsolate());
14365   const int kElementCount = 260;
14366   i::Handle<FixedTypedArrayClass> fixed_array =
14367     i::Handle<FixedTypedArrayClass>::cast(
14368         factory->NewFixedTypedArray(kElementCount, array_type));
14369   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
14370            fixed_array->map()->instance_type());
14371   CHECK_EQ(kElementCount, fixed_array->length());
14372   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
14373   for (int i = 0; i < kElementCount; i++) {
14374     fixed_array->set(i, static_cast<ElementType>(i));
14375   }
14376   // Force GC to trigger verification.
14377   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
14378   for (int i = 0; i < kElementCount; i++) {
14379     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
14380              static_cast<int64_t>(fixed_array->get_scalar(i)));
14381   }
14382   v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
14383   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
14384   i::Handle<i::Map> fixed_array_map =
14385       i::JSObject::GetElementsTransitionMap(jsobj, elements_kind);
14386   jsobj->set_map(*fixed_array_map);
14387   jsobj->set_elements(*fixed_array);
14388
14389   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
14390       context.local(), obj, kElementCount, array_type,
14391       static_cast<int64_t>(low),
14392       static_cast<int64_t>(high));
14393 }
14394
14395
14396 THREADED_TEST(FixedUint8Array) {
14397   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
14398     v8::kExternalUint8Array,
14399     0x0, 0xFF);
14400 }
14401
14402
14403 THREADED_TEST(FixedUint8ClampedArray) {
14404   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
14405                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
14406     v8::kExternalUint8ClampedArray,
14407     0x0, 0xFF);
14408 }
14409
14410
14411 THREADED_TEST(FixedInt8Array) {
14412   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
14413     v8::kExternalInt8Array,
14414     -0x80, 0x7F);
14415 }
14416
14417
14418 THREADED_TEST(FixedUint16Array) {
14419   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
14420     v8::kExternalUint16Array,
14421     0x0, 0xFFFF);
14422 }
14423
14424
14425 THREADED_TEST(FixedInt16Array) {
14426   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
14427     v8::kExternalInt16Array,
14428     -0x8000, 0x7FFF);
14429 }
14430
14431
14432 THREADED_TEST(FixedUint32Array) {
14433   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
14434     v8::kExternalUint32Array,
14435     0x0, UINT_MAX);
14436 }
14437
14438
14439 THREADED_TEST(FixedInt32Array) {
14440   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
14441     v8::kExternalInt32Array,
14442     INT_MIN, INT_MAX);
14443 }
14444
14445
14446 THREADED_TEST(FixedFloat32Array) {
14447   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
14448     v8::kExternalFloat32Array,
14449     -500, 500);
14450 }
14451
14452
14453 THREADED_TEST(FixedFloat64Array) {
14454   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
14455     v8::kExternalFloat64Array,
14456     -500, 500);
14457 }
14458
14459
14460 template <class ExternalArrayClass, class ElementType>
14461 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
14462                                     int64_t low,
14463                                     int64_t high) {
14464   LocalContext context;
14465   i::Isolate* isolate = CcTest::i_isolate();
14466   i::Factory* factory = isolate->factory();
14467   v8::HandleScope scope(context->GetIsolate());
14468   const int kElementCount = 40;
14469   int element_size = ExternalArrayElementSize(array_type);
14470   ElementType* array_data =
14471       static_cast<ElementType*>(malloc(kElementCount * element_size));
14472   i::Handle<ExternalArrayClass> array =
14473       i::Handle<ExternalArrayClass>::cast(
14474           factory->NewExternalArray(kElementCount, array_type, array_data));
14475   // Force GC to trigger verification.
14476   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
14477   for (int i = 0; i < kElementCount; i++) {
14478     array->set(i, static_cast<ElementType>(i));
14479   }
14480   // Force GC to trigger verification.
14481   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
14482   for (int i = 0; i < kElementCount; i++) {
14483     CHECK_EQ(static_cast<int64_t>(i),
14484              static_cast<int64_t>(array->get_scalar(i)));
14485     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
14486   }
14487
14488   v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
14489   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
14490   // Set the elements to be the external array.
14491   obj->SetIndexedPropertiesToExternalArrayData(array_data,
14492                                                array_type,
14493                                                kElementCount);
14494   CHECK_EQ(1,
14495            static_cast<int>(
14496                i::Object::GetElement(
14497                    isolate, jsobj, 1).ToHandleChecked()->Number()));
14498
14499   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
14500       context.local(), obj, kElementCount, array_type, low, high);
14501
14502   v8::Handle<v8::Value> result;
14503
14504   // Test more complex manipulations which cause eax to contain values
14505   // that won't be completely overwritten by loads from the arrays.
14506   // This catches bugs in the instructions used for the KeyedLoadIC
14507   // for byte and word types.
14508   {
14509     const int kXSize = 300;
14510     const int kYSize = 300;
14511     const int kLargeElementCount = kXSize * kYSize * 4;
14512     ElementType* large_array_data =
14513         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
14514     v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
14515     // Set the elements to be the external array.
14516     large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
14517                                                        array_type,
14518                                                        kLargeElementCount);
14519     context->Global()->Set(v8_str("large_array"), large_obj);
14520     // Initialize contents of a few rows.
14521     for (int x = 0; x < 300; x++) {
14522       int row = 0;
14523       int offset = row * 300 * 4;
14524       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
14525       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
14526       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
14527       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
14528       row = 150;
14529       offset = row * 300 * 4;
14530       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
14531       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
14532       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
14533       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
14534       row = 298;
14535       offset = row * 300 * 4;
14536       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
14537       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
14538       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
14539       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
14540     }
14541     // The goal of the code below is to make "offset" large enough
14542     // that the computation of the index (which goes into eax) has
14543     // high bits set which will not be overwritten by a byte or short
14544     // load.
14545     result = CompileRun("var failed = false;"
14546                         "var offset = 0;"
14547                         "for (var i = 0; i < 300; i++) {"
14548                         "  if (large_array[4 * i] != 127 ||"
14549                         "      large_array[4 * i + 1] != 0 ||"
14550                         "      large_array[4 * i + 2] != 0 ||"
14551                         "      large_array[4 * i + 3] != 127) {"
14552                         "    failed = true;"
14553                         "  }"
14554                         "}"
14555                         "offset = 150 * 300 * 4;"
14556                         "for (var i = 0; i < 300; i++) {"
14557                         "  if (large_array[offset + 4 * i] != 127 ||"
14558                         "      large_array[offset + 4 * i + 1] != 0 ||"
14559                         "      large_array[offset + 4 * i + 2] != 0 ||"
14560                         "      large_array[offset + 4 * i + 3] != 127) {"
14561                         "    failed = true;"
14562                         "  }"
14563                         "}"
14564                         "offset = 298 * 300 * 4;"
14565                         "for (var i = 0; i < 300; i++) {"
14566                         "  if (large_array[offset + 4 * i] != 127 ||"
14567                         "      large_array[offset + 4 * i + 1] != 0 ||"
14568                         "      large_array[offset + 4 * i + 2] != 0 ||"
14569                         "      large_array[offset + 4 * i + 3] != 127) {"
14570                         "    failed = true;"
14571                         "  }"
14572                         "}"
14573                         "!failed;");
14574     CHECK_EQ(true, result->BooleanValue());
14575     free(large_array_data);
14576   }
14577
14578   // The "" property descriptor is overloaded to store information about
14579   // the external array. Ensure that setting and accessing the "" property
14580   // works (it should overwrite the information cached about the external
14581   // array in the DescriptorArray) in various situations.
14582   result = CompileRun("ext_array[''] = 23; ext_array['']");
14583   CHECK_EQ(23, result->Int32Value());
14584
14585   // Property "" set after the external array is associated with the object.
14586   {
14587     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
14588     obj2->Set(v8_str("ee_test_field"),
14589               v8::Int32::New(context->GetIsolate(), 256));
14590     obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
14591     // Set the elements to be the external array.
14592     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
14593                                                   array_type,
14594                                                   kElementCount);
14595     context->Global()->Set(v8_str("ext_array"), obj2);
14596     result = CompileRun("ext_array['']");
14597     CHECK_EQ(1503, result->Int32Value());
14598   }
14599
14600   // Property "" set after the external array is associated with the object.
14601   {
14602     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
14603     obj2->Set(v8_str("ee_test_field_2"),
14604               v8::Int32::New(context->GetIsolate(), 256));
14605     // Set the elements to be the external array.
14606     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
14607                                                   array_type,
14608                                                   kElementCount);
14609     obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
14610     context->Global()->Set(v8_str("ext_array"), obj2);
14611     result = CompileRun("ext_array['']");
14612     CHECK_EQ(1503, result->Int32Value());
14613   }
14614
14615   // Should reuse the map from previous test.
14616   {
14617     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
14618     obj2->Set(v8_str("ee_test_field_2"),
14619               v8::Int32::New(context->GetIsolate(), 256));
14620     // Set the elements to be the external array. Should re-use the map
14621     // from previous test.
14622     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
14623                                                   array_type,
14624                                                   kElementCount);
14625     context->Global()->Set(v8_str("ext_array"), obj2);
14626     result = CompileRun("ext_array['']");
14627   }
14628
14629   // Property "" is a constant function that shouldn't not be interfered with
14630   // when an external array is set.
14631   {
14632     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
14633     // Start
14634     obj2->Set(v8_str("ee_test_field3"),
14635               v8::Int32::New(context->GetIsolate(), 256));
14636
14637     // Add a constant function to an object.
14638     context->Global()->Set(v8_str("ext_array"), obj2);
14639     result = CompileRun("ext_array[''] = function() {return 1503;};"
14640                         "ext_array['']();");
14641
14642     // Add an external array transition to the same map that
14643     // has the constant transition.
14644     v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
14645     obj3->Set(v8_str("ee_test_field3"),
14646               v8::Int32::New(context->GetIsolate(), 256));
14647     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
14648                                                   array_type,
14649                                                   kElementCount);
14650     context->Global()->Set(v8_str("ext_array"), obj3);
14651   }
14652
14653   // If a external array transition is in the map, it should get clobbered
14654   // by a constant function.
14655   {
14656     // Add an external array transition.
14657     v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
14658     obj3->Set(v8_str("ee_test_field4"),
14659               v8::Int32::New(context->GetIsolate(), 256));
14660     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
14661                                                   array_type,
14662                                                   kElementCount);
14663
14664     // Add a constant function to the same map that just got an external array
14665     // transition.
14666     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
14667     obj2->Set(v8_str("ee_test_field4"),
14668               v8::Int32::New(context->GetIsolate(), 256));
14669     context->Global()->Set(v8_str("ext_array"), obj2);
14670     result = CompileRun("ext_array[''] = function() {return 1503;};"
14671                         "ext_array['']();");
14672   }
14673
14674   free(array_data);
14675 }
14676
14677
14678 THREADED_TEST(ExternalInt8Array) {
14679   ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
14680       v8::kExternalInt8Array,
14681       -128,
14682       127);
14683 }
14684
14685
14686 THREADED_TEST(ExternalUint8Array) {
14687   ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
14688       v8::kExternalUint8Array,
14689       0,
14690       255);
14691 }
14692
14693
14694 THREADED_TEST(ExternalUint8ClampedArray) {
14695   ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
14696       v8::kExternalUint8ClampedArray,
14697       0,
14698       255);
14699 }
14700
14701
14702 THREADED_TEST(ExternalInt16Array) {
14703   ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
14704       v8::kExternalInt16Array,
14705       -32768,
14706       32767);
14707 }
14708
14709
14710 THREADED_TEST(ExternalUint16Array) {
14711   ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
14712       v8::kExternalUint16Array,
14713       0,
14714       65535);
14715 }
14716
14717
14718 THREADED_TEST(ExternalInt32Array) {
14719   ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
14720       v8::kExternalInt32Array,
14721       INT_MIN,   // -2147483648
14722       INT_MAX);  //  2147483647
14723 }
14724
14725
14726 THREADED_TEST(ExternalUint32Array) {
14727   ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
14728       v8::kExternalUint32Array,
14729       0,
14730       UINT_MAX);  // 4294967295
14731 }
14732
14733
14734 THREADED_TEST(ExternalFloat32Array) {
14735   ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
14736       v8::kExternalFloat32Array,
14737       -500,
14738       500);
14739 }
14740
14741
14742 THREADED_TEST(ExternalFloat64Array) {
14743   ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
14744       v8::kExternalFloat64Array,
14745       -500,
14746       500);
14747 }
14748
14749
14750 THREADED_TEST(ExternalArrays) {
14751   TestExternalInt8Array();
14752   TestExternalUint8Array();
14753   TestExternalInt16Array();
14754   TestExternalUint16Array();
14755   TestExternalInt32Array();
14756   TestExternalUint32Array();
14757   TestExternalFloat32Array();
14758 }
14759
14760
14761 void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
14762   LocalContext context;
14763   v8::HandleScope scope(context->GetIsolate());
14764   for (int size = 0; size < 100; size += 10) {
14765     int element_size = ExternalArrayElementSize(array_type);
14766     void* external_data = malloc(size * element_size);
14767     v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
14768     obj->SetIndexedPropertiesToExternalArrayData(
14769         external_data, array_type, size);
14770     CHECK(obj->HasIndexedPropertiesInExternalArrayData());
14771     CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
14772     CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
14773     CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
14774     free(external_data);
14775   }
14776 }
14777
14778
14779 THREADED_TEST(ExternalArrayInfo) {
14780   ExternalArrayInfoTestHelper(v8::kExternalInt8Array);
14781   ExternalArrayInfoTestHelper(v8::kExternalUint8Array);
14782   ExternalArrayInfoTestHelper(v8::kExternalInt16Array);
14783   ExternalArrayInfoTestHelper(v8::kExternalUint16Array);
14784   ExternalArrayInfoTestHelper(v8::kExternalInt32Array);
14785   ExternalArrayInfoTestHelper(v8::kExternalUint32Array);
14786   ExternalArrayInfoTestHelper(v8::kExternalFloat32Array);
14787   ExternalArrayInfoTestHelper(v8::kExternalFloat64Array);
14788   ExternalArrayInfoTestHelper(v8::kExternalUint8ClampedArray);
14789 }
14790
14791
14792 void ExtArrayLimitsHelper(v8::Isolate* isolate,
14793                           v8::ExternalArrayType array_type,
14794                           int size) {
14795   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
14796   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
14797   last_location = last_message = NULL;
14798   obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
14799   CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
14800   CHECK(last_location);
14801   CHECK(last_message);
14802 }
14803
14804
14805 TEST(ExternalArrayLimits) {
14806   LocalContext context;
14807   v8::Isolate* isolate = context->GetIsolate();
14808   v8::HandleScope scope(isolate);
14809   ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
14810   ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
14811   ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
14812   ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
14813   ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
14814   ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
14815   ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
14816   ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
14817   ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
14818   ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
14819   ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
14820   ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
14821   ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
14822   ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
14823   ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
14824   ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
14825   ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0x40000000);
14826   ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0xffffffff);
14827 }
14828
14829
14830 template <typename ElementType, typename TypedArray,
14831           class ExternalArrayClass>
14832 void TypedArrayTestHelper(v8::ExternalArrayType array_type,
14833                           int64_t low, int64_t high) {
14834   const int kElementCount = 50;
14835
14836   i::ScopedVector<ElementType> backing_store(kElementCount+2);
14837
14838   LocalContext env;
14839   v8::Isolate* isolate = env->GetIsolate();
14840   v8::HandleScope handle_scope(isolate);
14841
14842   Local<v8::ArrayBuffer> ab =
14843       v8::ArrayBuffer::New(isolate, backing_store.start(),
14844                            (kElementCount + 2) * sizeof(ElementType));
14845   Local<TypedArray> ta =
14846       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
14847   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
14848   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
14849   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
14850   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
14851   CHECK(ab->Equals(ta->Buffer()));
14852
14853   ElementType* data = backing_store.start() + 2;
14854   for (int i = 0; i < kElementCount; i++) {
14855     data[i] = static_cast<ElementType>(i);
14856   }
14857
14858   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
14859       env.local(), ta, kElementCount, array_type, low, high);
14860 }
14861
14862
14863 THREADED_TEST(Uint8Array) {
14864   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
14865       v8::kExternalUint8Array, 0, 0xFF);
14866 }
14867
14868
14869 THREADED_TEST(Int8Array) {
14870   TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
14871       v8::kExternalInt8Array, -0x80, 0x7F);
14872 }
14873
14874
14875 THREADED_TEST(Uint16Array) {
14876   TypedArrayTestHelper<uint16_t,
14877                        v8::Uint16Array,
14878                        i::ExternalUint16Array>(
14879       v8::kExternalUint16Array, 0, 0xFFFF);
14880 }
14881
14882
14883 THREADED_TEST(Int16Array) {
14884   TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
14885       v8::kExternalInt16Array, -0x8000, 0x7FFF);
14886 }
14887
14888
14889 THREADED_TEST(Uint32Array) {
14890   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
14891       v8::kExternalUint32Array, 0, UINT_MAX);
14892 }
14893
14894
14895 THREADED_TEST(Int32Array) {
14896   TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
14897       v8::kExternalInt32Array, INT_MIN, INT_MAX);
14898 }
14899
14900
14901 THREADED_TEST(Float32Array) {
14902   TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
14903       v8::kExternalFloat32Array, -500, 500);
14904 }
14905
14906
14907 THREADED_TEST(Float64Array) {
14908   TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
14909       v8::kExternalFloat64Array, -500, 500);
14910 }
14911
14912
14913 THREADED_TEST(Uint8ClampedArray) {
14914   TypedArrayTestHelper<uint8_t,
14915                        v8::Uint8ClampedArray, i::ExternalUint8ClampedArray>(
14916       v8::kExternalUint8ClampedArray, 0, 0xFF);
14917 }
14918
14919
14920 THREADED_TEST(DataView) {
14921   const int kSize = 50;
14922
14923   i::ScopedVector<uint8_t> backing_store(kSize+2);
14924
14925   LocalContext env;
14926   v8::Isolate* isolate = env->GetIsolate();
14927   v8::HandleScope handle_scope(isolate);
14928
14929   Local<v8::ArrayBuffer> ab =
14930       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
14931   Local<v8::DataView> dv =
14932       v8::DataView::New(ab, 2, kSize);
14933   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
14934   CHECK_EQ(2u, dv->ByteOffset());
14935   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
14936   CHECK(ab->Equals(dv->Buffer()));
14937 }
14938
14939
14940 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
14941   THREADED_TEST(Is##View) {                                                   \
14942     LocalContext env;                                                         \
14943     v8::Isolate* isolate = env->GetIsolate();                                 \
14944     v8::HandleScope handle_scope(isolate);                                    \
14945                                                                               \
14946     Handle<Value> result = CompileRun(                                        \
14947         "var ab = new ArrayBuffer(128);"                                      \
14948         "new " #View "(ab)");                                                 \
14949     CHECK(result->IsArrayBufferView());                                       \
14950     CHECK(result->Is##View());                                                \
14951     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
14952   }
14953
14954 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
14955 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
14956 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
14957 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
14958 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
14959 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
14960 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
14961 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
14962 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
14963 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
14964
14965 #undef IS_ARRAY_BUFFER_VIEW_TEST
14966
14967
14968
14969 THREADED_TEST(ScriptContextDependence) {
14970   LocalContext c1;
14971   v8::HandleScope scope(c1->GetIsolate());
14972   const char *source = "foo";
14973   v8::Handle<v8::Script> dep = v8_compile(source);
14974   v8::ScriptCompiler::Source script_source(v8::String::NewFromUtf8(
14975       c1->GetIsolate(), source));
14976   v8::Handle<v8::UnboundScript> indep =
14977       v8::ScriptCompiler::CompileUnbound(c1->GetIsolate(), &script_source);
14978   c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
14979                     v8::Integer::New(c1->GetIsolate(), 100));
14980   CHECK_EQ(dep->Run()->Int32Value(), 100);
14981   CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 100);
14982   LocalContext c2;
14983   c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
14984                     v8::Integer::New(c2->GetIsolate(), 101));
14985   CHECK_EQ(dep->Run()->Int32Value(), 100);
14986   CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 101);
14987 }
14988
14989
14990 THREADED_TEST(StackTrace) {
14991   LocalContext context;
14992   v8::HandleScope scope(context->GetIsolate());
14993   v8::TryCatch try_catch;
14994   const char *source = "function foo() { FAIL.FAIL; }; foo();";
14995   v8::Handle<v8::String> src =
14996       v8::String::NewFromUtf8(context->GetIsolate(), source);
14997   v8::Handle<v8::String> origin =
14998       v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
14999   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
15000   v8::ScriptCompiler::CompileUnbound(context->GetIsolate(), &script_source)
15001       ->BindToCurrentContext()
15002       ->Run();
15003   CHECK(try_catch.HasCaught());
15004   v8::String::Utf8Value stack(try_catch.StackTrace());
15005   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
15006 }
15007
15008
15009 // Checks that a StackFrame has certain expected values.
15010 void checkStackFrame(const char* expected_script_name,
15011     const char* expected_func_name, int expected_line_number,
15012     int expected_column, bool is_eval, bool is_constructor,
15013     v8::Handle<v8::StackFrame> frame) {
15014   v8::HandleScope scope(CcTest::isolate());
15015   v8::String::Utf8Value func_name(frame->GetFunctionName());
15016   v8::String::Utf8Value script_name(frame->GetScriptName());
15017   if (*script_name == NULL) {
15018     // The situation where there is no associated script, like for evals.
15019     CHECK(expected_script_name == NULL);
15020   } else {
15021     CHECK(strstr(*script_name, expected_script_name) != NULL);
15022   }
15023   CHECK(strstr(*func_name, expected_func_name) != NULL);
15024   CHECK_EQ(expected_line_number, frame->GetLineNumber());
15025   CHECK_EQ(expected_column, frame->GetColumn());
15026   CHECK_EQ(is_eval, frame->IsEval());
15027   CHECK_EQ(is_constructor, frame->IsConstructor());
15028 }
15029
15030
15031 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
15032   v8::HandleScope scope(args.GetIsolate());
15033   const char* origin = "capture-stack-trace-test";
15034   const int kOverviewTest = 1;
15035   const int kDetailedTest = 2;
15036
15037   DCHECK(args.Length() == 1);
15038
15039   int testGroup = args[0]->Int32Value();
15040   if (testGroup == kOverviewTest) {
15041     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15042         args.GetIsolate(), 10, v8::StackTrace::kOverview);
15043     CHECK_EQ(4, stackTrace->GetFrameCount());
15044     checkStackFrame(origin, "bar", 2, 10, false, false,
15045                     stackTrace->GetFrame(0));
15046     checkStackFrame(origin, "foo", 6, 3, false, false,
15047                     stackTrace->GetFrame(1));
15048     // This is the source string inside the eval which has the call to foo.
15049     checkStackFrame(NULL, "", 1, 5, false, false,
15050                     stackTrace->GetFrame(2));
15051     // The last frame is an anonymous function which has the initial eval call.
15052     checkStackFrame(origin, "", 8, 7, false, false,
15053                     stackTrace->GetFrame(3));
15054
15055     CHECK(stackTrace->AsArray()->IsArray());
15056   } else if (testGroup == kDetailedTest) {
15057     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15058         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15059     CHECK_EQ(4, stackTrace->GetFrameCount());
15060     checkStackFrame(origin, "bat", 4, 22, false, false,
15061                     stackTrace->GetFrame(0));
15062     checkStackFrame(origin, "baz", 8, 3, false, true,
15063                     stackTrace->GetFrame(1));
15064     bool is_eval = true;
15065     // This is the source string inside the eval which has the call to baz.
15066     checkStackFrame(NULL, "", 1, 5, is_eval, false,
15067                     stackTrace->GetFrame(2));
15068     // The last frame is an anonymous function which has the initial eval call.
15069     checkStackFrame(origin, "", 10, 1, false, false,
15070                     stackTrace->GetFrame(3));
15071
15072     CHECK(stackTrace->AsArray()->IsArray());
15073   }
15074 }
15075
15076
15077 // Tests the C++ StackTrace API.
15078 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
15079 // THREADED_TEST(CaptureStackTrace) {
15080 TEST(CaptureStackTrace) {
15081   v8::Isolate* isolate = CcTest::isolate();
15082   v8::HandleScope scope(isolate);
15083   v8::Handle<v8::String> origin =
15084       v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
15085   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15086   templ->Set(v8_str("AnalyzeStackInNativeCode"),
15087              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
15088   LocalContext context(0, templ);
15089
15090   // Test getting OVERVIEW information. Should ignore information that is not
15091   // script name, function name, line number, and column offset.
15092   const char *overview_source =
15093     "function bar() {\n"
15094     "  var y; AnalyzeStackInNativeCode(1);\n"
15095     "}\n"
15096     "function foo() {\n"
15097     "\n"
15098     "  bar();\n"
15099     "}\n"
15100     "var x;eval('new foo();');";
15101   v8::Handle<v8::String> overview_src =
15102       v8::String::NewFromUtf8(isolate, overview_source);
15103   v8::ScriptCompiler::Source script_source(overview_src,
15104                                            v8::ScriptOrigin(origin));
15105   v8::Handle<Value> overview_result(
15106       v8::ScriptCompiler::CompileUnbound(isolate, &script_source)
15107           ->BindToCurrentContext()
15108           ->Run());
15109   CHECK(!overview_result.IsEmpty());
15110   CHECK(overview_result->IsObject());
15111
15112   // Test getting DETAILED information.
15113   const char *detailed_source =
15114     "function bat() {AnalyzeStackInNativeCode(2);\n"
15115     "}\n"
15116     "\n"
15117     "function baz() {\n"
15118     "  bat();\n"
15119     "}\n"
15120     "eval('new baz();');";
15121   v8::Handle<v8::String> detailed_src =
15122       v8::String::NewFromUtf8(isolate, detailed_source);
15123   // Make the script using a non-zero line and column offset.
15124   v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
15125   v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
15126   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
15127   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
15128   v8::Handle<v8::UnboundScript> detailed_script(
15129       v8::ScriptCompiler::CompileUnbound(isolate, &script_source2));
15130   v8::Handle<Value> detailed_result(
15131       detailed_script->BindToCurrentContext()->Run());
15132   CHECK(!detailed_result.IsEmpty());
15133   CHECK(detailed_result->IsObject());
15134 }
15135
15136
15137 static void StackTraceForUncaughtExceptionListener(
15138     v8::Handle<v8::Message> message,
15139     v8::Handle<Value>) {
15140   report_count++;
15141   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
15142   CHECK_EQ(2, stack_trace->GetFrameCount());
15143   checkStackFrame("origin", "foo", 2, 3, false, false,
15144                   stack_trace->GetFrame(0));
15145   checkStackFrame("origin", "bar", 5, 3, false, false,
15146                   stack_trace->GetFrame(1));
15147 }
15148
15149
15150 TEST(CaptureStackTraceForUncaughtException) {
15151   report_count = 0;
15152   LocalContext env;
15153   v8::HandleScope scope(env->GetIsolate());
15154   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
15155   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
15156
15157   CompileRunWithOrigin(
15158       "function foo() {\n"
15159       "  throw 1;\n"
15160       "};\n"
15161       "function bar() {\n"
15162       "  foo();\n"
15163       "};",
15164       "origin");
15165   v8::Local<v8::Object> global = env->Global();
15166   Local<Value> trouble = global->Get(v8_str("bar"));
15167   CHECK(trouble->IsFunction());
15168   Function::Cast(*trouble)->Call(global, 0, NULL);
15169   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15170   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
15171   CHECK_EQ(1, report_count);
15172 }
15173
15174
15175 TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
15176   report_count = 0;
15177   LocalContext env;
15178   v8::HandleScope scope(env->GetIsolate());
15179
15180   // Create an Error object first.
15181   CompileRunWithOrigin(
15182       "function foo() {\n"
15183       "e=new Error('err');\n"
15184       "};\n"
15185       "function bar() {\n"
15186       "  foo();\n"
15187       "};\n"
15188       "var e;",
15189       "origin");
15190   v8::Local<v8::Object> global = env->Global();
15191   Local<Value> trouble = global->Get(v8_str("bar"));
15192   CHECK(trouble->IsFunction());
15193   Function::Cast(*trouble)->Call(global, 0, NULL);
15194
15195   // Enable capturing detailed stack trace late, and throw the exception.
15196   // The detailed stack trace should be extracted from the simple stack.
15197   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
15198   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
15199   CompileRunWithOrigin("throw e", "origin");
15200   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15201   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
15202   CHECK_EQ(1, report_count);
15203 }
15204
15205
15206 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
15207   LocalContext env;
15208   v8::HandleScope scope(env->GetIsolate());
15209   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
15210                                                     1024,
15211                                                     v8::StackTrace::kDetailed);
15212
15213   CompileRun(
15214       "var setters = ['column', 'lineNumber', 'scriptName',\n"
15215       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
15216       "    'isConstructor'];\n"
15217       "for (var i = 0; i < setters.length; i++) {\n"
15218       "  var prop = setters[i];\n"
15219       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
15220       "}\n");
15221   CompileRun("throw 'exception';");
15222   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15223 }
15224
15225
15226 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
15227                                      v8::Handle<v8::Value> data) {
15228   // Use the frame where JavaScript is called from.
15229   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
15230   CHECK(!stack_trace.IsEmpty());
15231   int frame_count = stack_trace->GetFrameCount();
15232   CHECK_EQ(3, frame_count);
15233   int line_number[] = {1, 2, 5};
15234   for (int i = 0; i < frame_count; i++) {
15235     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
15236   }
15237 }
15238
15239
15240 // Test that we only return the stack trace at the site where the exception
15241 // is first thrown (not where it is rethrown).
15242 TEST(RethrowStackTrace) {
15243   LocalContext env;
15244   v8::HandleScope scope(env->GetIsolate());
15245   // We make sure that
15246   // - the stack trace of the ReferenceError in g() is reported.
15247   // - the stack trace is not overwritten when e1 is rethrown by t().
15248   // - the stack trace of e2 does not overwrite that of e1.
15249   const char* source =
15250       "function g() { error; }          \n"
15251       "function f() { g(); }            \n"
15252       "function t(e) { throw e; }       \n"
15253       "try {                            \n"
15254       "  f();                           \n"
15255       "} catch (e1) {                   \n"
15256       "  try {                          \n"
15257       "    error;                       \n"
15258       "  } catch (e2) {                 \n"
15259       "    t(e1);                       \n"
15260       "  }                              \n"
15261       "}                                \n";
15262   v8::V8::AddMessageListener(RethrowStackTraceHandler);
15263   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
15264   CompileRun(source);
15265   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15266   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
15267 }
15268
15269
15270 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
15271                                               v8::Handle<v8::Value> data) {
15272   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
15273   CHECK(!stack_trace.IsEmpty());
15274   int frame_count = stack_trace->GetFrameCount();
15275   CHECK_EQ(2, frame_count);
15276   int line_number[] = {3, 7};
15277   for (int i = 0; i < frame_count; i++) {
15278     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
15279   }
15280 }
15281
15282
15283 // Test that we do not recognize identity for primitive exceptions.
15284 TEST(RethrowPrimitiveStackTrace) {
15285   LocalContext env;
15286   v8::HandleScope scope(env->GetIsolate());
15287   // We do not capture stack trace for non Error objects on creation time.
15288   // Instead, we capture the stack trace on last throw.
15289   const char* source =
15290       "function g() { throw 404; }      \n"
15291       "function f() { g(); }            \n"
15292       "function t(e) { throw e; }       \n"
15293       "try {                            \n"
15294       "  f();                           \n"
15295       "} catch (e1) {                   \n"
15296       "  t(e1)                          \n"
15297       "}                                \n";
15298   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
15299   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
15300   CompileRun(source);
15301   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15302   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
15303 }
15304
15305
15306 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
15307                                               v8::Handle<v8::Value> data) {
15308   // Use the frame where JavaScript is called from.
15309   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
15310   CHECK(!stack_trace.IsEmpty());
15311   CHECK_EQ(1, stack_trace->GetFrameCount());
15312   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
15313 }
15314
15315
15316 // Test that the stack trace is captured when the error object is created and
15317 // not where it is thrown.
15318 TEST(RethrowExistingStackTrace) {
15319   LocalContext env;
15320   v8::HandleScope scope(env->GetIsolate());
15321   const char* source =
15322       "var e = new Error();           \n"
15323       "throw e;                       \n";
15324   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
15325   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
15326   CompileRun(source);
15327   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15328   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
15329 }
15330
15331
15332 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
15333                                                v8::Handle<v8::Value> data) {
15334   // Use the frame where JavaScript is called from.
15335   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
15336   CHECK(!stack_trace.IsEmpty());
15337   CHECK_EQ(1, stack_trace->GetFrameCount());
15338   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
15339 }
15340
15341
15342 // Test that the stack trace is captured where the bogus Error object is thrown.
15343 TEST(RethrowBogusErrorStackTrace) {
15344   LocalContext env;
15345   v8::HandleScope scope(env->GetIsolate());
15346   const char* source =
15347       "var e = {__proto__: new Error()} \n"
15348       "throw e;                         \n";
15349   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
15350   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
15351   CompileRun(source);
15352   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15353   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
15354 }
15355
15356
15357 v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
15358 int promise_reject_counter = 0;
15359 int promise_revoke_counter = 0;
15360 int promise_reject_msg_line_number = -1;
15361 int promise_reject_msg_column_number = -1;
15362 int promise_reject_line_number = -1;
15363 int promise_reject_column_number = -1;
15364 int promise_reject_frame_count = -1;
15365
15366 void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
15367   if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
15368     promise_reject_counter++;
15369     CcTest::global()->Set(v8_str("rejected"), reject_message.GetPromise());
15370     CcTest::global()->Set(v8_str("value"), reject_message.GetValue());
15371     v8::Handle<v8::Message> message =
15372         v8::Exception::CreateMessage(reject_message.GetValue());
15373     v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
15374
15375     promise_reject_msg_line_number = message->GetLineNumber();
15376     promise_reject_msg_column_number = message->GetStartColumn() + 1;
15377
15378     if (!stack_trace.IsEmpty()) {
15379       promise_reject_frame_count = stack_trace->GetFrameCount();
15380       if (promise_reject_frame_count > 0) {
15381         CHECK(stack_trace->GetFrame(0)->GetScriptName()->Equals(v8_str("pro")));
15382         promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
15383         promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
15384       } else {
15385         promise_reject_line_number = -1;
15386         promise_reject_column_number = -1;
15387       }
15388     }
15389   } else {
15390     promise_revoke_counter++;
15391     CcTest::global()->Set(v8_str("revoked"), reject_message.GetPromise());
15392     CHECK(reject_message.GetValue().IsEmpty());
15393   }
15394 }
15395
15396
15397 v8::Handle<v8::Promise> GetPromise(const char* name) {
15398   return v8::Handle<v8::Promise>::Cast(CcTest::global()->Get(v8_str(name)));
15399 }
15400
15401
15402 v8::Handle<v8::Value> RejectValue() {
15403   return CcTest::global()->Get(v8_str("value"));
15404 }
15405
15406
15407 void ResetPromiseStates() {
15408   promise_reject_counter = 0;
15409   promise_revoke_counter = 0;
15410   promise_reject_msg_line_number = -1;
15411   promise_reject_msg_column_number = -1;
15412   promise_reject_line_number = -1;
15413   promise_reject_column_number = -1;
15414   promise_reject_frame_count = -1;
15415   CcTest::global()->Set(v8_str("rejected"), v8_str(""));
15416   CcTest::global()->Set(v8_str("value"), v8_str(""));
15417   CcTest::global()->Set(v8_str("revoked"), v8_str(""));
15418 }
15419
15420
15421 TEST(PromiseRejectCallback) {
15422   LocalContext env;
15423   v8::Isolate* isolate = env->GetIsolate();
15424   v8::HandleScope scope(isolate);
15425
15426   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
15427
15428   ResetPromiseStates();
15429
15430   // Create promise p0.
15431   CompileRun(
15432       "var reject;            \n"
15433       "var p0 = new Promise(  \n"
15434       "  function(res, rej) { \n"
15435       "    reject = rej;      \n"
15436       "  }                    \n"
15437       ");                     \n");
15438   CHECK(!GetPromise("p0")->HasHandler());
15439   CHECK_EQ(0, promise_reject_counter);
15440   CHECK_EQ(0, promise_revoke_counter);
15441
15442   // Add resolve handler (and default reject handler) to p0.
15443   CompileRun("var p1 = p0.then(function(){});");
15444   CHECK(GetPromise("p0")->HasHandler());
15445   CHECK(!GetPromise("p1")->HasHandler());
15446   CHECK_EQ(0, promise_reject_counter);
15447   CHECK_EQ(0, promise_revoke_counter);
15448
15449   // Reject p0.
15450   CompileRun("reject('ppp');");
15451   CHECK(GetPromise("p0")->HasHandler());
15452   CHECK(!GetPromise("p1")->HasHandler());
15453   CHECK_EQ(1, promise_reject_counter);
15454   CHECK_EQ(0, promise_revoke_counter);
15455   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
15456   CHECK(GetPromise("rejected")->Equals(GetPromise("p1")));
15457   CHECK(RejectValue()->Equals(v8_str("ppp")));
15458
15459   // Reject p0 again. Callback is not triggered again.
15460   CompileRun("reject();");
15461   CHECK(GetPromise("p0")->HasHandler());
15462   CHECK(!GetPromise("p1")->HasHandler());
15463   CHECK_EQ(1, promise_reject_counter);
15464   CHECK_EQ(0, promise_revoke_counter);
15465
15466   // Add resolve handler to p1.
15467   CompileRun("var p2 = p1.then(function(){});");
15468   CHECK(GetPromise("p0")->HasHandler());
15469   CHECK(GetPromise("p1")->HasHandler());
15470   CHECK(!GetPromise("p2")->HasHandler());
15471   CHECK_EQ(2, promise_reject_counter);
15472   CHECK_EQ(1, promise_revoke_counter);
15473   CHECK(GetPromise("rejected")->Equals(GetPromise("p2")));
15474   CHECK(RejectValue()->Equals(v8_str("ppp")));
15475   CHECK(GetPromise("revoked")->Equals(GetPromise("p1")));
15476
15477   ResetPromiseStates();
15478
15479   // Create promise q0.
15480   CompileRun(
15481       "var q0 = new Promise(  \n"
15482       "  function(res, rej) { \n"
15483       "    reject = rej;      \n"
15484       "  }                    \n"
15485       ");                     \n");
15486   CHECK(!GetPromise("q0")->HasHandler());
15487   CHECK_EQ(0, promise_reject_counter);
15488   CHECK_EQ(0, promise_revoke_counter);
15489
15490   // Add reject handler to q0.
15491   CompileRun("var q1 = q0.catch(function() {});");
15492   CHECK(GetPromise("q0")->HasHandler());
15493   CHECK(!GetPromise("q1")->HasHandler());
15494   CHECK_EQ(0, promise_reject_counter);
15495   CHECK_EQ(0, promise_revoke_counter);
15496
15497   // Reject q0.
15498   CompileRun("reject('qq')");
15499   CHECK(GetPromise("q0")->HasHandler());
15500   CHECK(!GetPromise("q1")->HasHandler());
15501   CHECK_EQ(0, promise_reject_counter);
15502   CHECK_EQ(0, promise_revoke_counter);
15503
15504   // Add a new reject handler, which rejects by returning Promise.reject().
15505   // The returned promise q_ triggers a reject callback at first, only to
15506   // revoke it when returning it causes q2 to be rejected.
15507   CompileRun(
15508       "var q_;"
15509       "var q2 = q0.catch(               \n"
15510       "   function() {                  \n"
15511       "     q_ = Promise.reject('qqq'); \n"
15512       "     return q_;                  \n"
15513       "   }                             \n"
15514       ");                               \n");
15515   CHECK(GetPromise("q0")->HasHandler());
15516   CHECK(!GetPromise("q1")->HasHandler());
15517   CHECK(!GetPromise("q2")->HasHandler());
15518   CHECK(GetPromise("q_")->HasHandler());
15519   CHECK_EQ(2, promise_reject_counter);
15520   CHECK_EQ(1, promise_revoke_counter);
15521   CHECK(GetPromise("rejected")->Equals(GetPromise("q2")));
15522   CHECK(GetPromise("revoked")->Equals(GetPromise("q_")));
15523   CHECK(RejectValue()->Equals(v8_str("qqq")));
15524
15525   // Add a reject handler to the resolved q1, which rejects by throwing.
15526   CompileRun(
15527       "var q3 = q1.then(  \n"
15528       "   function() {    \n"
15529       "     throw 'qqqq'; \n"
15530       "   }               \n"
15531       ");                 \n");
15532   CHECK(GetPromise("q0")->HasHandler());
15533   CHECK(GetPromise("q1")->HasHandler());
15534   CHECK(!GetPromise("q2")->HasHandler());
15535   CHECK(!GetPromise("q3")->HasHandler());
15536   CHECK_EQ(3, promise_reject_counter);
15537   CHECK_EQ(1, promise_revoke_counter);
15538   CHECK(GetPromise("rejected")->Equals(GetPromise("q3")));
15539   CHECK(RejectValue()->Equals(v8_str("qqqq")));
15540
15541   ResetPromiseStates();
15542
15543   // Create promise r0, which has three handlers, two of which handle rejects.
15544   CompileRun(
15545       "var r0 = new Promise(             \n"
15546       "  function(res, rej) {            \n"
15547       "    reject = rej;                 \n"
15548       "  }                               \n"
15549       ");                                \n"
15550       "var r1 = r0.catch(function() {}); \n"
15551       "var r2 = r0.then(function() {});  \n"
15552       "var r3 = r0.then(function() {},   \n"
15553       "                 function() {});  \n");
15554   CHECK(GetPromise("r0")->HasHandler());
15555   CHECK(!GetPromise("r1")->HasHandler());
15556   CHECK(!GetPromise("r2")->HasHandler());
15557   CHECK(!GetPromise("r3")->HasHandler());
15558   CHECK_EQ(0, promise_reject_counter);
15559   CHECK_EQ(0, promise_revoke_counter);
15560
15561   // Reject r0.
15562   CompileRun("reject('rrr')");
15563   CHECK(GetPromise("r0")->HasHandler());
15564   CHECK(!GetPromise("r1")->HasHandler());
15565   CHECK(!GetPromise("r2")->HasHandler());
15566   CHECK(!GetPromise("r3")->HasHandler());
15567   CHECK_EQ(1, promise_reject_counter);
15568   CHECK_EQ(0, promise_revoke_counter);
15569   CHECK(GetPromise("rejected")->Equals(GetPromise("r2")));
15570   CHECK(RejectValue()->Equals(v8_str("rrr")));
15571
15572   // Add reject handler to r2.
15573   CompileRun("var r4 = r2.catch(function() {});");
15574   CHECK(GetPromise("r0")->HasHandler());
15575   CHECK(!GetPromise("r1")->HasHandler());
15576   CHECK(GetPromise("r2")->HasHandler());
15577   CHECK(!GetPromise("r3")->HasHandler());
15578   CHECK(!GetPromise("r4")->HasHandler());
15579   CHECK_EQ(1, promise_reject_counter);
15580   CHECK_EQ(1, promise_revoke_counter);
15581   CHECK(GetPromise("revoked")->Equals(GetPromise("r2")));
15582   CHECK(RejectValue()->Equals(v8_str("rrr")));
15583
15584   // Add reject handlers to r4.
15585   CompileRun("var r5 = r4.then(function() {}, function() {});");
15586   CHECK(GetPromise("r0")->HasHandler());
15587   CHECK(!GetPromise("r1")->HasHandler());
15588   CHECK(GetPromise("r2")->HasHandler());
15589   CHECK(!GetPromise("r3")->HasHandler());
15590   CHECK(GetPromise("r4")->HasHandler());
15591   CHECK(!GetPromise("r5")->HasHandler());
15592   CHECK_EQ(1, promise_reject_counter);
15593   CHECK_EQ(1, promise_revoke_counter);
15594
15595   ResetPromiseStates();
15596
15597   // Create promise s0, which has three handlers, none of which handle rejects.
15598   CompileRun(
15599       "var s0 = new Promise(            \n"
15600       "  function(res, rej) {           \n"
15601       "    reject = rej;                \n"
15602       "  }                              \n"
15603       ");                               \n"
15604       "var s1 = s0.then(function() {}); \n"
15605       "var s2 = s0.then(function() {}); \n"
15606       "var s3 = s0.then(function() {}); \n");
15607   CHECK(GetPromise("s0")->HasHandler());
15608   CHECK(!GetPromise("s1")->HasHandler());
15609   CHECK(!GetPromise("s2")->HasHandler());
15610   CHECK(!GetPromise("s3")->HasHandler());
15611   CHECK_EQ(0, promise_reject_counter);
15612   CHECK_EQ(0, promise_revoke_counter);
15613
15614   // Reject s0.
15615   CompileRun("reject('sss')");
15616   CHECK(GetPromise("s0")->HasHandler());
15617   CHECK(!GetPromise("s1")->HasHandler());
15618   CHECK(!GetPromise("s2")->HasHandler());
15619   CHECK(!GetPromise("s3")->HasHandler());
15620   CHECK_EQ(3, promise_reject_counter);
15621   CHECK_EQ(0, promise_revoke_counter);
15622   CHECK(RejectValue()->Equals(v8_str("sss")));
15623
15624   // Test stack frames.
15625   V8::SetCaptureStackTraceForUncaughtExceptions(true);
15626
15627   ResetPromiseStates();
15628
15629   // Create promise t0, which is rejected in the constructor with an error.
15630   CompileRunWithOrigin(
15631       "var t0 = new Promise(  \n"
15632       "  function(res, rej) { \n"
15633       "    reference_error;   \n"
15634       "  }                    \n"
15635       ");                     \n",
15636       "pro", 0, 0);
15637   CHECK(!GetPromise("t0")->HasHandler());
15638   CHECK_EQ(1, promise_reject_counter);
15639   CHECK_EQ(0, promise_revoke_counter);
15640   CHECK_EQ(2, promise_reject_frame_count);
15641   CHECK_EQ(3, promise_reject_line_number);
15642   CHECK_EQ(5, promise_reject_column_number);
15643   CHECK_EQ(3, promise_reject_msg_line_number);
15644   CHECK_EQ(5, promise_reject_msg_column_number);
15645
15646   ResetPromiseStates();
15647
15648   // Create promise u0 and chain u1 to it, which is rejected via throw.
15649   CompileRunWithOrigin(
15650       "var u0 = Promise.resolve();        \n"
15651       "var u1 = u0.then(                  \n"
15652       "           function() {            \n"
15653       "             (function() {         \n"
15654       "                throw new Error(); \n"
15655       "              })();                \n"
15656       "           }                       \n"
15657       "         );                        \n",
15658       "pro", 0, 0);
15659   CHECK(GetPromise("u0")->HasHandler());
15660   CHECK(!GetPromise("u1")->HasHandler());
15661   CHECK_EQ(1, promise_reject_counter);
15662   CHECK_EQ(0, promise_revoke_counter);
15663   CHECK_EQ(2, promise_reject_frame_count);
15664   CHECK_EQ(5, promise_reject_line_number);
15665   CHECK_EQ(23, promise_reject_column_number);
15666   CHECK_EQ(5, promise_reject_msg_line_number);
15667   CHECK_EQ(23, promise_reject_msg_column_number);
15668
15669   // Throw in u3, which handles u1's rejection.
15670   CompileRunWithOrigin(
15671       "function f() {                \n"
15672       "  return (function() {        \n"
15673       "    return new Error();       \n"
15674       "  })();                       \n"
15675       "}                             \n"
15676       "var u2 = Promise.reject(f()); \n"
15677       "var u3 = u1.catch(            \n"
15678       "           function() {       \n"
15679       "             return u2;       \n"
15680       "           }                  \n"
15681       "         );                   \n",
15682       "pro", 0, 0);
15683   CHECK(GetPromise("u0")->HasHandler());
15684   CHECK(GetPromise("u1")->HasHandler());
15685   CHECK(GetPromise("u2")->HasHandler());
15686   CHECK(!GetPromise("u3")->HasHandler());
15687   CHECK_EQ(3, promise_reject_counter);
15688   CHECK_EQ(2, promise_revoke_counter);
15689   CHECK_EQ(3, promise_reject_frame_count);
15690   CHECK_EQ(3, promise_reject_line_number);
15691   CHECK_EQ(12, promise_reject_column_number);
15692   CHECK_EQ(3, promise_reject_msg_line_number);
15693   CHECK_EQ(12, promise_reject_msg_column_number);
15694
15695   ResetPromiseStates();
15696
15697   // Create promise rejected promise v0, which is incorrectly handled by v1
15698   // via chaining cycle.
15699   CompileRunWithOrigin(
15700       "var v0 = Promise.reject(); \n"
15701       "var v1 = v0.catch(         \n"
15702       "           function() {    \n"
15703       "             return v1;    \n"
15704       "           }               \n"
15705       "         );                \n",
15706       "pro", 0, 0);
15707   CHECK(GetPromise("v0")->HasHandler());
15708   CHECK(!GetPromise("v1")->HasHandler());
15709   CHECK_EQ(2, promise_reject_counter);
15710   CHECK_EQ(1, promise_revoke_counter);
15711   CHECK_EQ(0, promise_reject_frame_count);
15712   CHECK_EQ(-1, promise_reject_line_number);
15713   CHECK_EQ(-1, promise_reject_column_number);
15714
15715   ResetPromiseStates();
15716
15717   // Create promise t1, which rejects by throwing syntax error from eval.
15718   CompileRunWithOrigin(
15719       "var t1 = new Promise(   \n"
15720       "  function(res, rej) {  \n"
15721       "    var content = '\\n\\\n"
15722       "      }';               \n"
15723       "    eval(content);      \n"
15724       "  }                     \n"
15725       ");                      \n",
15726       "pro", 0, 0);
15727   CHECK(!GetPromise("t1")->HasHandler());
15728   CHECK_EQ(1, promise_reject_counter);
15729   CHECK_EQ(0, promise_revoke_counter);
15730   CHECK_EQ(2, promise_reject_frame_count);
15731   CHECK_EQ(5, promise_reject_line_number);
15732   CHECK_EQ(10, promise_reject_column_number);
15733   CHECK_EQ(2, promise_reject_msg_line_number);
15734   CHECK_EQ(7, promise_reject_msg_column_number);
15735 }
15736
15737
15738 void AnalyzeStackOfEvalWithSourceURL(
15739     const v8::FunctionCallbackInfo<v8::Value>& args) {
15740   v8::HandleScope scope(args.GetIsolate());
15741   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15742       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15743   CHECK_EQ(5, stackTrace->GetFrameCount());
15744   v8::Handle<v8::String> url = v8_str("eval_url");
15745   for (int i = 0; i < 3; i++) {
15746     v8::Handle<v8::String> name =
15747         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15748     CHECK(!name.IsEmpty());
15749     CHECK(url->Equals(name));
15750   }
15751 }
15752
15753
15754 TEST(SourceURLInStackTrace) {
15755   v8::Isolate* isolate = CcTest::isolate();
15756   v8::HandleScope scope(isolate);
15757   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15758   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
15759              v8::FunctionTemplate::New(isolate,
15760                                        AnalyzeStackOfEvalWithSourceURL));
15761   LocalContext context(0, templ);
15762
15763   const char *source =
15764     "function outer() {\n"
15765     "function bar() {\n"
15766     "  AnalyzeStackOfEvalWithSourceURL();\n"
15767     "}\n"
15768     "function foo() {\n"
15769     "\n"
15770     "  bar();\n"
15771     "}\n"
15772     "foo();\n"
15773     "}\n"
15774     "eval('(' + outer +')()%s');";
15775
15776   i::ScopedVector<char> code(1024);
15777   i::SNPrintF(code, source, "//# sourceURL=eval_url");
15778   CHECK(CompileRun(code.start())->IsUndefined());
15779   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
15780   CHECK(CompileRun(code.start())->IsUndefined());
15781 }
15782
15783
15784 static int scriptIdInStack[2];
15785
15786 void AnalyzeScriptIdInStack(
15787     const v8::FunctionCallbackInfo<v8::Value>& args) {
15788   v8::HandleScope scope(args.GetIsolate());
15789   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15790       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
15791   CHECK_EQ(2, stackTrace->GetFrameCount());
15792   for (int i = 0; i < 2; i++) {
15793     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
15794   }
15795 }
15796
15797
15798 TEST(ScriptIdInStackTrace) {
15799   v8::Isolate* isolate = CcTest::isolate();
15800   v8::HandleScope scope(isolate);
15801   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15802   templ->Set(v8_str("AnalyzeScriptIdInStack"),
15803              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
15804   LocalContext context(0, templ);
15805
15806   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
15807     isolate,
15808     "function foo() {\n"
15809     "  AnalyzeScriptIdInStack();"
15810     "}\n"
15811     "foo();\n");
15812   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
15813   script->Run();
15814   for (int i = 0; i < 2; i++) {
15815     CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
15816     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
15817   }
15818 }
15819
15820
15821 void AnalyzeStackOfInlineScriptWithSourceURL(
15822     const v8::FunctionCallbackInfo<v8::Value>& args) {
15823   v8::HandleScope scope(args.GetIsolate());
15824   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15825       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15826   CHECK_EQ(4, stackTrace->GetFrameCount());
15827   v8::Handle<v8::String> url = v8_str("url");
15828   for (int i = 0; i < 3; i++) {
15829     v8::Handle<v8::String> name =
15830         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15831     CHECK(!name.IsEmpty());
15832     CHECK(url->Equals(name));
15833   }
15834 }
15835
15836
15837 TEST(InlineScriptWithSourceURLInStackTrace) {
15838   v8::Isolate* isolate = CcTest::isolate();
15839   v8::HandleScope scope(isolate);
15840   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15841   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
15842              v8::FunctionTemplate::New(
15843                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
15844   LocalContext context(0, templ);
15845
15846   const char *source =
15847     "function outer() {\n"
15848     "function bar() {\n"
15849     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
15850     "}\n"
15851     "function foo() {\n"
15852     "\n"
15853     "  bar();\n"
15854     "}\n"
15855     "foo();\n"
15856     "}\n"
15857     "outer()\n%s";
15858
15859   i::ScopedVector<char> code(1024);
15860   i::SNPrintF(code, source, "//# sourceURL=source_url");
15861   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
15862   i::SNPrintF(code, source, "//@ sourceURL=source_url");
15863   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
15864 }
15865
15866
15867 void AnalyzeStackOfDynamicScriptWithSourceURL(
15868     const v8::FunctionCallbackInfo<v8::Value>& args) {
15869   v8::HandleScope scope(args.GetIsolate());
15870   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15871       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15872   CHECK_EQ(4, stackTrace->GetFrameCount());
15873   v8::Handle<v8::String> url = v8_str("source_url");
15874   for (int i = 0; i < 3; i++) {
15875     v8::Handle<v8::String> name =
15876         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15877     CHECK(!name.IsEmpty());
15878     CHECK(url->Equals(name));
15879   }
15880 }
15881
15882
15883 TEST(DynamicWithSourceURLInStackTrace) {
15884   v8::Isolate* isolate = CcTest::isolate();
15885   v8::HandleScope scope(isolate);
15886   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15887   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
15888              v8::FunctionTemplate::New(
15889                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
15890   LocalContext context(0, templ);
15891
15892   const char *source =
15893     "function outer() {\n"
15894     "function bar() {\n"
15895     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
15896     "}\n"
15897     "function foo() {\n"
15898     "\n"
15899     "  bar();\n"
15900     "}\n"
15901     "foo();\n"
15902     "}\n"
15903     "outer()\n%s";
15904
15905   i::ScopedVector<char> code(1024);
15906   i::SNPrintF(code, source, "//# sourceURL=source_url");
15907   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
15908   i::SNPrintF(code, source, "//@ sourceURL=source_url");
15909   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
15910 }
15911
15912
15913 TEST(DynamicWithSourceURLInStackTraceString) {
15914   LocalContext context;
15915   v8::HandleScope scope(context->GetIsolate());
15916
15917   const char *source =
15918     "function outer() {\n"
15919     "  function foo() {\n"
15920     "    FAIL.FAIL;\n"
15921     "  }\n"
15922     "  foo();\n"
15923     "}\n"
15924     "outer()\n%s";
15925
15926   i::ScopedVector<char> code(1024);
15927   i::SNPrintF(code, source, "//# sourceURL=source_url");
15928   v8::TryCatch try_catch;
15929   CompileRunWithOrigin(code.start(), "", 0, 0);
15930   CHECK(try_catch.HasCaught());
15931   v8::String::Utf8Value stack(try_catch.StackTrace());
15932   CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
15933 }
15934
15935
15936 TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
15937   LocalContext context;
15938   v8::HandleScope scope(context->GetIsolate());
15939
15940   const char *source =
15941     "function outer() {\n"
15942     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
15943     "  //# sourceURL=source_url\";\n"
15944     "  eval(scriptContents);\n"
15945     "  foo(); }\n"
15946     "outer();\n"
15947     "//# sourceURL=outer_url";
15948
15949   v8::TryCatch try_catch;
15950   CompileRun(source);
15951   CHECK(try_catch.HasCaught());
15952
15953   Local<v8::Message> message = try_catch.Message();
15954   Handle<Value> sourceURL =
15955     message->GetScriptOrigin().ResourceName();
15956   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
15957 }
15958
15959
15960 TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
15961   LocalContext context;
15962   v8::HandleScope scope(context->GetIsolate());
15963
15964   const char *source =
15965     "function outer() {\n"
15966     "  var scriptContents = \"function boo(){ boo(); }\\\n"
15967     "  //# sourceURL=source_url\";\n"
15968     "  eval(scriptContents);\n"
15969     "  boo(); }\n"
15970     "outer();\n"
15971     "//# sourceURL=outer_url";
15972
15973   v8::TryCatch try_catch;
15974   CompileRun(source);
15975   CHECK(try_catch.HasCaught());
15976
15977   Local<v8::Message> message = try_catch.Message();
15978   Handle<Value> sourceURL =
15979     message->GetScriptOrigin().ResourceName();
15980   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
15981 }
15982
15983
15984 static void CreateGarbageInOldSpace() {
15985   i::Factory* factory = CcTest::i_isolate()->factory();
15986   v8::HandleScope scope(CcTest::isolate());
15987   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
15988   for (int i = 0; i < 1000; i++) {
15989     factory->NewFixedArray(1000, i::TENURED);
15990   }
15991 }
15992
15993
15994 // Test that idle notification can be handled and eventually returns true.
15995 TEST(IdleNotification) {
15996   const intptr_t MB = 1024 * 1024;
15997   const int IdlePauseInMs = 1000;
15998   LocalContext env;
15999   v8::HandleScope scope(env->GetIsolate());
16000   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
16001   CreateGarbageInOldSpace();
16002   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
16003   CHECK_GT(size_with_garbage, initial_size + MB);
16004   bool finished = false;
16005   for (int i = 0; i < 200 && !finished; i++) {
16006     finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
16007   }
16008   intptr_t final_size = CcTest::heap()->SizeOfObjects();
16009   CHECK(finished);
16010   CHECK_LT(final_size, initial_size + 1);
16011 }
16012
16013
16014 // Test that idle notification can be handled and eventually collects garbage.
16015 TEST(IdleNotificationWithSmallHint) {
16016   const intptr_t MB = 1024 * 1024;
16017   const int IdlePauseInMs = 900;
16018   LocalContext env;
16019   v8::HandleScope scope(env->GetIsolate());
16020   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
16021   CreateGarbageInOldSpace();
16022   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
16023   CHECK_GT(size_with_garbage, initial_size + MB);
16024   bool finished = false;
16025   for (int i = 0; i < 200 && !finished; i++) {
16026     finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
16027   }
16028   intptr_t final_size = CcTest::heap()->SizeOfObjects();
16029   CHECK(finished);
16030   CHECK_LT(final_size, initial_size + 1);
16031 }
16032
16033
16034 // Test that idle notification can be handled and eventually collects garbage.
16035 TEST(IdleNotificationWithLargeHint) {
16036   const intptr_t MB = 1024 * 1024;
16037   const int IdlePauseInMs = 900;
16038   LocalContext env;
16039   v8::HandleScope scope(env->GetIsolate());
16040   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
16041   CreateGarbageInOldSpace();
16042   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
16043   CHECK_GT(size_with_garbage, initial_size + MB);
16044   bool finished = false;
16045   for (int i = 0; i < 200 && !finished; i++) {
16046     finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
16047   }
16048   intptr_t final_size = CcTest::heap()->SizeOfObjects();
16049   CHECK(finished);
16050   CHECK_LT(final_size, initial_size + 1);
16051 }
16052
16053
16054 TEST(Regress2333) {
16055   LocalContext env;
16056   for (int i = 0; i < 3; i++) {
16057     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
16058   }
16059 }
16060
16061 static uint32_t* stack_limit;
16062
16063 static void GetStackLimitCallback(
16064     const v8::FunctionCallbackInfo<v8::Value>& args) {
16065   stack_limit = reinterpret_cast<uint32_t*>(
16066       CcTest::i_isolate()->stack_guard()->real_climit());
16067 }
16068
16069
16070 // Uses the address of a local variable to determine the stack top now.
16071 // Given a size, returns an address that is that far from the current
16072 // top of stack.
16073 static uint32_t* ComputeStackLimit(uint32_t size) {
16074   uint32_t* answer = &size - (size / sizeof(size));
16075   // If the size is very large and the stack is very near the bottom of
16076   // memory then the calculation above may wrap around and give an address
16077   // that is above the (downwards-growing) stack.  In that case we return
16078   // a very low address.
16079   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
16080   return answer;
16081 }
16082
16083
16084 // We need at least 165kB for an x64 debug build with clang and ASAN.
16085 static const int stack_breathing_room = 256 * i::KB;
16086
16087
16088 TEST(SetStackLimit) {
16089   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
16090
16091   // Set stack limit.
16092   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
16093
16094   // Execute a script.
16095   LocalContext env;
16096   v8::HandleScope scope(env->GetIsolate());
16097   Local<v8::FunctionTemplate> fun_templ =
16098       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
16099   Local<Function> fun = fun_templ->GetFunction();
16100   env->Global()->Set(v8_str("get_stack_limit"), fun);
16101   CompileRun("get_stack_limit();");
16102
16103   CHECK(stack_limit == set_limit);
16104 }
16105
16106
16107 TEST(SetStackLimitInThread) {
16108   uint32_t* set_limit;
16109   {
16110     v8::Locker locker(CcTest::isolate());
16111     set_limit = ComputeStackLimit(stack_breathing_room);
16112
16113     // Set stack limit.
16114     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
16115
16116     // Execute a script.
16117     v8::HandleScope scope(CcTest::isolate());
16118     LocalContext env;
16119     Local<v8::FunctionTemplate> fun_templ =
16120         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
16121     Local<Function> fun = fun_templ->GetFunction();
16122     env->Global()->Set(v8_str("get_stack_limit"), fun);
16123     CompileRun("get_stack_limit();");
16124
16125     CHECK(stack_limit == set_limit);
16126   }
16127   {
16128     v8::Locker locker(CcTest::isolate());
16129     CHECK(stack_limit == set_limit);
16130   }
16131 }
16132
16133
16134 THREADED_TEST(GetHeapStatistics) {
16135   LocalContext c1;
16136   v8::HandleScope scope(c1->GetIsolate());
16137   v8::HeapStatistics heap_statistics;
16138   CHECK_EQ(0u, heap_statistics.total_heap_size());
16139   CHECK_EQ(0u, heap_statistics.used_heap_size());
16140   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
16141   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
16142   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
16143 }
16144
16145
16146 class VisitorImpl : public v8::ExternalResourceVisitor {
16147  public:
16148   explicit VisitorImpl(TestResource** resource) {
16149     for (int i = 0; i < 4; i++) {
16150       resource_[i] = resource[i];
16151       found_resource_[i] = false;
16152     }
16153   }
16154   virtual ~VisitorImpl() {}
16155   virtual void VisitExternalString(v8::Handle<v8::String> string) {
16156     if (!string->IsExternal()) {
16157       CHECK(string->IsExternalOneByte());
16158       return;
16159     }
16160     v8::String::ExternalStringResource* resource =
16161         string->GetExternalStringResource();
16162     CHECK(resource);
16163     for (int i = 0; i < 4; i++) {
16164       if (resource_[i] == resource) {
16165         CHECK(!found_resource_[i]);
16166         found_resource_[i] = true;
16167       }
16168     }
16169   }
16170   void CheckVisitedResources() {
16171     for (int i = 0; i < 4; i++) {
16172       CHECK(found_resource_[i]);
16173     }
16174   }
16175
16176  private:
16177   v8::String::ExternalStringResource* resource_[4];
16178   bool found_resource_[4];
16179 };
16180
16181
16182 TEST(ExternalizeOldSpaceTwoByteCons) {
16183   v8::Isolate* isolate = CcTest::isolate();
16184   LocalContext env;
16185   v8::HandleScope scope(isolate);
16186   v8::Local<v8::String> cons =
16187       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
16188   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
16189   CcTest::heap()->CollectAllAvailableGarbage();
16190   CHECK(CcTest::heap()->old_pointer_space()->Contains(
16191             *v8::Utils::OpenHandle(*cons)));
16192
16193   TestResource* resource = new TestResource(
16194       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
16195   cons->MakeExternal(resource);
16196
16197   CHECK(cons->IsExternal());
16198   CHECK_EQ(resource, cons->GetExternalStringResource());
16199   String::Encoding encoding;
16200   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
16201   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
16202 }
16203
16204
16205 TEST(ExternalizeOldSpaceOneByteCons) {
16206   v8::Isolate* isolate = CcTest::isolate();
16207   LocalContext env;
16208   v8::HandleScope scope(isolate);
16209   v8::Local<v8::String> cons =
16210       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
16211   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
16212   CcTest::heap()->CollectAllAvailableGarbage();
16213   CHECK(CcTest::heap()->old_pointer_space()->Contains(
16214             *v8::Utils::OpenHandle(*cons)));
16215
16216   TestOneByteResource* resource =
16217       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
16218   cons->MakeExternal(resource);
16219
16220   CHECK(cons->IsExternalOneByte());
16221   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
16222   String::Encoding encoding;
16223   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
16224   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
16225 }
16226
16227
16228 TEST(VisitExternalStrings) {
16229   v8::Isolate* isolate = CcTest::isolate();
16230   LocalContext env;
16231   v8::HandleScope scope(isolate);
16232   const char* string = "Some string";
16233   uint16_t* two_byte_string = AsciiToTwoByteString(string);
16234   TestResource* resource[4];
16235   resource[0] = new TestResource(two_byte_string);
16236   v8::Local<v8::String> string0 =
16237       v8::String::NewExternal(env->GetIsolate(), resource[0]);
16238   resource[1] = new TestResource(two_byte_string, NULL, false);
16239   v8::Local<v8::String> string1 =
16240       v8::String::NewExternal(env->GetIsolate(), resource[1]);
16241
16242   // Externalized symbol.
16243   resource[2] = new TestResource(two_byte_string, NULL, false);
16244   v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
16245       env->GetIsolate(), string, v8::String::kInternalizedString);
16246   CHECK(string2->MakeExternal(resource[2]));
16247
16248   // Symbolized External.
16249   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
16250   v8::Local<v8::String> string3 =
16251       v8::String::NewExternal(env->GetIsolate(), resource[3]);
16252   CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
16253   // Turn into a symbol.
16254   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
16255   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
16256       string3_i).is_null());
16257   CHECK(string3_i->IsInternalizedString());
16258
16259   // We need to add usages for string* to avoid warnings in GCC 4.7
16260   CHECK(string0->IsExternal());
16261   CHECK(string1->IsExternal());
16262   CHECK(string2->IsExternal());
16263   CHECK(string3->IsExternal());
16264
16265   VisitorImpl visitor(resource);
16266   v8::V8::VisitExternalResources(&visitor);
16267   visitor.CheckVisitedResources();
16268 }
16269
16270
16271 TEST(ExternalStringCollectedAtTearDown) {
16272   int destroyed = 0;
16273   v8::Isolate* isolate = v8::Isolate::New();
16274   { v8::Isolate::Scope isolate_scope(isolate);
16275     v8::HandleScope handle_scope(isolate);
16276     const char* s = "One string to test them all, one string to find them.";
16277     TestOneByteResource* inscription =
16278         new TestOneByteResource(i::StrDup(s), &destroyed);
16279     v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
16280     // Ring is still alive.  Orcs are roaming freely across our lands.
16281     CHECK_EQ(0, destroyed);
16282     USE(ring);
16283   }
16284
16285   isolate->Dispose();
16286   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
16287   CHECK_EQ(1, destroyed);
16288 }
16289
16290
16291 TEST(ExternalInternalizedStringCollectedAtTearDown) {
16292   int destroyed = 0;
16293   v8::Isolate* isolate = v8::Isolate::New();
16294   { v8::Isolate::Scope isolate_scope(isolate);
16295     LocalContext env(isolate);
16296     v8::HandleScope handle_scope(isolate);
16297     CompileRun("var ring = 'One string to test them all';");
16298     const char* s = "One string to test them all";
16299     TestOneByteResource* inscription =
16300         new TestOneByteResource(i::StrDup(s), &destroyed);
16301     v8::Local<v8::String> ring = CompileRun("ring")->ToString(isolate);
16302     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
16303     ring->MakeExternal(inscription);
16304     // Ring is still alive.  Orcs are roaming freely across our lands.
16305     CHECK_EQ(0, destroyed);
16306     USE(ring);
16307   }
16308
16309   isolate->Dispose();
16310   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
16311   CHECK_EQ(1, destroyed);
16312 }
16313
16314
16315 TEST(ExternalInternalizedStringCollectedAtGC) {
16316   // TODO(mvstanton): vector ics need weak support.
16317   if (i::FLAG_vector_ics) return;
16318
16319   int destroyed = 0;
16320   { LocalContext env;
16321     v8::HandleScope handle_scope(env->GetIsolate());
16322     CompileRun("var ring = 'One string to test them all';");
16323     const char* s = "One string to test them all";
16324     TestOneByteResource* inscription =
16325         new TestOneByteResource(i::StrDup(s), &destroyed);
16326     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
16327     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
16328     ring->MakeExternal(inscription);
16329     // Ring is still alive.  Orcs are roaming freely across our lands.
16330     CHECK_EQ(0, destroyed);
16331     USE(ring);
16332   }
16333
16334   // Garbage collector deals swift blows to evil.
16335   CcTest::i_isolate()->compilation_cache()->Clear();
16336   CcTest::heap()->CollectAllAvailableGarbage();
16337
16338   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
16339   CHECK_EQ(1, destroyed);
16340 }
16341
16342
16343 static double DoubleFromBits(uint64_t value) {
16344   double target;
16345   i::MemCopy(&target, &value, sizeof(target));
16346   return target;
16347 }
16348
16349
16350 static uint64_t DoubleToBits(double value) {
16351   uint64_t target;
16352   i::MemCopy(&target, &value, sizeof(target));
16353   return target;
16354 }
16355
16356
16357 static double DoubleToDateTime(double input) {
16358   double date_limit = 864e13;
16359   if (std::isnan(input) || input < -date_limit || input > date_limit) {
16360     return std::numeric_limits<double>::quiet_NaN();
16361   }
16362   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
16363 }
16364
16365
16366 // We don't have a consistent way to write 64-bit constants syntactically, so we
16367 // split them into two 32-bit constants and combine them programmatically.
16368 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
16369   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
16370 }
16371
16372
16373 THREADED_TEST(QuietSignalingNaNs) {
16374   LocalContext context;
16375   v8::Isolate* isolate = context->GetIsolate();
16376   v8::HandleScope scope(isolate);
16377   v8::TryCatch try_catch;
16378
16379   // Special double values.
16380   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
16381   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
16382   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
16383   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
16384   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
16385   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
16386   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
16387
16388   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
16389   // on either side of the epoch.
16390   double date_limit = 864e13;
16391
16392   double test_values[] = {
16393       snan,
16394       qnan,
16395       infinity,
16396       max_normal,
16397       date_limit + 1,
16398       date_limit,
16399       min_normal,
16400       max_denormal,
16401       min_denormal,
16402       0,
16403       -0,
16404       -min_denormal,
16405       -max_denormal,
16406       -min_normal,
16407       -date_limit,
16408       -date_limit - 1,
16409       -max_normal,
16410       -infinity,
16411       -qnan,
16412       -snan
16413   };
16414   int num_test_values = 20;
16415
16416   for (int i = 0; i < num_test_values; i++) {
16417     double test_value = test_values[i];
16418
16419     // Check that Number::New preserves non-NaNs and quiets SNaNs.
16420     v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
16421     double stored_number = number->NumberValue();
16422     if (!std::isnan(test_value)) {
16423       CHECK_EQ(test_value, stored_number);
16424     } else {
16425       uint64_t stored_bits = DoubleToBits(stored_number);
16426       // Check if quiet nan (bits 51..62 all set).
16427 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
16428     !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
16429       // Most significant fraction bit for quiet nan is set to 0
16430       // on MIPS architecture. Allowed by IEEE-754.
16431       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
16432 #else
16433       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
16434 #endif
16435     }
16436
16437     // Check that Date::New preserves non-NaNs in the date range and
16438     // quiets SNaNs.
16439     v8::Handle<v8::Value> date =
16440         v8::Date::New(isolate, test_value);
16441     double expected_stored_date = DoubleToDateTime(test_value);
16442     double stored_date = date->NumberValue();
16443     if (!std::isnan(expected_stored_date)) {
16444       CHECK_EQ(expected_stored_date, stored_date);
16445     } else {
16446       uint64_t stored_bits = DoubleToBits(stored_date);
16447       // Check if quiet nan (bits 51..62 all set).
16448 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
16449     !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
16450       // Most significant fraction bit for quiet nan is set to 0
16451       // on MIPS architecture. Allowed by IEEE-754.
16452       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
16453 #else
16454       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
16455 #endif
16456     }
16457   }
16458 }
16459
16460
16461 static void SpaghettiIncident(
16462     const v8::FunctionCallbackInfo<v8::Value>& args) {
16463   v8::HandleScope scope(args.GetIsolate());
16464   v8::TryCatch tc;
16465   v8::Handle<v8::String> str(args[0]->ToString(args.GetIsolate()));
16466   USE(str);
16467   if (tc.HasCaught())
16468     tc.ReThrow();
16469 }
16470
16471
16472 // Test that an exception can be propagated down through a spaghetti
16473 // stack using ReThrow.
16474 THREADED_TEST(SpaghettiStackReThrow) {
16475   v8::Isolate* isolate = CcTest::isolate();
16476   v8::HandleScope scope(isolate);
16477   LocalContext context;
16478   context->Global()->Set(
16479       v8::String::NewFromUtf8(isolate, "s"),
16480       v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
16481   v8::TryCatch try_catch;
16482   CompileRun(
16483       "var i = 0;"
16484       "var o = {"
16485       "  toString: function () {"
16486       "    if (i == 10) {"
16487       "      throw 'Hey!';"
16488       "    } else {"
16489       "      i++;"
16490       "      return s(o);"
16491       "    }"
16492       "  }"
16493       "};"
16494       "s(o);");
16495   CHECK(try_catch.HasCaught());
16496   v8::String::Utf8Value value(try_catch.Exception());
16497   CHECK_EQ(0, strcmp(*value, "Hey!"));
16498 }
16499
16500
16501 TEST(Regress528) {
16502   v8::V8::Initialize();
16503   v8::Isolate* isolate = CcTest::isolate();
16504   v8::HandleScope scope(isolate);
16505   v8::Local<Context> other_context;
16506   int gc_count;
16507
16508   // Create a context used to keep the code from aging in the compilation
16509   // cache.
16510   other_context = Context::New(isolate);
16511
16512   // Context-dependent context data creates reference from the compilation
16513   // cache to the global object.
16514   const char* source_simple = "1";
16515   {
16516     v8::HandleScope scope(isolate);
16517     v8::Local<Context> context = Context::New(isolate);
16518
16519     context->Enter();
16520     Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
16521     context->SetEmbedderData(0, obj);
16522     CompileRun(source_simple);
16523     context->Exit();
16524   }
16525   isolate->ContextDisposedNotification();
16526   for (gc_count = 1; gc_count < 10; gc_count++) {
16527     other_context->Enter();
16528     CompileRun(source_simple);
16529     other_context->Exit();
16530     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16531     if (GetGlobalObjectsCount() == 1) break;
16532   }
16533   CHECK_GE(2, gc_count);
16534   CHECK_EQ(1, GetGlobalObjectsCount());
16535
16536   // Eval in a function creates reference from the compilation cache to the
16537   // global object.
16538   const char* source_eval = "function f(){eval('1')}; f()";
16539   {
16540     v8::HandleScope scope(isolate);
16541     v8::Local<Context> context = Context::New(isolate);
16542
16543     context->Enter();
16544     CompileRun(source_eval);
16545     context->Exit();
16546   }
16547   isolate->ContextDisposedNotification();
16548   for (gc_count = 1; gc_count < 10; gc_count++) {
16549     other_context->Enter();
16550     CompileRun(source_eval);
16551     other_context->Exit();
16552     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16553     if (GetGlobalObjectsCount() == 1) break;
16554   }
16555   CHECK_GE(2, gc_count);
16556   CHECK_EQ(1, GetGlobalObjectsCount());
16557
16558   // Looking up the line number for an exception creates reference from the
16559   // compilation cache to the global object.
16560   const char* source_exception = "function f(){throw 1;} f()";
16561   {
16562     v8::HandleScope scope(isolate);
16563     v8::Local<Context> context = Context::New(isolate);
16564
16565     context->Enter();
16566     v8::TryCatch try_catch;
16567     CompileRun(source_exception);
16568     CHECK(try_catch.HasCaught());
16569     v8::Handle<v8::Message> message = try_catch.Message();
16570     CHECK(!message.IsEmpty());
16571     CHECK_EQ(1, message->GetLineNumber());
16572     context->Exit();
16573   }
16574   isolate->ContextDisposedNotification();
16575   for (gc_count = 1; gc_count < 10; gc_count++) {
16576     other_context->Enter();
16577     CompileRun(source_exception);
16578     other_context->Exit();
16579     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16580     if (GetGlobalObjectsCount() == 1) break;
16581   }
16582   CHECK_GE(2, gc_count);
16583   CHECK_EQ(1, GetGlobalObjectsCount());
16584
16585   isolate->ContextDisposedNotification();
16586 }
16587
16588
16589 THREADED_TEST(ScriptOrigin) {
16590   LocalContext env;
16591   v8::HandleScope scope(env->GetIsolate());
16592   v8::ScriptOrigin origin = v8::ScriptOrigin(
16593       v8::String::NewFromUtf8(env->GetIsolate(), "test"),
16594       v8::Integer::New(env->GetIsolate(), 1),
16595       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
16596       v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()));
16597   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16598       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
16599   v8::Script::Compile(script, &origin)->Run();
16600   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16601       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16602   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16603       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16604
16605   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
16606   CHECK_EQ(0, strcmp("test",
16607                      *v8::String::Utf8Value(script_origin_f.ResourceName())));
16608   CHECK_EQ(1, script_origin_f.ResourceLineOffset()->Int32Value());
16609   CHECK(script_origin_f.ResourceIsSharedCrossOrigin()->Value());
16610   CHECK(script_origin_f.ResourceIsEmbedderDebugScript()->Value());
16611
16612   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
16613   CHECK_EQ(0, strcmp("test",
16614                      *v8::String::Utf8Value(script_origin_g.ResourceName())));
16615   CHECK_EQ(1, script_origin_g.ResourceLineOffset()->Int32Value());
16616   CHECK(script_origin_g.ResourceIsSharedCrossOrigin()->Value());
16617   CHECK(script_origin_g.ResourceIsEmbedderDebugScript()->Value());
16618 }
16619
16620
16621 THREADED_TEST(FunctionGetInferredName) {
16622   LocalContext env;
16623   v8::HandleScope scope(env->GetIsolate());
16624   v8::ScriptOrigin origin =
16625       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16626   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16627       env->GetIsolate(),
16628       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
16629   v8::Script::Compile(script, &origin)->Run();
16630   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16631       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16632   CHECK_EQ(0,
16633            strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
16634 }
16635
16636
16637 THREADED_TEST(FunctionGetDisplayName) {
16638   LocalContext env;
16639   v8::HandleScope scope(env->GetIsolate());
16640   const char* code = "var error = false;"
16641                      "function a() { this.x = 1; };"
16642                      "a.displayName = 'display_a';"
16643                      "var b = (function() {"
16644                      "  var f = function() { this.x = 2; };"
16645                      "  f.displayName = 'display_b';"
16646                      "  return f;"
16647                      "})();"
16648                      "var c = function() {};"
16649                      "c.__defineGetter__('displayName', function() {"
16650                      "  error = true;"
16651                      "  throw new Error();"
16652                      "});"
16653                      "function d() {};"
16654                      "d.__defineGetter__('displayName', function() {"
16655                      "  error = true;"
16656                      "  return 'wrong_display_name';"
16657                      "});"
16658                      "function e() {};"
16659                      "e.displayName = 'wrong_display_name';"
16660                      "e.__defineSetter__('displayName', function() {"
16661                      "  error = true;"
16662                      "  throw new Error();"
16663                      "});"
16664                      "function f() {};"
16665                      "f.displayName = { 'foo': 6, toString: function() {"
16666                      "  error = true;"
16667                      "  return 'wrong_display_name';"
16668                      "}};"
16669                      "var g = function() {"
16670                      "  arguments.callee.displayName = 'set_in_runtime';"
16671                      "}; g();"
16672                      ;
16673   v8::ScriptOrigin origin =
16674       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16675   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
16676       ->Run();
16677   v8::Local<v8::Value> error =
16678       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
16679   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
16680       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
16681   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
16682       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
16683   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
16684       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
16685   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
16686       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
16687   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
16688       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
16689   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16690       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16691   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16692       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16693   CHECK_EQ(false, error->BooleanValue());
16694   CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
16695   CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
16696   CHECK(c->GetDisplayName()->IsUndefined());
16697   CHECK(d->GetDisplayName()->IsUndefined());
16698   CHECK(e->GetDisplayName()->IsUndefined());
16699   CHECK(f->GetDisplayName()->IsUndefined());
16700   CHECK_EQ(
16701       0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
16702 }
16703
16704
16705 THREADED_TEST(ScriptLineNumber) {
16706   LocalContext env;
16707   v8::HandleScope scope(env->GetIsolate());
16708   v8::ScriptOrigin origin =
16709       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16710   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16711       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
16712   v8::Script::Compile(script, &origin)->Run();
16713   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16714       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16715   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16716       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16717   CHECK_EQ(0, f->GetScriptLineNumber());
16718   CHECK_EQ(2, g->GetScriptLineNumber());
16719 }
16720
16721
16722 THREADED_TEST(ScriptColumnNumber) {
16723   LocalContext env;
16724   v8::Isolate* isolate = env->GetIsolate();
16725   v8::HandleScope scope(isolate);
16726   v8::ScriptOrigin origin =
16727       v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
16728                        v8::Integer::New(isolate, 3),
16729                        v8::Integer::New(isolate, 2));
16730   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16731       isolate, "function foo() {}\n\n     function bar() {}");
16732   v8::Script::Compile(script, &origin)->Run();
16733   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
16734       env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
16735   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
16736       env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
16737   CHECK_EQ(14, foo->GetScriptColumnNumber());
16738   CHECK_EQ(17, bar->GetScriptColumnNumber());
16739 }
16740
16741
16742 THREADED_TEST(FunctionIsBuiltin) {
16743   LocalContext env;
16744   v8::Isolate* isolate = env->GetIsolate();
16745   v8::HandleScope scope(isolate);
16746   v8::Local<v8::Function> f;
16747   f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
16748   CHECK(f->IsBuiltin());
16749   f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
16750   CHECK(f->IsBuiltin());
16751   f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
16752   CHECK(f->IsBuiltin());
16753   f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
16754   CHECK(f->IsBuiltin());
16755   f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
16756   CHECK(!f->IsBuiltin());
16757 }
16758
16759
16760 THREADED_TEST(FunctionGetScriptId) {
16761   LocalContext env;
16762   v8::Isolate* isolate = env->GetIsolate();
16763   v8::HandleScope scope(isolate);
16764   v8::ScriptOrigin origin =
16765       v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
16766                        v8::Integer::New(isolate, 3),
16767                        v8::Integer::New(isolate, 2));
16768   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
16769       isolate, "function foo() {}\n\n     function bar() {}");
16770   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
16771   script->Run();
16772   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
16773       env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
16774   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
16775       env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
16776   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
16777   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
16778 }
16779
16780
16781 THREADED_TEST(FunctionGetBoundFunction) {
16782   LocalContext env;
16783   v8::HandleScope scope(env->GetIsolate());
16784   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
16785       env->GetIsolate(), "test"));
16786   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16787       env->GetIsolate(),
16788       "var a = new Object();\n"
16789       "a.x = 1;\n"
16790       "function f () { return this.x };\n"
16791       "var g = f.bind(a);\n"
16792       "var b = g();");
16793   v8::Script::Compile(script, &origin)->Run();
16794   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16795       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16796   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16797       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16798   CHECK(g->GetBoundFunction()->IsFunction());
16799   Local<v8::Function> original_function = Local<v8::Function>::Cast(
16800       g->GetBoundFunction());
16801   CHECK(f->GetName()->Equals(original_function->GetName()));
16802   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
16803   CHECK_EQ(f->GetScriptColumnNumber(),
16804            original_function->GetScriptColumnNumber());
16805 }
16806
16807
16808 static void GetterWhichReturns42(
16809     Local<String> name,
16810     const v8::PropertyCallbackInfo<v8::Value>& info) {
16811   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16812   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16813   info.GetReturnValue().Set(v8_num(42));
16814 }
16815
16816
16817 static void SetterWhichSetsYOnThisTo23(
16818     Local<String> name,
16819     Local<Value> value,
16820     const v8::PropertyCallbackInfo<void>& info) {
16821   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16822   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16823   Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16824 }
16825
16826
16827 void FooGetInterceptor(Local<Name> name,
16828                        const v8::PropertyCallbackInfo<v8::Value>& info) {
16829   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16830   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16831   if (!name->Equals(v8_str("foo"))) return;
16832   info.GetReturnValue().Set(v8_num(42));
16833 }
16834
16835
16836 void FooSetInterceptor(Local<Name> name, Local<Value> value,
16837                        const v8::PropertyCallbackInfo<v8::Value>& info) {
16838   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16839   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16840   if (!name->Equals(v8_str("foo"))) return;
16841   Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16842   info.GetReturnValue().Set(v8_num(23));
16843 }
16844
16845
16846 TEST(SetterOnConstructorPrototype) {
16847   v8::Isolate* isolate = CcTest::isolate();
16848   v8::HandleScope scope(isolate);
16849   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16850   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
16851                      SetterWhichSetsYOnThisTo23);
16852   LocalContext context;
16853   context->Global()->Set(v8_str("P"), templ->NewInstance());
16854   CompileRun("function C1() {"
16855              "  this.x = 23;"
16856              "};"
16857              "C1.prototype = P;"
16858              "function C2() {"
16859              "  this.x = 23"
16860              "};"
16861              "C2.prototype = { };"
16862              "C2.prototype.__proto__ = P;");
16863
16864   v8::Local<v8::Script> script;
16865   script = v8_compile("new C1();");
16866   for (int i = 0; i < 10; i++) {
16867     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16868     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
16869     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
16870   }
16871
16872 script = v8_compile("new C2();");
16873   for (int i = 0; i < 10; i++) {
16874     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
16875     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
16876     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
16877   }
16878 }
16879
16880
16881 static void NamedPropertyGetterWhichReturns42(
16882     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
16883   info.GetReturnValue().Set(v8_num(42));
16884 }
16885
16886
16887 static void NamedPropertySetterWhichSetsYOnThisTo23(
16888     Local<Name> name, Local<Value> value,
16889     const v8::PropertyCallbackInfo<v8::Value>& info) {
16890   if (name->Equals(v8_str("x"))) {
16891     Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16892   }
16893 }
16894
16895
16896 THREADED_TEST(InterceptorOnConstructorPrototype) {
16897   v8::Isolate* isolate = CcTest::isolate();
16898   v8::HandleScope scope(isolate);
16899   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16900   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
16901       NamedPropertyGetterWhichReturns42,
16902       NamedPropertySetterWhichSetsYOnThisTo23));
16903   LocalContext context;
16904   context->Global()->Set(v8_str("P"), templ->NewInstance());
16905   CompileRun("function C1() {"
16906              "  this.x = 23;"
16907              "};"
16908              "C1.prototype = P;"
16909              "function C2() {"
16910              "  this.x = 23"
16911              "};"
16912              "C2.prototype = { };"
16913              "C2.prototype.__proto__ = P;");
16914
16915   v8::Local<v8::Script> script;
16916   script = v8_compile("new C1();");
16917   for (int i = 0; i < 10; i++) {
16918     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16919     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
16920     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
16921   }
16922
16923   script = v8_compile("new C2();");
16924   for (int i = 0; i < 10; i++) {
16925     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
16926     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
16927     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
16928   }
16929 }
16930
16931
16932 TEST(Regress618) {
16933   const char* source = "function C1() {"
16934                        "  this.x = 23;"
16935                        "};"
16936                        "C1.prototype = P;";
16937
16938   LocalContext context;
16939   v8::Isolate* isolate = context->GetIsolate();
16940   v8::HandleScope scope(isolate);
16941   v8::Local<v8::Script> script;
16942
16943   // Use a simple object as prototype.
16944   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
16945   prototype->Set(v8_str("y"), v8_num(42));
16946   context->Global()->Set(v8_str("P"), prototype);
16947
16948   // This compile will add the code to the compilation cache.
16949   CompileRun(source);
16950
16951   script = v8_compile("new C1();");
16952   // Allow enough iterations for the inobject slack tracking logic
16953   // to finalize instance size and install the fast construct stub.
16954   for (int i = 0; i < 256; i++) {
16955     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16956     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
16957     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
16958   }
16959
16960   // Use an API object with accessors as prototype.
16961   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16962   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
16963                      SetterWhichSetsYOnThisTo23);
16964   context->Global()->Set(v8_str("P"), templ->NewInstance());
16965
16966   // This compile will get the code from the compilation cache.
16967   CompileRun(source);
16968
16969   script = v8_compile("new C1();");
16970   for (int i = 0; i < 10; i++) {
16971     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16972     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
16973     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
16974   }
16975 }
16976
16977 v8::Isolate* gc_callbacks_isolate = NULL;
16978 int prologue_call_count = 0;
16979 int epilogue_call_count = 0;
16980 int prologue_call_count_second = 0;
16981 int epilogue_call_count_second = 0;
16982 int prologue_call_count_alloc = 0;
16983 int epilogue_call_count_alloc = 0;
16984
16985 void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
16986   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16987   ++prologue_call_count;
16988 }
16989
16990
16991 void PrologueCallback(v8::Isolate* isolate,
16992                       v8::GCType,
16993                       v8::GCCallbackFlags flags) {
16994   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16995   CHECK_EQ(gc_callbacks_isolate, isolate);
16996   ++prologue_call_count;
16997 }
16998
16999
17000 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
17001   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17002   ++epilogue_call_count;
17003 }
17004
17005
17006 void EpilogueCallback(v8::Isolate* isolate,
17007                       v8::GCType,
17008                       v8::GCCallbackFlags flags) {
17009   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17010   CHECK_EQ(gc_callbacks_isolate, isolate);
17011   ++epilogue_call_count;
17012 }
17013
17014
17015 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
17016   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17017   ++prologue_call_count_second;
17018 }
17019
17020
17021 void PrologueCallbackSecond(v8::Isolate* isolate,
17022                             v8::GCType,
17023                             v8::GCCallbackFlags flags) {
17024   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17025   CHECK_EQ(gc_callbacks_isolate, isolate);
17026   ++prologue_call_count_second;
17027 }
17028
17029
17030 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
17031   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17032   ++epilogue_call_count_second;
17033 }
17034
17035
17036 void EpilogueCallbackSecond(v8::Isolate* isolate,
17037                             v8::GCType,
17038                             v8::GCCallbackFlags flags) {
17039   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17040   CHECK_EQ(gc_callbacks_isolate, isolate);
17041   ++epilogue_call_count_second;
17042 }
17043
17044
17045 void PrologueCallbackAlloc(v8::Isolate* isolate,
17046                            v8::GCType,
17047                            v8::GCCallbackFlags flags) {
17048   v8::HandleScope scope(isolate);
17049
17050   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17051   CHECK_EQ(gc_callbacks_isolate, isolate);
17052   ++prologue_call_count_alloc;
17053
17054   // Simulate full heap to see if we will reenter this callback
17055   SimulateFullSpace(CcTest::heap()->new_space());
17056
17057   Local<Object> obj = Object::New(isolate);
17058   CHECK(!obj.IsEmpty());
17059
17060   CcTest::heap()->CollectAllGarbage(
17061       i::Heap::kAbortIncrementalMarkingMask);
17062 }
17063
17064
17065 void EpilogueCallbackAlloc(v8::Isolate* isolate,
17066                            v8::GCType,
17067                            v8::GCCallbackFlags flags) {
17068   v8::HandleScope scope(isolate);
17069
17070   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17071   CHECK_EQ(gc_callbacks_isolate, isolate);
17072   ++epilogue_call_count_alloc;
17073
17074   // Simulate full heap to see if we will reenter this callback
17075   SimulateFullSpace(CcTest::heap()->new_space());
17076
17077   Local<Object> obj = Object::New(isolate);
17078   CHECK(!obj.IsEmpty());
17079
17080   CcTest::heap()->CollectAllGarbage(
17081       i::Heap::kAbortIncrementalMarkingMask);
17082 }
17083
17084
17085 TEST(GCCallbacksOld) {
17086   LocalContext context;
17087
17088   v8::V8::AddGCPrologueCallback(PrologueCallback);
17089   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
17090   CHECK_EQ(0, prologue_call_count);
17091   CHECK_EQ(0, epilogue_call_count);
17092   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17093   CHECK_EQ(1, prologue_call_count);
17094   CHECK_EQ(1, epilogue_call_count);
17095   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
17096   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
17097   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17098   CHECK_EQ(2, prologue_call_count);
17099   CHECK_EQ(2, epilogue_call_count);
17100   CHECK_EQ(1, prologue_call_count_second);
17101   CHECK_EQ(1, epilogue_call_count_second);
17102   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
17103   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
17104   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17105   CHECK_EQ(2, prologue_call_count);
17106   CHECK_EQ(2, epilogue_call_count);
17107   CHECK_EQ(2, prologue_call_count_second);
17108   CHECK_EQ(2, epilogue_call_count_second);
17109   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
17110   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
17111   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17112   CHECK_EQ(2, prologue_call_count);
17113   CHECK_EQ(2, epilogue_call_count);
17114   CHECK_EQ(2, prologue_call_count_second);
17115   CHECK_EQ(2, epilogue_call_count_second);
17116 }
17117
17118
17119 TEST(GCCallbacks) {
17120   LocalContext context;
17121   v8::Isolate* isolate = context->GetIsolate();
17122   gc_callbacks_isolate = isolate;
17123   isolate->AddGCPrologueCallback(PrologueCallback);
17124   isolate->AddGCEpilogueCallback(EpilogueCallback);
17125   CHECK_EQ(0, prologue_call_count);
17126   CHECK_EQ(0, epilogue_call_count);
17127   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17128   CHECK_EQ(1, prologue_call_count);
17129   CHECK_EQ(1, epilogue_call_count);
17130   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
17131   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
17132   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17133   CHECK_EQ(2, prologue_call_count);
17134   CHECK_EQ(2, epilogue_call_count);
17135   CHECK_EQ(1, prologue_call_count_second);
17136   CHECK_EQ(1, epilogue_call_count_second);
17137   isolate->RemoveGCPrologueCallback(PrologueCallback);
17138   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
17139   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17140   CHECK_EQ(2, prologue_call_count);
17141   CHECK_EQ(2, epilogue_call_count);
17142   CHECK_EQ(2, prologue_call_count_second);
17143   CHECK_EQ(2, epilogue_call_count_second);
17144   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
17145   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
17146   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17147   CHECK_EQ(2, prologue_call_count);
17148   CHECK_EQ(2, epilogue_call_count);
17149   CHECK_EQ(2, prologue_call_count_second);
17150   CHECK_EQ(2, epilogue_call_count_second);
17151
17152   CHECK_EQ(0, prologue_call_count_alloc);
17153   CHECK_EQ(0, epilogue_call_count_alloc);
17154   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
17155   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
17156   CcTest::heap()->CollectAllGarbage(
17157       i::Heap::kAbortIncrementalMarkingMask);
17158   CHECK_EQ(1, prologue_call_count_alloc);
17159   CHECK_EQ(1, epilogue_call_count_alloc);
17160   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
17161   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
17162 }
17163
17164
17165 THREADED_TEST(AddToJSFunctionResultCache) {
17166   i::FLAG_stress_compaction = false;
17167   i::FLAG_allow_natives_syntax = true;
17168   v8::HandleScope scope(CcTest::isolate());
17169
17170   LocalContext context;
17171
17172   const char* code =
17173       "(function() {"
17174       "  var key0 = 'a';"
17175       "  var key1 = 'b';"
17176       "  var r0 = %_GetFromCache(0, key0);"
17177       "  var r1 = %_GetFromCache(0, key1);"
17178       "  var r0_ = %_GetFromCache(0, key0);"
17179       "  if (r0 !== r0_)"
17180       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
17181       "  var r1_ = %_GetFromCache(0, key1);"
17182       "  if (r1 !== r1_)"
17183       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
17184       "  return 'PASSED';"
17185       "})()";
17186   CcTest::heap()->ClearJSFunctionResultCaches();
17187   ExpectString(code, "PASSED");
17188 }
17189
17190
17191 THREADED_TEST(FillJSFunctionResultCache) {
17192   i::FLAG_allow_natives_syntax = true;
17193   LocalContext context;
17194   v8::HandleScope scope(context->GetIsolate());
17195
17196   const char* code =
17197       "(function() {"
17198       "  var k = 'a';"
17199       "  var r = %_GetFromCache(0, k);"
17200       "  for (var i = 0; i < 16; i++) {"
17201       "    %_GetFromCache(0, 'a' + i);"
17202       "  };"
17203       "  if (r === %_GetFromCache(0, k))"
17204       "    return 'FAILED: k0CacheSize is too small';"
17205       "  return 'PASSED';"
17206       "})()";
17207   CcTest::heap()->ClearJSFunctionResultCaches();
17208   ExpectString(code, "PASSED");
17209 }
17210
17211
17212 THREADED_TEST(RoundRobinGetFromCache) {
17213   i::FLAG_allow_natives_syntax = true;
17214   LocalContext context;
17215   v8::HandleScope scope(context->GetIsolate());
17216
17217   const char* code =
17218       "(function() {"
17219       "  var keys = [];"
17220       "  for (var i = 0; i < 16; i++) keys.push(i);"
17221       "  var values = [];"
17222       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
17223       "  for (var i = 0; i < 16; i++) {"
17224       "    var v = %_GetFromCache(0, keys[i]);"
17225       "    if (v.toString() !== values[i].toString())"
17226       "      return 'Wrong value for ' + "
17227       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
17228       "  };"
17229       "  return 'PASSED';"
17230       "})()";
17231   CcTest::heap()->ClearJSFunctionResultCaches();
17232   ExpectString(code, "PASSED");
17233 }
17234
17235
17236 THREADED_TEST(ReverseGetFromCache) {
17237   i::FLAG_allow_natives_syntax = true;
17238   LocalContext context;
17239   v8::HandleScope scope(context->GetIsolate());
17240
17241   const char* code =
17242       "(function() {"
17243       "  var keys = [];"
17244       "  for (var i = 0; i < 16; i++) keys.push(i);"
17245       "  var values = [];"
17246       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
17247       "  for (var i = 15; i >= 16; i--) {"
17248       "    var v = %_GetFromCache(0, keys[i]);"
17249       "    if (v !== values[i])"
17250       "      return 'Wrong value for ' + "
17251       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
17252       "  };"
17253       "  return 'PASSED';"
17254       "})()";
17255   CcTest::heap()->ClearJSFunctionResultCaches();
17256   ExpectString(code, "PASSED");
17257 }
17258
17259
17260 THREADED_TEST(TestEviction) {
17261   i::FLAG_allow_natives_syntax = true;
17262   LocalContext context;
17263   v8::HandleScope scope(context->GetIsolate());
17264
17265   const char* code =
17266       "(function() {"
17267       "  for (var i = 0; i < 2*16; i++) {"
17268       "    %_GetFromCache(0, 'a' + i);"
17269       "  };"
17270       "  return 'PASSED';"
17271       "})()";
17272   CcTest::heap()->ClearJSFunctionResultCaches();
17273   ExpectString(code, "PASSED");
17274 }
17275
17276
17277 THREADED_TEST(TwoByteStringInOneByteCons) {
17278   // See Chromium issue 47824.
17279   LocalContext context;
17280   v8::HandleScope scope(context->GetIsolate());
17281
17282   const char* init_code =
17283       "var str1 = 'abelspendabel';"
17284       "var str2 = str1 + str1 + str1;"
17285       "str2;";
17286   Local<Value> result = CompileRun(init_code);
17287
17288   Local<Value> indexof = CompileRun("str2.indexOf('els')");
17289   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
17290
17291   CHECK(result->IsString());
17292   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
17293   int length = string->length();
17294   CHECK(string->IsOneByteRepresentation());
17295
17296   i::Handle<i::String> flat_string = i::String::Flatten(string);
17297
17298   CHECK(string->IsOneByteRepresentation());
17299   CHECK(flat_string->IsOneByteRepresentation());
17300
17301   // Create external resource.
17302   uint16_t* uc16_buffer = new uint16_t[length + 1];
17303
17304   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
17305   uc16_buffer[length] = 0;
17306
17307   TestResource resource(uc16_buffer);
17308
17309   flat_string->MakeExternal(&resource);
17310
17311   CHECK(flat_string->IsTwoByteRepresentation());
17312
17313   // If the cons string has been short-circuited, skip the following checks.
17314   if (!string.is_identical_to(flat_string)) {
17315     // At this point, we should have a Cons string which is flat and one-byte,
17316     // with a first half that is a two-byte string (although it only contains
17317     // one-byte characters). This is a valid sequence of steps, and it can
17318     // happen in real pages.
17319     CHECK(string->IsOneByteRepresentation());
17320     i::ConsString* cons = i::ConsString::cast(*string);
17321     CHECK_EQ(0, cons->second()->length());
17322     CHECK(cons->first()->IsTwoByteRepresentation());
17323   }
17324
17325   // Check that some string operations work.
17326
17327   // Atom RegExp.
17328   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
17329   CHECK_EQ(6, reresult->Int32Value());
17330
17331   // Nonatom RegExp.
17332   reresult = CompileRun("str2.match(/abe./g).length;");
17333   CHECK_EQ(6, reresult->Int32Value());
17334
17335   reresult = CompileRun("str2.search(/bel/g);");
17336   CHECK_EQ(1, reresult->Int32Value());
17337
17338   reresult = CompileRun("str2.search(/be./g);");
17339   CHECK_EQ(1, reresult->Int32Value());
17340
17341   ExpectTrue("/bel/g.test(str2);");
17342
17343   ExpectTrue("/be./g.test(str2);");
17344
17345   reresult = CompileRun("/bel/g.exec(str2);");
17346   CHECK(!reresult->IsNull());
17347
17348   reresult = CompileRun("/be./g.exec(str2);");
17349   CHECK(!reresult->IsNull());
17350
17351   ExpectString("str2.substring(2, 10);", "elspenda");
17352
17353   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
17354
17355   ExpectString("str2.charAt(2);", "e");
17356
17357   ExpectObject("str2.indexOf('els');", indexof);
17358
17359   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
17360
17361   reresult = CompileRun("str2.charCodeAt(2);");
17362   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
17363 }
17364
17365
17366 TEST(ContainsOnlyOneByte) {
17367   v8::V8::Initialize();
17368   v8::Isolate* isolate = CcTest::isolate();
17369   v8::HandleScope scope(isolate);
17370   // Make a buffer long enough that it won't automatically be converted.
17371   const int length = 512;
17372   // Ensure word aligned assignment.
17373   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
17374   i::SmartArrayPointer<uintptr_t>
17375   aligned_contents(new uintptr_t[aligned_length]);
17376   uint16_t* string_contents =
17377       reinterpret_cast<uint16_t*>(aligned_contents.get());
17378   // Set to contain only one byte.
17379   for (int i = 0; i < length-1; i++) {
17380     string_contents[i] = 0x41;
17381   }
17382   string_contents[length-1] = 0;
17383   // Simple case.
17384   Handle<String> string =
17385       String::NewExternal(isolate,
17386                           new TestResource(string_contents, NULL, false));
17387   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
17388   // Counter example.
17389   string = String::NewFromTwoByte(isolate, string_contents);
17390   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
17391   // Test left right and balanced cons strings.
17392   Handle<String> base = String::NewFromUtf8(isolate, "a");
17393   Handle<String> left = base;
17394   Handle<String> right = base;
17395   for (int i = 0; i < 1000; i++) {
17396     left = String::Concat(base, left);
17397     right = String::Concat(right, base);
17398   }
17399   Handle<String> balanced = String::Concat(left, base);
17400   balanced = String::Concat(balanced, right);
17401   Handle<String> cons_strings[] = {left, balanced, right};
17402   Handle<String> two_byte =
17403       String::NewExternal(isolate,
17404                           new TestResource(string_contents, NULL, false));
17405   USE(two_byte); USE(cons_strings);
17406   for (size_t i = 0; i < arraysize(cons_strings); i++) {
17407     // Base assumptions.
17408     string = cons_strings[i];
17409     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
17410     // Test left and right concatentation.
17411     string = String::Concat(two_byte, cons_strings[i]);
17412     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
17413     string = String::Concat(cons_strings[i], two_byte);
17414     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
17415   }
17416   // Set bits in different positions
17417   // for strings of different lengths and alignments.
17418   for (int alignment = 0; alignment < 7; alignment++) {
17419     for (int size = 2; alignment + size < length; size *= 2) {
17420       int zero_offset = size + alignment;
17421       string_contents[zero_offset] = 0;
17422       for (int i = 0; i < size; i++) {
17423         int shift = 8 + (i % 7);
17424         string_contents[alignment + i] = 1 << shift;
17425         string = String::NewExternal(
17426             isolate,
17427             new TestResource(string_contents + alignment, NULL, false));
17428         CHECK_EQ(size, string->Length());
17429         CHECK(!string->ContainsOnlyOneByte());
17430         string_contents[alignment + i] = 0x41;
17431       }
17432       string_contents[zero_offset] = 0x41;
17433     }
17434   }
17435 }
17436
17437
17438 // Failed access check callback that performs a GC on each invocation.
17439 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
17440                                  v8::AccessType type,
17441                                  Local<v8::Value> data) {
17442   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17443 }
17444
17445
17446 TEST(GCInFailedAccessCheckCallback) {
17447   // Install a failed access check callback that performs a GC on each
17448   // invocation. Then force the callback to be called from va
17449
17450   v8::V8::Initialize();
17451   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
17452
17453   v8::Isolate* isolate = CcTest::isolate();
17454   v8::HandleScope scope(isolate);
17455
17456   // Create an ObjectTemplate for global objects and install access
17457   // check callbacks that will block access.
17458   v8::Handle<v8::ObjectTemplate> global_template =
17459       v8::ObjectTemplate::New(isolate);
17460   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
17461                                            IndexedGetAccessBlocker,
17462                                            v8::Handle<v8::Value>(),
17463                                            false);
17464
17465   // Create a context and set an x property on it's global object.
17466   LocalContext context0(NULL, global_template);
17467   context0->Global()->Set(v8_str("x"), v8_num(42));
17468   v8::Handle<v8::Object> global0 = context0->Global();
17469
17470   // Create a context with a different security token so that the
17471   // failed access check callback will be called on each access.
17472   LocalContext context1(NULL, global_template);
17473   context1->Global()->Set(v8_str("other"), global0);
17474
17475   // Get property with failed access check.
17476   ExpectUndefined("other.x");
17477
17478   // Get element with failed access check.
17479   ExpectUndefined("other[0]");
17480
17481   // Set property with failed access check.
17482   v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
17483   CHECK(result->IsObject());
17484
17485   // Set element with failed access check.
17486   result = CompileRun("other[0] = new Object()");
17487   CHECK(result->IsObject());
17488
17489   // Get property attribute with failed access check.
17490   ExpectFalse("\'x\' in other");
17491
17492   // Get property attribute for element with failed access check.
17493   ExpectFalse("0 in other");
17494
17495   // Delete property.
17496   ExpectFalse("delete other.x");
17497
17498   // Delete element.
17499   CHECK_EQ(false, global0->Delete(0));
17500
17501   // DefineAccessor.
17502   CHECK_EQ(false,
17503            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
17504
17505   // Define JavaScript accessor.
17506   ExpectUndefined("Object.prototype.__defineGetter__.call("
17507                   "    other, \'x\', function() { return 42; })");
17508
17509   // LookupAccessor.
17510   ExpectUndefined("Object.prototype.__lookupGetter__.call("
17511                   "    other, \'x\')");
17512
17513   // HasOwnElement.
17514   ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
17515
17516   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
17517   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
17518   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
17519
17520   // Reset the failed access check callback so it does not influence
17521   // the other tests.
17522   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
17523 }
17524
17525
17526 TEST(IsolateNewDispose) {
17527   v8::Isolate* current_isolate = CcTest::isolate();
17528   v8::Isolate* isolate = v8::Isolate::New();
17529   CHECK(isolate != NULL);
17530   CHECK(current_isolate != isolate);
17531   CHECK(current_isolate == CcTest::isolate());
17532
17533   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
17534   last_location = last_message = NULL;
17535   isolate->Dispose();
17536   CHECK(!last_location);
17537   CHECK(!last_message);
17538 }
17539
17540
17541 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
17542   v8::Isolate* isolate = v8::Isolate::New();
17543   {
17544     v8::Isolate::Scope i_scope(isolate);
17545     v8::HandleScope scope(isolate);
17546     LocalContext context(isolate);
17547     // Run something in this isolate.
17548     ExpectTrue("true");
17549     v8::V8::SetFatalErrorHandler(StoringErrorCallback);
17550     last_location = last_message = NULL;
17551     // Still entered, should fail.
17552     isolate->Dispose();
17553     CHECK(last_location);
17554     CHECK(last_message);
17555   }
17556   isolate->Dispose();
17557 }
17558
17559
17560 TEST(RunTwoIsolatesOnSingleThread) {
17561   // Run isolate 1.
17562   v8::Isolate* isolate1 = v8::Isolate::New();
17563   isolate1->Enter();
17564   v8::Persistent<v8::Context> context1;
17565   {
17566     v8::HandleScope scope(isolate1);
17567     context1.Reset(isolate1, Context::New(isolate1));
17568   }
17569
17570   {
17571     v8::HandleScope scope(isolate1);
17572     v8::Local<v8::Context> context =
17573         v8::Local<v8::Context>::New(isolate1, context1);
17574     v8::Context::Scope context_scope(context);
17575     // Run something in new isolate.
17576     CompileRun("var foo = 'isolate 1';");
17577     ExpectString("function f() { return foo; }; f()", "isolate 1");
17578   }
17579
17580   // Run isolate 2.
17581   v8::Isolate* isolate2 = v8::Isolate::New();
17582   v8::Persistent<v8::Context> context2;
17583
17584   {
17585     v8::Isolate::Scope iscope(isolate2);
17586     v8::HandleScope scope(isolate2);
17587     context2.Reset(isolate2, Context::New(isolate2));
17588     v8::Local<v8::Context> context =
17589         v8::Local<v8::Context>::New(isolate2, context2);
17590     v8::Context::Scope context_scope(context);
17591
17592     // Run something in new isolate.
17593     CompileRun("var foo = 'isolate 2';");
17594     ExpectString("function f() { return foo; }; f()", "isolate 2");
17595   }
17596
17597   {
17598     v8::HandleScope scope(isolate1);
17599     v8::Local<v8::Context> context =
17600         v8::Local<v8::Context>::New(isolate1, context1);
17601     v8::Context::Scope context_scope(context);
17602     // Now again in isolate 1
17603     ExpectString("function f() { return foo; }; f()", "isolate 1");
17604   }
17605
17606   isolate1->Exit();
17607
17608   // Run some stuff in default isolate.
17609   v8::Persistent<v8::Context> context_default;
17610   {
17611     v8::Isolate* isolate = CcTest::isolate();
17612     v8::Isolate::Scope iscope(isolate);
17613     v8::HandleScope scope(isolate);
17614     context_default.Reset(isolate, Context::New(isolate));
17615   }
17616
17617   {
17618     v8::HandleScope scope(CcTest::isolate());
17619     v8::Local<v8::Context> context =
17620         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
17621     v8::Context::Scope context_scope(context);
17622     // Variables in other isolates should be not available, verify there
17623     // is an exception.
17624     ExpectTrue("function f() {"
17625                "  try {"
17626                "    foo;"
17627                "    return false;"
17628                "  } catch(e) {"
17629                "    return true;"
17630                "  }"
17631                "};"
17632                "var isDefaultIsolate = true;"
17633                "f()");
17634   }
17635
17636   isolate1->Enter();
17637
17638   {
17639     v8::Isolate::Scope iscope(isolate2);
17640     v8::HandleScope scope(isolate2);
17641     v8::Local<v8::Context> context =
17642         v8::Local<v8::Context>::New(isolate2, context2);
17643     v8::Context::Scope context_scope(context);
17644     ExpectString("function f() { return foo; }; f()", "isolate 2");
17645   }
17646
17647   {
17648     v8::HandleScope scope(v8::Isolate::GetCurrent());
17649     v8::Local<v8::Context> context =
17650         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
17651     v8::Context::Scope context_scope(context);
17652     ExpectString("function f() { return foo; }; f()", "isolate 1");
17653   }
17654
17655   {
17656     v8::Isolate::Scope iscope(isolate2);
17657     context2.Reset();
17658   }
17659
17660   context1.Reset();
17661   isolate1->Exit();
17662
17663   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
17664   last_location = last_message = NULL;
17665
17666   isolate1->Dispose();
17667   CHECK(!last_location);
17668   CHECK(!last_message);
17669
17670   isolate2->Dispose();
17671   CHECK(!last_location);
17672   CHECK(!last_message);
17673
17674   // Check that default isolate still runs.
17675   {
17676     v8::HandleScope scope(CcTest::isolate());
17677     v8::Local<v8::Context> context =
17678         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
17679     v8::Context::Scope context_scope(context);
17680     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
17681   }
17682 }
17683
17684
17685 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
17686   v8::Isolate::Scope isolate_scope(isolate);
17687   v8::HandleScope scope(isolate);
17688   LocalContext context(isolate);
17689   i::ScopedVector<char> code(1024);
17690   i::SNPrintF(code, "function fib(n) {"
17691                     "  if (n <= 2) return 1;"
17692                     "  return fib(n-1) + fib(n-2);"
17693                     "}"
17694                     "fib(%d)", limit);
17695   Local<Value> value = CompileRun(code.start());
17696   CHECK(value->IsNumber());
17697   return static_cast<int>(value->NumberValue());
17698 }
17699
17700 class IsolateThread : public v8::base::Thread {
17701  public:
17702   explicit IsolateThread(int fib_limit)
17703       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
17704
17705   void Run() {
17706     v8::Isolate* isolate = v8::Isolate::New();
17707     result_ = CalcFibonacci(isolate, fib_limit_);
17708     isolate->Dispose();
17709   }
17710
17711   int result() { return result_; }
17712
17713  private:
17714   int fib_limit_;
17715   int result_;
17716 };
17717
17718
17719 TEST(MultipleIsolatesOnIndividualThreads) {
17720   IsolateThread thread1(21);
17721   IsolateThread thread2(12);
17722
17723   // Compute some fibonacci numbers on 3 threads in 3 isolates.
17724   thread1.Start();
17725   thread2.Start();
17726
17727   int result1 = CalcFibonacci(CcTest::isolate(), 21);
17728   int result2 = CalcFibonacci(CcTest::isolate(), 12);
17729
17730   thread1.Join();
17731   thread2.Join();
17732
17733   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
17734   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
17735   CHECK_EQ(result1, 10946);
17736   CHECK_EQ(result2, 144);
17737   CHECK_EQ(result1, thread1.result());
17738   CHECK_EQ(result2, thread2.result());
17739 }
17740
17741
17742 TEST(IsolateDifferentContexts) {
17743   v8::Isolate* isolate = v8::Isolate::New();
17744   Local<v8::Context> context;
17745   {
17746     v8::Isolate::Scope isolate_scope(isolate);
17747     v8::HandleScope handle_scope(isolate);
17748     context = v8::Context::New(isolate);
17749     v8::Context::Scope context_scope(context);
17750     Local<Value> v = CompileRun("2");
17751     CHECK(v->IsNumber());
17752     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
17753   }
17754   {
17755     v8::Isolate::Scope isolate_scope(isolate);
17756     v8::HandleScope handle_scope(isolate);
17757     context = v8::Context::New(isolate);
17758     v8::Context::Scope context_scope(context);
17759     Local<Value> v = CompileRun("22");
17760     CHECK(v->IsNumber());
17761     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
17762   }
17763   isolate->Dispose();
17764 }
17765
17766 class InitDefaultIsolateThread : public v8::base::Thread {
17767  public:
17768   enum TestCase {
17769     SetResourceConstraints,
17770     SetFatalHandler,
17771     SetCounterFunction,
17772     SetCreateHistogramFunction,
17773     SetAddHistogramSampleFunction
17774   };
17775
17776   explicit InitDefaultIsolateThread(TestCase testCase)
17777       : Thread(Options("InitDefaultIsolateThread")),
17778         testCase_(testCase),
17779         result_(false) {}
17780
17781   void Run() {
17782     v8::Isolate::CreateParams create_params;
17783     switch (testCase_) {
17784       case SetResourceConstraints: {
17785         create_params.constraints.set_max_semi_space_size(1);
17786         create_params.constraints.set_max_old_space_size(4);
17787         break;
17788       }
17789       default:
17790         break;
17791     }
17792     v8::Isolate* isolate = v8::Isolate::New(create_params);
17793     isolate->Enter();
17794     switch (testCase_) {
17795       case SetResourceConstraints:
17796         // Already handled in pre-Isolate-creation block.
17797         break;
17798
17799       case SetFatalHandler:
17800         v8::V8::SetFatalErrorHandler(NULL);
17801         break;
17802
17803       case SetCounterFunction:
17804         CcTest::isolate()->SetCounterFunction(NULL);
17805         break;
17806
17807       case SetCreateHistogramFunction:
17808         CcTest::isolate()->SetCreateHistogramFunction(NULL);
17809         break;
17810
17811       case SetAddHistogramSampleFunction:
17812         CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
17813         break;
17814     }
17815     isolate->Exit();
17816     isolate->Dispose();
17817     result_ = true;
17818   }
17819
17820   bool result() { return result_; }
17821
17822  private:
17823   TestCase testCase_;
17824   bool result_;
17825 };
17826
17827
17828 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
17829   InitDefaultIsolateThread thread(testCase);
17830   thread.Start();
17831   thread.Join();
17832   CHECK_EQ(thread.result(), true);
17833 }
17834
17835
17836 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
17837   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
17838 }
17839
17840
17841 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
17842   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
17843 }
17844
17845
17846 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
17847   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
17848 }
17849
17850
17851 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
17852   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
17853 }
17854
17855
17856 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
17857   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
17858 }
17859
17860
17861 TEST(StringCheckMultipleContexts) {
17862   const char* code =
17863       "(function() { return \"a\".charAt(0); })()";
17864
17865   {
17866     // Run the code twice in the first context to initialize the call IC.
17867     LocalContext context1;
17868     v8::HandleScope scope(context1->GetIsolate());
17869     ExpectString(code, "a");
17870     ExpectString(code, "a");
17871   }
17872
17873   {
17874     // Change the String.prototype in the second context and check
17875     // that the right function gets called.
17876     LocalContext context2;
17877     v8::HandleScope scope(context2->GetIsolate());
17878     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
17879     ExpectString(code, "not a");
17880   }
17881 }
17882
17883
17884 TEST(NumberCheckMultipleContexts) {
17885   const char* code =
17886       "(function() { return (42).toString(); })()";
17887
17888   {
17889     // Run the code twice in the first context to initialize the call IC.
17890     LocalContext context1;
17891     v8::HandleScope scope(context1->GetIsolate());
17892     ExpectString(code, "42");
17893     ExpectString(code, "42");
17894   }
17895
17896   {
17897     // Change the Number.prototype in the second context and check
17898     // that the right function gets called.
17899     LocalContext context2;
17900     v8::HandleScope scope(context2->GetIsolate());
17901     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
17902     ExpectString(code, "not 42");
17903   }
17904 }
17905
17906
17907 TEST(BooleanCheckMultipleContexts) {
17908   const char* code =
17909       "(function() { return true.toString(); })()";
17910
17911   {
17912     // Run the code twice in the first context to initialize the call IC.
17913     LocalContext context1;
17914     v8::HandleScope scope(context1->GetIsolate());
17915     ExpectString(code, "true");
17916     ExpectString(code, "true");
17917   }
17918
17919   {
17920     // Change the Boolean.prototype in the second context and check
17921     // that the right function gets called.
17922     LocalContext context2;
17923     v8::HandleScope scope(context2->GetIsolate());
17924     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
17925     ExpectString(code, "");
17926   }
17927 }
17928
17929
17930 TEST(DontDeleteCellLoadIC) {
17931   const char* function_code =
17932       "function readCell() { while (true) { return cell; } }";
17933
17934   {
17935     // Run the code twice in the first context to initialize the load
17936     // IC for a don't delete cell.
17937     LocalContext context1;
17938     v8::HandleScope scope(context1->GetIsolate());
17939     CompileRun("var cell = \"first\";");
17940     ExpectBoolean("delete cell", false);
17941     CompileRun(function_code);
17942     ExpectString("readCell()", "first");
17943     ExpectString("readCell()", "first");
17944   }
17945
17946   {
17947     // Use a deletable cell in the second context.
17948     LocalContext context2;
17949     v8::HandleScope scope(context2->GetIsolate());
17950     CompileRun("cell = \"second\";");
17951     CompileRun(function_code);
17952     ExpectString("readCell()", "second");
17953     ExpectBoolean("delete cell", true);
17954     ExpectString("(function() {"
17955                  "  try {"
17956                  "    return readCell();"
17957                  "  } catch(e) {"
17958                  "    return e.toString();"
17959                  "  }"
17960                  "})()",
17961                  "ReferenceError: cell is not defined");
17962     CompileRun("cell = \"new_second\";");
17963     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17964     ExpectString("readCell()", "new_second");
17965     ExpectString("readCell()", "new_second");
17966   }
17967 }
17968
17969
17970 class Visitor42 : public v8::PersistentHandleVisitor {
17971  public:
17972   explicit Visitor42(v8::Persistent<v8::Object>* object)
17973       : counter_(0), object_(object) { }
17974
17975   virtual void VisitPersistentHandle(Persistent<Value>* value,
17976                                      uint16_t class_id) {
17977     if (class_id != 42) return;
17978     CHECK_EQ(42, value->WrapperClassId());
17979     v8::Isolate* isolate = CcTest::isolate();
17980     v8::HandleScope handle_scope(isolate);
17981     v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
17982     v8::Handle<v8::Value> object =
17983         v8::Local<v8::Object>::New(isolate, *object_);
17984     CHECK(handle->IsObject());
17985     CHECK(Handle<Object>::Cast(handle)->Equals(object));
17986     ++counter_;
17987   }
17988
17989   int counter_;
17990   v8::Persistent<v8::Object>* object_;
17991 };
17992
17993
17994 TEST(PersistentHandleVisitor) {
17995   LocalContext context;
17996   v8::Isolate* isolate = context->GetIsolate();
17997   v8::HandleScope scope(isolate);
17998   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
17999   CHECK_EQ(0, object.WrapperClassId());
18000   object.SetWrapperClassId(42);
18001   CHECK_EQ(42, object.WrapperClassId());
18002
18003   Visitor42 visitor(&object);
18004   v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
18005   CHECK_EQ(1, visitor.counter_);
18006
18007   object.Reset();
18008 }
18009
18010
18011 TEST(WrapperClassId) {
18012   LocalContext context;
18013   v8::Isolate* isolate = context->GetIsolate();
18014   v8::HandleScope scope(isolate);
18015   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
18016   CHECK_EQ(0, object.WrapperClassId());
18017   object.SetWrapperClassId(65535);
18018   CHECK_EQ(65535, object.WrapperClassId());
18019   object.Reset();
18020 }
18021
18022
18023 TEST(PersistentHandleInNewSpaceVisitor) {
18024   LocalContext context;
18025   v8::Isolate* isolate = context->GetIsolate();
18026   v8::HandleScope scope(isolate);
18027   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
18028   CHECK_EQ(0, object1.WrapperClassId());
18029   object1.SetWrapperClassId(42);
18030   CHECK_EQ(42, object1.WrapperClassId());
18031
18032   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18033   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18034
18035   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
18036   CHECK_EQ(0, object2.WrapperClassId());
18037   object2.SetWrapperClassId(42);
18038   CHECK_EQ(42, object2.WrapperClassId());
18039
18040   Visitor42 visitor(&object2);
18041   v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
18042   CHECK_EQ(1, visitor.counter_);
18043
18044   object1.Reset();
18045   object2.Reset();
18046 }
18047
18048
18049 TEST(RegExp) {
18050   LocalContext context;
18051   v8::HandleScope scope(context->GetIsolate());
18052
18053   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
18054   CHECK(re->IsRegExp());
18055   CHECK(re->GetSource()->Equals(v8_str("foo")));
18056   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
18057
18058   re = v8::RegExp::New(v8_str("bar"),
18059                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18060                                                       v8::RegExp::kGlobal));
18061   CHECK(re->IsRegExp());
18062   CHECK(re->GetSource()->Equals(v8_str("bar")));
18063   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
18064            static_cast<int>(re->GetFlags()));
18065
18066   re = v8::RegExp::New(v8_str("baz"),
18067                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18068                                                       v8::RegExp::kMultiline));
18069   CHECK(re->IsRegExp());
18070   CHECK(re->GetSource()->Equals(v8_str("baz")));
18071   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
18072            static_cast<int>(re->GetFlags()));
18073
18074   re = CompileRun("/quux/").As<v8::RegExp>();
18075   CHECK(re->IsRegExp());
18076   CHECK(re->GetSource()->Equals(v8_str("quux")));
18077   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
18078
18079   re = CompileRun("/quux/gm").As<v8::RegExp>();
18080   CHECK(re->IsRegExp());
18081   CHECK(re->GetSource()->Equals(v8_str("quux")));
18082   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
18083            static_cast<int>(re->GetFlags()));
18084
18085   // Override the RegExp constructor and check the API constructor
18086   // still works.
18087   CompileRun("RegExp = function() {}");
18088
18089   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
18090   CHECK(re->IsRegExp());
18091   CHECK(re->GetSource()->Equals(v8_str("foobar")));
18092   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
18093
18094   re = v8::RegExp::New(v8_str("foobarbaz"),
18095                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18096                                                       v8::RegExp::kMultiline));
18097   CHECK(re->IsRegExp());
18098   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
18099   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
18100            static_cast<int>(re->GetFlags()));
18101
18102   context->Global()->Set(v8_str("re"), re);
18103   ExpectTrue("re.test('FoobarbaZ')");
18104
18105   // RegExps are objects on which you can set properties.
18106   re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
18107   v8::Handle<v8::Value> value(CompileRun("re.property"));
18108   CHECK_EQ(32, value->Int32Value());
18109
18110   v8::TryCatch try_catch;
18111   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
18112   CHECK(re.IsEmpty());
18113   CHECK(try_catch.HasCaught());
18114   context->Global()->Set(v8_str("ex"), try_catch.Exception());
18115   ExpectTrue("ex instanceof SyntaxError");
18116 }
18117
18118
18119 THREADED_TEST(Equals) {
18120   LocalContext localContext;
18121   v8::HandleScope handleScope(localContext->GetIsolate());
18122
18123   v8::Handle<v8::Object> globalProxy = localContext->Global();
18124   v8::Handle<Value> global = globalProxy->GetPrototype();
18125
18126   CHECK(global->StrictEquals(global));
18127   CHECK(!global->StrictEquals(globalProxy));
18128   CHECK(!globalProxy->StrictEquals(global));
18129   CHECK(globalProxy->StrictEquals(globalProxy));
18130
18131   CHECK(global->Equals(global));
18132   CHECK(!global->Equals(globalProxy));
18133   CHECK(!globalProxy->Equals(global));
18134   CHECK(globalProxy->Equals(globalProxy));
18135 }
18136
18137
18138 static void Getter(v8::Local<v8::Name> property,
18139                    const v8::PropertyCallbackInfo<v8::Value>& info) {
18140   info.GetReturnValue().Set(v8_str("42!"));
18141 }
18142
18143
18144 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
18145   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
18146   result->Set(0, v8_str("universalAnswer"));
18147   info.GetReturnValue().Set(result);
18148 }
18149
18150
18151 TEST(NamedEnumeratorAndForIn) {
18152   LocalContext context;
18153   v8::Isolate* isolate = context->GetIsolate();
18154   v8::HandleScope handle_scope(isolate);
18155   v8::Context::Scope context_scope(context.local());
18156
18157   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
18158   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
18159                                                          NULL, Enumerator));
18160   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
18161   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
18162         "var result = []; for (var k in o) result.push(k); result"));
18163   CHECK_EQ(1u, result->Length());
18164   CHECK(v8_str("universalAnswer")->Equals(result->Get(0)));
18165 }
18166
18167
18168 TEST(DefinePropertyPostDetach) {
18169   LocalContext context;
18170   v8::HandleScope scope(context->GetIsolate());
18171   v8::Handle<v8::Object> proxy = context->Global();
18172   v8::Handle<v8::Function> define_property =
18173       CompileRun("(function() {"
18174                  "  Object.defineProperty("
18175                  "    this,"
18176                  "    1,"
18177                  "    { configurable: true, enumerable: true, value: 3 });"
18178                  "})").As<Function>();
18179   context->DetachGlobal();
18180   define_property->Call(proxy, 0, NULL);
18181 }
18182
18183
18184 static void InstallContextId(v8::Handle<Context> context, int id) {
18185   Context::Scope scope(context);
18186   CompileRun("Object.prototype").As<Object>()->
18187       Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
18188 }
18189
18190
18191 static void CheckContextId(v8::Handle<Object> object, int expected) {
18192   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
18193 }
18194
18195
18196 THREADED_TEST(CreationContext) {
18197   v8::Isolate* isolate = CcTest::isolate();
18198   HandleScope handle_scope(isolate);
18199   Handle<Context> context1 = Context::New(isolate);
18200   InstallContextId(context1, 1);
18201   Handle<Context> context2 = Context::New(isolate);
18202   InstallContextId(context2, 2);
18203   Handle<Context> context3 = Context::New(isolate);
18204   InstallContextId(context3, 3);
18205
18206   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
18207
18208   Local<Object> object1;
18209   Local<Function> func1;
18210   {
18211     Context::Scope scope(context1);
18212     object1 = Object::New(isolate);
18213     func1 = tmpl->GetFunction();
18214   }
18215
18216   Local<Object> object2;
18217   Local<Function> func2;
18218   {
18219     Context::Scope scope(context2);
18220     object2 = Object::New(isolate);
18221     func2 = tmpl->GetFunction();
18222   }
18223
18224   Local<Object> instance1;
18225   Local<Object> instance2;
18226
18227   {
18228     Context::Scope scope(context3);
18229     instance1 = func1->NewInstance();
18230     instance2 = func2->NewInstance();
18231   }
18232
18233   CHECK(object1->CreationContext() == context1);
18234   CheckContextId(object1, 1);
18235   CHECK(func1->CreationContext() == context1);
18236   CheckContextId(func1, 1);
18237   CHECK(instance1->CreationContext() == context1);
18238   CheckContextId(instance1, 1);
18239   CHECK(object2->CreationContext() == context2);
18240   CheckContextId(object2, 2);
18241   CHECK(func2->CreationContext() == context2);
18242   CheckContextId(func2, 2);
18243   CHECK(instance2->CreationContext() == context2);
18244   CheckContextId(instance2, 2);
18245
18246   {
18247     Context::Scope scope(context1);
18248     CHECK(object1->CreationContext() == context1);
18249     CheckContextId(object1, 1);
18250     CHECK(func1->CreationContext() == context1);
18251     CheckContextId(func1, 1);
18252     CHECK(instance1->CreationContext() == context1);
18253     CheckContextId(instance1, 1);
18254     CHECK(object2->CreationContext() == context2);
18255     CheckContextId(object2, 2);
18256     CHECK(func2->CreationContext() == context2);
18257     CheckContextId(func2, 2);
18258     CHECK(instance2->CreationContext() == context2);
18259     CheckContextId(instance2, 2);
18260   }
18261
18262   {
18263     Context::Scope scope(context2);
18264     CHECK(object1->CreationContext() == context1);
18265     CheckContextId(object1, 1);
18266     CHECK(func1->CreationContext() == context1);
18267     CheckContextId(func1, 1);
18268     CHECK(instance1->CreationContext() == context1);
18269     CheckContextId(instance1, 1);
18270     CHECK(object2->CreationContext() == context2);
18271     CheckContextId(object2, 2);
18272     CHECK(func2->CreationContext() == context2);
18273     CheckContextId(func2, 2);
18274     CHECK(instance2->CreationContext() == context2);
18275     CheckContextId(instance2, 2);
18276   }
18277 }
18278
18279
18280 THREADED_TEST(CreationContextOfJsFunction) {
18281   HandleScope handle_scope(CcTest::isolate());
18282   Handle<Context> context = Context::New(CcTest::isolate());
18283   InstallContextId(context, 1);
18284
18285   Local<Object> function;
18286   {
18287     Context::Scope scope(context);
18288     function = CompileRun("function foo() {}; foo").As<Object>();
18289   }
18290
18291   CHECK(function->CreationContext() == context);
18292   CheckContextId(function, 1);
18293 }
18294
18295
18296 void HasOwnPropertyIndexedPropertyGetter(
18297     uint32_t index,
18298     const v8::PropertyCallbackInfo<v8::Value>& info) {
18299   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
18300 }
18301
18302
18303 void HasOwnPropertyNamedPropertyGetter(
18304     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
18305   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
18306 }
18307
18308
18309 void HasOwnPropertyIndexedPropertyQuery(
18310     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
18311   if (index == 42) info.GetReturnValue().Set(1);
18312 }
18313
18314
18315 void HasOwnPropertyNamedPropertyQuery(
18316     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
18317   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
18318 }
18319
18320
18321 void HasOwnPropertyNamedPropertyQuery2(
18322     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
18323   if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
18324 }
18325
18326
18327 void HasOwnPropertyAccessorGetter(
18328     Local<String> property,
18329     const v8::PropertyCallbackInfo<v8::Value>& info) {
18330   info.GetReturnValue().Set(v8_str("yes"));
18331 }
18332
18333
18334 TEST(HasOwnProperty) {
18335   LocalContext env;
18336   v8::Isolate* isolate = env->GetIsolate();
18337   v8::HandleScope scope(isolate);
18338   { // Check normal properties and defined getters.
18339     Handle<Value> value = CompileRun(
18340         "function Foo() {"
18341         "    this.foo = 11;"
18342         "    this.__defineGetter__('baz', function() { return 1; });"
18343         "};"
18344         "function Bar() { "
18345         "    this.bar = 13;"
18346         "    this.__defineGetter__('bla', function() { return 2; });"
18347         "};"
18348         "Bar.prototype = new Foo();"
18349         "new Bar();");
18350     CHECK(value->IsObject());
18351     Handle<Object> object = value->ToObject(isolate);
18352     CHECK(object->Has(v8_str("foo")));
18353     CHECK(!object->HasOwnProperty(v8_str("foo")));
18354     CHECK(object->HasOwnProperty(v8_str("bar")));
18355     CHECK(object->Has(v8_str("baz")));
18356     CHECK(!object->HasOwnProperty(v8_str("baz")));
18357     CHECK(object->HasOwnProperty(v8_str("bla")));
18358   }
18359   { // Check named getter interceptors.
18360     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18361     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
18362         HasOwnPropertyNamedPropertyGetter));
18363     Handle<Object> instance = templ->NewInstance();
18364     CHECK(!instance->HasOwnProperty(v8_str("42")));
18365     CHECK(instance->HasOwnProperty(v8_str("foo")));
18366     CHECK(!instance->HasOwnProperty(v8_str("bar")));
18367   }
18368   { // Check indexed getter interceptors.
18369     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18370     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
18371         HasOwnPropertyIndexedPropertyGetter));
18372     Handle<Object> instance = templ->NewInstance();
18373     CHECK(instance->HasOwnProperty(v8_str("42")));
18374     CHECK(!instance->HasOwnProperty(v8_str("43")));
18375     CHECK(!instance->HasOwnProperty(v8_str("foo")));
18376   }
18377   { // Check named query interceptors.
18378     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18379     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
18380         0, 0, HasOwnPropertyNamedPropertyQuery));
18381     Handle<Object> instance = templ->NewInstance();
18382     CHECK(instance->HasOwnProperty(v8_str("foo")));
18383     CHECK(!instance->HasOwnProperty(v8_str("bar")));
18384   }
18385   { // Check indexed query interceptors.
18386     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18387     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
18388         0, 0, HasOwnPropertyIndexedPropertyQuery));
18389     Handle<Object> instance = templ->NewInstance();
18390     CHECK(instance->HasOwnProperty(v8_str("42")));
18391     CHECK(!instance->HasOwnProperty(v8_str("41")));
18392   }
18393   { // Check callbacks.
18394     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18395     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
18396     Handle<Object> instance = templ->NewInstance();
18397     CHECK(instance->HasOwnProperty(v8_str("foo")));
18398     CHECK(!instance->HasOwnProperty(v8_str("bar")));
18399   }
18400   { // Check that query wins on disagreement.
18401     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18402     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
18403         HasOwnPropertyNamedPropertyGetter, 0,
18404         HasOwnPropertyNamedPropertyQuery2));
18405     Handle<Object> instance = templ->NewInstance();
18406     CHECK(!instance->HasOwnProperty(v8_str("foo")));
18407     CHECK(instance->HasOwnProperty(v8_str("bar")));
18408   }
18409 }
18410
18411
18412 TEST(IndexedInterceptorWithStringProto) {
18413   v8::Isolate* isolate = CcTest::isolate();
18414   v8::HandleScope scope(isolate);
18415   Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18416   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
18417       NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
18418   LocalContext context;
18419   context->Global()->Set(v8_str("obj"), templ->NewInstance());
18420   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
18421   // These should be intercepted.
18422   CHECK(CompileRun("42 in obj")->BooleanValue());
18423   CHECK(CompileRun("'42' in obj")->BooleanValue());
18424   // These should fall through to the String prototype.
18425   CHECK(CompileRun("0 in obj")->BooleanValue());
18426   CHECK(CompileRun("'0' in obj")->BooleanValue());
18427   // And these should both fail.
18428   CHECK(!CompileRun("32 in obj")->BooleanValue());
18429   CHECK(!CompileRun("'32' in obj")->BooleanValue());
18430 }
18431
18432
18433 void CheckCodeGenerationAllowed() {
18434   Handle<Value> result = CompileRun("eval('42')");
18435   CHECK_EQ(42, result->Int32Value());
18436   result = CompileRun("(function(e) { return e('42'); })(eval)");
18437   CHECK_EQ(42, result->Int32Value());
18438   result = CompileRun("var f = new Function('return 42'); f()");
18439   CHECK_EQ(42, result->Int32Value());
18440 }
18441
18442
18443 void CheckCodeGenerationDisallowed() {
18444   TryCatch try_catch;
18445
18446   Handle<Value> result = CompileRun("eval('42')");
18447   CHECK(result.IsEmpty());
18448   CHECK(try_catch.HasCaught());
18449   try_catch.Reset();
18450
18451   result = CompileRun("(function(e) { return e('42'); })(eval)");
18452   CHECK(result.IsEmpty());
18453   CHECK(try_catch.HasCaught());
18454   try_catch.Reset();
18455
18456   result = CompileRun("var f = new Function('return 42'); f()");
18457   CHECK(result.IsEmpty());
18458   CHECK(try_catch.HasCaught());
18459 }
18460
18461
18462 bool CodeGenerationAllowed(Local<Context> context) {
18463   ApiTestFuzzer::Fuzz();
18464   return true;
18465 }
18466
18467
18468 bool CodeGenerationDisallowed(Local<Context> context) {
18469   ApiTestFuzzer::Fuzz();
18470   return false;
18471 }
18472
18473
18474 THREADED_TEST(AllowCodeGenFromStrings) {
18475   LocalContext context;
18476   v8::HandleScope scope(context->GetIsolate());
18477
18478   // eval and the Function constructor allowed by default.
18479   CHECK(context->IsCodeGenerationFromStringsAllowed());
18480   CheckCodeGenerationAllowed();
18481
18482   // Disallow eval and the Function constructor.
18483   context->AllowCodeGenerationFromStrings(false);
18484   CHECK(!context->IsCodeGenerationFromStringsAllowed());
18485   CheckCodeGenerationDisallowed();
18486
18487   // Allow again.
18488   context->AllowCodeGenerationFromStrings(true);
18489   CheckCodeGenerationAllowed();
18490
18491   // Disallow but setting a global callback that will allow the calls.
18492   context->AllowCodeGenerationFromStrings(false);
18493   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
18494   CHECK(!context->IsCodeGenerationFromStringsAllowed());
18495   CheckCodeGenerationAllowed();
18496
18497   // Set a callback that disallows the code generation.
18498   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
18499   CHECK(!context->IsCodeGenerationFromStringsAllowed());
18500   CheckCodeGenerationDisallowed();
18501 }
18502
18503
18504 TEST(SetErrorMessageForCodeGenFromStrings) {
18505   LocalContext context;
18506   v8::HandleScope scope(context->GetIsolate());
18507   TryCatch try_catch;
18508
18509   Handle<String> message = v8_str("Message") ;
18510   Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
18511   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
18512   context->AllowCodeGenerationFromStrings(false);
18513   context->SetErrorMessageForCodeGenerationFromStrings(message);
18514   Handle<Value> result = CompileRun("eval('42')");
18515   CHECK(result.IsEmpty());
18516   CHECK(try_catch.HasCaught());
18517   Handle<String> actual_message = try_catch.Message()->Get();
18518   CHECK(expected_message->Equals(actual_message));
18519 }
18520
18521
18522 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
18523 }
18524
18525
18526 THREADED_TEST(CallAPIFunctionOnNonObject) {
18527   LocalContext context;
18528   v8::Isolate* isolate = context->GetIsolate();
18529   v8::HandleScope scope(isolate);
18530   Handle<FunctionTemplate> templ =
18531       v8::FunctionTemplate::New(isolate, NonObjectThis);
18532   Handle<Function> function = templ->GetFunction();
18533   context->Global()->Set(v8_str("f"), function);
18534   TryCatch try_catch;
18535   CompileRun("f.call(2)");
18536 }
18537
18538
18539 // Regression test for issue 1470.
18540 THREADED_TEST(ReadOnlyIndexedProperties) {
18541   v8::Isolate* isolate = CcTest::isolate();
18542   v8::HandleScope scope(isolate);
18543   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18544
18545   LocalContext context;
18546   Local<v8::Object> obj = templ->NewInstance();
18547   context->Global()->Set(v8_str("obj"), obj);
18548   obj->ForceSet(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
18549   obj->Set(v8_str("1"), v8_str("foobar"));
18550   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("1"))));
18551   obj->ForceSet(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
18552   obj->Set(v8_num(2), v8_str("foobar"));
18553   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_num(2))));
18554
18555   // Test non-smi case.
18556   obj->ForceSet(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
18557   obj->Set(v8_str("2000000000"), v8_str("foobar"));
18558   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("2000000000"))));
18559 }
18560
18561
18562 static int CountLiveMapsInMapCache(i::Context* context) {
18563   i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
18564   int length = map_cache->length();
18565   int count = 0;
18566   for (int i = 0; i < length; i++) {
18567     i::Object* value = map_cache->get(i);
18568     if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
18569   }
18570   return count;
18571 }
18572
18573
18574 THREADED_TEST(Regress1516) {
18575   LocalContext context;
18576   v8::HandleScope scope(context->GetIsolate());
18577
18578   // Object with 20 properties is not a common case, so it should be removed
18579   // from the cache after GC.
18580   { v8::HandleScope temp_scope(context->GetIsolate());
18581     CompileRun(
18582         "({"
18583         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
18584         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
18585         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
18586         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
18587         "})");
18588   }
18589
18590   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
18591   CHECK_LE(1, elements);
18592
18593   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
18594
18595   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
18596 }
18597
18598
18599 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
18600                                                 Local<Value> name,
18601                                                 v8::AccessType type,
18602                                                 Local<Value> data) {
18603   // Only block read access to __proto__.
18604   if (type == v8::ACCESS_GET && name->IsString() &&
18605       name.As<v8::String>()->Length() == 9 &&
18606       name.As<v8::String>()->Utf8Length() == 9) {
18607     char buffer[10];
18608     CHECK_EQ(10, name.As<v8::String>()->WriteUtf8(buffer));
18609     return strncmp(buffer, "__proto__", 9) != 0;
18610   }
18611
18612   return true;
18613 }
18614
18615
18616 THREADED_TEST(Regress93759) {
18617   v8::Isolate* isolate = CcTest::isolate();
18618   HandleScope scope(isolate);
18619
18620   // Template for object with security check.
18621   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
18622   // We don't do indexing, so any callback can be used for that.
18623   no_proto_template->SetAccessCheckCallbacks(
18624       BlockProtoNamedSecurityTestCallback,
18625       IndexedSecurityTestCallback);
18626
18627   // Templates for objects with hidden prototypes and possibly security check.
18628   Local<FunctionTemplate> hidden_proto_template =
18629       v8::FunctionTemplate::New(isolate);
18630   hidden_proto_template->SetHiddenPrototype(true);
18631
18632   Local<FunctionTemplate> protected_hidden_proto_template =
18633       v8::FunctionTemplate::New(isolate);
18634   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
18635       BlockProtoNamedSecurityTestCallback,
18636       IndexedSecurityTestCallback);
18637   protected_hidden_proto_template->SetHiddenPrototype(true);
18638
18639   // Context for "foreign" objects used in test.
18640   Local<Context> context = v8::Context::New(isolate);
18641   context->Enter();
18642
18643   // Plain object, no security check.
18644   Local<Object> simple_object = Object::New(isolate);
18645
18646   // Object with explicit security check.
18647   Local<Object> protected_object =
18648       no_proto_template->NewInstance();
18649
18650   // JSGlobalProxy object, always have security check.
18651   Local<Object> proxy_object =
18652       context->Global();
18653
18654   // Global object, the  prototype of proxy_object. No security checks.
18655   Local<Object> global_object = proxy_object->GetPrototype()->ToObject(isolate);
18656
18657   // Hidden prototype without security check.
18658   Local<Object> hidden_prototype =
18659       hidden_proto_template->GetFunction()->NewInstance();
18660   Local<Object> object_with_hidden =
18661     Object::New(isolate);
18662   object_with_hidden->SetPrototype(hidden_prototype);
18663
18664   // Hidden prototype with security check on the hidden prototype.
18665   Local<Object> protected_hidden_prototype =
18666       protected_hidden_proto_template->GetFunction()->NewInstance();
18667   Local<Object> object_with_protected_hidden =
18668     Object::New(isolate);
18669   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
18670
18671   context->Exit();
18672
18673   // Template for object for second context. Values to test are put on it as
18674   // properties.
18675   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
18676   global_template->Set(v8_str("simple"), simple_object);
18677   global_template->Set(v8_str("protected"), protected_object);
18678   global_template->Set(v8_str("global"), global_object);
18679   global_template->Set(v8_str("proxy"), proxy_object);
18680   global_template->Set(v8_str("hidden"), object_with_hidden);
18681   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
18682
18683   LocalContext context2(NULL, global_template);
18684
18685   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
18686   CHECK(result1->Equals(simple_object->GetPrototype()));
18687
18688   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
18689   CHECK(result2.IsEmpty());
18690
18691   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
18692   CHECK(result3->Equals(global_object->GetPrototype()));
18693
18694   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
18695   CHECK(result4.IsEmpty());
18696
18697   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
18698   CHECK(result5->Equals(
18699       object_with_hidden->GetPrototype()->ToObject(isolate)->GetPrototype()));
18700
18701   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
18702   CHECK(result6.IsEmpty());
18703 }
18704
18705
18706 static void TestReceiver(Local<Value> expected_result,
18707                          Local<Value> expected_receiver,
18708                          const char* code) {
18709   Local<Value> result = CompileRun(code);
18710   CHECK(result->IsObject());
18711   CHECK(expected_receiver->Equals(result.As<v8::Object>()->Get(1)));
18712   CHECK(expected_result->Equals(result.As<v8::Object>()->Get(0)));
18713 }
18714
18715
18716 THREADED_TEST(ForeignFunctionReceiver) {
18717   v8::Isolate* isolate = CcTest::isolate();
18718   HandleScope scope(isolate);
18719
18720   // Create two contexts with different "id" properties ('i' and 'o').
18721   // Call a function both from its own context and from a the foreign
18722   // context, and see what "this" is bound to (returning both "this"
18723   // and "this.id" for comparison).
18724
18725   Local<Context> foreign_context = v8::Context::New(isolate);
18726   foreign_context->Enter();
18727   Local<Value> foreign_function =
18728     CompileRun("function func() { return { 0: this.id, "
18729                "                           1: this, "
18730                "                           toString: function() { "
18731                "                               return this[0];"
18732                "                           }"
18733                "                         };"
18734                "}"
18735                "var id = 'i';"
18736                "func;");
18737   CHECK(foreign_function->IsFunction());
18738   foreign_context->Exit();
18739
18740   LocalContext context;
18741
18742   Local<String> password = v8_str("Password");
18743   // Don't get hit by security checks when accessing foreign_context's
18744   // global receiver (aka. global proxy).
18745   context->SetSecurityToken(password);
18746   foreign_context->SetSecurityToken(password);
18747
18748   Local<String> i = v8_str("i");
18749   Local<String> o = v8_str("o");
18750   Local<String> id = v8_str("id");
18751
18752   CompileRun("function ownfunc() { return { 0: this.id, "
18753              "                              1: this, "
18754              "                              toString: function() { "
18755              "                                  return this[0];"
18756              "                              }"
18757              "                             };"
18758              "}"
18759              "var id = 'o';"
18760              "ownfunc");
18761   context->Global()->Set(v8_str("func"), foreign_function);
18762
18763   // Sanity check the contexts.
18764   CHECK(i->Equals(foreign_context->Global()->Get(id)));
18765   CHECK(o->Equals(context->Global()->Get(id)));
18766
18767   // Checking local function's receiver.
18768   // Calling function using its call/apply methods.
18769   TestReceiver(o, context->Global(), "ownfunc.call()");
18770   TestReceiver(o, context->Global(), "ownfunc.apply()");
18771   // Making calls through built-in functions.
18772   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
18773   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
18774   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
18775   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
18776   // Calling with environment record as base.
18777   TestReceiver(o, context->Global(), "ownfunc()");
18778   // Calling with no base.
18779   TestReceiver(o, context->Global(), "(1,ownfunc)()");
18780
18781   // Checking foreign function return value.
18782   // Calling function using its call/apply methods.
18783   TestReceiver(i, foreign_context->Global(), "func.call()");
18784   TestReceiver(i, foreign_context->Global(), "func.apply()");
18785   // Calling function using another context's call/apply methods.
18786   TestReceiver(i, foreign_context->Global(),
18787                "Function.prototype.call.call(func)");
18788   TestReceiver(i, foreign_context->Global(),
18789                "Function.prototype.call.apply(func)");
18790   TestReceiver(i, foreign_context->Global(),
18791                "Function.prototype.apply.call(func)");
18792   TestReceiver(i, foreign_context->Global(),
18793                "Function.prototype.apply.apply(func)");
18794   // Making calls through built-in functions.
18795   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
18796   // ToString(func()) is func()[0], i.e., the returned this.id.
18797   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
18798   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
18799   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
18800
18801   // Calling with environment record as base.
18802   TestReceiver(i, foreign_context->Global(), "func()");
18803   // Calling with no base.
18804   TestReceiver(i, foreign_context->Global(), "(1,func)()");
18805 }
18806
18807
18808 uint8_t callback_fired = 0;
18809
18810
18811 void CallCompletedCallback1() {
18812   v8::base::OS::Print("Firing callback 1.\n");
18813   callback_fired ^= 1;  // Toggle first bit.
18814 }
18815
18816
18817 void CallCompletedCallback2() {
18818   v8::base::OS::Print("Firing callback 2.\n");
18819   callback_fired ^= 2;  // Toggle second bit.
18820 }
18821
18822
18823 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
18824   int32_t level = args[0]->Int32Value();
18825   if (level < 3) {
18826     level++;
18827     v8::base::OS::Print("Entering recursion level %d.\n", level);
18828     char script[64];
18829     i::Vector<char> script_vector(script, sizeof(script));
18830     i::SNPrintF(script_vector, "recursion(%d)", level);
18831     CompileRun(script_vector.start());
18832     v8::base::OS::Print("Leaving recursion level %d.\n", level);
18833     CHECK_EQ(0, callback_fired);
18834   } else {
18835     v8::base::OS::Print("Recursion ends.\n");
18836     CHECK_EQ(0, callback_fired);
18837   }
18838 }
18839
18840
18841 TEST(CallCompletedCallback) {
18842   LocalContext env;
18843   v8::HandleScope scope(env->GetIsolate());
18844   v8::Handle<v8::FunctionTemplate> recursive_runtime =
18845       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
18846   env->Global()->Set(v8_str("recursion"),
18847                      recursive_runtime->GetFunction());
18848   // Adding the same callback a second time has no effect.
18849   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
18850   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
18851   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
18852   v8::base::OS::Print("--- Script (1) ---\n");
18853   Local<Script> script = v8::Script::Compile(
18854       v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
18855   script->Run();
18856   CHECK_EQ(3, callback_fired);
18857
18858   v8::base::OS::Print("\n--- Script (2) ---\n");
18859   callback_fired = 0;
18860   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
18861   script->Run();
18862   CHECK_EQ(2, callback_fired);
18863
18864   v8::base::OS::Print("\n--- Function ---\n");
18865   callback_fired = 0;
18866   Local<Function> recursive_function =
18867       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
18868   v8::Handle<Value> args[] = { v8_num(0) };
18869   recursive_function->Call(env->Global(), 1, args);
18870   CHECK_EQ(2, callback_fired);
18871 }
18872
18873
18874 void CallCompletedCallbackNoException() {
18875   v8::HandleScope scope(CcTest::isolate());
18876   CompileRun("1+1;");
18877 }
18878
18879
18880 void CallCompletedCallbackException() {
18881   v8::HandleScope scope(CcTest::isolate());
18882   CompileRun("throw 'second exception';");
18883 }
18884
18885
18886 TEST(CallCompletedCallbackOneException) {
18887   LocalContext env;
18888   v8::HandleScope scope(env->GetIsolate());
18889   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
18890   CompileRun("throw 'exception';");
18891 }
18892
18893
18894 TEST(CallCompletedCallbackTwoExceptions) {
18895   LocalContext env;
18896   v8::HandleScope scope(env->GetIsolate());
18897   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
18898   CompileRun("throw 'first exception';");
18899 }
18900
18901
18902 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
18903   v8::HandleScope scope(info.GetIsolate());
18904   CompileRun("ext1Calls++;");
18905 }
18906
18907
18908 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
18909   v8::HandleScope scope(info.GetIsolate());
18910   CompileRun("ext2Calls++;");
18911 }
18912
18913
18914 void* g_passed_to_three = NULL;
18915
18916
18917 static void MicrotaskThree(void* data) {
18918   g_passed_to_three = data;
18919 }
18920
18921
18922 TEST(EnqueueMicrotask) {
18923   LocalContext env;
18924   v8::HandleScope scope(env->GetIsolate());
18925   CompileRun(
18926       "var ext1Calls = 0;"
18927       "var ext2Calls = 0;");
18928   CompileRun("1+1;");
18929   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
18930   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18931
18932   env->GetIsolate()->EnqueueMicrotask(
18933       Function::New(env->GetIsolate(), MicrotaskOne));
18934   CompileRun("1+1;");
18935   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18936   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18937
18938   env->GetIsolate()->EnqueueMicrotask(
18939       Function::New(env->GetIsolate(), MicrotaskOne));
18940   env->GetIsolate()->EnqueueMicrotask(
18941       Function::New(env->GetIsolate(), MicrotaskTwo));
18942   CompileRun("1+1;");
18943   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18944   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18945
18946   env->GetIsolate()->EnqueueMicrotask(
18947       Function::New(env->GetIsolate(), MicrotaskTwo));
18948   CompileRun("1+1;");
18949   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18950   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18951
18952   CompileRun("1+1;");
18953   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18954   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18955
18956   g_passed_to_three = NULL;
18957   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
18958   CompileRun("1+1;");
18959   CHECK(!g_passed_to_three);
18960   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18961   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18962
18963   int dummy;
18964   env->GetIsolate()->EnqueueMicrotask(
18965       Function::New(env->GetIsolate(), MicrotaskOne));
18966   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
18967   env->GetIsolate()->EnqueueMicrotask(
18968       Function::New(env->GetIsolate(), MicrotaskTwo));
18969   CompileRun("1+1;");
18970   CHECK_EQ(&dummy, g_passed_to_three);
18971   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
18972   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18973   g_passed_to_three = NULL;
18974 }
18975
18976
18977 static void MicrotaskExceptionOne(
18978     const v8::FunctionCallbackInfo<Value>& info) {
18979   v8::HandleScope scope(info.GetIsolate());
18980   CompileRun("exception1Calls++;");
18981   info.GetIsolate()->ThrowException(
18982       v8::Exception::Error(v8_str("first")));
18983 }
18984
18985
18986 static void MicrotaskExceptionTwo(
18987     const v8::FunctionCallbackInfo<Value>& info) {
18988   v8::HandleScope scope(info.GetIsolate());
18989   CompileRun("exception2Calls++;");
18990   info.GetIsolate()->ThrowException(
18991       v8::Exception::Error(v8_str("second")));
18992 }
18993
18994
18995 TEST(RunMicrotasksIgnoresThrownExceptions) {
18996   LocalContext env;
18997   v8::Isolate* isolate = env->GetIsolate();
18998   v8::HandleScope scope(isolate);
18999   CompileRun(
19000       "var exception1Calls = 0;"
19001       "var exception2Calls = 0;");
19002   isolate->EnqueueMicrotask(
19003       Function::New(isolate, MicrotaskExceptionOne));
19004   isolate->EnqueueMicrotask(
19005       Function::New(isolate, MicrotaskExceptionTwo));
19006   TryCatch try_catch;
19007   CompileRun("1+1;");
19008   CHECK(!try_catch.HasCaught());
19009   CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
19010   CHECK_EQ(1, CompileRun("exception2Calls")->Int32Value());
19011 }
19012
19013
19014 TEST(SetAutorunMicrotasks) {
19015   LocalContext env;
19016   v8::HandleScope scope(env->GetIsolate());
19017   CompileRun(
19018       "var ext1Calls = 0;"
19019       "var ext2Calls = 0;");
19020   CompileRun("1+1;");
19021   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
19022   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
19023
19024   env->GetIsolate()->EnqueueMicrotask(
19025       Function::New(env->GetIsolate(), MicrotaskOne));
19026   CompileRun("1+1;");
19027   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
19028   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
19029
19030   env->GetIsolate()->SetAutorunMicrotasks(false);
19031   env->GetIsolate()->EnqueueMicrotask(
19032       Function::New(env->GetIsolate(), MicrotaskOne));
19033   env->GetIsolate()->EnqueueMicrotask(
19034       Function::New(env->GetIsolate(), MicrotaskTwo));
19035   CompileRun("1+1;");
19036   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
19037   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
19038
19039   env->GetIsolate()->RunMicrotasks();
19040   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
19041   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
19042
19043   env->GetIsolate()->EnqueueMicrotask(
19044       Function::New(env->GetIsolate(), MicrotaskTwo));
19045   CompileRun("1+1;");
19046   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
19047   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
19048
19049   env->GetIsolate()->RunMicrotasks();
19050   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
19051   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
19052
19053   env->GetIsolate()->SetAutorunMicrotasks(true);
19054   env->GetIsolate()->EnqueueMicrotask(
19055       Function::New(env->GetIsolate(), MicrotaskTwo));
19056   CompileRun("1+1;");
19057   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
19058   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
19059
19060   env->GetIsolate()->EnqueueMicrotask(
19061       Function::New(env->GetIsolate(), MicrotaskTwo));
19062   {
19063     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
19064     CompileRun("1+1;");
19065     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
19066     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
19067   }
19068
19069   CompileRun("1+1;");
19070   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
19071   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value());
19072 }
19073
19074
19075 TEST(RunMicrotasksWithoutEnteringContext) {
19076   v8::Isolate* isolate = CcTest::isolate();
19077   HandleScope handle_scope(isolate);
19078   isolate->SetAutorunMicrotasks(false);
19079   Handle<Context> context = Context::New(isolate);
19080   {
19081     Context::Scope context_scope(context);
19082     CompileRun("var ext1Calls = 0;");
19083     isolate->EnqueueMicrotask(Function::New(isolate, MicrotaskOne));
19084   }
19085   isolate->RunMicrotasks();
19086   {
19087     Context::Scope context_scope(context);
19088     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
19089   }
19090   isolate->SetAutorunMicrotasks(true);
19091 }
19092
19093
19094 static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
19095   v8::DebugEvent event = event_details.GetEvent();
19096   if (event != v8::Break) return;
19097   Handle<Object> exec_state = event_details.GetExecutionState();
19098   Handle<Value> break_id = exec_state->Get(v8_str("break_id"));
19099   CompileRun("function f(id) { new FrameDetails(id, 0); }");
19100   Handle<Function> fun =
19101       Handle<Function>::Cast(CcTest::global()->Get(v8_str("f")));
19102   fun->Call(CcTest::global(), 1, &break_id);
19103 }
19104
19105
19106 TEST(Regress385349) {
19107   i::FLAG_allow_natives_syntax = true;
19108   v8::Isolate* isolate = CcTest::isolate();
19109   HandleScope handle_scope(isolate);
19110   isolate->SetAutorunMicrotasks(false);
19111   Handle<Context> context = Context::New(isolate);
19112   v8::Debug::SetDebugEventListener(DebugEventInObserver);
19113   {
19114     Context::Scope context_scope(context);
19115     CompileRun("var obj = {};"
19116                "Object.observe(obj, function(changes) { debugger; });"
19117                "obj.a = 0;");
19118   }
19119   isolate->RunMicrotasks();
19120   isolate->SetAutorunMicrotasks(true);
19121   v8::Debug::SetDebugEventListener(NULL);
19122 }
19123
19124
19125 #ifdef ENABLE_DISASSEMBLER
19126 static int probes_counter = 0;
19127 static int misses_counter = 0;
19128 static int updates_counter = 0;
19129
19130
19131 static int* LookupCounter(const char* name) {
19132   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
19133     return &probes_counter;
19134   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
19135     return &misses_counter;
19136   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
19137     return &updates_counter;
19138   }
19139   return NULL;
19140 }
19141
19142
19143 static const char* kMegamorphicTestProgram =
19144     "function ClassA() { };"
19145     "function ClassB() { };"
19146     "ClassA.prototype.foo = function() { };"
19147     "ClassB.prototype.foo = function() { };"
19148     "function fooify(obj) { obj.foo(); };"
19149     "var a = new ClassA();"
19150     "var b = new ClassB();"
19151     "for (var i = 0; i < 10000; i++) {"
19152     "  fooify(a);"
19153     "  fooify(b);"
19154     "}";
19155 #endif
19156
19157
19158 static void StubCacheHelper(bool primary) {
19159 #ifdef ENABLE_DISASSEMBLER
19160   i::FLAG_native_code_counters = true;
19161   if (primary) {
19162     i::FLAG_test_primary_stub_cache = true;
19163   } else {
19164     i::FLAG_test_secondary_stub_cache = true;
19165   }
19166   i::FLAG_crankshaft = false;
19167   LocalContext env;
19168   env->GetIsolate()->SetCounterFunction(LookupCounter);
19169   v8::HandleScope scope(env->GetIsolate());
19170   int initial_probes = probes_counter;
19171   int initial_misses = misses_counter;
19172   int initial_updates = updates_counter;
19173   CompileRun(kMegamorphicTestProgram);
19174   int probes = probes_counter - initial_probes;
19175   int misses = misses_counter - initial_misses;
19176   int updates = updates_counter - initial_updates;
19177   CHECK_LT(updates, 10);
19178   CHECK_LT(misses, 10);
19179   // TODO(verwaest): Update this test to overflow the degree of polymorphism
19180   // before megamorphism. The number of probes will only work once we teach the
19181   // serializer to embed references to counters in the stubs, given that the
19182   // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
19183   CHECK_GE(probes, 0);
19184 #endif
19185 }
19186
19187
19188 TEST(SecondaryStubCache) {
19189   StubCacheHelper(true);
19190 }
19191
19192
19193 TEST(PrimaryStubCache) {
19194   StubCacheHelper(false);
19195 }
19196
19197
19198 #ifdef DEBUG
19199 static int cow_arrays_created_runtime = 0;
19200
19201
19202 static int* LookupCounterCOWArrays(const char* name) {
19203   if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
19204     return &cow_arrays_created_runtime;
19205   }
19206   return NULL;
19207 }
19208 #endif
19209
19210
19211 TEST(CheckCOWArraysCreatedRuntimeCounter) {
19212 #ifdef DEBUG
19213   i::FLAG_native_code_counters = true;
19214   LocalContext env;
19215   env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
19216   v8::HandleScope scope(env->GetIsolate());
19217   int initial_cow_arrays = cow_arrays_created_runtime;
19218   CompileRun("var o = [1, 2, 3];");
19219   CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
19220   CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
19221   CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
19222   CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
19223   CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
19224 #endif
19225 }
19226
19227
19228 TEST(StaticGetters) {
19229   LocalContext context;
19230   i::Factory* factory = CcTest::i_isolate()->factory();
19231   v8::Isolate* isolate = CcTest::isolate();
19232   v8::HandleScope scope(isolate);
19233   i::Handle<i::Object> undefined_value = factory->undefined_value();
19234   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
19235   i::Handle<i::Object> null_value = factory->null_value();
19236   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
19237   i::Handle<i::Object> true_value = factory->true_value();
19238   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
19239   i::Handle<i::Object> false_value = factory->false_value();
19240   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
19241 }
19242
19243
19244 UNINITIALIZED_TEST(IsolateEmbedderData) {
19245   CcTest::DisableAutomaticDispose();
19246   v8::Isolate* isolate = v8::Isolate::New();
19247   isolate->Enter();
19248   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
19249   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
19250     CHECK(!isolate->GetData(slot));
19251     CHECK(!i_isolate->GetData(slot));
19252   }
19253   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
19254     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
19255     isolate->SetData(slot, data);
19256   }
19257   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
19258     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
19259     CHECK_EQ(data, isolate->GetData(slot));
19260     CHECK_EQ(data, i_isolate->GetData(slot));
19261   }
19262   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
19263     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
19264     isolate->SetData(slot, data);
19265   }
19266   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
19267     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
19268     CHECK_EQ(data, isolate->GetData(slot));
19269     CHECK_EQ(data, i_isolate->GetData(slot));
19270   }
19271   isolate->Exit();
19272   isolate->Dispose();
19273 }
19274
19275
19276 TEST(StringEmpty) {
19277   LocalContext context;
19278   i::Factory* factory = CcTest::i_isolate()->factory();
19279   v8::Isolate* isolate = CcTest::isolate();
19280   v8::HandleScope scope(isolate);
19281   i::Handle<i::Object> empty_string = factory->empty_string();
19282   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
19283 }
19284
19285
19286 static int instance_checked_getter_count = 0;
19287 static void InstanceCheckedGetter(
19288     Local<String> name,
19289     const v8::PropertyCallbackInfo<v8::Value>& info) {
19290   CHECK(name->Equals(v8_str("foo")));
19291   instance_checked_getter_count++;
19292   info.GetReturnValue().Set(v8_num(11));
19293 }
19294
19295
19296 static int instance_checked_setter_count = 0;
19297 static void InstanceCheckedSetter(Local<String> name,
19298                       Local<Value> value,
19299                       const v8::PropertyCallbackInfo<void>& info) {
19300   CHECK(name->Equals(v8_str("foo")));
19301   CHECK(value->Equals(v8_num(23)));
19302   instance_checked_setter_count++;
19303 }
19304
19305
19306 static void CheckInstanceCheckedResult(int getters, int setters,
19307                                        bool expects_callbacks,
19308                                        TryCatch* try_catch) {
19309   if (expects_callbacks) {
19310     CHECK(!try_catch->HasCaught());
19311     CHECK_EQ(getters, instance_checked_getter_count);
19312     CHECK_EQ(setters, instance_checked_setter_count);
19313   } else {
19314     CHECK(try_catch->HasCaught());
19315     CHECK_EQ(0, instance_checked_getter_count);
19316     CHECK_EQ(0, instance_checked_setter_count);
19317   }
19318   try_catch->Reset();
19319 }
19320
19321
19322 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
19323   instance_checked_getter_count = 0;
19324   instance_checked_setter_count = 0;
19325   TryCatch try_catch;
19326
19327   // Test path through generic runtime code.
19328   CompileRun("obj.foo");
19329   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
19330   CompileRun("obj.foo = 23");
19331   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
19332
19333   // Test path through generated LoadIC and StoredIC.
19334   CompileRun("function test_get(o) { o.foo; }"
19335              "test_get(obj);");
19336   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
19337   CompileRun("test_get(obj);");
19338   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
19339   CompileRun("test_get(obj);");
19340   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
19341   CompileRun("function test_set(o) { o.foo = 23; }"
19342              "test_set(obj);");
19343   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
19344   CompileRun("test_set(obj);");
19345   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
19346   CompileRun("test_set(obj);");
19347   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
19348
19349   // Test path through optimized code.
19350   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
19351              "test_get(obj);");
19352   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
19353   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
19354              "test_set(obj);");
19355   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
19356
19357   // Cleanup so that closures start out fresh in next check.
19358   CompileRun("%DeoptimizeFunction(test_get);"
19359              "%ClearFunctionTypeFeedback(test_get);"
19360              "%DeoptimizeFunction(test_set);"
19361              "%ClearFunctionTypeFeedback(test_set);");
19362 }
19363
19364
19365 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
19366   v8::internal::FLAG_allow_natives_syntax = true;
19367   LocalContext context;
19368   v8::HandleScope scope(context->GetIsolate());
19369
19370   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
19371   Local<ObjectTemplate> inst = templ->InstanceTemplate();
19372   inst->SetAccessor(v8_str("foo"),
19373                     InstanceCheckedGetter, InstanceCheckedSetter,
19374                     Handle<Value>(),
19375                     v8::DEFAULT,
19376                     v8::None,
19377                     v8::AccessorSignature::New(context->GetIsolate(), templ));
19378   context->Global()->Set(v8_str("f"), templ->GetFunction());
19379
19380   printf("Testing positive ...\n");
19381   CompileRun("var obj = new f();");
19382   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19383   CheckInstanceCheckedAccessors(true);
19384
19385   printf("Testing negative ...\n");
19386   CompileRun("var obj = {};"
19387              "obj.__proto__ = new f();");
19388   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19389   CheckInstanceCheckedAccessors(false);
19390 }
19391
19392
19393 static void EmptyInterceptorGetter(
19394     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
19395
19396
19397 static void EmptyInterceptorSetter(
19398     Local<String> name, Local<Value> value,
19399     const v8::PropertyCallbackInfo<v8::Value>& info) {}
19400
19401
19402 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
19403   v8::internal::FLAG_allow_natives_syntax = true;
19404   LocalContext context;
19405   v8::HandleScope scope(context->GetIsolate());
19406
19407   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
19408   Local<ObjectTemplate> inst = templ->InstanceTemplate();
19409   templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
19410                                                      EmptyInterceptorSetter);
19411   inst->SetAccessor(v8_str("foo"),
19412                     InstanceCheckedGetter, InstanceCheckedSetter,
19413                     Handle<Value>(),
19414                     v8::DEFAULT,
19415                     v8::None,
19416                     v8::AccessorSignature::New(context->GetIsolate(), templ));
19417   context->Global()->Set(v8_str("f"), templ->GetFunction());
19418
19419   printf("Testing positive ...\n");
19420   CompileRun("var obj = new f();");
19421   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19422   CheckInstanceCheckedAccessors(true);
19423
19424   printf("Testing negative ...\n");
19425   CompileRun("var obj = {};"
19426              "obj.__proto__ = new f();");
19427   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19428   CheckInstanceCheckedAccessors(false);
19429 }
19430
19431
19432 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
19433   v8::internal::FLAG_allow_natives_syntax = true;
19434   LocalContext context;
19435   v8::HandleScope scope(context->GetIsolate());
19436
19437   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
19438   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
19439   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
19440                      InstanceCheckedSetter, Handle<Value>(), v8::DEFAULT,
19441                      v8::None,
19442                      v8::AccessorSignature::New(context->GetIsolate(), templ));
19443   context->Global()->Set(v8_str("f"), templ->GetFunction());
19444
19445   printf("Testing positive ...\n");
19446   CompileRun("var obj = new f();");
19447   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19448   CheckInstanceCheckedAccessors(true);
19449
19450   printf("Testing negative ...\n");
19451   CompileRun("var obj = {};"
19452              "obj.__proto__ = new f();");
19453   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19454   CheckInstanceCheckedAccessors(false);
19455
19456   printf("Testing positive with modified prototype chain ...\n");
19457   CompileRun("var obj = new f();"
19458              "var pro = {};"
19459              "pro.__proto__ = obj.__proto__;"
19460              "obj.__proto__ = pro;");
19461   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19462   CheckInstanceCheckedAccessors(true);
19463 }
19464
19465
19466 TEST(TryFinallyMessage) {
19467   LocalContext context;
19468   v8::HandleScope scope(context->GetIsolate());
19469   {
19470     // Test that the original error message is not lost if there is a
19471     // recursive call into Javascript is done in the finally block, e.g. to
19472     // initialize an IC. (crbug.com/129171)
19473     TryCatch try_catch;
19474     const char* trigger_ic =
19475         "try {                      \n"
19476         "  throw new Error('test'); \n"
19477         "} finally {                \n"
19478         "  var x = 0;               \n"
19479         "  x++;                     \n"  // Trigger an IC initialization here.
19480         "}                          \n";
19481     CompileRun(trigger_ic);
19482     CHECK(try_catch.HasCaught());
19483     Local<Message> message = try_catch.Message();
19484     CHECK(!message.IsEmpty());
19485     CHECK_EQ(2, message->GetLineNumber());
19486   }
19487
19488   {
19489     // Test that the original exception message is indeed overwritten if
19490     // a new error is thrown in the finally block.
19491     TryCatch try_catch;
19492     const char* throw_again =
19493         "try {                       \n"
19494         "  throw new Error('test');  \n"
19495         "} finally {                 \n"
19496         "  var x = 0;                \n"
19497         "  x++;                      \n"
19498         "  throw new Error('again'); \n"  // This is the new uncaught error.
19499         "}                           \n";
19500     CompileRun(throw_again);
19501     CHECK(try_catch.HasCaught());
19502     Local<Message> message = try_catch.Message();
19503     CHECK(!message.IsEmpty());
19504     CHECK_EQ(6, message->GetLineNumber());
19505   }
19506 }
19507
19508
19509 static void Helper137002(bool do_store,
19510                          bool polymorphic,
19511                          bool remove_accessor,
19512                          bool interceptor) {
19513   LocalContext context;
19514   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
19515   if (interceptor) {
19516     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
19517                                                             FooSetInterceptor));
19518   } else {
19519     templ->SetAccessor(v8_str("foo"),
19520                        GetterWhichReturns42,
19521                        SetterWhichSetsYOnThisTo23);
19522   }
19523   context->Global()->Set(v8_str("obj"), templ->NewInstance());
19524
19525   // Turn monomorphic on slow object with native accessor, then turn
19526   // polymorphic, finally optimize to create negative lookup and fail.
19527   CompileRun(do_store ?
19528              "function f(x) { x.foo = void 0; }" :
19529              "function f(x) { return x.foo; }");
19530   CompileRun("obj.y = void 0;");
19531   if (!interceptor) {
19532     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
19533   }
19534   CompileRun("obj.__proto__ = null;"
19535              "f(obj); f(obj); f(obj);");
19536   if (polymorphic) {
19537     CompileRun("f({});");
19538   }
19539   CompileRun("obj.y = void 0;"
19540              "%OptimizeFunctionOnNextCall(f);");
19541   if (remove_accessor) {
19542     CompileRun("delete obj.foo;");
19543   }
19544   CompileRun("var result = f(obj);");
19545   if (do_store) {
19546     CompileRun("result = obj.y;");
19547   }
19548   if (remove_accessor && !interceptor) {
19549     CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
19550   } else {
19551     CHECK_EQ(do_store ? 23 : 42,
19552              context->Global()->Get(v8_str("result"))->Int32Value());
19553   }
19554 }
19555
19556
19557 THREADED_TEST(Regress137002a) {
19558   i::FLAG_allow_natives_syntax = true;
19559   i::FLAG_compilation_cache = false;
19560   v8::HandleScope scope(CcTest::isolate());
19561   for (int i = 0; i < 16; i++) {
19562     Helper137002(i & 8, i & 4, i & 2, i & 1);
19563   }
19564 }
19565
19566
19567 THREADED_TEST(Regress137002b) {
19568   i::FLAG_allow_natives_syntax = true;
19569   LocalContext context;
19570   v8::Isolate* isolate = context->GetIsolate();
19571   v8::HandleScope scope(isolate);
19572   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19573   templ->SetAccessor(v8_str("foo"),
19574                      GetterWhichReturns42,
19575                      SetterWhichSetsYOnThisTo23);
19576   context->Global()->Set(v8_str("obj"), templ->NewInstance());
19577
19578   // Turn monomorphic on slow object with native accessor, then just
19579   // delete the property and fail.
19580   CompileRun("function load(x) { return x.foo; }"
19581              "function store(x) { x.foo = void 0; }"
19582              "function keyed_load(x, key) { return x[key]; }"
19583              // Second version of function has a different source (add void 0)
19584              // so that it does not share code with the first version.  This
19585              // ensures that the ICs are monomorphic.
19586              "function load2(x) { void 0; return x.foo; }"
19587              "function store2(x) { void 0; x.foo = void 0; }"
19588              "function keyed_load2(x, key) { void 0; return x[key]; }"
19589
19590              "obj.y = void 0;"
19591              "obj.__proto__ = null;"
19592              "var subobj = {};"
19593              "subobj.y = void 0;"
19594              "subobj.__proto__ = obj;"
19595              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
19596
19597              // Make the ICs monomorphic.
19598              "load(obj); load(obj);"
19599              "load2(subobj); load2(subobj);"
19600              "store(obj); store(obj);"
19601              "store2(subobj); store2(subobj);"
19602              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
19603              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
19604
19605              // Actually test the shiny new ICs and better not crash. This
19606              // serves as a regression test for issue 142088 as well.
19607              "load(obj);"
19608              "load2(subobj);"
19609              "store(obj);"
19610              "store2(subobj);"
19611              "keyed_load(obj, 'foo');"
19612              "keyed_load2(subobj, 'foo');"
19613
19614              // Delete the accessor.  It better not be called any more now.
19615              "delete obj.foo;"
19616              "obj.y = void 0;"
19617              "subobj.y = void 0;"
19618
19619              "var load_result = load(obj);"
19620              "var load_result2 = load2(subobj);"
19621              "var keyed_load_result = keyed_load(obj, 'foo');"
19622              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
19623              "store(obj);"
19624              "store2(subobj);"
19625              "var y_from_obj = obj.y;"
19626              "var y_from_subobj = subobj.y;");
19627   CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
19628   CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
19629   CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
19630   CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
19631   CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
19632   CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
19633 }
19634
19635
19636 THREADED_TEST(Regress142088) {
19637   i::FLAG_allow_natives_syntax = true;
19638   LocalContext context;
19639   v8::Isolate* isolate = context->GetIsolate();
19640   v8::HandleScope scope(isolate);
19641   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19642   templ->SetAccessor(v8_str("foo"),
19643                      GetterWhichReturns42,
19644                      SetterWhichSetsYOnThisTo23);
19645   context->Global()->Set(v8_str("obj"), templ->NewInstance());
19646
19647   CompileRun("function load(x) { return x.foo; }"
19648              "var o = Object.create(obj);"
19649              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
19650              "load(o); load(o); load(o); load(o);");
19651 }
19652
19653
19654 THREADED_TEST(Regress3337) {
19655   LocalContext context;
19656   v8::Isolate* isolate = context->GetIsolate();
19657   v8::HandleScope scope(isolate);
19658   Local<v8::Object> o1 = Object::New(isolate);
19659   Local<v8::Object> o2 = Object::New(isolate);
19660   i::Handle<i::JSObject> io1 = v8::Utils::OpenHandle(*o1);
19661   i::Handle<i::JSObject> io2 = v8::Utils::OpenHandle(*o2);
19662   CHECK(io1->map() == io2->map());
19663   o1->SetIndexedPropertiesToExternalArrayData(
19664       NULL, v8::kExternalUint32Array, 0);
19665   o2->SetIndexedPropertiesToExternalArrayData(
19666       NULL, v8::kExternalUint32Array, 0);
19667   CHECK(io1->map() == io2->map());
19668 }
19669
19670
19671 THREADED_TEST(Regress137496) {
19672   i::FLAG_expose_gc = true;
19673   LocalContext context;
19674   v8::HandleScope scope(context->GetIsolate());
19675
19676   // Compile a try-finally clause where the finally block causes a GC
19677   // while there still is a message pending for external reporting.
19678   TryCatch try_catch;
19679   try_catch.SetVerbose(true);
19680   CompileRun("try { throw new Error(); } finally { gc(); }");
19681   CHECK(try_catch.HasCaught());
19682 }
19683
19684
19685 THREADED_TEST(Regress157124) {
19686   LocalContext context;
19687   v8::Isolate* isolate = context->GetIsolate();
19688   v8::HandleScope scope(isolate);
19689   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19690   Local<Object> obj = templ->NewInstance();
19691   obj->GetIdentityHash();
19692   obj->DeleteHiddenValue(v8_str("Bug"));
19693 }
19694
19695
19696 THREADED_TEST(Regress2535) {
19697   LocalContext context;
19698   v8::HandleScope scope(context->GetIsolate());
19699   Local<Value> set_value = CompileRun("new Set();");
19700   Local<Object> set_object(Local<Object>::Cast(set_value));
19701   CHECK_EQ(0, set_object->InternalFieldCount());
19702   Local<Value> map_value = CompileRun("new Map();");
19703   Local<Object> map_object(Local<Object>::Cast(map_value));
19704   CHECK_EQ(0, map_object->InternalFieldCount());
19705 }
19706
19707
19708 THREADED_TEST(Regress2746) {
19709   LocalContext context;
19710   v8::Isolate* isolate = context->GetIsolate();
19711   v8::HandleScope scope(isolate);
19712   Local<Object> obj = Object::New(isolate);
19713   Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
19714   obj->SetHiddenValue(key, v8::Undefined(isolate));
19715   Local<Value> value = obj->GetHiddenValue(key);
19716   CHECK(!value.IsEmpty());
19717   CHECK(value->IsUndefined());
19718 }
19719
19720
19721 THREADED_TEST(Regress260106) {
19722   LocalContext context;
19723   v8::Isolate* isolate = context->GetIsolate();
19724   v8::HandleScope scope(isolate);
19725   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
19726                                                         DummyCallHandler);
19727   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
19728   Local<Function> function = templ->GetFunction();
19729   CHECK(!function.IsEmpty());
19730   CHECK(function->IsFunction());
19731 }
19732
19733
19734 THREADED_TEST(JSONParseObject) {
19735   LocalContext context;
19736   HandleScope scope(context->GetIsolate());
19737   Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
19738   Handle<Object> global = context->Global();
19739   global->Set(v8_str("obj"), obj);
19740   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
19741 }
19742
19743
19744 THREADED_TEST(JSONParseNumber) {
19745   LocalContext context;
19746   HandleScope scope(context->GetIsolate());
19747   Local<Value> obj = v8::JSON::Parse(v8_str("42"));
19748   Handle<Object> global = context->Global();
19749   global->Set(v8_str("obj"), obj);
19750   ExpectString("JSON.stringify(obj)", "42");
19751 }
19752
19753
19754 #if V8_OS_POSIX && !V8_OS_NACL
19755 class ThreadInterruptTest {
19756  public:
19757   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
19758   ~ThreadInterruptTest() {}
19759
19760   void RunTest() {
19761     InterruptThread i_thread(this);
19762     i_thread.Start();
19763
19764     sem_.Wait();
19765     CHECK_EQ(kExpectedValue, sem_value_);
19766   }
19767
19768  private:
19769   static const int kExpectedValue = 1;
19770
19771   class InterruptThread : public v8::base::Thread {
19772    public:
19773     explicit InterruptThread(ThreadInterruptTest* test)
19774         : Thread(Options("InterruptThread")), test_(test) {}
19775
19776     virtual void Run() {
19777       struct sigaction action;
19778
19779       // Ensure that we'll enter waiting condition
19780       v8::base::OS::Sleep(100);
19781
19782       // Setup signal handler
19783       memset(&action, 0, sizeof(action));
19784       action.sa_handler = SignalHandler;
19785       sigaction(SIGCHLD, &action, NULL);
19786
19787       // Send signal
19788       kill(getpid(), SIGCHLD);
19789
19790       // Ensure that if wait has returned because of error
19791       v8::base::OS::Sleep(100);
19792
19793       // Set value and signal semaphore
19794       test_->sem_value_ = 1;
19795       test_->sem_.Signal();
19796     }
19797
19798     static void SignalHandler(int signal) {
19799     }
19800
19801    private:
19802      ThreadInterruptTest* test_;
19803   };
19804
19805   v8::base::Semaphore sem_;
19806   volatile int sem_value_;
19807 };
19808
19809
19810 THREADED_TEST(SemaphoreInterruption) {
19811   ThreadInterruptTest().RunTest();
19812 }
19813
19814
19815 #endif  // V8_OS_POSIX
19816
19817
19818 static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
19819                                      Local<Value> name,
19820                                      v8::AccessType type,
19821                                      Local<Value> data) {
19822   i::PrintF("Named access blocked.\n");
19823   return false;
19824 }
19825
19826
19827 static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
19828                                      uint32_t key,
19829                                      v8::AccessType type,
19830                                      Local<Value> data) {
19831   i::PrintF("Indexed access blocked.\n");
19832   return false;
19833 }
19834
19835
19836 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19837   CHECK(false);
19838 }
19839
19840
19841 TEST(JSONStringifyAccessCheck) {
19842   v8::V8::Initialize();
19843   v8::Isolate* isolate = CcTest::isolate();
19844   v8::HandleScope scope(isolate);
19845
19846   // Create an ObjectTemplate for global objects and install access
19847   // check callbacks that will block access.
19848   v8::Handle<v8::ObjectTemplate> global_template =
19849       v8::ObjectTemplate::New(isolate);
19850   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
19851                                            IndexAccessAlwaysBlocked);
19852
19853   // Create a context and set an x property on it's global object.
19854   LocalContext context0(NULL, global_template);
19855   v8::Handle<v8::Object> global0 = context0->Global();
19856   global0->Set(v8_str("x"), v8_num(42));
19857   ExpectString("JSON.stringify(this)", "{\"x\":42}");
19858
19859   for (int i = 0; i < 2; i++) {
19860     if (i == 1) {
19861       // Install a toJSON function on the second run.
19862       v8::Handle<v8::FunctionTemplate> toJSON =
19863           v8::FunctionTemplate::New(isolate, UnreachableCallback);
19864
19865       global0->Set(v8_str("toJSON"), toJSON->GetFunction());
19866     }
19867     // Create a context with a different security token so that the
19868     // failed access check callback will be called on each access.
19869     LocalContext context1(NULL, global_template);
19870     context1->Global()->Set(v8_str("other"), global0);
19871
19872     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
19873     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
19874     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
19875
19876     v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
19877     array->Set(0, v8_str("a"));
19878     array->Set(1, v8_str("b"));
19879     context1->Global()->Set(v8_str("array"), array);
19880     ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
19881     array->TurnOnAccessCheck();
19882     CHECK(CompileRun("JSON.stringify(array)").IsEmpty());
19883     CHECK(CompileRun("JSON.stringify([array])").IsEmpty());
19884     CHECK(CompileRun("JSON.stringify({'a' : array})").IsEmpty());
19885   }
19886 }
19887
19888
19889 bool access_check_fail_thrown = false;
19890 bool catch_callback_called = false;
19891
19892
19893 // Failed access check callback that performs a GC on each invocation.
19894 void FailedAccessCheckThrows(Local<v8::Object> target,
19895                              v8::AccessType type,
19896                              Local<v8::Value> data) {
19897   access_check_fail_thrown = true;
19898   i::PrintF("Access check failed. Error thrown.\n");
19899   CcTest::isolate()->ThrowException(
19900       v8::Exception::Error(v8_str("cross context")));
19901 }
19902
19903
19904 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19905   for (int i = 0; i < args.Length(); i++) {
19906     i::PrintF("%s\n", *String::Utf8Value(args[i]));
19907   }
19908   catch_callback_called = true;
19909 }
19910
19911
19912 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19913   args[0]->ToObject(args.GetIsolate())->HasOwnProperty(
19914       args[1]->ToString(args.GetIsolate()));
19915 }
19916
19917
19918 void CheckCorrectThrow(const char* script) {
19919   // Test that the script, when wrapped into a try-catch, triggers the catch
19920   // clause due to failed access check throwing an exception.
19921   // The subsequent try-catch should run without any exception.
19922   access_check_fail_thrown = false;
19923   catch_callback_called = false;
19924   i::ScopedVector<char> source(1024);
19925   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
19926   CompileRun(source.start());
19927   CHECK(access_check_fail_thrown);
19928   CHECK(catch_callback_called);
19929
19930   access_check_fail_thrown = false;
19931   catch_callback_called = false;
19932   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
19933   CHECK(!access_check_fail_thrown);
19934   CHECK(!catch_callback_called);
19935 }
19936
19937
19938 TEST(AccessCheckThrows) {
19939   i::FLAG_allow_natives_syntax = true;
19940   v8::V8::Initialize();
19941   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
19942   v8::Isolate* isolate = CcTest::isolate();
19943   v8::HandleScope scope(isolate);
19944
19945   // Create an ObjectTemplate for global objects and install access
19946   // check callbacks that will block access.
19947   v8::Handle<v8::ObjectTemplate> global_template =
19948       v8::ObjectTemplate::New(isolate);
19949   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
19950                                            IndexAccessAlwaysBlocked);
19951
19952   // Create a context and set an x property on it's global object.
19953   LocalContext context0(NULL, global_template);
19954   v8::Handle<v8::Object> global0 = context0->Global();
19955
19956   // Create a context with a different security token so that the
19957   // failed access check callback will be called on each access.
19958   LocalContext context1(NULL, global_template);
19959   context1->Global()->Set(v8_str("other"), global0);
19960
19961   v8::Handle<v8::FunctionTemplate> catcher_fun =
19962       v8::FunctionTemplate::New(isolate, CatcherCallback);
19963   context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
19964
19965   v8::Handle<v8::FunctionTemplate> has_own_property_fun =
19966       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
19967   context1->Global()->Set(v8_str("has_own_property"),
19968                           has_own_property_fun->GetFunction());
19969
19970   { v8::TryCatch try_catch;
19971     access_check_fail_thrown = false;
19972     CompileRun("other.x;");
19973     CHECK(access_check_fail_thrown);
19974     CHECK(try_catch.HasCaught());
19975   }
19976
19977   CheckCorrectThrow("other.x");
19978   CheckCorrectThrow("other[1]");
19979   CheckCorrectThrow("JSON.stringify(other)");
19980   CheckCorrectThrow("has_own_property(other, 'x')");
19981   CheckCorrectThrow("%GetProperty(other, 'x')");
19982   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
19983   CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
19984   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
19985   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
19986   CheckCorrectThrow("%HasOwnProperty(other, 'x')");
19987   CheckCorrectThrow("%HasProperty(other, 'x')");
19988   CheckCorrectThrow("%HasElement(other, 1)");
19989   CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
19990   CheckCorrectThrow("%GetPropertyNames(other)");
19991   // PROPERTY_ATTRIBUTES_NONE = 0
19992   CheckCorrectThrow("%GetOwnPropertyNames(other, 0)");
19993   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
19994                         "other, 'x', null, null, 1)");
19995
19996   // Reset the failed access check callback so it does not influence
19997   // the other tests.
19998   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19999 }
20000
20001
20002 class RequestInterruptTestBase {
20003  public:
20004   RequestInterruptTestBase()
20005       : env_(),
20006         isolate_(env_->GetIsolate()),
20007         sem_(0),
20008         warmup_(20000),
20009         should_continue_(true) {
20010   }
20011
20012   virtual ~RequestInterruptTestBase() { }
20013
20014   virtual void StartInterruptThread() = 0;
20015
20016   virtual void TestBody() = 0;
20017
20018   void RunTest() {
20019     StartInterruptThread();
20020
20021     v8::HandleScope handle_scope(isolate_);
20022
20023     TestBody();
20024
20025     // Verify we arrived here because interruptor was called
20026     // not due to a bug causing us to exit the loop too early.
20027     CHECK(!should_continue());
20028   }
20029
20030   void WakeUpInterruptor() {
20031     sem_.Signal();
20032   }
20033
20034   bool should_continue() const { return should_continue_; }
20035
20036   bool ShouldContinue() {
20037     if (warmup_ > 0) {
20038       if (--warmup_ == 0) {
20039         WakeUpInterruptor();
20040       }
20041     }
20042
20043     return should_continue_;
20044   }
20045
20046   static void ShouldContinueCallback(
20047       const v8::FunctionCallbackInfo<Value>& info) {
20048     RequestInterruptTestBase* test =
20049         reinterpret_cast<RequestInterruptTestBase*>(
20050             info.Data().As<v8::External>()->Value());
20051     info.GetReturnValue().Set(test->ShouldContinue());
20052   }
20053
20054   LocalContext env_;
20055   v8::Isolate* isolate_;
20056   v8::base::Semaphore sem_;
20057   int warmup_;
20058   bool should_continue_;
20059 };
20060
20061
20062 class RequestInterruptTestBaseWithSimpleInterrupt
20063     : public RequestInterruptTestBase {
20064  public:
20065   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
20066
20067   virtual void StartInterruptThread() {
20068     i_thread.Start();
20069   }
20070
20071  private:
20072   class InterruptThread : public v8::base::Thread {
20073    public:
20074     explicit InterruptThread(RequestInterruptTestBase* test)
20075         : Thread(Options("RequestInterruptTest")), test_(test) {}
20076
20077     virtual void Run() {
20078       test_->sem_.Wait();
20079       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
20080     }
20081
20082     static void OnInterrupt(v8::Isolate* isolate, void* data) {
20083       reinterpret_cast<RequestInterruptTestBase*>(data)->
20084           should_continue_ = false;
20085     }
20086
20087    private:
20088      RequestInterruptTestBase* test_;
20089   };
20090
20091   InterruptThread i_thread;
20092 };
20093
20094
20095 class RequestInterruptTestWithFunctionCall
20096     : public RequestInterruptTestBaseWithSimpleInterrupt {
20097  public:
20098   virtual void TestBody() {
20099     Local<Function> func = Function::New(
20100         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
20101     env_->Global()->Set(v8_str("ShouldContinue"), func);
20102
20103     CompileRun("while (ShouldContinue()) { }");
20104   }
20105 };
20106
20107
20108 class RequestInterruptTestWithMethodCall
20109     : public RequestInterruptTestBaseWithSimpleInterrupt {
20110  public:
20111   virtual void TestBody() {
20112     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
20113     v8::Local<v8::Template> proto = t->PrototypeTemplate();
20114     proto->Set(v8_str("shouldContinue"), Function::New(
20115         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
20116     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
20117
20118     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
20119   }
20120 };
20121
20122
20123 class RequestInterruptTestWithAccessor
20124     : public RequestInterruptTestBaseWithSimpleInterrupt {
20125  public:
20126   virtual void TestBody() {
20127     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
20128     v8::Local<v8::Template> proto = t->PrototypeTemplate();
20129     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
20130         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
20131     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
20132
20133     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
20134   }
20135 };
20136
20137
20138 class RequestInterruptTestWithNativeAccessor
20139     : public RequestInterruptTestBaseWithSimpleInterrupt {
20140  public:
20141   virtual void TestBody() {
20142     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
20143     t->InstanceTemplate()->SetNativeDataProperty(
20144         v8_str("shouldContinue"),
20145         &ShouldContinueNativeGetter,
20146         NULL,
20147         v8::External::New(isolate_, this));
20148     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
20149
20150     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
20151   }
20152
20153  private:
20154   static void ShouldContinueNativeGetter(
20155       Local<String> property,
20156       const v8::PropertyCallbackInfo<v8::Value>& info) {
20157     RequestInterruptTestBase* test =
20158         reinterpret_cast<RequestInterruptTestBase*>(
20159             info.Data().As<v8::External>()->Value());
20160     info.GetReturnValue().Set(test->ShouldContinue());
20161   }
20162 };
20163
20164
20165 class RequestInterruptTestWithMethodCallAndInterceptor
20166     : public RequestInterruptTestBaseWithSimpleInterrupt {
20167  public:
20168   virtual void TestBody() {
20169     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
20170     v8::Local<v8::Template> proto = t->PrototypeTemplate();
20171     proto->Set(v8_str("shouldContinue"), Function::New(
20172         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
20173     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
20174     instance_template->SetHandler(
20175         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
20176
20177     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
20178
20179     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
20180   }
20181
20182  private:
20183   static void EmptyInterceptor(
20184       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
20185 };
20186
20187
20188 class RequestInterruptTestWithMathAbs
20189     : public RequestInterruptTestBaseWithSimpleInterrupt {
20190  public:
20191   virtual void TestBody() {
20192     env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
20193         isolate_,
20194         WakeUpInterruptorCallback,
20195         v8::External::New(isolate_, this)));
20196
20197     env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
20198         isolate_,
20199         ShouldContinueCallback,
20200         v8::External::New(isolate_, this)));
20201
20202     i::FLAG_allow_natives_syntax = true;
20203     CompileRun("function loopish(o) {"
20204                "  var pre = 10;"
20205                "  while (o.abs(1) > 0) {"
20206                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
20207                "    if (pre > 0) {"
20208                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
20209                "    }"
20210                "  }"
20211                "}"
20212                "var i = 50;"
20213                "var obj = {abs: function () { return i-- }, x: null};"
20214                "delete obj.x;"
20215                "loopish(obj);"
20216                "%OptimizeFunctionOnNextCall(loopish);"
20217                "loopish(Math);");
20218
20219     i::FLAG_allow_natives_syntax = false;
20220   }
20221
20222  private:
20223   static void WakeUpInterruptorCallback(
20224       const v8::FunctionCallbackInfo<Value>& info) {
20225     if (!info[0]->BooleanValue()) return;
20226
20227     RequestInterruptTestBase* test =
20228         reinterpret_cast<RequestInterruptTestBase*>(
20229             info.Data().As<v8::External>()->Value());
20230     test->WakeUpInterruptor();
20231   }
20232
20233   static void ShouldContinueCallback(
20234       const v8::FunctionCallbackInfo<Value>& info) {
20235     RequestInterruptTestBase* test =
20236         reinterpret_cast<RequestInterruptTestBase*>(
20237             info.Data().As<v8::External>()->Value());
20238     info.GetReturnValue().Set(test->should_continue());
20239   }
20240 };
20241
20242
20243 TEST(RequestInterruptTestWithFunctionCall) {
20244   RequestInterruptTestWithFunctionCall().RunTest();
20245 }
20246
20247
20248 TEST(RequestInterruptTestWithMethodCall) {
20249   RequestInterruptTestWithMethodCall().RunTest();
20250 }
20251
20252
20253 TEST(RequestInterruptTestWithAccessor) {
20254   RequestInterruptTestWithAccessor().RunTest();
20255 }
20256
20257
20258 TEST(RequestInterruptTestWithNativeAccessor) {
20259   RequestInterruptTestWithNativeAccessor().RunTest();
20260 }
20261
20262
20263 TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
20264   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
20265 }
20266
20267
20268 TEST(RequestInterruptTestWithMathAbs) {
20269   RequestInterruptTestWithMathAbs().RunTest();
20270 }
20271
20272
20273 class RequestMultipleInterrupts : public RequestInterruptTestBase {
20274  public:
20275   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
20276
20277   virtual void StartInterruptThread() {
20278     i_thread.Start();
20279   }
20280
20281   virtual void TestBody() {
20282     Local<Function> func = Function::New(
20283         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
20284     env_->Global()->Set(v8_str("ShouldContinue"), func);
20285
20286     CompileRun("while (ShouldContinue()) { }");
20287   }
20288
20289  private:
20290   class InterruptThread : public v8::base::Thread {
20291    public:
20292     enum { NUM_INTERRUPTS = 10 };
20293     explicit InterruptThread(RequestMultipleInterrupts* test)
20294         : Thread(Options("RequestInterruptTest")), test_(test) {}
20295
20296     virtual void Run() {
20297       test_->sem_.Wait();
20298       for (int i = 0; i < NUM_INTERRUPTS; i++) {
20299         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
20300       }
20301     }
20302
20303     static void OnInterrupt(v8::Isolate* isolate, void* data) {
20304       RequestMultipleInterrupts* test =
20305           reinterpret_cast<RequestMultipleInterrupts*>(data);
20306       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
20307     }
20308
20309    private:
20310     RequestMultipleInterrupts* test_;
20311   };
20312
20313   InterruptThread i_thread;
20314   int counter_;
20315 };
20316
20317
20318 TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
20319
20320
20321 static Local<Value> function_new_expected_env;
20322 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
20323   CHECK(function_new_expected_env->Equals(info.Data()));
20324   info.GetReturnValue().Set(17);
20325 }
20326
20327
20328 THREADED_TEST(FunctionNew) {
20329   LocalContext env;
20330   v8::Isolate* isolate = env->GetIsolate();
20331   v8::HandleScope scope(isolate);
20332   Local<Object> data = v8::Object::New(isolate);
20333   function_new_expected_env = data;
20334   Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
20335   env->Global()->Set(v8_str("func"), func);
20336   Local<Value> result = CompileRun("func();");
20337   CHECK(v8::Integer::New(isolate, 17)->Equals(result));
20338   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
20339   // Verify function not cached
20340   auto serial_number = handle(i::Smi::cast(v8::Utils::OpenHandle(*func)
20341                                                ->shared()
20342                                                ->get_api_func_data()
20343                                                ->serial_number()),
20344                               i_isolate);
20345   auto cache = i_isolate->function_cache();
20346   CHECK(cache->Lookup(serial_number)->IsTheHole());
20347   // Verify that each Function::New creates a new function instance
20348   Local<Object> data2 = v8::Object::New(isolate);
20349   function_new_expected_env = data2;
20350   Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
20351   CHECK(!func2->IsNull());
20352   CHECK(!func->Equals(func2));
20353   env->Global()->Set(v8_str("func2"), func2);
20354   Local<Value> result2 = CompileRun("func2();");
20355   CHECK(v8::Integer::New(isolate, 17)->Equals(result2));
20356 }
20357
20358
20359 TEST(EscapeableHandleScope) {
20360   HandleScope outer_scope(CcTest::isolate());
20361   LocalContext context;
20362   const int runs = 10;
20363   Local<String> values[runs];
20364   for (int i = 0; i < runs; i++) {
20365     v8::EscapableHandleScope inner_scope(CcTest::isolate());
20366     Local<String> value;
20367     if (i != 0) value = v8_str("escape value");
20368     values[i] = inner_scope.Escape(value);
20369   }
20370   for (int i = 0; i < runs; i++) {
20371     Local<String> expected;
20372     if (i != 0) {
20373       CHECK(v8_str("escape value")->Equals(values[i]));
20374     } else {
20375       CHECK(values[i].IsEmpty());
20376     }
20377   }
20378 }
20379
20380
20381 static void SetterWhichExpectsThisAndHolderToDiffer(
20382     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
20383   CHECK(info.Holder() != info.This());
20384 }
20385
20386
20387 TEST(Regress239669) {
20388   LocalContext context;
20389   v8::Isolate* isolate = context->GetIsolate();
20390   v8::HandleScope scope(isolate);
20391   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20392   templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
20393   context->Global()->Set(v8_str("P"), templ->NewInstance());
20394   CompileRun(
20395       "function C1() {"
20396       "  this.x = 23;"
20397       "};"
20398       "C1.prototype = P;"
20399       "for (var i = 0; i < 4; i++ ) {"
20400       "  new C1();"
20401       "}");
20402 }
20403
20404
20405 class ApiCallOptimizationChecker {
20406  private:
20407   static Local<Object> data;
20408   static Local<Object> receiver;
20409   static Local<Object> holder;
20410   static Local<Object> callee;
20411   static int count;
20412
20413   static void OptimizationCallback(
20414       const v8::FunctionCallbackInfo<v8::Value>& info) {
20415     CHECK(callee == info.Callee());
20416     CHECK(data == info.Data());
20417     CHECK(receiver == info.This());
20418     if (info.Length() == 1) {
20419       CHECK(v8_num(1)->Equals(info[0]));
20420     }
20421     CHECK(holder == info.Holder());
20422     count++;
20423     info.GetReturnValue().Set(v8_str("returned"));
20424   }
20425
20426  public:
20427   enum SignatureType {
20428     kNoSignature,
20429     kSignatureOnReceiver,
20430     kSignatureOnPrototype
20431   };
20432
20433   void RunAll() {
20434     SignatureType signature_types[] =
20435       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
20436     for (unsigned i = 0; i < arraysize(signature_types); i++) {
20437       SignatureType signature_type = signature_types[i];
20438       for (int j = 0; j < 2; j++) {
20439         bool global = j == 0;
20440         int key = signature_type +
20441             arraysize(signature_types) * (global ? 1 : 0);
20442         Run(signature_type, global, key);
20443       }
20444     }
20445   }
20446
20447   void Run(SignatureType signature_type, bool global, int key) {
20448     v8::Isolate* isolate = CcTest::isolate();
20449     v8::HandleScope scope(isolate);
20450     // Build a template for signature checks.
20451     Local<v8::ObjectTemplate> signature_template;
20452     Local<v8::Signature> signature;
20453     {
20454       Local<v8::FunctionTemplate> parent_template =
20455         FunctionTemplate::New(isolate);
20456       parent_template->SetHiddenPrototype(true);
20457       Local<v8::FunctionTemplate> function_template
20458           = FunctionTemplate::New(isolate);
20459       function_template->Inherit(parent_template);
20460       switch (signature_type) {
20461         case kNoSignature:
20462           break;
20463         case kSignatureOnReceiver:
20464           signature = v8::Signature::New(isolate, function_template);
20465           break;
20466         case kSignatureOnPrototype:
20467           signature = v8::Signature::New(isolate, parent_template);
20468           break;
20469       }
20470       signature_template = function_template->InstanceTemplate();
20471     }
20472     // Global object must pass checks.
20473     Local<v8::Context> context =
20474         v8::Context::New(isolate, NULL, signature_template);
20475     v8::Context::Scope context_scope(context);
20476     // Install regular object that can pass signature checks.
20477     Local<Object> function_receiver = signature_template->NewInstance();
20478     context->Global()->Set(v8_str("function_receiver"), function_receiver);
20479     // Get the holder objects.
20480     Local<Object> inner_global =
20481         Local<Object>::Cast(context->Global()->GetPrototype());
20482     // Install functions on hidden prototype object if there is one.
20483     data = Object::New(isolate);
20484     Local<FunctionTemplate> function_template = FunctionTemplate::New(
20485         isolate, OptimizationCallback, data, signature);
20486     Local<Function> function = function_template->GetFunction();
20487     Local<Object> global_holder = inner_global;
20488     Local<Object> function_holder = function_receiver;
20489     if (signature_type == kSignatureOnPrototype) {
20490       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
20491       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
20492     }
20493     global_holder->Set(v8_str("g_f"), function);
20494     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
20495     function_holder->Set(v8_str("f"), function);
20496     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
20497     // Initialize expected values.
20498     callee = function;
20499     count = 0;
20500     if (global) {
20501       receiver = context->Global();
20502       holder = inner_global;
20503     } else {
20504       holder = function_receiver;
20505       // If not using a signature, add something else to the prototype chain
20506       // to test the case that holder != receiver
20507       if (signature_type == kNoSignature) {
20508         receiver = Local<Object>::Cast(CompileRun(
20509             "var receiver_subclass = {};\n"
20510             "receiver_subclass.__proto__ = function_receiver;\n"
20511             "receiver_subclass"));
20512       } else {
20513         receiver = Local<Object>::Cast(CompileRun(
20514           "var receiver_subclass = function_receiver;\n"
20515           "receiver_subclass"));
20516       }
20517     }
20518     // With no signature, the holder is not set.
20519     if (signature_type == kNoSignature) holder = receiver;
20520     // build wrap_function
20521     i::ScopedVector<char> wrap_function(200);
20522     if (global) {
20523       i::SNPrintF(
20524           wrap_function,
20525           "function wrap_f_%d() { var f = g_f; return f(); }\n"
20526           "function wrap_get_%d() { return this.g_acc; }\n"
20527           "function wrap_set_%d() { return this.g_acc = 1; }\n",
20528           key, key, key);
20529     } else {
20530       i::SNPrintF(
20531           wrap_function,
20532           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
20533           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
20534           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
20535           key, key, key);
20536     }
20537     // build source string
20538     i::ScopedVector<char> source(1000);
20539     i::SNPrintF(
20540         source,
20541         "%s\n"  // wrap functions
20542         "function wrap_f() { return wrap_f_%d(); }\n"
20543         "function wrap_get() { return wrap_get_%d(); }\n"
20544         "function wrap_set() { return wrap_set_%d(); }\n"
20545         "check = function(returned) {\n"
20546         "  if (returned !== 'returned') { throw returned; }\n"
20547         "}\n"
20548         "\n"
20549         "check(wrap_f());\n"
20550         "check(wrap_f());\n"
20551         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
20552         "check(wrap_f());\n"
20553         "\n"
20554         "check(wrap_get());\n"
20555         "check(wrap_get());\n"
20556         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
20557         "check(wrap_get());\n"
20558         "\n"
20559         "check = function(returned) {\n"
20560         "  if (returned !== 1) { throw returned; }\n"
20561         "}\n"
20562         "check(wrap_set());\n"
20563         "check(wrap_set());\n"
20564         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
20565         "check(wrap_set());\n",
20566         wrap_function.start(), key, key, key, key, key, key);
20567     v8::TryCatch try_catch;
20568     CompileRun(source.start());
20569     DCHECK(!try_catch.HasCaught());
20570     CHECK_EQ(9, count);
20571   }
20572 };
20573
20574
20575 Local<Object> ApiCallOptimizationChecker::data;
20576 Local<Object> ApiCallOptimizationChecker::receiver;
20577 Local<Object> ApiCallOptimizationChecker::holder;
20578 Local<Object> ApiCallOptimizationChecker::callee;
20579 int ApiCallOptimizationChecker::count = 0;
20580
20581
20582 TEST(FunctionCallOptimization) {
20583   i::FLAG_allow_natives_syntax = true;
20584   ApiCallOptimizationChecker checker;
20585   checker.RunAll();
20586 }
20587
20588
20589 TEST(FunctionCallOptimizationMultipleArgs) {
20590   i::FLAG_allow_natives_syntax = true;
20591   LocalContext context;
20592   v8::Isolate* isolate = context->GetIsolate();
20593   v8::HandleScope scope(isolate);
20594   Handle<Object> global = context->Global();
20595   Local<v8::Function> function = Function::New(isolate, Returns42);
20596   global->Set(v8_str("x"), function);
20597   CompileRun(
20598       "function x_wrap() {\n"
20599       "  for (var i = 0; i < 5; i++) {\n"
20600       "    x(1,2,3);\n"
20601       "  }\n"
20602       "}\n"
20603       "x_wrap();\n"
20604       "%OptimizeFunctionOnNextCall(x_wrap);"
20605       "x_wrap();\n");
20606 }
20607
20608
20609 static void ReturnsSymbolCallback(
20610     const v8::FunctionCallbackInfo<v8::Value>& info) {
20611   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
20612 }
20613
20614
20615 TEST(ApiCallbackCanReturnSymbols) {
20616   i::FLAG_allow_natives_syntax = true;
20617   LocalContext context;
20618   v8::Isolate* isolate = context->GetIsolate();
20619   v8::HandleScope scope(isolate);
20620   Handle<Object> global = context->Global();
20621   Local<v8::Function> function = Function::New(isolate, ReturnsSymbolCallback);
20622   global->Set(v8_str("x"), function);
20623   CompileRun(
20624       "function x_wrap() {\n"
20625       "  for (var i = 0; i < 5; i++) {\n"
20626       "    x();\n"
20627       "  }\n"
20628       "}\n"
20629       "x_wrap();\n"
20630       "%OptimizeFunctionOnNextCall(x_wrap);"
20631       "x_wrap();\n");
20632 }
20633
20634
20635 TEST(EmptyApiCallback) {
20636   LocalContext context;
20637   auto isolate = context->GetIsolate();
20638   v8::HandleScope scope(isolate);
20639   auto global = context->Global();
20640   auto function = FunctionTemplate::New(isolate)->GetFunction();
20641   global->Set(v8_str("x"), function);
20642
20643   auto result = CompileRun("x()");
20644   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
20645
20646   result = CompileRun("x(1,2,3)");
20647   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
20648
20649   result = CompileRun("7 + x.call(3) + 11");
20650   CHECK(result->IsInt32());
20651   CHECK_EQ(21, result->Int32Value());
20652
20653   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
20654   CHECK(result->IsInt32());
20655   CHECK_EQ(21, result->Int32Value());
20656
20657   result = CompileRun("var y = []; x.call(y)");
20658   CHECK(result->IsArray());
20659
20660   result = CompileRun("x.call(y, 1, 2, 3, 4)");
20661   CHECK(result->IsArray());
20662 }
20663
20664
20665 TEST(SimpleSignatureCheck) {
20666   LocalContext context;
20667   auto isolate = context->GetIsolate();
20668   v8::HandleScope scope(isolate);
20669   auto global = context->Global();
20670   auto sig_obj = FunctionTemplate::New(isolate);
20671   auto sig = v8::Signature::New(isolate, sig_obj);
20672   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20673   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20674   global->Set(v8_str("x"), x->GetFunction());
20675   CompileRun("var s = new sig_obj();");
20676   {
20677     TryCatch try_catch(isolate);
20678     CompileRun("x()");
20679     CHECK(try_catch.HasCaught());
20680   }
20681   {
20682     TryCatch try_catch(isolate);
20683     CompileRun("x.call(1)");
20684     CHECK(try_catch.HasCaught());
20685   }
20686   {
20687     TryCatch try_catch(isolate);
20688     auto result = CompileRun("s.x = x; s.x()");
20689     CHECK(!try_catch.HasCaught());
20690     CHECK_EQ(42, result->Int32Value());
20691   }
20692   {
20693     TryCatch try_catch(isolate);
20694     auto result = CompileRun("x.call(s)");
20695     CHECK(!try_catch.HasCaught());
20696     CHECK_EQ(42, result->Int32Value());
20697   }
20698 }
20699
20700
20701 TEST(ChainSignatureCheck) {
20702   LocalContext context;
20703   auto isolate = context->GetIsolate();
20704   v8::HandleScope scope(isolate);
20705   auto global = context->Global();
20706   auto sig_obj = FunctionTemplate::New(isolate);
20707   auto sig = v8::Signature::New(isolate, sig_obj);
20708   for (int i = 0; i < 4; ++i) {
20709     auto temp = FunctionTemplate::New(isolate);
20710     temp->Inherit(sig_obj);
20711     sig_obj = temp;
20712   }
20713   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20714   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20715   global->Set(v8_str("x"), x->GetFunction());
20716   CompileRun("var s = new sig_obj();");
20717   {
20718     TryCatch try_catch(isolate);
20719     CompileRun("x()");
20720     CHECK(try_catch.HasCaught());
20721   }
20722   {
20723     TryCatch try_catch(isolate);
20724     CompileRun("x.call(1)");
20725     CHECK(try_catch.HasCaught());
20726   }
20727   {
20728     TryCatch try_catch(isolate);
20729     auto result = CompileRun("s.x = x; s.x()");
20730     CHECK(!try_catch.HasCaught());
20731     CHECK_EQ(42, result->Int32Value());
20732   }
20733   {
20734     TryCatch try_catch(isolate);
20735     auto result = CompileRun("x.call(s)");
20736     CHECK(!try_catch.HasCaught());
20737     CHECK_EQ(42, result->Int32Value());
20738   }
20739 }
20740
20741
20742 TEST(PrototypeSignatureCheck) {
20743   LocalContext context;
20744   auto isolate = context->GetIsolate();
20745   v8::HandleScope scope(isolate);
20746   auto global = context->Global();
20747   auto sig_obj = FunctionTemplate::New(isolate);
20748   sig_obj->SetHiddenPrototype(true);
20749   auto sig = v8::Signature::New(isolate, sig_obj);
20750   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20751   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20752   global->Set(v8_str("x"), x->GetFunction());
20753   CompileRun("s = {}; s.__proto__ = new sig_obj();");
20754   {
20755     TryCatch try_catch(isolate);
20756     CompileRun("x()");
20757     CHECK(try_catch.HasCaught());
20758   }
20759   {
20760     TryCatch try_catch(isolate);
20761     CompileRun("x.call(1)");
20762     CHECK(try_catch.HasCaught());
20763   }
20764   {
20765     TryCatch try_catch(isolate);
20766     auto result = CompileRun("s.x = x; s.x()");
20767     CHECK(!try_catch.HasCaught());
20768     CHECK_EQ(42, result->Int32Value());
20769   }
20770   {
20771     TryCatch try_catch(isolate);
20772     auto result = CompileRun("x.call(s)");
20773     CHECK(!try_catch.HasCaught());
20774     CHECK_EQ(42, result->Int32Value());
20775   }
20776 }
20777
20778
20779 static const char* last_event_message;
20780 static int last_event_status;
20781 void StoringEventLoggerCallback(const char* message, int status) {
20782     last_event_message = message;
20783     last_event_status = status;
20784 }
20785
20786
20787 TEST(EventLogging) {
20788   v8::Isolate* isolate = CcTest::isolate();
20789   isolate->SetEventLogger(StoringEventLoggerCallback);
20790   v8::internal::HistogramTimer histogramTimer(
20791       "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
20792       reinterpret_cast<v8::internal::Isolate*>(isolate));
20793   histogramTimer.Start();
20794   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
20795   CHECK_EQ(0, last_event_status);
20796   histogramTimer.Stop();
20797   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
20798   CHECK_EQ(1, last_event_status);
20799 }
20800
20801
20802 TEST(Promises) {
20803   LocalContext context;
20804   v8::Isolate* isolate = context->GetIsolate();
20805   v8::HandleScope scope(isolate);
20806   Handle<Object> global = context->Global();
20807
20808   // Creation.
20809   Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
20810   Handle<v8::Promise::Resolver> rr = v8::Promise::Resolver::New(isolate);
20811   Handle<v8::Promise> p = pr->GetPromise();
20812   Handle<v8::Promise> r = rr->GetPromise();
20813   CHECK_EQ(isolate, p->GetIsolate());
20814
20815   // IsPromise predicate.
20816   CHECK(p->IsPromise());
20817   CHECK(r->IsPromise());
20818   Handle<Value> o = v8::Object::New(isolate);
20819   CHECK(!o->IsPromise());
20820
20821   // Resolution and rejection.
20822   pr->Resolve(v8::Integer::New(isolate, 1));
20823   CHECK(p->IsPromise());
20824   rr->Reject(v8::Integer::New(isolate, 2));
20825   CHECK(r->IsPromise());
20826
20827   // Chaining non-pending promises.
20828   CompileRun(
20829       "var x1 = 0;\n"
20830       "var x2 = 0;\n"
20831       "function f1(x) { x1 = x; return x+1 };\n"
20832       "function f2(x) { x2 = x; return x+1 };\n");
20833   Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
20834   Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
20835
20836   p->Chain(f1);
20837   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20838   isolate->RunMicrotasks();
20839   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20840
20841   p->Catch(f2);
20842   isolate->RunMicrotasks();
20843   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20844
20845   r->Catch(f2);
20846   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20847   isolate->RunMicrotasks();
20848   CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
20849
20850   r->Chain(f1);
20851   isolate->RunMicrotasks();
20852   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20853
20854   // Chaining pending promises.
20855   CompileRun("x1 = x2 = 0;");
20856   pr = v8::Promise::Resolver::New(isolate);
20857   rr = v8::Promise::Resolver::New(isolate);
20858
20859   pr->GetPromise()->Chain(f1);
20860   rr->GetPromise()->Catch(f2);
20861   isolate->RunMicrotasks();
20862   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20863   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20864
20865   pr->Resolve(v8::Integer::New(isolate, 1));
20866   rr->Reject(v8::Integer::New(isolate, 2));
20867   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20868   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20869
20870   isolate->RunMicrotasks();
20871   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20872   CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
20873
20874   // Multi-chaining.
20875   CompileRun("x1 = x2 = 0;");
20876   pr = v8::Promise::Resolver::New(isolate);
20877   pr->GetPromise()->Chain(f1)->Chain(f2);
20878   pr->Resolve(v8::Integer::New(isolate, 3));
20879   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20880   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20881   isolate->RunMicrotasks();
20882   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20883   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20884
20885   CompileRun("x1 = x2 = 0;");
20886   rr = v8::Promise::Resolver::New(isolate);
20887   rr->GetPromise()->Catch(f1)->Chain(f2);
20888   rr->Reject(v8::Integer::New(isolate, 3));
20889   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20890   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20891   isolate->RunMicrotasks();
20892   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20893   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20894 }
20895
20896
20897 TEST(PromiseThen) {
20898   LocalContext context;
20899   v8::Isolate* isolate = context->GetIsolate();
20900   v8::HandleScope scope(isolate);
20901   Handle<Object> global = context->Global();
20902
20903   // Creation.
20904   Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
20905   Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
20906   Handle<v8::Promise> p = pr->GetPromise();
20907   Handle<v8::Promise> q = qr->GetPromise();
20908
20909   CHECK(p->IsPromise());
20910   CHECK(q->IsPromise());
20911
20912   pr->Resolve(v8::Integer::New(isolate, 1));
20913   qr->Resolve(p);
20914
20915   // Chaining non-pending promises.
20916   CompileRun(
20917       "var x1 = 0;\n"
20918       "var x2 = 0;\n"
20919       "function f1(x) { x1 = x; return x+1 };\n"
20920       "function f2(x) { x2 = x; return x+1 };\n");
20921   Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
20922   Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
20923
20924   // Chain
20925   q->Chain(f1);
20926   CHECK(global->Get(v8_str("x1"))->IsNumber());
20927   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20928   isolate->RunMicrotasks();
20929   CHECK(!global->Get(v8_str("x1"))->IsNumber());
20930   CHECK(p->Equals(global->Get(v8_str("x1"))));
20931
20932   // Then
20933   CompileRun("x1 = x2 = 0;");
20934   q->Then(f1);
20935   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20936   isolate->RunMicrotasks();
20937   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20938
20939   // Then
20940   CompileRun("x1 = x2 = 0;");
20941   pr = v8::Promise::Resolver::New(isolate);
20942   qr = v8::Promise::Resolver::New(isolate);
20943
20944   qr->Resolve(pr);
20945   qr->GetPromise()->Then(f1)->Then(f2);
20946
20947   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20948   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20949   isolate->RunMicrotasks();
20950   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20951   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20952
20953   pr->Resolve(v8::Integer::New(isolate, 3));
20954
20955   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20956   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20957   isolate->RunMicrotasks();
20958   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20959   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20960 }
20961
20962
20963 TEST(DisallowJavascriptExecutionScope) {
20964   LocalContext context;
20965   v8::Isolate* isolate = context->GetIsolate();
20966   v8::HandleScope scope(isolate);
20967   v8::Isolate::DisallowJavascriptExecutionScope no_js(
20968       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
20969   CompileRun("2+2");
20970 }
20971
20972
20973 TEST(AllowJavascriptExecutionScope) {
20974   LocalContext context;
20975   v8::Isolate* isolate = context->GetIsolate();
20976   v8::HandleScope scope(isolate);
20977   v8::Isolate::DisallowJavascriptExecutionScope no_js(
20978       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
20979   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
20980       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
20981   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
20982     CompileRun("1+1");
20983   }
20984 }
20985
20986
20987 TEST(ThrowOnJavascriptExecution) {
20988   LocalContext context;
20989   v8::Isolate* isolate = context->GetIsolate();
20990   v8::HandleScope scope(isolate);
20991   v8::TryCatch try_catch;
20992   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
20993       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
20994   CompileRun("1+1");
20995   CHECK(try_catch.HasCaught());
20996 }
20997
20998
20999 TEST(Regress354123) {
21000   LocalContext current;
21001   v8::Isolate* isolate = current->GetIsolate();
21002   v8::HandleScope scope(isolate);
21003
21004   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
21005   templ->SetAccessCheckCallbacks(NamedAccessCounter, IndexedAccessCounter);
21006   current->Global()->Set(v8_str("friend"), templ->NewInstance());
21007
21008   // Test access using __proto__ from the prototype chain.
21009   named_access_count = 0;
21010   CompileRun("friend.__proto__ = {};");
21011   CHECK_EQ(2, named_access_count);
21012   CompileRun("friend.__proto__;");
21013   CHECK_EQ(4, named_access_count);
21014
21015   // Test access using __proto__ as a hijacked function (A).
21016   named_access_count = 0;
21017   CompileRun("var p = Object.prototype;"
21018              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
21019              "f.call(friend, {});");
21020   CHECK_EQ(1, named_access_count);
21021   CompileRun("var p = Object.prototype;"
21022              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
21023              "f.call(friend);");
21024   CHECK_EQ(2, named_access_count);
21025
21026   // Test access using __proto__ as a hijacked function (B).
21027   named_access_count = 0;
21028   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
21029              "f.call(friend, {});");
21030   CHECK_EQ(1, named_access_count);
21031   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
21032              "f.call(friend);");
21033   CHECK_EQ(2, named_access_count);
21034
21035   // Test access using Object.setPrototypeOf reflective method.
21036   named_access_count = 0;
21037   CompileRun("Object.setPrototypeOf(friend, {});");
21038   CHECK_EQ(1, named_access_count);
21039   CompileRun("Object.getPrototypeOf(friend);");
21040   CHECK_EQ(2, named_access_count);
21041 }
21042
21043
21044 TEST(CaptureStackTraceForStackOverflow) {
21045   v8::internal::FLAG_stack_size = 150;
21046   LocalContext current;
21047   v8::Isolate* isolate = current->GetIsolate();
21048   v8::HandleScope scope(isolate);
21049   V8::SetCaptureStackTraceForUncaughtExceptions(
21050       true, 10, v8::StackTrace::kDetailed);
21051   v8::TryCatch try_catch;
21052   CompileRun("(function f(x) { f(x+1); })(0)");
21053   CHECK(try_catch.HasCaught());
21054 }
21055
21056
21057 TEST(ScriptNameAndLineNumber) {
21058   LocalContext env;
21059   v8::Isolate* isolate = env->GetIsolate();
21060   v8::HandleScope scope(isolate);
21061   const char* url = "http://www.foo.com/foo.js";
21062   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
21063   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
21064   Local<Script> script = v8::ScriptCompiler::Compile(
21065       isolate, &script_source);
21066   Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
21067   CHECK(!script_name.IsEmpty());
21068   CHECK(script_name->IsString());
21069   String::Utf8Value utf8_name(script_name);
21070   CHECK_EQ(0, strcmp(url, *utf8_name));
21071   int line_number = script->GetUnboundScript()->GetLineNumber(0);
21072   CHECK_EQ(13, line_number);
21073 }
21074
21075 void CheckMagicComments(Handle<Script> script, const char* expected_source_url,
21076                         const char* expected_source_mapping_url) {
21077   if (expected_source_url != NULL) {
21078     v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
21079     CHECK_EQ(0, strcmp(expected_source_url, *url));
21080   } else {
21081     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
21082   }
21083   if (expected_source_mapping_url != NULL) {
21084     v8::String::Utf8Value url(
21085         script->GetUnboundScript()->GetSourceMappingURL());
21086     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
21087   } else {
21088     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
21089   }
21090 }
21091
21092 void SourceURLHelper(const char* source, const char* expected_source_url,
21093                      const char* expected_source_mapping_url) {
21094   Local<Script> script = v8_compile(source);
21095   CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
21096 }
21097
21098
21099 TEST(ScriptSourceURLAndSourceMappingURL) {
21100   LocalContext env;
21101   v8::Isolate* isolate = env->GetIsolate();
21102   v8::HandleScope scope(isolate);
21103   SourceURLHelper("function foo() {}\n"
21104                   "//# sourceURL=bar1.js\n", "bar1.js", NULL);
21105   SourceURLHelper("function foo() {}\n"
21106                   "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
21107
21108   // Both sourceURL and sourceMappingURL.
21109   SourceURLHelper("function foo() {}\n"
21110                   "//# sourceURL=bar3.js\n"
21111                   "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
21112
21113   // Two source URLs; the first one is ignored.
21114   SourceURLHelper("function foo() {}\n"
21115                   "//# sourceURL=ignoreme.js\n"
21116                   "//# sourceURL=bar5.js\n", "bar5.js", NULL);
21117   SourceURLHelper("function foo() {}\n"
21118                   "//# sourceMappingURL=ignoreme.js\n"
21119                   "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
21120
21121   // SourceURL or sourceMappingURL in the middle of the script.
21122   SourceURLHelper("function foo() {}\n"
21123                   "//# sourceURL=bar7.js\n"
21124                   "function baz() {}\n", "bar7.js", NULL);
21125   SourceURLHelper("function foo() {}\n"
21126                   "//# sourceMappingURL=bar8.js\n"
21127                   "function baz() {}\n", NULL, "bar8.js");
21128
21129   // Too much whitespace.
21130   SourceURLHelper("function foo() {}\n"
21131                   "//#  sourceURL=bar9.js\n"
21132                   "//#  sourceMappingURL=bar10.js\n", NULL, NULL);
21133   SourceURLHelper("function foo() {}\n"
21134                   "//# sourceURL =bar11.js\n"
21135                   "//# sourceMappingURL =bar12.js\n", NULL, NULL);
21136
21137   // Disallowed characters in value.
21138   SourceURLHelper("function foo() {}\n"
21139                   "//# sourceURL=bar13 .js   \n"
21140                   "//# sourceMappingURL=bar14 .js \n",
21141                   NULL, NULL);
21142   SourceURLHelper("function foo() {}\n"
21143                   "//# sourceURL=bar15\t.js   \n"
21144                   "//# sourceMappingURL=bar16\t.js \n",
21145                   NULL, NULL);
21146   SourceURLHelper("function foo() {}\n"
21147                   "//# sourceURL=bar17'.js   \n"
21148                   "//# sourceMappingURL=bar18'.js \n",
21149                   NULL, NULL);
21150   SourceURLHelper("function foo() {}\n"
21151                   "//# sourceURL=bar19\".js   \n"
21152                   "//# sourceMappingURL=bar20\".js \n",
21153                   NULL, NULL);
21154
21155   // Not too much whitespace.
21156   SourceURLHelper("function foo() {}\n"
21157                   "//# sourceURL=  bar21.js   \n"
21158                   "//# sourceMappingURL=  bar22.js \n", "bar21.js", "bar22.js");
21159 }
21160
21161
21162 TEST(GetOwnPropertyDescriptor) {
21163   LocalContext env;
21164   v8::Isolate* isolate = env->GetIsolate();
21165   v8::HandleScope scope(isolate);
21166   CompileRun(
21167     "var x = { value : 13};"
21168     "Object.defineProperty(x, 'p0', {value : 12});"
21169     "Object.defineProperty(x, 'p1', {"
21170     "  set : function(value) { this.value = value; },"
21171     "  get : function() { return this.value; },"
21172     "});");
21173   Local<Object> x = Local<Object>::Cast(env->Global()->Get(v8_str("x")));
21174   Local<Value> desc = x->GetOwnPropertyDescriptor(v8_str("no_prop"));
21175   CHECK(desc->IsUndefined());
21176   desc = x->GetOwnPropertyDescriptor(v8_str("p0"));
21177   CHECK(v8_num(12)->Equals(Local<Object>::Cast(desc)->Get(v8_str("value"))));
21178   desc = x->GetOwnPropertyDescriptor(v8_str("p1"));
21179   Local<Function> set =
21180     Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("set")));
21181   Local<Function> get =
21182     Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("get")));
21183   CHECK(v8_num(13)->Equals(get->Call(x, 0, NULL)));
21184   Handle<Value> args[] = { v8_num(14) };
21185   set->Call(x, 1, args);
21186   CHECK(v8_num(14)->Equals(get->Call(x, 0, NULL)));
21187 }
21188
21189
21190 TEST(Regress411877) {
21191   v8::Isolate* isolate = CcTest::isolate();
21192   v8::HandleScope handle_scope(isolate);
21193   v8::Handle<v8::ObjectTemplate> object_template =
21194       v8::ObjectTemplate::New(isolate);
21195   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
21196                                            IndexedAccessCounter);
21197
21198   v8::Handle<Context> context = Context::New(isolate);
21199   v8::Context::Scope context_scope(context);
21200
21201   context->Global()->Set(v8_str("o"), object_template->NewInstance());
21202   CompileRun("Object.getOwnPropertyNames(o)");
21203 }
21204
21205
21206 TEST(GetHiddenPropertyTableAfterAccessCheck) {
21207   v8::Isolate* isolate = CcTest::isolate();
21208   v8::HandleScope handle_scope(isolate);
21209   v8::Handle<v8::ObjectTemplate> object_template =
21210       v8::ObjectTemplate::New(isolate);
21211   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
21212                                            IndexedAccessCounter);
21213
21214   v8::Handle<Context> context = Context::New(isolate);
21215   v8::Context::Scope context_scope(context);
21216
21217   v8::Handle<v8::Object> obj = object_template->NewInstance();
21218   obj->Set(v8_str("key"), v8_str("value"));
21219   obj->Delete(v8_str("key"));
21220
21221   obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
21222 }
21223
21224
21225 TEST(Regress411793) {
21226   v8::Isolate* isolate = CcTest::isolate();
21227   v8::HandleScope handle_scope(isolate);
21228   v8::Handle<v8::ObjectTemplate> object_template =
21229       v8::ObjectTemplate::New(isolate);
21230   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
21231                                            IndexedAccessCounter);
21232
21233   v8::Handle<Context> context = Context::New(isolate);
21234   v8::Context::Scope context_scope(context);
21235
21236   context->Global()->Set(v8_str("o"), object_template->NewInstance());
21237   CompileRun(
21238       "Object.defineProperty(o, 'key', "
21239       "    { get: function() {}, set: function() {} });");
21240 }
21241
21242 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
21243  public:
21244   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
21245
21246   virtual size_t GetMoreData(const uint8_t** src) {
21247     // Unlike in real use cases, this function will never block.
21248     if (chunks_[index_] == NULL) {
21249       return 0;
21250     }
21251     // Copy the data, since the caller takes ownership of it.
21252     size_t len = strlen(chunks_[index_]);
21253     // We don't need to zero-terminate since we return the length.
21254     uint8_t* copy = new uint8_t[len];
21255     memcpy(copy, chunks_[index_], len);
21256     *src = copy;
21257     ++index_;
21258     return len;
21259   }
21260
21261   // Helper for constructing a string from chunks (the compilation needs it
21262   // too).
21263   static char* FullSourceString(const char** chunks) {
21264     size_t total_len = 0;
21265     for (size_t i = 0; chunks[i] != NULL; ++i) {
21266       total_len += strlen(chunks[i]);
21267     }
21268     char* full_string = new char[total_len + 1];
21269     size_t offset = 0;
21270     for (size_t i = 0; chunks[i] != NULL; ++i) {
21271       size_t len = strlen(chunks[i]);
21272       memcpy(full_string + offset, chunks[i], len);
21273       offset += len;
21274     }
21275     full_string[total_len] = 0;
21276     return full_string;
21277   }
21278
21279  private:
21280   const char** chunks_;
21281   unsigned index_;
21282 };
21283
21284
21285 // Helper function for running streaming tests.
21286 void RunStreamingTest(const char** chunks,
21287                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
21288                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
21289                       bool expected_success = true,
21290                       const char* expected_source_url = NULL,
21291                       const char* expected_source_mapping_url = NULL) {
21292   LocalContext env;
21293   v8::Isolate* isolate = env->GetIsolate();
21294   v8::HandleScope scope(isolate);
21295   v8::TryCatch try_catch;
21296
21297   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
21298                                             encoding);
21299   v8::ScriptCompiler::ScriptStreamingTask* task =
21300       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
21301
21302   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
21303   // task here in the main thread.
21304   task->Run();
21305   delete task;
21306
21307   // Possible errors are only produced while compiling.
21308   CHECK_EQ(false, try_catch.HasCaught());
21309
21310   v8::ScriptOrigin origin(v8_str("http://foo.com"));
21311   char* full_source = TestSourceStream::FullSourceString(chunks);
21312   v8::Handle<Script> script = v8::ScriptCompiler::Compile(
21313       isolate, &source, v8_str(full_source), origin);
21314   if (expected_success) {
21315     CHECK(!script.IsEmpty());
21316     v8::Handle<Value> result(script->Run());
21317     // All scripts are supposed to return the fixed value 13 when ran.
21318     CHECK_EQ(13, result->Int32Value());
21319     CheckMagicComments(script, expected_source_url,
21320                        expected_source_mapping_url);
21321   } else {
21322     CHECK(script.IsEmpty());
21323     CHECK(try_catch.HasCaught());
21324   }
21325   delete[] full_source;
21326 }
21327
21328
21329 TEST(StreamingSimpleScript) {
21330   // This script is unrealistically small, since no one chunk is enough to fill
21331   // the backing buffer of Scanner, let alone overflow it.
21332   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
21333                           NULL};
21334   RunStreamingTest(chunks);
21335 }
21336
21337
21338 TEST(StreamingBiggerScript) {
21339   const char* chunk1 =
21340       "function foo() {\n"
21341       "  // Make this chunk sufficiently long so that it will overflow the\n"
21342       "  // backing buffer of the Scanner.\n"
21343       "  var i = 0;\n"
21344       "  var result = 0;\n"
21345       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
21346       "  result = 0;\n"
21347       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
21348       "  result = 0;\n"
21349       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
21350       "  result = 0;\n"
21351       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
21352       "  return result;\n"
21353       "}\n";
21354   const char* chunks[] = {chunk1, "foo(); ", NULL};
21355   RunStreamingTest(chunks);
21356 }
21357
21358
21359 TEST(StreamingScriptWithParseError) {
21360   // Test that parse errors from streamed scripts are propagated correctly.
21361   {
21362     char chunk1[] =
21363         "  // This will result in a parse error.\n"
21364         "  var if else then foo";
21365     char chunk2[] = "  13\n";
21366     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21367
21368     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
21369                      false);
21370   }
21371   // Test that the next script succeeds normally.
21372   {
21373     char chunk1[] =
21374         "  // This will be parsed successfully.\n"
21375         "  function foo() { return ";
21376     char chunk2[] = "  13; }\n";
21377     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21378
21379     RunStreamingTest(chunks);
21380   }
21381 }
21382
21383
21384 TEST(StreamingUtf8Script) {
21385   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
21386   // don't like it.
21387   const char* chunk1 =
21388       "function foo() {\n"
21389       "  // This function will contain an UTF-8 character which is not in\n"
21390       "  // ASCII.\n"
21391       "  var foob\xec\x92\x81r = 13;\n"
21392       "  return foob\xec\x92\x81r;\n"
21393       "}\n";
21394   const char* chunks[] = {chunk1, "foo(); ", NULL};
21395   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21396 }
21397
21398
21399 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
21400   // A sanity check to prove that the approach of splitting UTF-8
21401   // characters is correct. Here is an UTF-8 character which will take three
21402   // bytes.
21403   const char* reference = "\xec\x92\x81";
21404   CHECK(3u == strlen(reference));  // NOLINT - no CHECK_EQ for unsigned.
21405
21406   char chunk1[] =
21407       "function foo() {\n"
21408       "  // This function will contain an UTF-8 character which is not in\n"
21409       "  // ASCII.\n"
21410       "  var foob";
21411   char chunk2[] =
21412       "XXXr = 13;\n"
21413       "  return foob\xec\x92\x81r;\n"
21414       "}\n";
21415   for (int i = 0; i < 3; ++i) {
21416     chunk2[i] = reference[i];
21417   }
21418   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21419   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21420 }
21421
21422
21423 TEST(StreamingUtf8ScriptWithSplitCharacters) {
21424   // Stream data where a multi-byte UTF-8 character is split between two data
21425   // chunks.
21426   const char* reference = "\xec\x92\x81";
21427   char chunk1[] =
21428       "function foo() {\n"
21429       "  // This function will contain an UTF-8 character which is not in\n"
21430       "  // ASCII.\n"
21431       "  var foobX";
21432   char chunk2[] =
21433       "XXr = 13;\n"
21434       "  return foob\xec\x92\x81r;\n"
21435       "}\n";
21436   chunk1[strlen(chunk1) - 1] = reference[0];
21437   chunk2[0] = reference[1];
21438   chunk2[1] = reference[2];
21439   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21440   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21441 }
21442
21443
21444 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
21445   // Tests edge cases which should still be decoded correctly.
21446
21447   // Case 1: a chunk contains only bytes for a split character (and no other
21448   // data). This kind of a chunk would be exceptionally small, but we should
21449   // still decode it correctly.
21450   const char* reference = "\xec\x92\x81";
21451   // The small chunk is at the beginning of the split character
21452   {
21453     char chunk1[] =
21454         "function foo() {\n"
21455         "  // This function will contain an UTF-8 character which is not in\n"
21456         "  // ASCII.\n"
21457         "  var foob";
21458     char chunk2[] = "XX";
21459     char chunk3[] =
21460         "Xr = 13;\n"
21461         "  return foob\xec\x92\x81r;\n"
21462         "}\n";
21463     chunk2[0] = reference[0];
21464     chunk2[1] = reference[1];
21465     chunk3[0] = reference[2];
21466     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
21467     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21468   }
21469   // The small chunk is at the end of a character
21470   {
21471     char chunk1[] =
21472         "function foo() {\n"
21473         "  // This function will contain an UTF-8 character which is not in\n"
21474         "  // ASCII.\n"
21475         "  var foobX";
21476     char chunk2[] = "XX";
21477     char chunk3[] =
21478         "r = 13;\n"
21479         "  return foob\xec\x92\x81r;\n"
21480         "}\n";
21481     chunk1[strlen(chunk1) - 1] = reference[0];
21482     chunk2[0] = reference[1];
21483     chunk2[1] = reference[2];
21484     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
21485     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21486   }
21487   // Case 2: the script ends with a multi-byte character. Make sure that it's
21488   // decoded correctly and not just ignored.
21489   {
21490     char chunk1[] =
21491         "var foob\xec\x92\x81 = 13;\n"
21492         "foob\xec\x92\x81";
21493     const char* chunks[] = {chunk1, NULL};
21494     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21495   }
21496 }
21497
21498
21499 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
21500   // Test cases where a UTF-8 character is split over several chunks. Those
21501   // cases are not supported (the embedder should give the data in big enough
21502   // chunks), but we shouldn't crash, just produce a parse error.
21503   const char* reference = "\xec\x92\x81";
21504   char chunk1[] =
21505       "function foo() {\n"
21506       "  // This function will contain an UTF-8 character which is not in\n"
21507       "  // ASCII.\n"
21508       "  var foobX";
21509   char chunk2[] = "X";
21510   char chunk3[] =
21511       "Xr = 13;\n"
21512       "  return foob\xec\x92\x81r;\n"
21513       "}\n";
21514   chunk1[strlen(chunk1) - 1] = reference[0];
21515   chunk2[0] = reference[1];
21516   chunk3[0] = reference[2];
21517   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
21518
21519   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
21520 }
21521
21522
21523 TEST(StreamingProducesParserCache) {
21524   i::FLAG_min_preparse_length = 0;
21525   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
21526                           NULL};
21527
21528   LocalContext env;
21529   v8::Isolate* isolate = env->GetIsolate();
21530   v8::HandleScope scope(isolate);
21531
21532   v8::ScriptCompiler::StreamedSource source(
21533       new TestSourceStream(chunks),
21534       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
21535   v8::ScriptCompiler::ScriptStreamingTask* task =
21536       v8::ScriptCompiler::StartStreamingScript(
21537           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
21538
21539   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
21540   // task here in the main thread.
21541   task->Run();
21542   delete task;
21543
21544   const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
21545   CHECK(cached_data != NULL);
21546   CHECK(cached_data->data != NULL);
21547   CHECK(!cached_data->rejected);
21548   CHECK_GT(cached_data->length, 0);
21549 }
21550
21551
21552 TEST(StreamingWithDebuggingDoesNotProduceParserCache) {
21553   // If the debugger is active, we should just not produce parser cache at
21554   // all. This is a regeression test: We used to produce a parser cache without
21555   // any data in it (just headers).
21556   i::FLAG_min_preparse_length = 0;
21557   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
21558                           NULL};
21559
21560   LocalContext env;
21561   v8::Isolate* isolate = env->GetIsolate();
21562   v8::HandleScope scope(isolate);
21563
21564   // Make the debugger active by setting a breakpoint.
21565   CompileRun("function break_here() { }");
21566   i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(
21567       v8::Utils::OpenHandle(*env->Global()->Get(v8_str("break_here"))));
21568   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
21569   int position = 0;
21570   debug->SetBreakPoint(func, i::Handle<i::Object>(v8::internal::Smi::FromInt(1),
21571                                                   CcTest::i_isolate()),
21572                        &position);
21573
21574   v8::ScriptCompiler::StreamedSource source(
21575       new TestSourceStream(chunks),
21576       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
21577   v8::ScriptCompiler::ScriptStreamingTask* task =
21578       v8::ScriptCompiler::StartStreamingScript(
21579           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
21580
21581   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
21582   // task here in the main thread.
21583   task->Run();
21584   delete task;
21585
21586   // Check that we got no cached data.
21587   CHECK(source.GetCachedData() == NULL);
21588 }
21589
21590
21591 TEST(StreamingScriptWithInvalidUtf8) {
21592   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
21593   // chunk don't produce a crash.
21594   const char* reference = "\xec\x92\x81\x80\x80";
21595   char chunk1[] =
21596       "function foo() {\n"
21597       "  // This function will contain an UTF-8 character which is not in\n"
21598       "  // ASCII.\n"
21599       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
21600   char chunk2[] =
21601       "r = 13;\n"
21602       "  return foob\xec\x92\x81\x80\x80r;\n"
21603       "}\n";
21604   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
21605
21606   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21607   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
21608 }
21609
21610
21611 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
21612   // Regression test: Stream data where there are several multi-byte UTF-8
21613   // characters in a sequence and one of them is split between two data chunks.
21614   const char* reference = "\xec\x92\x81";
21615   char chunk1[] =
21616       "function foo() {\n"
21617       "  // This function will contain an UTF-8 character which is not in\n"
21618       "  // ASCII.\n"
21619       "  var foob\xec\x92\x81X";
21620   char chunk2[] =
21621       "XXr = 13;\n"
21622       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
21623       "}\n";
21624   chunk1[strlen(chunk1) - 1] = reference[0];
21625   chunk2[0] = reference[1];
21626   chunk2[1] = reference[2];
21627   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21628   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21629 }
21630
21631
21632 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
21633   // Another regression test, similar to the previous one. The difference is
21634   // that the split character is not the last one in the sequence.
21635   const char* reference = "\xec\x92\x81";
21636   char chunk1[] =
21637       "function foo() {\n"
21638       "  // This function will contain an UTF-8 character which is not in\n"
21639       "  // ASCII.\n"
21640       "  var foobX";
21641   char chunk2[] =
21642       "XX\xec\x92\x81r = 13;\n"
21643       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
21644       "}\n";
21645   chunk1[strlen(chunk1) - 1] = reference[0];
21646   chunk2[0] = reference[1];
21647   chunk2[1] = reference[2];
21648   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21649   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21650 }
21651
21652
21653 TEST(StreamingWithHarmonyScopes) {
21654   // Don't use RunStreamingTest here so that both scripts get to use the same
21655   // LocalContext and HandleScope.
21656   LocalContext env;
21657   v8::Isolate* isolate = env->GetIsolate();
21658   v8::HandleScope scope(isolate);
21659
21660   // First, run a script with a let variable.
21661   CompileRun("\"use strict\"; let x = 1;");
21662
21663   // Then stream a script which (erroneously) tries to introduce the same
21664   // variable again.
21665   const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
21666
21667   v8::TryCatch try_catch;
21668   v8::ScriptCompiler::StreamedSource source(
21669       new TestSourceStream(chunks),
21670       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
21671   v8::ScriptCompiler::ScriptStreamingTask* task =
21672       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
21673   task->Run();
21674   delete task;
21675
21676   // Parsing should succeed (the script will be parsed and compiled in a context
21677   // independent way, so the error is not detected).
21678   CHECK_EQ(false, try_catch.HasCaught());
21679
21680   v8::ScriptOrigin origin(v8_str("http://foo.com"));
21681   char* full_source = TestSourceStream::FullSourceString(chunks);
21682   v8::Handle<Script> script = v8::ScriptCompiler::Compile(
21683       isolate, &source, v8_str(full_source), origin);
21684   CHECK(!script.IsEmpty());
21685   CHECK_EQ(false, try_catch.HasCaught());
21686
21687   // Running the script exposes the error.
21688   v8::Handle<Value> result(script->Run());
21689   CHECK(result.IsEmpty());
21690   CHECK(try_catch.HasCaught());
21691   delete[] full_source;
21692 }
21693
21694
21695 void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
21696   const char* garbage = "garbage garbage garbage garbage garbage garbage";
21697   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
21698   int length = 16;
21699   v8::ScriptCompiler::CachedData* cached_data =
21700       new v8::ScriptCompiler::CachedData(data, length);
21701   DCHECK(!cached_data->rejected);
21702   v8::ScriptOrigin origin(v8_str("origin"));
21703   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
21704   v8::Handle<v8::Script> script =
21705       v8::ScriptCompiler::Compile(CcTest::isolate(), &source, option);
21706   CHECK(cached_data->rejected);
21707   CHECK_EQ(42, script->Run()->Int32Value());
21708 }
21709
21710
21711 TEST(InvalidCacheData) {
21712   v8::V8::Initialize();
21713   v8::HandleScope scope(CcTest::isolate());
21714   LocalContext context;
21715   TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
21716   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
21717 }
21718
21719
21720 TEST(ParserCacheRejectedGracefully) {
21721   i::FLAG_min_preparse_length = 0;
21722   v8::V8::Initialize();
21723   v8::HandleScope scope(CcTest::isolate());
21724   LocalContext context;
21725   // Produce valid cached data.
21726   v8::ScriptOrigin origin(v8_str("origin"));
21727   v8::Local<v8::String> source_str = v8_str("function foo() {}");
21728   v8::ScriptCompiler::Source source(source_str, origin);
21729   v8::Handle<v8::Script> script = v8::ScriptCompiler::Compile(
21730       CcTest::isolate(), &source, v8::ScriptCompiler::kProduceParserCache);
21731   CHECK(!script.IsEmpty());
21732   const v8::ScriptCompiler::CachedData* original_cached_data =
21733       source.GetCachedData();
21734   CHECK(original_cached_data != NULL);
21735   CHECK(original_cached_data->data != NULL);
21736   CHECK(!original_cached_data->rejected);
21737   CHECK_GT(original_cached_data->length, 0);
21738   // Recompiling the same script with it won't reject the data.
21739   {
21740     v8::ScriptCompiler::Source source_with_cached_data(
21741         source_str, origin,
21742         new v8::ScriptCompiler::CachedData(original_cached_data->data,
21743                                            original_cached_data->length));
21744     v8::Handle<v8::Script> script =
21745         v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
21746                                     v8::ScriptCompiler::kConsumeParserCache);
21747     CHECK(!script.IsEmpty());
21748     const v8::ScriptCompiler::CachedData* new_cached_data =
21749         source_with_cached_data.GetCachedData();
21750     CHECK(new_cached_data != NULL);
21751     CHECK(!new_cached_data->rejected);
21752   }
21753   // Compile an incompatible script with the cached data. The new script doesn't
21754   // have the same starting position for the function as the old one, so the old
21755   // cached data will be incompatible with it and will be rejected.
21756   {
21757     v8::Local<v8::String> incompatible_source_str =
21758         v8_str("   function foo() {}");
21759     v8::ScriptCompiler::Source source_with_cached_data(
21760         incompatible_source_str, origin,
21761         new v8::ScriptCompiler::CachedData(original_cached_data->data,
21762                                            original_cached_data->length));
21763     v8::Handle<v8::Script> script =
21764         v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
21765                                     v8::ScriptCompiler::kConsumeParserCache);
21766     CHECK(!script.IsEmpty());
21767     const v8::ScriptCompiler::CachedData* new_cached_data =
21768         source_with_cached_data.GetCachedData();
21769     CHECK(new_cached_data != NULL);
21770     CHECK(new_cached_data->rejected);
21771   }
21772 }
21773
21774
21775 TEST(StringConcatOverflow) {
21776   v8::V8::Initialize();
21777   v8::HandleScope scope(CcTest::isolate());
21778   RandomLengthOneByteResource* r =
21779       new RandomLengthOneByteResource(i::String::kMaxLength);
21780   v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), r);
21781   CHECK(!str.IsEmpty());
21782   v8::TryCatch try_catch;
21783   v8::Local<v8::String> result = v8::String::Concat(str, str);
21784   CHECK(result.IsEmpty());
21785   CHECK(!try_catch.HasCaught());
21786 }
21787
21788
21789 TEST(TurboAsmDisablesNeuter) {
21790   v8::V8::Initialize();
21791   v8::HandleScope scope(CcTest::isolate());
21792   LocalContext context;
21793 #if V8_TURBOFAN_TARGET
21794   bool should_be_neuterable = !i::FLAG_turbo_asm;
21795 #else
21796   bool should_be_neuterable = true;
21797 #endif
21798   const char* load =
21799       "function Module(stdlib, foreign, heap) {"
21800       "  'use asm';"
21801       "  var MEM32 = new stdlib.Int32Array(heap);"
21802       "  function load() { return MEM32[0]; }"
21803       "  return { load: load };"
21804       "}"
21805       "var buffer = new ArrayBuffer(4);"
21806       "Module(this, {}, buffer).load();"
21807       "buffer";
21808
21809   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
21810   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
21811
21812   const char* store =
21813       "function Module(stdlib, foreign, heap) {"
21814       "  'use asm';"
21815       "  var MEM32 = new stdlib.Int32Array(heap);"
21816       "  function store() { MEM32[0] = 0; }"
21817       "  return { store: store };"
21818       "}"
21819       "var buffer = new ArrayBuffer(4);"
21820       "Module(this, {}, buffer).store();"
21821       "buffer";
21822
21823   result = CompileRun(store).As<v8::ArrayBuffer>();
21824   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
21825 }
21826
21827
21828 TEST(GetPrototypeAccessControl) {
21829   i::FLAG_allow_natives_syntax = true;
21830   v8::Isolate* isolate = CcTest::isolate();
21831   v8::HandleScope handle_scope(isolate);
21832   LocalContext env;
21833
21834   v8::Handle<v8::ObjectTemplate> obj_template =
21835       v8::ObjectTemplate::New(isolate);
21836   obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
21837                                         BlockEverythingIndexed);
21838
21839   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
21840
21841   {
21842     v8::TryCatch try_catch;
21843     CompileRun(
21844         "function f() { %_GetPrototype(prohibited); }"
21845         "%OptimizeFunctionOnNextCall(f);"
21846         "f();");
21847     CHECK(try_catch.HasCaught());
21848   }
21849 }
21850
21851
21852 TEST(GetPrototypeHidden) {
21853   i::FLAG_allow_natives_syntax = true;
21854   v8::Isolate* isolate = CcTest::isolate();
21855   v8::HandleScope handle_scope(isolate);
21856   LocalContext env;
21857
21858   Handle<FunctionTemplate> t = FunctionTemplate::New(isolate);
21859   t->SetHiddenPrototype(true);
21860   Handle<Object> proto = t->GetFunction()->NewInstance();
21861   Handle<Object> object = Object::New(isolate);
21862   Handle<Object> proto2 = Object::New(isolate);
21863   object->SetPrototype(proto);
21864   proto->SetPrototype(proto2);
21865
21866   env->Global()->Set(v8_str("object"), object);
21867   env->Global()->Set(v8_str("proto"), proto);
21868   env->Global()->Set(v8_str("proto2"), proto2);
21869
21870   v8::Handle<v8::Value> result = CompileRun("%_GetPrototype(object)");
21871   CHECK(result->Equals(proto2));
21872
21873   result = CompileRun(
21874       "function f() { return %_GetPrototype(object); }"
21875       "%OptimizeFunctionOnNextCall(f);"
21876       "f()");
21877   CHECK(result->Equals(proto2));
21878 }
21879
21880
21881 TEST(ClassPrototypeCreationContext) {
21882   i::FLAG_harmony_classes = true;
21883   v8::Isolate* isolate = CcTest::isolate();
21884   v8::HandleScope handle_scope(isolate);
21885   LocalContext env;
21886
21887   Handle<Object> result = Handle<Object>::Cast(
21888       CompileRun("'use strict'; class Example { }; Example.prototype"));
21889   CHECK(env.local() == result->CreationContext());
21890 }
21891
21892
21893 TEST(SimpleStreamingScriptWithSourceURL) {
21894   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
21895                           "//# sourceURL=bar2.js\n", NULL};
21896   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
21897                    "bar2.js");
21898 }
21899
21900
21901 TEST(StreamingScriptWithSplitSourceURL) {
21902   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
21903                           "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
21904   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
21905                    "bar2.js");
21906 }
21907
21908
21909 TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
21910   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
21911                           " sourceMappingURL=bar2.js\n", "foo();", NULL};
21912   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
21913                    "bar2.js");
21914 }
21915
21916
21917 TEST(NewStringRangeError) {
21918   v8::Isolate* isolate = CcTest::isolate();
21919   v8::HandleScope handle_scope(isolate);
21920   LocalContext env;
21921   const int length = i::String::kMaxLength + 1;
21922   const int buffer_size = length * sizeof(uint16_t);
21923   void* buffer = malloc(buffer_size);
21924   if (buffer == NULL) return;
21925   memset(buffer, 'A', buffer_size);
21926   {
21927     v8::TryCatch try_catch;
21928     char* data = reinterpret_cast<char*>(buffer);
21929     CHECK(v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString,
21930                                   length).IsEmpty());
21931     CHECK(try_catch.HasCaught());
21932   }
21933   {
21934     v8::TryCatch try_catch;
21935     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
21936     CHECK(v8::String::NewFromOneByte(isolate, data, v8::String::kNormalString,
21937                                      length).IsEmpty());
21938     CHECK(try_catch.HasCaught());
21939   }
21940   {
21941     v8::TryCatch try_catch;
21942     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
21943     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString,
21944                                      length).IsEmpty());
21945     CHECK(try_catch.HasCaught());
21946   }
21947   free(buffer);
21948 }
21949
21950
21951 TEST(SealHandleScope) {
21952   v8::Isolate* isolate = CcTest::isolate();
21953   v8::HandleScope handle_scope(isolate);
21954   LocalContext env;
21955
21956   v8::SealHandleScope seal(isolate);
21957
21958   // Should fail
21959   v8::Local<v8::Object> obj = v8::Object::New(isolate);
21960
21961   USE(obj);
21962 }
21963
21964
21965 TEST(SealHandleScopeNested) {
21966   v8::Isolate* isolate = CcTest::isolate();
21967   v8::HandleScope handle_scope(isolate);
21968   LocalContext env;
21969
21970   v8::SealHandleScope seal(isolate);
21971
21972   {
21973     v8::HandleScope handle_scope(isolate);
21974
21975     // Should work
21976     v8::Local<v8::Object> obj = v8::Object::New(isolate);
21977
21978     USE(obj);
21979   }
21980 }