[runtime] Remove useless IN builtin.
[platform/upstream/v8.git] / 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/base/smart-pointers.h"
44 #include "src/compilation-cache.h"
45 #include "src/debug/debug.h"
46 #include "src/execution.h"
47 #include "src/futex-emulation.h"
48 #include "src/objects.h"
49 #include "src/parser.h"
50 #include "src/unicode-inl.h"
51 #include "src/utils.h"
52 #include "src/vm-state.h"
53
54 static const bool kLogThreading = false;
55
56 using ::v8::Boolean;
57 using ::v8::BooleanObject;
58 using ::v8::Context;
59 using ::v8::Extension;
60 using ::v8::Function;
61 using ::v8::FunctionTemplate;
62 using ::v8::Handle;
63 using ::v8::HandleScope;
64 using ::v8::Local;
65 using ::v8::Maybe;
66 using ::v8::Message;
67 using ::v8::MessageCallback;
68 using ::v8::Name;
69 using ::v8::None;
70 using ::v8::Object;
71 using ::v8::ObjectTemplate;
72 using ::v8::Persistent;
73 using ::v8::PropertyAttribute;
74 using ::v8::Script;
75 using ::v8::StackTrace;
76 using ::v8::String;
77 using ::v8::Symbol;
78 using ::v8::TryCatch;
79 using ::v8::Undefined;
80 using ::v8::UniqueId;
81 using ::v8::V8;
82 using ::v8::Value;
83
84
85 #define THREADED_PROFILED_TEST(Name)                                 \
86   static void Test##Name();                                          \
87   TEST(Name##WithProfiler) {                                         \
88     RunWithProfiler(&Test##Name);                                    \
89   }                                                                  \
90   THREADED_TEST(Name)
91
92
93 void RunWithProfiler(void (*test)()) {
94   LocalContext env;
95   v8::HandleScope scope(env->GetIsolate());
96   v8::Local<v8::String> profile_name =
97       v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
98   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
99
100   cpu_profiler->StartProfiling(profile_name);
101   (*test)();
102   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
103 }
104
105
106 static int signature_callback_count;
107 static Local<Value> signature_expected_receiver;
108 static void IncrementingSignatureCallback(
109     const v8::FunctionCallbackInfo<v8::Value>& args) {
110   ApiTestFuzzer::Fuzz();
111   signature_callback_count++;
112   CHECK(signature_expected_receiver->Equals(args.Holder()));
113   CHECK(signature_expected_receiver->Equals(args.This()));
114   v8::Handle<v8::Array> result =
115       v8::Array::New(args.GetIsolate(), args.Length());
116   for (int i = 0; i < args.Length(); i++)
117     result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
118   args.GetReturnValue().Set(result);
119 }
120
121
122 static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
123   info.GetReturnValue().Set(42);
124 }
125
126
127 // Tests that call v8::V8::Dispose() cannot be threaded.
128 UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
129   CHECK(v8::V8::Initialize());
130   CHECK(v8::V8::Dispose());
131 }
132
133
134 // Tests that call v8::V8::Dispose() cannot be threaded.
135 UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
136   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
137   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
138   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
139   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
140   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
141 }
142
143
144 THREADED_TEST(Handles) {
145   v8::HandleScope scope(CcTest::isolate());
146   Local<Context> local_env;
147   {
148     LocalContext env;
149     local_env = env.local();
150   }
151
152   // Local context should still be live.
153   CHECK(!local_env.IsEmpty());
154   local_env->Enter();
155
156   v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
157   CHECK(!undef.IsEmpty());
158   CHECK(undef->IsUndefined());
159
160   const char* source = "1 + 2 + 3";
161   Local<Script> script = v8_compile(source);
162   CHECK_EQ(6, script->Run()->Int32Value());
163
164   local_env->Exit();
165 }
166
167
168 THREADED_TEST(IsolateOfContext) {
169   v8::HandleScope scope(CcTest::isolate());
170   v8::Handle<Context> env = Context::New(CcTest::isolate());
171
172   CHECK(!env->GetIsolate()->InContext());
173   CHECK(env->GetIsolate() == CcTest::isolate());
174   env->Enter();
175   CHECK(env->GetIsolate()->InContext());
176   CHECK(env->GetIsolate() == CcTest::isolate());
177   env->Exit();
178   CHECK(!env->GetIsolate()->InContext());
179   CHECK(env->GetIsolate() == CcTest::isolate());
180 }
181
182
183 static void TestSignature(const char* loop_js, Local<Value> receiver,
184                           v8::Isolate* isolate) {
185   i::ScopedVector<char> source(200);
186   i::SNPrintF(source,
187               "for (var i = 0; i < 10; i++) {"
188               "  %s"
189               "}",
190               loop_js);
191   signature_callback_count = 0;
192   signature_expected_receiver = receiver;
193   bool expected_to_throw = receiver.IsEmpty();
194   v8::TryCatch try_catch(isolate);
195   CompileRun(source.start());
196   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
197   if (!expected_to_throw) {
198     CHECK_EQ(10, signature_callback_count);
199   } else {
200     CHECK(v8_str("TypeError: Illegal invocation")
201               ->Equals(try_catch.Exception()->ToString(isolate)));
202   }
203 }
204
205
206 THREADED_TEST(ReceiverSignature) {
207   LocalContext env;
208   v8::Isolate* isolate = env->GetIsolate();
209   v8::HandleScope scope(isolate);
210   // Setup templates.
211   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
212   v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
213   v8::Handle<v8::FunctionTemplate> callback_sig =
214       v8::FunctionTemplate::New(
215           isolate, IncrementingSignatureCallback, Local<Value>(), sig);
216   v8::Handle<v8::FunctionTemplate> callback =
217       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
218   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
219   sub_fun->Inherit(fun);
220   v8::Handle<v8::FunctionTemplate> unrel_fun =
221       v8::FunctionTemplate::New(isolate);
222   // Install properties.
223   v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
224   fun_proto->Set(v8_str("prop_sig"), callback_sig);
225   fun_proto->Set(v8_str("prop"), callback);
226   fun_proto->SetAccessorProperty(
227       v8_str("accessor_sig"), callback_sig, callback_sig);
228   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
229   // Instantiate templates.
230   Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
231   Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
232   // Setup global variables.
233   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
234   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
235   env->Global()->Set(v8_str("fun_instance"), fun_instance);
236   env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
237   CompileRun(
238       "var accessor_sig_key = 'accessor_sig';"
239       "var accessor_key = 'accessor';"
240       "var prop_sig_key = 'prop_sig';"
241       "var prop_key = 'prop';"
242       ""
243       "function copy_props(obj) {"
244       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
245       "  var source = Fun.prototype;"
246       "  for (var i in keys) {"
247       "    var key = keys[i];"
248       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
249       "    Object.defineProperty(obj, key, desc);"
250       "  }"
251       "}"
252       ""
253       "var obj = {};"
254       "copy_props(obj);"
255       "var unrel = new UnrelFun();"
256       "copy_props(unrel);");
257   // Test with and without ICs
258   const char* test_objects[] = {
259       "fun_instance", "sub_fun_instance", "obj", "unrel" };
260   unsigned bad_signature_start_offset = 2;
261   for (unsigned i = 0; i < arraysize(test_objects); i++) {
262     i::ScopedVector<char> source(200);
263     i::SNPrintF(
264         source, "var test_object = %s; test_object", test_objects[i]);
265     Local<Value> test_object = CompileRun(source.start());
266     TestSignature("test_object.prop();", test_object, isolate);
267     TestSignature("test_object.accessor;", test_object, isolate);
268     TestSignature("test_object[accessor_key];", test_object, isolate);
269     TestSignature("test_object.accessor = 1;", test_object, isolate);
270     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
271     if (i >= bad_signature_start_offset) test_object = Local<Value>();
272     TestSignature("test_object.prop_sig();", test_object, isolate);
273     TestSignature("test_object.accessor_sig;", test_object, isolate);
274     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
275     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
276     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
277   }
278 }
279
280
281 THREADED_TEST(HulIgennem) {
282   LocalContext env;
283   v8::Isolate* isolate = env->GetIsolate();
284   v8::HandleScope scope(isolate);
285   v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
286   Local<String> undef_str = undef->ToString(isolate);
287   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
288   undef_str->WriteUtf8(value);
289   CHECK_EQ(0, strcmp(value, "undefined"));
290   i::DeleteArray(value);
291 }
292
293
294 THREADED_TEST(Access) {
295   LocalContext env;
296   v8::Isolate* isolate = env->GetIsolate();
297   v8::HandleScope scope(isolate);
298   Local<v8::Object> obj = v8::Object::New(isolate);
299   Local<Value> foo_before = obj->Get(v8_str("foo"));
300   CHECK(foo_before->IsUndefined());
301   Local<String> bar_str = v8_str("bar");
302   obj->Set(v8_str("foo"), bar_str);
303   Local<Value> foo_after = obj->Get(v8_str("foo"));
304   CHECK(!foo_after->IsUndefined());
305   CHECK(foo_after->IsString());
306   CHECK(bar_str->Equals(foo_after));
307 }
308
309
310 THREADED_TEST(AccessElement) {
311   LocalContext env;
312   v8::HandleScope scope(env->GetIsolate());
313   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
314   Local<Value> before = obj->Get(1);
315   CHECK(before->IsUndefined());
316   Local<String> bar_str = v8_str("bar");
317   obj->Set(1, bar_str);
318   Local<Value> after = obj->Get(1);
319   CHECK(!after->IsUndefined());
320   CHECK(after->IsString());
321   CHECK(bar_str->Equals(after));
322
323   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
324   CHECK(v8_str("a")->Equals(value->Get(0)));
325   CHECK(v8_str("b")->Equals(value->Get(1)));
326 }
327
328
329 THREADED_TEST(Script) {
330   LocalContext env;
331   v8::HandleScope scope(env->GetIsolate());
332   const char* source = "1 + 2 + 3";
333   Local<Script> script = v8_compile(source);
334   CHECK_EQ(6, script->Run()->Int32Value());
335 }
336
337
338 class TestResource: public String::ExternalStringResource {
339  public:
340   explicit TestResource(uint16_t* data, int* counter = NULL,
341                         bool owning_data = true)
342       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
343     while (data[length_]) ++length_;
344   }
345
346   ~TestResource() {
347     if (owning_data_) i::DeleteArray(data_);
348     if (counter_ != NULL) ++*counter_;
349   }
350
351   const uint16_t* data() const {
352     return data_;
353   }
354
355   size_t length() const {
356     return length_;
357   }
358
359  private:
360   uint16_t* data_;
361   size_t length_;
362   int* counter_;
363   bool owning_data_;
364 };
365
366
367 class TestOneByteResource : public String::ExternalOneByteStringResource {
368  public:
369   explicit TestOneByteResource(const char* data, int* counter = NULL,
370                                size_t offset = 0)
371       : orig_data_(data),
372         data_(data + offset),
373         length_(strlen(data) - offset),
374         counter_(counter) {}
375
376   ~TestOneByteResource() {
377     i::DeleteArray(orig_data_);
378     if (counter_ != NULL) ++*counter_;
379   }
380
381   const char* data() const {
382     return data_;
383   }
384
385   size_t length() const {
386     return length_;
387   }
388
389  private:
390   const char* orig_data_;
391   const char* data_;
392   size_t length_;
393   int* counter_;
394 };
395
396
397 THREADED_TEST(ScriptUsingStringResource) {
398   int dispose_count = 0;
399   const char* c_source = "1 + 2 * 3";
400   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
401   {
402     LocalContext env;
403     v8::HandleScope scope(env->GetIsolate());
404     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
405     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
406     Local<Script> script = v8_compile(source);
407     Local<Value> value = script->Run();
408     CHECK(value->IsNumber());
409     CHECK_EQ(7, value->Int32Value());
410     CHECK(source->IsExternal());
411     CHECK_EQ(resource,
412              static_cast<TestResource*>(source->GetExternalStringResource()));
413     String::Encoding encoding = String::UNKNOWN_ENCODING;
414     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
415              source->GetExternalStringResourceBase(&encoding));
416     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
417     CcTest::heap()->CollectAllGarbage();
418     CHECK_EQ(0, dispose_count);
419   }
420   CcTest::i_isolate()->compilation_cache()->Clear();
421   CcTest::heap()->CollectAllAvailableGarbage();
422   CHECK_EQ(1, dispose_count);
423 }
424
425
426 THREADED_TEST(ScriptUsingOneByteStringResource) {
427   int dispose_count = 0;
428   const char* c_source = "1 + 2 * 3";
429   {
430     LocalContext env;
431     v8::HandleScope scope(env->GetIsolate());
432     TestOneByteResource* resource =
433         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
434     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
435     CHECK(source->IsExternalOneByte());
436     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
437              source->GetExternalOneByteStringResource());
438     String::Encoding encoding = String::UNKNOWN_ENCODING;
439     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
440              source->GetExternalStringResourceBase(&encoding));
441     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
442     Local<Script> script = v8_compile(source);
443     Local<Value> value = script->Run();
444     CHECK(value->IsNumber());
445     CHECK_EQ(7, value->Int32Value());
446     CcTest::heap()->CollectAllGarbage();
447     CHECK_EQ(0, dispose_count);
448   }
449   CcTest::i_isolate()->compilation_cache()->Clear();
450   CcTest::heap()->CollectAllAvailableGarbage();
451   CHECK_EQ(1, dispose_count);
452 }
453
454
455 THREADED_TEST(ScriptMakingExternalString) {
456   int dispose_count = 0;
457   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
458   {
459     LocalContext env;
460     v8::HandleScope scope(env->GetIsolate());
461     Local<String> source =
462         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
463     // Trigger GCs so that the newly allocated string moves to old gen.
464     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
465     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
466     CHECK_EQ(source->IsExternal(), false);
467     CHECK_EQ(source->IsExternalOneByte(), false);
468     String::Encoding encoding = String::UNKNOWN_ENCODING;
469     CHECK(!source->GetExternalStringResourceBase(&encoding));
470     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
471     bool success = source->MakeExternal(new TestResource(two_byte_source,
472                                                          &dispose_count));
473     CHECK(success);
474     Local<Script> script = v8_compile(source);
475     Local<Value> value = script->Run();
476     CHECK(value->IsNumber());
477     CHECK_EQ(7, value->Int32Value());
478     CcTest::heap()->CollectAllGarbage();
479     CHECK_EQ(0, dispose_count);
480   }
481   CcTest::i_isolate()->compilation_cache()->Clear();
482   CcTest::heap()->CollectAllGarbage();
483   CHECK_EQ(1, dispose_count);
484 }
485
486
487 THREADED_TEST(ScriptMakingExternalOneByteString) {
488   int dispose_count = 0;
489   const char* c_source = "1 + 2 * 3";
490   {
491     LocalContext env;
492     v8::HandleScope scope(env->GetIsolate());
493     Local<String> source = v8_str(c_source);
494     // Trigger GCs so that the newly allocated string moves to old gen.
495     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
496     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
497     bool success = source->MakeExternal(
498         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
499     CHECK(success);
500     Local<Script> script = v8_compile(source);
501     Local<Value> value = script->Run();
502     CHECK(value->IsNumber());
503     CHECK_EQ(7, value->Int32Value());
504     CcTest::heap()->CollectAllGarbage();
505     CHECK_EQ(0, dispose_count);
506   }
507   CcTest::i_isolate()->compilation_cache()->Clear();
508   CcTest::heap()->CollectAllGarbage();
509   CHECK_EQ(1, dispose_count);
510 }
511
512
513 TEST(MakingExternalStringConditions) {
514   LocalContext env;
515   v8::HandleScope scope(env->GetIsolate());
516
517   // Free some space in the new space so that we can check freshness.
518   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
519   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
520
521   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
522   Local<String> small_string =
523       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
524   i::DeleteArray(two_byte_string);
525
526   // We should refuse to externalize small strings.
527   CHECK(!small_string->CanMakeExternal());
528   // Trigger GCs so that the newly allocated string moves to old gen.
529   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
530   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
531   // Old space strings should be accepted.
532   CHECK(small_string->CanMakeExternal());
533
534   two_byte_string = AsciiToTwoByteString("small string 2");
535   small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
536   i::DeleteArray(two_byte_string);
537
538   const int buf_size = 10 * 1024;
539   char* buf = i::NewArray<char>(buf_size);
540   memset(buf, 'a', buf_size);
541   buf[buf_size - 1] = '\0';
542
543   two_byte_string = AsciiToTwoByteString(buf);
544   Local<String> large_string =
545       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
546   i::DeleteArray(buf);
547   i::DeleteArray(two_byte_string);
548   // Large strings should be immediately accepted.
549   CHECK(large_string->CanMakeExternal());
550 }
551
552
553 TEST(MakingExternalOneByteStringConditions) {
554   LocalContext env;
555   v8::HandleScope scope(env->GetIsolate());
556
557   // Free some space in the new space so that we can check freshness.
558   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
559   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
560
561   Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
562   // We should refuse to externalize small strings.
563   CHECK(!small_string->CanMakeExternal());
564   // Trigger GCs so that the newly allocated string moves to old gen.
565   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
566   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
567   // Old space strings should be accepted.
568   CHECK(small_string->CanMakeExternal());
569
570   const int buf_size = 10 * 1024;
571   char* buf = i::NewArray<char>(buf_size);
572   memset(buf, 'a', buf_size);
573   buf[buf_size - 1] = '\0';
574   Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
575   i::DeleteArray(buf);
576   // Large strings should be immediately accepted.
577   CHECK(large_string->CanMakeExternal());
578 }
579
580
581 TEST(MakingExternalUnalignedOneByteString) {
582   LocalContext env;
583   v8::HandleScope scope(env->GetIsolate());
584
585   CompileRun("function cons(a, b) { return a + b; }"
586              "function slice(a) { return a.substring(1); }");
587   // Create a cons string that will land in old pointer space.
588   Local<String> cons = Local<String>::Cast(CompileRun(
589       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
590   // Create a sliced string that will land in old pointer space.
591   Local<String> slice = Local<String>::Cast(CompileRun(
592       "slice('abcdefghijklmnopqrstuvwxyz');"));
593
594   // Trigger GCs so that the newly allocated string moves to old gen.
595   SimulateFullSpace(CcTest::heap()->old_space());
596   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
597   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
598
599   // Turn into external string with unaligned resource data.
600   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
601   bool success =
602       cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
603   CHECK(success);
604   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
605   success =
606       slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
607   CHECK(success);
608
609   // Trigger GCs and force evacuation.
610   CcTest::heap()->CollectAllGarbage();
611   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
612 }
613
614
615 THREADED_TEST(UsingExternalString) {
616   i::Factory* factory = CcTest::i_isolate()->factory();
617   {
618     v8::HandleScope scope(CcTest::isolate());
619     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
620     Local<String> string = String::NewExternal(
621         CcTest::isolate(), new TestResource(two_byte_string));
622     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
623     // Trigger GCs so that the newly allocated string moves to old gen.
624     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
625     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
626     i::Handle<i::String> isymbol =
627         factory->InternalizeString(istring);
628     CHECK(isymbol->IsInternalizedString());
629   }
630   CcTest::heap()->CollectAllGarbage();
631   CcTest::heap()->CollectAllGarbage();
632 }
633
634
635 THREADED_TEST(UsingExternalOneByteString) {
636   i::Factory* factory = CcTest::i_isolate()->factory();
637   {
638     v8::HandleScope scope(CcTest::isolate());
639     const char* one_byte_string = "test string";
640     Local<String> string = String::NewExternal(
641         CcTest::isolate(), new TestOneByteResource(i::StrDup(one_byte_string)));
642     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
643     // Trigger GCs so that the newly allocated string moves to old gen.
644     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
645     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
646     i::Handle<i::String> isymbol =
647         factory->InternalizeString(istring);
648     CHECK(isymbol->IsInternalizedString());
649   }
650   CcTest::heap()->CollectAllGarbage();
651   CcTest::heap()->CollectAllGarbage();
652 }
653
654
655 class RandomLengthResource : public v8::String::ExternalStringResource {
656  public:
657   explicit RandomLengthResource(int length) : length_(length) {}
658   virtual const uint16_t* data() const { return string_; }
659   virtual size_t length() const { return length_; }
660
661  private:
662   uint16_t string_[10];
663   int length_;
664 };
665
666
667 class RandomLengthOneByteResource
668     : public v8::String::ExternalOneByteStringResource {
669  public:
670   explicit RandomLengthOneByteResource(int length) : length_(length) {}
671   virtual const char* data() const { return string_; }
672   virtual size_t length() const { return length_; }
673
674  private:
675   char string_[10];
676   int length_;
677 };
678
679
680 THREADED_TEST(NewExternalForVeryLongString) {
681   auto isolate = CcTest::isolate();
682   {
683     v8::HandleScope scope(isolate);
684     v8::TryCatch try_catch(isolate);
685     RandomLengthOneByteResource r(1 << 30);
686     v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
687     CHECK(str.IsEmpty());
688     CHECK(!try_catch.HasCaught());
689   }
690
691   {
692     v8::HandleScope scope(isolate);
693     v8::TryCatch try_catch(isolate);
694     RandomLengthResource r(1 << 30);
695     v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
696     CHECK(str.IsEmpty());
697     CHECK(!try_catch.HasCaught());
698   }
699 }
700
701
702 THREADED_TEST(ScavengeExternalString) {
703   i::FLAG_stress_compaction = false;
704   i::FLAG_gc_global = false;
705   int dispose_count = 0;
706   bool in_new_space = false;
707   {
708     v8::HandleScope scope(CcTest::isolate());
709     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
710     Local<String> string = String::NewExternal(
711         CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
712     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
713     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
714     in_new_space = CcTest::heap()->InNewSpace(*istring);
715     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
716     CHECK_EQ(0, dispose_count);
717   }
718   CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
719   CHECK_EQ(1, dispose_count);
720 }
721
722
723 THREADED_TEST(ScavengeExternalOneByteString) {
724   i::FLAG_stress_compaction = false;
725   i::FLAG_gc_global = false;
726   int dispose_count = 0;
727   bool in_new_space = false;
728   {
729     v8::HandleScope scope(CcTest::isolate());
730     const char* one_byte_string = "test string";
731     Local<String> string = String::NewExternal(
732         CcTest::isolate(),
733         new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count));
734     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
735     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
736     in_new_space = CcTest::heap()->InNewSpace(*istring);
737     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
738     CHECK_EQ(0, dispose_count);
739   }
740   CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
741   CHECK_EQ(1, dispose_count);
742 }
743
744
745 class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
746  public:
747   // Only used by non-threaded tests, so it can use static fields.
748   static int dispose_calls;
749   static int dispose_count;
750
751   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
752       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
753
754   void Dispose() {
755     ++dispose_calls;
756     if (dispose_) delete this;
757   }
758  private:
759   bool dispose_;
760 };
761
762
763 int TestOneByteResourceWithDisposeControl::dispose_count = 0;
764 int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
765
766
767 TEST(ExternalStringWithDisposeHandling) {
768   const char* c_source = "1 + 2 * 3";
769
770   // Use a stack allocated external string resource allocated object.
771   TestOneByteResourceWithDisposeControl::dispose_count = 0;
772   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
773   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
774   {
775     LocalContext env;
776     v8::HandleScope scope(env->GetIsolate());
777     Local<String> source =  String::NewExternal(env->GetIsolate(), &res_stack);
778     Local<Script> script = v8_compile(source);
779     Local<Value> value = script->Run();
780     CHECK(value->IsNumber());
781     CHECK_EQ(7, value->Int32Value());
782     CcTest::heap()->CollectAllAvailableGarbage();
783     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
784   }
785   CcTest::i_isolate()->compilation_cache()->Clear();
786   CcTest::heap()->CollectAllAvailableGarbage();
787   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
788   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
789
790   // Use a heap allocated external string resource allocated object.
791   TestOneByteResourceWithDisposeControl::dispose_count = 0;
792   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
793   TestOneByteResource* res_heap =
794       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
795   {
796     LocalContext env;
797     v8::HandleScope scope(env->GetIsolate());
798     Local<String> source =  String::NewExternal(env->GetIsolate(), res_heap);
799     Local<Script> script = v8_compile(source);
800     Local<Value> value = script->Run();
801     CHECK(value->IsNumber());
802     CHECK_EQ(7, value->Int32Value());
803     CcTest::heap()->CollectAllAvailableGarbage();
804     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
805   }
806   CcTest::i_isolate()->compilation_cache()->Clear();
807   CcTest::heap()->CollectAllAvailableGarbage();
808   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
809   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
810 }
811
812
813 THREADED_TEST(StringConcat) {
814   {
815     LocalContext env;
816     v8::HandleScope scope(env->GetIsolate());
817     const char* one_byte_string_1 = "function a_times_t";
818     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
819     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
820     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
821     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
822     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
823     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
824     Local<String> left = v8_str(one_byte_string_1);
825
826     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
827     Local<String> right =
828         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
829     i::DeleteArray(two_byte_source);
830
831     Local<String> source = String::Concat(left, right);
832     right = String::NewExternal(
833         env->GetIsolate(),
834         new TestOneByteResource(i::StrDup(one_byte_extern_1)));
835     source = String::Concat(source, right);
836     right = String::NewExternal(
837         env->GetIsolate(),
838         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
839     source = String::Concat(source, right);
840     right = v8_str(one_byte_string_2);
841     source = String::Concat(source, right);
842
843     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
844     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
845     i::DeleteArray(two_byte_source);
846
847     source = String::Concat(source, right);
848     right = String::NewExternal(
849         env->GetIsolate(),
850         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
851     source = String::Concat(source, right);
852     Local<Script> script = v8_compile(source);
853     Local<Value> value = script->Run();
854     CHECK(value->IsNumber());
855     CHECK_EQ(68, value->Int32Value());
856   }
857   CcTest::i_isolate()->compilation_cache()->Clear();
858   CcTest::heap()->CollectAllGarbage();
859   CcTest::heap()->CollectAllGarbage();
860 }
861
862
863 THREADED_TEST(GlobalProperties) {
864   LocalContext env;
865   v8::HandleScope scope(env->GetIsolate());
866   v8::Handle<v8::Object> global = env->Global();
867   global->Set(v8_str("pi"), v8_num(3.1415926));
868   Local<Value> pi = global->Get(v8_str("pi"));
869   CHECK_EQ(3.1415926, pi->NumberValue());
870 }
871
872
873 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
874                                  i::Address callback) {
875   ApiTestFuzzer::Fuzz();
876   CheckReturnValue(info, callback);
877   info.GetReturnValue().Set(v8_str("bad value"));
878   info.GetReturnValue().Set(v8_num(102));
879 }
880
881
882 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
883   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
884 }
885
886
887 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
888   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
889 }
890
891 static void construct_callback(
892     const v8::FunctionCallbackInfo<Value>& info) {
893   ApiTestFuzzer::Fuzz();
894   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
895   info.This()->Set(v8_str("x"), v8_num(1));
896   info.This()->Set(v8_str("y"), v8_num(2));
897   info.GetReturnValue().Set(v8_str("bad value"));
898   info.GetReturnValue().Set(info.This());
899 }
900
901
902 static void Return239Callback(
903     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
904   ApiTestFuzzer::Fuzz();
905   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
906   info.GetReturnValue().Set(v8_str("bad value"));
907   info.GetReturnValue().Set(v8_num(239));
908 }
909
910
911 template<typename Handler>
912 static void TestFunctionTemplateInitializer(Handler handler,
913                                             Handler handler_2) {
914   // Test constructor calls.
915   {
916     LocalContext env;
917     v8::Isolate* isolate = env->GetIsolate();
918     v8::HandleScope scope(isolate);
919
920     Local<v8::FunctionTemplate> fun_templ =
921         v8::FunctionTemplate::New(isolate, handler);
922     Local<Function> fun = fun_templ->GetFunction();
923     env->Global()->Set(v8_str("obj"), fun);
924     Local<Script> script = v8_compile("obj()");
925     for (int i = 0; i < 30; i++) {
926       CHECK_EQ(102, script->Run()->Int32Value());
927     }
928   }
929   // Use SetCallHandler to initialize a function template, should work like
930   // the previous one.
931   {
932     LocalContext env;
933     v8::Isolate* isolate = env->GetIsolate();
934     v8::HandleScope scope(isolate);
935
936     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
937     fun_templ->SetCallHandler(handler_2);
938     Local<Function> fun = fun_templ->GetFunction();
939     env->Global()->Set(v8_str("obj"), fun);
940     Local<Script> script = v8_compile("obj()");
941     for (int i = 0; i < 30; i++) {
942       CHECK_EQ(102, script->Run()->Int32Value());
943     }
944   }
945 }
946
947
948 template<typename Constructor, typename Accessor>
949 static void TestFunctionTemplateAccessor(Constructor constructor,
950                                          Accessor accessor) {
951   LocalContext env;
952   v8::HandleScope scope(env->GetIsolate());
953
954   Local<v8::FunctionTemplate> fun_templ =
955       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
956   fun_templ->SetClassName(v8_str("funky"));
957   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
958   Local<Function> fun = fun_templ->GetFunction();
959   env->Global()->Set(v8_str("obj"), fun);
960   Local<Value> result = v8_compile("(new obj()).toString()")->Run();
961   CHECK(v8_str("[object funky]")->Equals(result));
962   CompileRun("var obj_instance = new obj();");
963   Local<Script> script;
964   script = v8_compile("obj_instance.x");
965   for (int i = 0; i < 30; i++) {
966     CHECK_EQ(1, script->Run()->Int32Value());
967   }
968   script = v8_compile("obj_instance.m");
969   for (int i = 0; i < 30; i++) {
970     CHECK_EQ(239, script->Run()->Int32Value());
971   }
972 }
973
974
975 THREADED_PROFILED_TEST(FunctionTemplate) {
976   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
977   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
978 }
979
980
981 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
982   ApiTestFuzzer::Fuzz();
983   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
984   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
985 }
986
987
988 template<typename Callback>
989 static void TestSimpleCallback(Callback callback) {
990   LocalContext env;
991   v8::Isolate* isolate = env->GetIsolate();
992   v8::HandleScope scope(isolate);
993
994   v8::Handle<v8::ObjectTemplate> object_template =
995       v8::ObjectTemplate::New(isolate);
996   object_template->Set(isolate, "callback",
997                        v8::FunctionTemplate::New(isolate, callback));
998   v8::Local<v8::Object> object = object_template->NewInstance();
999   (*env)->Global()->Set(v8_str("callback_object"), object);
1000   v8::Handle<v8::Script> script;
1001   script = v8_compile("callback_object.callback(17)");
1002   for (int i = 0; i < 30; i++) {
1003     CHECK_EQ(51424, script->Run()->Int32Value());
1004   }
1005   script = v8_compile("callback_object.callback(17, 24)");
1006   for (int i = 0; i < 30; i++) {
1007     CHECK_EQ(51425, script->Run()->Int32Value());
1008   }
1009 }
1010
1011
1012 THREADED_PROFILED_TEST(SimpleCallback) {
1013   TestSimpleCallback(SimpleCallback);
1014 }
1015
1016
1017 template<typename T>
1018 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1019
1020 // constant return values
1021 static int32_t fast_return_value_int32 = 471;
1022 static uint32_t fast_return_value_uint32 = 571;
1023 static const double kFastReturnValueDouble = 2.7;
1024 // variable return values
1025 static bool fast_return_value_bool = false;
1026 enum ReturnValueOddball {
1027   kNullReturnValue,
1028   kUndefinedReturnValue,
1029   kEmptyStringReturnValue
1030 };
1031 static ReturnValueOddball fast_return_value_void;
1032 static bool fast_return_value_object_is_empty = false;
1033
1034 // Helper function to avoid compiler error: insufficient contextual information
1035 // to determine type when applying FUNCTION_ADDR to a template function.
1036 static i::Address address_of(v8::FunctionCallback callback) {
1037   return FUNCTION_ADDR(callback);
1038 }
1039
1040 template<>
1041 void FastReturnValueCallback<int32_t>(
1042     const v8::FunctionCallbackInfo<v8::Value>& info) {
1043   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1044   info.GetReturnValue().Set(fast_return_value_int32);
1045 }
1046
1047 template<>
1048 void FastReturnValueCallback<uint32_t>(
1049     const v8::FunctionCallbackInfo<v8::Value>& info) {
1050   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1051   info.GetReturnValue().Set(fast_return_value_uint32);
1052 }
1053
1054 template<>
1055 void FastReturnValueCallback<double>(
1056     const v8::FunctionCallbackInfo<v8::Value>& info) {
1057   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1058   info.GetReturnValue().Set(kFastReturnValueDouble);
1059 }
1060
1061 template<>
1062 void FastReturnValueCallback<bool>(
1063     const v8::FunctionCallbackInfo<v8::Value>& info) {
1064   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1065   info.GetReturnValue().Set(fast_return_value_bool);
1066 }
1067
1068 template<>
1069 void FastReturnValueCallback<void>(
1070     const v8::FunctionCallbackInfo<v8::Value>& info) {
1071   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1072   switch (fast_return_value_void) {
1073     case kNullReturnValue:
1074       info.GetReturnValue().SetNull();
1075       break;
1076     case kUndefinedReturnValue:
1077       info.GetReturnValue().SetUndefined();
1078       break;
1079     case kEmptyStringReturnValue:
1080       info.GetReturnValue().SetEmptyString();
1081       break;
1082   }
1083 }
1084
1085 template<>
1086 void FastReturnValueCallback<Object>(
1087     const v8::FunctionCallbackInfo<v8::Value>& info) {
1088   v8::Handle<v8::Object> object;
1089   if (!fast_return_value_object_is_empty) {
1090     object = Object::New(info.GetIsolate());
1091   }
1092   info.GetReturnValue().Set(object);
1093 }
1094
1095 template<typename T>
1096 Handle<Value> TestFastReturnValues() {
1097   LocalContext env;
1098   v8::Isolate* isolate = env->GetIsolate();
1099   v8::EscapableHandleScope scope(isolate);
1100   v8::Handle<v8::ObjectTemplate> object_template =
1101       v8::ObjectTemplate::New(isolate);
1102   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1103   object_template->Set(isolate, "callback",
1104                        v8::FunctionTemplate::New(isolate, callback));
1105   v8::Local<v8::Object> object = object_template->NewInstance();
1106   (*env)->Global()->Set(v8_str("callback_object"), object);
1107   return scope.Escape(CompileRun("callback_object.callback()"));
1108 }
1109
1110
1111 THREADED_PROFILED_TEST(FastReturnValues) {
1112   LocalContext env;
1113   v8::Isolate* isolate = env->GetIsolate();
1114   v8::HandleScope scope(isolate);
1115   v8::Handle<v8::Value> value;
1116   // check int32_t and uint32_t
1117   int32_t int_values[] = {
1118       0, 234, -723,
1119       i::Smi::kMinValue, i::Smi::kMaxValue
1120   };
1121   for (size_t i = 0; i < arraysize(int_values); i++) {
1122     for (int modifier = -1; modifier <= 1; modifier++) {
1123       int int_value = int_values[i] + modifier;
1124       // check int32_t
1125       fast_return_value_int32 = int_value;
1126       value = TestFastReturnValues<int32_t>();
1127       CHECK(value->IsInt32());
1128       CHECK(fast_return_value_int32 == value->Int32Value());
1129       // check uint32_t
1130       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1131       value = TestFastReturnValues<uint32_t>();
1132       CHECK(value->IsUint32());
1133       CHECK(fast_return_value_uint32 == value->Uint32Value());
1134     }
1135   }
1136   // check double
1137   value = TestFastReturnValues<double>();
1138   CHECK(value->IsNumber());
1139   CHECK_EQ(kFastReturnValueDouble, value->ToNumber(isolate)->Value());
1140   // check bool values
1141   for (int i = 0; i < 2; i++) {
1142     fast_return_value_bool = i == 0;
1143     value = TestFastReturnValues<bool>();
1144     CHECK(value->IsBoolean());
1145     CHECK_EQ(fast_return_value_bool, value->ToBoolean(isolate)->Value());
1146   }
1147   // check oddballs
1148   ReturnValueOddball oddballs[] = {
1149       kNullReturnValue,
1150       kUndefinedReturnValue,
1151       kEmptyStringReturnValue
1152   };
1153   for (size_t i = 0; i < arraysize(oddballs); i++) {
1154     fast_return_value_void = oddballs[i];
1155     value = TestFastReturnValues<void>();
1156     switch (fast_return_value_void) {
1157       case kNullReturnValue:
1158         CHECK(value->IsNull());
1159         break;
1160       case kUndefinedReturnValue:
1161         CHECK(value->IsUndefined());
1162         break;
1163       case kEmptyStringReturnValue:
1164         CHECK(value->IsString());
1165         CHECK_EQ(0, v8::String::Cast(*value)->Length());
1166         break;
1167     }
1168   }
1169   // check handles
1170   fast_return_value_object_is_empty = false;
1171   value = TestFastReturnValues<Object>();
1172   CHECK(value->IsObject());
1173   fast_return_value_object_is_empty = true;
1174   value = TestFastReturnValues<Object>();
1175   CHECK(value->IsUndefined());
1176 }
1177
1178
1179 THREADED_TEST(FunctionTemplateSetLength) {
1180   LocalContext env;
1181   v8::Isolate* isolate = env->GetIsolate();
1182   v8::HandleScope scope(isolate);
1183   {
1184     Local<v8::FunctionTemplate> fun_templ =
1185         v8::FunctionTemplate::New(isolate,
1186                                   handle_callback,
1187                                   Handle<v8::Value>(),
1188                                   Handle<v8::Signature>(),
1189                                   23);
1190     Local<Function> fun = fun_templ->GetFunction();
1191     env->Global()->Set(v8_str("obj"), fun);
1192     Local<Script> script = v8_compile("obj.length");
1193     CHECK_EQ(23, script->Run()->Int32Value());
1194   }
1195   {
1196     Local<v8::FunctionTemplate> fun_templ =
1197         v8::FunctionTemplate::New(isolate, handle_callback);
1198     fun_templ->SetLength(22);
1199     Local<Function> fun = fun_templ->GetFunction();
1200     env->Global()->Set(v8_str("obj"), fun);
1201     Local<Script> script = v8_compile("obj.length");
1202     CHECK_EQ(22, script->Run()->Int32Value());
1203   }
1204   {
1205     // Without setting length it defaults to 0.
1206     Local<v8::FunctionTemplate> fun_templ =
1207         v8::FunctionTemplate::New(isolate, handle_callback);
1208     Local<Function> fun = fun_templ->GetFunction();
1209     env->Global()->Set(v8_str("obj"), fun);
1210     Local<Script> script = v8_compile("obj.length");
1211     CHECK_EQ(0, script->Run()->Int32Value());
1212   }
1213 }
1214
1215
1216 static void* expected_ptr;
1217 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1218   void* ptr = v8::External::Cast(*args.Data())->Value();
1219   CHECK_EQ(expected_ptr, ptr);
1220   args.GetReturnValue().Set(true);
1221 }
1222
1223
1224 static void TestExternalPointerWrapping() {
1225   LocalContext env;
1226   v8::Isolate* isolate = env->GetIsolate();
1227   v8::HandleScope scope(isolate);
1228
1229   v8::Handle<v8::Value> data =
1230       v8::External::New(isolate, expected_ptr);
1231
1232   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
1233   obj->Set(v8_str("func"),
1234            v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
1235   env->Global()->Set(v8_str("obj"), obj);
1236
1237   CHECK(CompileRun(
1238         "function foo() {\n"
1239         "  for (var i = 0; i < 13; i++) obj.func();\n"
1240         "}\n"
1241         "foo(), true")->BooleanValue());
1242 }
1243
1244
1245 THREADED_TEST(ExternalWrap) {
1246   // Check heap allocated object.
1247   int* ptr = new int;
1248   expected_ptr = ptr;
1249   TestExternalPointerWrapping();
1250   delete ptr;
1251
1252   // Check stack allocated object.
1253   int foo;
1254   expected_ptr = &foo;
1255   TestExternalPointerWrapping();
1256
1257   // Check not aligned addresses.
1258   const int n = 100;
1259   char* s = new char[n];
1260   for (int i = 0; i < n; i++) {
1261     expected_ptr = s + i;
1262     TestExternalPointerWrapping();
1263   }
1264
1265   delete[] s;
1266
1267   // Check several invalid addresses.
1268   expected_ptr = reinterpret_cast<void*>(1);
1269   TestExternalPointerWrapping();
1270
1271   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1272   TestExternalPointerWrapping();
1273
1274   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1275   TestExternalPointerWrapping();
1276
1277 #if defined(V8_HOST_ARCH_X64)
1278   // Check a value with a leading 1 bit in x64 Smi encoding.
1279   expected_ptr = reinterpret_cast<void*>(0x400000000);
1280   TestExternalPointerWrapping();
1281
1282   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1283   TestExternalPointerWrapping();
1284
1285   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1286   TestExternalPointerWrapping();
1287 #endif
1288 }
1289
1290
1291 THREADED_TEST(FindInstanceInPrototypeChain) {
1292   LocalContext env;
1293   v8::Isolate* isolate = env->GetIsolate();
1294   v8::HandleScope scope(isolate);
1295
1296   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1297   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1298   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
1299   derived->Inherit(base);
1300
1301   Local<v8::Function> base_function = base->GetFunction();
1302   Local<v8::Function> derived_function = derived->GetFunction();
1303   Local<v8::Function> other_function = other->GetFunction();
1304
1305   Local<v8::Object> base_instance = base_function->NewInstance();
1306   Local<v8::Object> derived_instance = derived_function->NewInstance();
1307   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1308   Local<v8::Object> other_instance = other_function->NewInstance();
1309   derived_instance2->Set(v8_str("__proto__"), derived_instance);
1310   other_instance->Set(v8_str("__proto__"), derived_instance2);
1311
1312   // base_instance is only an instance of base.
1313   CHECK(
1314       base_instance->Equals(base_instance->FindInstanceInPrototypeChain(base)));
1315   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1316   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1317
1318   // derived_instance is an instance of base and derived.
1319   CHECK(derived_instance->Equals(
1320       derived_instance->FindInstanceInPrototypeChain(base)));
1321   CHECK(derived_instance->Equals(
1322       derived_instance->FindInstanceInPrototypeChain(derived)));
1323   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1324
1325   // other_instance is an instance of other and its immediate
1326   // prototype derived_instance2 is an instance of base and derived.
1327   // Note, derived_instance is an instance of base and derived too,
1328   // but it comes after derived_instance2 in the prototype chain of
1329   // other_instance.
1330   CHECK(derived_instance2->Equals(
1331       other_instance->FindInstanceInPrototypeChain(base)));
1332   CHECK(derived_instance2->Equals(
1333       other_instance->FindInstanceInPrototypeChain(derived)));
1334   CHECK(other_instance->Equals(
1335       other_instance->FindInstanceInPrototypeChain(other)));
1336 }
1337
1338
1339 THREADED_TEST(TinyInteger) {
1340   LocalContext env;
1341   v8::Isolate* isolate = env->GetIsolate();
1342   v8::HandleScope scope(isolate);
1343
1344   int32_t value = 239;
1345   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1346   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1347
1348   value_obj = v8::Integer::New(isolate, value);
1349   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1350 }
1351
1352
1353 THREADED_TEST(BigSmiInteger) {
1354   LocalContext env;
1355   v8::HandleScope scope(env->GetIsolate());
1356   v8::Isolate* isolate = CcTest::isolate();
1357
1358   int32_t value = i::Smi::kMaxValue;
1359   // We cannot add one to a Smi::kMaxValue without wrapping.
1360   if (i::SmiValuesAre31Bits()) {
1361     CHECK(i::Smi::IsValid(value));
1362     CHECK(!i::Smi::IsValid(value + 1));
1363
1364     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1365     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1366
1367     value_obj = v8::Integer::New(isolate, value);
1368     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1369   }
1370 }
1371
1372
1373 THREADED_TEST(BigInteger) {
1374   LocalContext env;
1375   v8::HandleScope scope(env->GetIsolate());
1376   v8::Isolate* isolate = CcTest::isolate();
1377
1378   // We cannot add one to a Smi::kMaxValue without wrapping.
1379   if (i::SmiValuesAre31Bits()) {
1380     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1381     // The code will not be run in that case, due to the "if" guard.
1382     int32_t value =
1383         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1384     CHECK(value > i::Smi::kMaxValue);
1385     CHECK(!i::Smi::IsValid(value));
1386
1387     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1388     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1389
1390     value_obj = v8::Integer::New(isolate, value);
1391     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1392   }
1393 }
1394
1395
1396 THREADED_TEST(TinyUnsignedInteger) {
1397   LocalContext env;
1398   v8::HandleScope scope(env->GetIsolate());
1399   v8::Isolate* isolate = CcTest::isolate();
1400
1401   uint32_t value = 239;
1402
1403   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1404   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1405
1406   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1407   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1408 }
1409
1410
1411 THREADED_TEST(BigUnsignedSmiInteger) {
1412   LocalContext env;
1413   v8::HandleScope scope(env->GetIsolate());
1414   v8::Isolate* isolate = CcTest::isolate();
1415
1416   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1417   CHECK(i::Smi::IsValid(value));
1418   CHECK(!i::Smi::IsValid(value + 1));
1419
1420   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1421   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1422
1423   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1424   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1425 }
1426
1427
1428 THREADED_TEST(BigUnsignedInteger) {
1429   LocalContext env;
1430   v8::HandleScope scope(env->GetIsolate());
1431   v8::Isolate* isolate = CcTest::isolate();
1432
1433   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1434   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1435   CHECK(!i::Smi::IsValid(value));
1436
1437   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1438   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1439
1440   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1441   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1442 }
1443
1444
1445 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
1446   LocalContext env;
1447   v8::HandleScope scope(env->GetIsolate());
1448   v8::Isolate* isolate = CcTest::isolate();
1449
1450   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1451   uint32_t value = INT32_MAX_AS_UINT + 1;
1452   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
1453
1454   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1455   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1456
1457   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1458   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1459 }
1460
1461
1462 THREADED_TEST(IsNativeError) {
1463   LocalContext env;
1464   v8::HandleScope scope(env->GetIsolate());
1465   v8::Handle<Value> syntax_error = CompileRun(
1466       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1467   CHECK(syntax_error->IsNativeError());
1468   v8::Handle<Value> not_error = CompileRun("{a:42}");
1469   CHECK(!not_error->IsNativeError());
1470   v8::Handle<Value> not_object = CompileRun("42");
1471   CHECK(!not_object->IsNativeError());
1472 }
1473
1474
1475 THREADED_TEST(IsGeneratorFunctionOrObject) {
1476   LocalContext env;
1477   v8::HandleScope scope(env->GetIsolate());
1478
1479   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
1480   v8::Handle<Value> gen = CompileRun("gen");
1481   v8::Handle<Value> genObj = CompileRun("gen()");
1482   v8::Handle<Value> object = CompileRun("{a:42}");
1483   v8::Handle<Value> func = CompileRun("func");
1484
1485   CHECK(gen->IsGeneratorFunction());
1486   CHECK(gen->IsFunction());
1487   CHECK(!gen->IsGeneratorObject());
1488
1489   CHECK(!genObj->IsGeneratorFunction());
1490   CHECK(!genObj->IsFunction());
1491   CHECK(genObj->IsGeneratorObject());
1492
1493   CHECK(!object->IsGeneratorFunction());
1494   CHECK(!object->IsFunction());
1495   CHECK(!object->IsGeneratorObject());
1496
1497   CHECK(!func->IsGeneratorFunction());
1498   CHECK(func->IsFunction());
1499   CHECK(!func->IsGeneratorObject());
1500 }
1501
1502
1503 THREADED_TEST(ArgumentsObject) {
1504   LocalContext env;
1505   v8::HandleScope scope(env->GetIsolate());
1506   v8::Handle<Value> arguments_object =
1507       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
1508   CHECK(arguments_object->IsArgumentsObject());
1509   v8::Handle<Value> array = CompileRun("[1,2,3]");
1510   CHECK(!array->IsArgumentsObject());
1511   v8::Handle<Value> object = CompileRun("{a:42}");
1512   CHECK(!object->IsArgumentsObject());
1513 }
1514
1515
1516 THREADED_TEST(IsMapOrSet) {
1517   LocalContext env;
1518   v8::HandleScope scope(env->GetIsolate());
1519   v8::Handle<Value> map = CompileRun("new Map()");
1520   v8::Handle<Value> set = CompileRun("new Set()");
1521   v8::Handle<Value> weak_map = CompileRun("new WeakMap()");
1522   v8::Handle<Value> weak_set = CompileRun("new WeakSet()");
1523   CHECK(map->IsMap());
1524   CHECK(set->IsSet());
1525   CHECK(weak_map->IsWeakMap());
1526   CHECK(weak_set->IsWeakSet());
1527
1528   CHECK(!map->IsSet());
1529   CHECK(!map->IsWeakMap());
1530   CHECK(!map->IsWeakSet());
1531
1532   CHECK(!set->IsMap());
1533   CHECK(!set->IsWeakMap());
1534   CHECK(!set->IsWeakSet());
1535
1536   CHECK(!weak_map->IsMap());
1537   CHECK(!weak_map->IsSet());
1538   CHECK(!weak_map->IsWeakSet());
1539
1540   CHECK(!weak_set->IsMap());
1541   CHECK(!weak_set->IsSet());
1542   CHECK(!weak_set->IsWeakMap());
1543
1544   v8::Handle<Value> object = CompileRun("{a:42}");
1545   CHECK(!object->IsMap());
1546   CHECK(!object->IsSet());
1547   CHECK(!object->IsWeakMap());
1548   CHECK(!object->IsWeakSet());
1549 }
1550
1551
1552 THREADED_TEST(StringObject) {
1553   LocalContext env;
1554   v8::HandleScope scope(env->GetIsolate());
1555   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1556   CHECK(boxed_string->IsStringObject());
1557   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1558   CHECK(!unboxed_string->IsStringObject());
1559   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1560   CHECK(!boxed_not_string->IsStringObject());
1561   v8::Handle<Value> not_object = CompileRun("0");
1562   CHECK(!not_object->IsStringObject());
1563   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1564   CHECK(!as_boxed.IsEmpty());
1565   Local<v8::String> the_string = as_boxed->ValueOf();
1566   CHECK(!the_string.IsEmpty());
1567   ExpectObject("\"test\"", the_string);
1568   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1569   CHECK(new_boxed_string->IsStringObject());
1570   as_boxed = new_boxed_string.As<v8::StringObject>();
1571   the_string = as_boxed->ValueOf();
1572   CHECK(!the_string.IsEmpty());
1573   ExpectObject("\"test\"", the_string);
1574 }
1575
1576
1577 TEST(StringObjectDelete) {
1578   LocalContext context;
1579   v8::HandleScope scope(context->GetIsolate());
1580   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1581   CHECK(boxed_string->IsStringObject());
1582   v8::Handle<v8::Object> str_obj = boxed_string.As<v8::Object>();
1583   CHECK(!str_obj->Delete(2));
1584   CHECK(!str_obj->Delete(v8_num(2)));
1585 }
1586
1587
1588 THREADED_TEST(NumberObject) {
1589   LocalContext env;
1590   v8::HandleScope scope(env->GetIsolate());
1591   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1592   CHECK(boxed_number->IsNumberObject());
1593   v8::Handle<Value> unboxed_number = CompileRun("42");
1594   CHECK(!unboxed_number->IsNumberObject());
1595   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1596   CHECK(!boxed_not_number->IsNumberObject());
1597   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1598   CHECK(!as_boxed.IsEmpty());
1599   double the_number = as_boxed->ValueOf();
1600   CHECK_EQ(42.0, the_number);
1601   v8::Handle<v8::Value> new_boxed_number =
1602       v8::NumberObject::New(env->GetIsolate(), 43);
1603   CHECK(new_boxed_number->IsNumberObject());
1604   as_boxed = new_boxed_number.As<v8::NumberObject>();
1605   the_number = as_boxed->ValueOf();
1606   CHECK_EQ(43.0, the_number);
1607 }
1608
1609
1610 THREADED_TEST(BooleanObject) {
1611   LocalContext env;
1612   v8::HandleScope scope(env->GetIsolate());
1613   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1614   CHECK(boxed_boolean->IsBooleanObject());
1615   v8::Handle<Value> unboxed_boolean = CompileRun("true");
1616   CHECK(!unboxed_boolean->IsBooleanObject());
1617   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1618   CHECK(!boxed_not_boolean->IsBooleanObject());
1619   v8::Handle<v8::BooleanObject> as_boxed =
1620       boxed_boolean.As<v8::BooleanObject>();
1621   CHECK(!as_boxed.IsEmpty());
1622   bool the_boolean = as_boxed->ValueOf();
1623   CHECK_EQ(true, the_boolean);
1624   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1625   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1626   CHECK(boxed_true->IsBooleanObject());
1627   CHECK(boxed_false->IsBooleanObject());
1628   as_boxed = boxed_true.As<v8::BooleanObject>();
1629   CHECK_EQ(true, as_boxed->ValueOf());
1630   as_boxed = boxed_false.As<v8::BooleanObject>();
1631   CHECK_EQ(false, as_boxed->ValueOf());
1632 }
1633
1634
1635 THREADED_TEST(PrimitiveAndWrappedBooleans) {
1636   LocalContext env;
1637   v8::HandleScope scope(env->GetIsolate());
1638
1639   Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1640   CHECK(primitive_false->IsBoolean());
1641   CHECK(!primitive_false->IsBooleanObject());
1642   CHECK(!primitive_false->BooleanValue());
1643   CHECK(!primitive_false->IsTrue());
1644   CHECK(primitive_false->IsFalse());
1645
1646   Local<Value> false_value = BooleanObject::New(false);
1647   CHECK(!false_value->IsBoolean());
1648   CHECK(false_value->IsBooleanObject());
1649   CHECK(false_value->BooleanValue());
1650   CHECK(!false_value->IsTrue());
1651   CHECK(!false_value->IsFalse());
1652
1653   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1654   CHECK(!false_boolean_object->IsBoolean());
1655   CHECK(false_boolean_object->IsBooleanObject());
1656   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1657   // CHECK(false_boolean_object->BooleanValue());
1658   CHECK(!false_boolean_object->ValueOf());
1659   CHECK(!false_boolean_object->IsTrue());
1660   CHECK(!false_boolean_object->IsFalse());
1661
1662   Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1663   CHECK(primitive_true->IsBoolean());
1664   CHECK(!primitive_true->IsBooleanObject());
1665   CHECK(primitive_true->BooleanValue());
1666   CHECK(primitive_true->IsTrue());
1667   CHECK(!primitive_true->IsFalse());
1668
1669   Local<Value> true_value = BooleanObject::New(true);
1670   CHECK(!true_value->IsBoolean());
1671   CHECK(true_value->IsBooleanObject());
1672   CHECK(true_value->BooleanValue());
1673   CHECK(!true_value->IsTrue());
1674   CHECK(!true_value->IsFalse());
1675
1676   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1677   CHECK(!true_boolean_object->IsBoolean());
1678   CHECK(true_boolean_object->IsBooleanObject());
1679   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1680   // CHECK(true_boolean_object->BooleanValue());
1681   CHECK(true_boolean_object->ValueOf());
1682   CHECK(!true_boolean_object->IsTrue());
1683   CHECK(!true_boolean_object->IsFalse());
1684 }
1685
1686
1687 THREADED_TEST(Number) {
1688   LocalContext env;
1689   v8::HandleScope scope(env->GetIsolate());
1690   double PI = 3.1415926;
1691   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
1692   CHECK_EQ(PI, pi_obj->NumberValue());
1693 }
1694
1695
1696 THREADED_TEST(ToNumber) {
1697   LocalContext env;
1698   v8::Isolate* isolate = CcTest::isolate();
1699   v8::HandleScope scope(isolate);
1700   Local<String> str = v8_str("3.1415926");
1701   CHECK_EQ(3.1415926, str->NumberValue());
1702   v8::Handle<v8::Boolean> t = v8::True(isolate);
1703   CHECK_EQ(1.0, t->NumberValue());
1704   v8::Handle<v8::Boolean> f = v8::False(isolate);
1705   CHECK_EQ(0.0, f->NumberValue());
1706 }
1707
1708
1709 THREADED_TEST(Date) {
1710   LocalContext env;
1711   v8::HandleScope scope(env->GetIsolate());
1712   double PI = 3.1415926;
1713   Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
1714   CHECK_EQ(3.0, date->NumberValue());
1715   date.As<v8::Date>()->Set(v8_str("property"),
1716                            v8::Integer::New(env->GetIsolate(), 42));
1717   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
1718 }
1719
1720
1721 THREADED_TEST(Boolean) {
1722   LocalContext env;
1723   v8::Isolate* isolate = env->GetIsolate();
1724   v8::HandleScope scope(isolate);
1725   v8::Handle<v8::Boolean> t = v8::True(isolate);
1726   CHECK(t->Value());
1727   v8::Handle<v8::Boolean> f = v8::False(isolate);
1728   CHECK(!f->Value());
1729   v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
1730   CHECK(!u->BooleanValue());
1731   v8::Handle<v8::Primitive> n = v8::Null(isolate);
1732   CHECK(!n->BooleanValue());
1733   v8::Handle<String> str1 = v8_str("");
1734   CHECK(!str1->BooleanValue());
1735   v8::Handle<String> str2 = v8_str("x");
1736   CHECK(str2->BooleanValue());
1737   CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1738   CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1739   CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1740   CHECK(v8::Number::New(isolate, 42)->BooleanValue());
1741   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1742 }
1743
1744
1745 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
1746   ApiTestFuzzer::Fuzz();
1747   args.GetReturnValue().Set(v8_num(13.4));
1748 }
1749
1750
1751 static void GetM(Local<String> name,
1752                  const v8::PropertyCallbackInfo<v8::Value>& info) {
1753   ApiTestFuzzer::Fuzz();
1754   info.GetReturnValue().Set(v8_num(876));
1755 }
1756
1757
1758 THREADED_TEST(GlobalPrototype) {
1759   v8::Isolate* isolate = CcTest::isolate();
1760   v8::HandleScope scope(isolate);
1761   v8::Handle<v8::FunctionTemplate> func_templ =
1762       v8::FunctionTemplate::New(isolate);
1763   func_templ->PrototypeTemplate()->Set(
1764       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
1765   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1766   templ->Set(isolate, "x", v8_num(200));
1767   templ->SetAccessor(v8_str("m"), GetM);
1768   LocalContext env(0, templ);
1769   v8::Handle<Script> script(v8_compile("dummy()"));
1770   v8::Handle<Value> result(script->Run());
1771   CHECK_EQ(13.4, result->NumberValue());
1772   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1773   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1774 }
1775
1776
1777 THREADED_TEST(ObjectTemplate) {
1778   v8::Isolate* isolate = CcTest::isolate();
1779   v8::HandleScope scope(isolate);
1780   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1781   v8::Local<v8::String> class_name =
1782       v8::String::NewFromUtf8(isolate, "the_class_name");
1783   fun->SetClassName(class_name);
1784   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
1785   templ1->Set(isolate, "x", v8_num(10));
1786   templ1->Set(isolate, "y", v8_num(13));
1787   LocalContext env;
1788   Local<v8::Object> instance1 = templ1->NewInstance();
1789   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
1790   env->Global()->Set(v8_str("p"), instance1);
1791   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1792   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1793   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
1794   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1795   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
1796   templ2->Set(isolate, "a", v8_num(12));
1797   templ2->Set(isolate, "b", templ1);
1798   Local<v8::Object> instance2 = templ2->NewInstance();
1799   env->Global()->Set(v8_str("q"), instance2);
1800   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1801   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1802   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1803   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1804 }
1805
1806
1807 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
1808   ApiTestFuzzer::Fuzz();
1809   args.GetReturnValue().Set(v8_num(17.2));
1810 }
1811
1812
1813 static void GetKnurd(Local<String> property,
1814                      const v8::PropertyCallbackInfo<v8::Value>& info) {
1815   ApiTestFuzzer::Fuzz();
1816   info.GetReturnValue().Set(v8_num(15.2));
1817 }
1818
1819
1820 THREADED_TEST(DescriptorInheritance) {
1821   v8::Isolate* isolate = CcTest::isolate();
1822   v8::HandleScope scope(isolate);
1823   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1824   super->PrototypeTemplate()->Set(isolate, "flabby",
1825                                   v8::FunctionTemplate::New(isolate,
1826                                                             GetFlabby));
1827   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
1828
1829   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1830
1831   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
1832   base1->Inherit(super);
1833   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
1834
1835   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
1836   base2->Inherit(super);
1837   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
1838
1839   LocalContext env;
1840
1841   env->Global()->Set(v8_str("s"), super->GetFunction());
1842   env->Global()->Set(v8_str("base1"), base1->GetFunction());
1843   env->Global()->Set(v8_str("base2"), base2->GetFunction());
1844
1845   // Checks right __proto__ chain.
1846   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1847   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1848
1849   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1850
1851   // Instance accessor should not be visible on function object or its prototype
1852   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1853   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1854   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1855
1856   env->Global()->Set(v8_str("obj"),
1857                      base1->GetFunction()->NewInstance());
1858   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1859   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1860   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1861   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1862   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1863
1864   env->Global()->Set(v8_str("obj2"),
1865                      base2->GetFunction()->NewInstance());
1866   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1867   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1868   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1869   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1870   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1871
1872   // base1 and base2 cannot cross reference to each's prototype
1873   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1874   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1875 }
1876
1877
1878 // Helper functions for Interceptor/Accessor interaction tests
1879
1880 void SimpleAccessorGetter(Local<String> name,
1881                           const v8::PropertyCallbackInfo<v8::Value>& info) {
1882   Handle<Object> self = Handle<Object>::Cast(info.This());
1883   info.GetReturnValue().Set(
1884       self->Get(String::Concat(v8_str("accessor_"), name)));
1885 }
1886
1887 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1888                           const v8::PropertyCallbackInfo<void>& info) {
1889   Handle<Object> self = Handle<Object>::Cast(info.This());
1890   self->Set(String::Concat(v8_str("accessor_"), name), value);
1891 }
1892
1893 void SymbolAccessorGetter(Local<Name> name,
1894                           const v8::PropertyCallbackInfo<v8::Value>& info) {
1895   CHECK(name->IsSymbol());
1896   Local<Symbol> sym = Local<Symbol>::Cast(name);
1897   if (sym->Name()->IsUndefined())
1898     return;
1899   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
1900 }
1901
1902 void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
1903                           const v8::PropertyCallbackInfo<void>& info) {
1904   CHECK(name->IsSymbol());
1905   Local<Symbol> sym = Local<Symbol>::Cast(name);
1906   if (sym->Name()->IsUndefined())
1907     return;
1908   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
1909 }
1910
1911 void SymbolAccessorGetterReturnsDefault(
1912     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1913   CHECK(name->IsSymbol());
1914   Local<Symbol> sym = Local<Symbol>::Cast(name);
1915   if (sym->Name()->IsUndefined()) return;
1916   info.GetReturnValue().Set(info.Data());
1917 }
1918
1919 static void ThrowingSymbolAccessorGetter(
1920     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1921   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
1922 }
1923
1924
1925 THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
1926   v8::Isolate* isolate = CcTest::isolate();
1927   v8::HandleScope scope(isolate);
1928   LocalContext env;
1929   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
1930   i::Handle<i::JSObject> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
1931   CHECK(a->map()->instance_descriptors()->IsFixedArray());
1932   CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
1933   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
1934   CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
1935   // But we should still have an ExecutableAccessorInfo.
1936   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
1937   i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
1938   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
1939   CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
1940 }
1941
1942
1943 THREADED_TEST(UndefinedIsNotEnumerable) {
1944   LocalContext env;
1945   v8::HandleScope scope(env->GetIsolate());
1946   v8::Handle<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
1947   CHECK(result->IsFalse());
1948 }
1949
1950
1951 v8::Handle<Script> call_recursively_script;
1952 static const int kTargetRecursionDepth = 150;  // near maximum
1953
1954
1955 static void CallScriptRecursivelyCall(
1956     const v8::FunctionCallbackInfo<v8::Value>& args) {
1957   ApiTestFuzzer::Fuzz();
1958   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1959   if (depth == kTargetRecursionDepth) return;
1960   args.This()->Set(v8_str("depth"),
1961                    v8::Integer::New(args.GetIsolate(), depth + 1));
1962   args.GetReturnValue().Set(call_recursively_script->Run());
1963 }
1964
1965
1966 static void CallFunctionRecursivelyCall(
1967     const v8::FunctionCallbackInfo<v8::Value>& args) {
1968   ApiTestFuzzer::Fuzz();
1969   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1970   if (depth == kTargetRecursionDepth) {
1971     printf("[depth = %d]\n", depth);
1972     return;
1973   }
1974   args.This()->Set(v8_str("depth"),
1975                    v8::Integer::New(args.GetIsolate(), depth + 1));
1976   v8::Handle<Value> function =
1977       args.This()->Get(v8_str("callFunctionRecursively"));
1978   args.GetReturnValue().Set(
1979       function.As<Function>()->Call(args.This(), 0, NULL));
1980 }
1981
1982
1983 THREADED_TEST(DeepCrossLanguageRecursion) {
1984   v8::Isolate* isolate = CcTest::isolate();
1985   v8::HandleScope scope(isolate);
1986   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
1987   global->Set(v8_str("callScriptRecursively"),
1988               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
1989   global->Set(v8_str("callFunctionRecursively"),
1990               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
1991   LocalContext env(NULL, global);
1992
1993   env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
1994   call_recursively_script = v8_compile("callScriptRecursively()");
1995   call_recursively_script->Run();
1996   call_recursively_script = v8::Handle<Script>();
1997
1998   env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
1999   CompileRun("callFunctionRecursively()");
2000 }
2001
2002
2003 static void ThrowingPropertyHandlerGet(
2004     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
2005   // Since this interceptor is used on "with" objects, the runtime will look up
2006   // @@unscopables.  Punt.
2007   if (key->IsSymbol()) return;
2008   ApiTestFuzzer::Fuzz();
2009   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
2010 }
2011
2012
2013 static void ThrowingPropertyHandlerSet(
2014     Local<Name> key, Local<Value>,
2015     const v8::PropertyCallbackInfo<v8::Value>& info) {
2016   info.GetIsolate()->ThrowException(key);
2017   info.GetReturnValue().SetUndefined();  // not the same as empty handle
2018 }
2019
2020
2021 THREADED_TEST(CallbackExceptionRegression) {
2022   v8::Isolate* isolate = CcTest::isolate();
2023   v8::HandleScope scope(isolate);
2024   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
2025   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
2026       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
2027   LocalContext env;
2028   env->Global()->Set(v8_str("obj"), obj->NewInstance());
2029   v8::Handle<Value> otto =
2030       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
2031   CHECK(v8_str("otto")->Equals(otto));
2032   v8::Handle<Value> netto =
2033       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
2034   CHECK(v8_str("netto")->Equals(netto));
2035 }
2036
2037
2038 THREADED_TEST(FunctionPrototype) {
2039   v8::Isolate* isolate = CcTest::isolate();
2040   v8::HandleScope scope(isolate);
2041   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
2042   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2043   LocalContext env;
2044   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2045   Local<Script> script = v8_compile("Foo.prototype.plak");
2046   CHECK_EQ(script->Run()->Int32Value(), 321);
2047 }
2048
2049
2050 THREADED_TEST(InternalFields) {
2051   LocalContext env;
2052   v8::Isolate* isolate = env->GetIsolate();
2053   v8::HandleScope scope(isolate);
2054
2055   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2056   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2057   instance_templ->SetInternalFieldCount(1);
2058   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2059   CHECK_EQ(1, obj->InternalFieldCount());
2060   CHECK(obj->GetInternalField(0)->IsUndefined());
2061   obj->SetInternalField(0, v8_num(17));
2062   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2063 }
2064
2065
2066 THREADED_TEST(GlobalObjectInternalFields) {
2067   v8::Isolate* isolate = CcTest::isolate();
2068   v8::HandleScope scope(isolate);
2069   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
2070   global_template->SetInternalFieldCount(1);
2071   LocalContext env(NULL, global_template);
2072   v8::Handle<v8::Object> global_proxy = env->Global();
2073   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2074   CHECK_EQ(1, global->InternalFieldCount());
2075   CHECK(global->GetInternalField(0)->IsUndefined());
2076   global->SetInternalField(0, v8_num(17));
2077   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2078 }
2079
2080
2081 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2082   LocalContext env;
2083   v8::HandleScope scope(CcTest::isolate());
2084
2085   v8::Local<v8::Object> global = env->Global();
2086   global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
2087   CHECK(global->HasRealIndexedProperty(0));
2088 }
2089
2090
2091 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2092                                                void* value) {
2093   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2094   obj->SetAlignedPointerInInternalField(0, value);
2095   CcTest::heap()->CollectAllGarbage();
2096   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2097 }
2098
2099
2100 THREADED_TEST(InternalFieldsAlignedPointers) {
2101   LocalContext env;
2102   v8::Isolate* isolate = env->GetIsolate();
2103   v8::HandleScope scope(isolate);
2104
2105   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2106   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2107   instance_templ->SetInternalFieldCount(1);
2108   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2109   CHECK_EQ(1, obj->InternalFieldCount());
2110
2111   CheckAlignedPointerInInternalField(obj, NULL);
2112
2113   int* heap_allocated = new int[100];
2114   CheckAlignedPointerInInternalField(obj, heap_allocated);
2115   delete[] heap_allocated;
2116
2117   int stack_allocated[100];
2118   CheckAlignedPointerInInternalField(obj, stack_allocated);
2119
2120   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2121   CheckAlignedPointerInInternalField(obj, huge);
2122
2123   v8::Global<v8::Object> persistent(isolate, obj);
2124   CHECK_EQ(1, Object::InternalFieldCount(persistent));
2125   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2126 }
2127
2128
2129 static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
2130                                               void* value) {
2131   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2132   (*env)->SetAlignedPointerInEmbedderData(index, value);
2133   CcTest::heap()->CollectAllGarbage();
2134   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2135 }
2136
2137
2138 static void* AlignedTestPointer(int i) {
2139   return reinterpret_cast<void*>(i * 1234);
2140 }
2141
2142
2143 THREADED_TEST(EmbedderDataAlignedPointers) {
2144   LocalContext env;
2145   v8::HandleScope scope(env->GetIsolate());
2146
2147   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2148
2149   int* heap_allocated = new int[100];
2150   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2151   delete[] heap_allocated;
2152
2153   int stack_allocated[100];
2154   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2155
2156   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2157   CheckAlignedPointerInEmbedderData(&env, 3, huge);
2158
2159   // Test growing of the embedder data's backing store.
2160   for (int i = 0; i < 100; i++) {
2161     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2162   }
2163   CcTest::heap()->CollectAllGarbage();
2164   for (int i = 0; i < 100; i++) {
2165     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2166   }
2167 }
2168
2169
2170 static void CheckEmbedderData(LocalContext* env, int index,
2171                               v8::Handle<Value> data) {
2172   (*env)->SetEmbedderData(index, data);
2173   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2174 }
2175
2176
2177 THREADED_TEST(EmbedderData) {
2178   LocalContext env;
2179   v8::Isolate* isolate = env->GetIsolate();
2180   v8::HandleScope scope(isolate);
2181
2182   CheckEmbedderData(
2183       &env, 3, v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2184   CheckEmbedderData(&env, 2,
2185                     v8::String::NewFromUtf8(isolate, "over the lazy dog."));
2186   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2187   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
2188 }
2189
2190
2191 THREADED_TEST(GetIsolate) {
2192   LocalContext env;
2193   v8::Isolate* isolate = env->GetIsolate();
2194   v8::HandleScope scope(isolate);
2195   Local<v8::Object> obj = v8::Object::New(isolate);
2196   CHECK_EQ(isolate, obj->GetIsolate());
2197   CHECK_EQ(isolate, CcTest::global()->GetIsolate());
2198 }
2199
2200
2201 THREADED_TEST(IdentityHash) {
2202   LocalContext env;
2203   v8::Isolate* isolate = env->GetIsolate();
2204   v8::HandleScope scope(isolate);
2205
2206   // Ensure that the test starts with an fresh heap to test whether the hash
2207   // code is based on the address.
2208   CcTest::heap()->CollectAllGarbage();
2209   Local<v8::Object> obj = v8::Object::New(isolate);
2210   int hash = obj->GetIdentityHash();
2211   int hash1 = obj->GetIdentityHash();
2212   CHECK_EQ(hash, hash1);
2213   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
2214   // Since the identity hash is essentially a random number two consecutive
2215   // objects should not be assigned the same hash code. If the test below fails
2216   // the random number generator should be evaluated.
2217   CHECK_NE(hash, hash2);
2218   CcTest::heap()->CollectAllGarbage();
2219   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
2220   // Make sure that the identity hash is not based on the initial address of
2221   // the object alone. If the test below fails the random number generator
2222   // should be evaluated.
2223   CHECK_NE(hash, hash3);
2224   int hash4 = obj->GetIdentityHash();
2225   CHECK_EQ(hash, hash4);
2226
2227   // Check identity hashes behaviour in the presence of JS accessors.
2228   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2229   {
2230     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2231     Local<v8::Object> o1 = v8::Object::New(isolate);
2232     Local<v8::Object> o2 = v8::Object::New(isolate);
2233     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2234   }
2235   {
2236     CompileRun(
2237         "function cnst() { return 42; };\n"
2238         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2239     Local<v8::Object> o1 = v8::Object::New(isolate);
2240     Local<v8::Object> o2 = v8::Object::New(isolate);
2241     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2242   }
2243 }
2244
2245
2246 void GlobalProxyIdentityHash(bool set_in_js) {
2247   LocalContext env;
2248   v8::Isolate* isolate = env->GetIsolate();
2249   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2250   v8::HandleScope scope(isolate);
2251   Handle<Object> global_proxy = env->Global();
2252   i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
2253   env->Global()->Set(v8_str("global"), global_proxy);
2254   i::Handle<i::Object> original_hash;
2255   if (set_in_js) {
2256     CompileRun("var m = new Set(); m.add(global);");
2257     original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
2258   } else {
2259     original_hash = i::Handle<i::Object>(
2260         i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
2261   }
2262   CHECK(original_hash->IsSmi());
2263   int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
2264   // Hash should be retained after being detached.
2265   env->DetachGlobal();
2266   int hash2 = global_proxy->GetIdentityHash();
2267   CHECK_EQ(hash1, hash2);
2268   {
2269     // Re-attach global proxy to a new context, hash should stay the same.
2270     LocalContext env2(NULL, Handle<ObjectTemplate>(), global_proxy);
2271     int hash3 = global_proxy->GetIdentityHash();
2272     CHECK_EQ(hash1, hash3);
2273   }
2274 }
2275
2276
2277 THREADED_TEST(GlobalProxyIdentityHash) {
2278   GlobalProxyIdentityHash(true);
2279   GlobalProxyIdentityHash(false);
2280 }
2281
2282
2283 TEST(SymbolIdentityHash) {
2284   LocalContext env;
2285   v8::Isolate* isolate = env->GetIsolate();
2286   v8::HandleScope scope(isolate);
2287
2288   {
2289     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
2290     int hash = symbol->GetIdentityHash();
2291     int hash1 = symbol->GetIdentityHash();
2292     CHECK_EQ(hash, hash1);
2293     CcTest::heap()->CollectAllGarbage();
2294     int hash3 = symbol->GetIdentityHash();
2295     CHECK_EQ(hash, hash3);
2296   }
2297
2298   {
2299     v8::Handle<v8::Symbol> js_symbol =
2300         CompileRun("Symbol('foo')").As<v8::Symbol>();
2301     int hash = js_symbol->GetIdentityHash();
2302     int hash1 = js_symbol->GetIdentityHash();
2303     CHECK_EQ(hash, hash1);
2304     CcTest::heap()->CollectAllGarbage();
2305     int hash3 = js_symbol->GetIdentityHash();
2306     CHECK_EQ(hash, hash3);
2307   }
2308 }
2309
2310
2311 TEST(StringIdentityHash) {
2312   LocalContext env;
2313   v8::Isolate* isolate = env->GetIsolate();
2314   v8::HandleScope scope(isolate);
2315
2316   Local<v8::String> str = v8::String::NewFromUtf8(isolate, "str1");
2317   int hash = str->GetIdentityHash();
2318   int hash1 = str->GetIdentityHash();
2319   CHECK_EQ(hash, hash1);
2320   CcTest::heap()->CollectAllGarbage();
2321   int hash3 = str->GetIdentityHash();
2322   CHECK_EQ(hash, hash3);
2323
2324   Local<v8::String> str2 = v8::String::NewFromUtf8(isolate, "str1");
2325   int hash4 = str2->GetIdentityHash();
2326   CHECK_EQ(hash, hash4);
2327 }
2328
2329
2330 THREADED_TEST(SymbolProperties) {
2331   LocalContext env;
2332   v8::Isolate* isolate = env->GetIsolate();
2333   v8::HandleScope scope(isolate);
2334
2335   v8::Local<v8::Object> obj = v8::Object::New(isolate);
2336   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2337   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
2338   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
2339
2340   CcTest::heap()->CollectAllGarbage();
2341
2342   // Check basic symbol functionality.
2343   CHECK(sym1->IsSymbol());
2344   CHECK(sym2->IsSymbol());
2345   CHECK(!obj->IsSymbol());
2346
2347   CHECK(sym1->Equals(sym1));
2348   CHECK(sym2->Equals(sym2));
2349   CHECK(!sym1->Equals(sym2));
2350   CHECK(!sym2->Equals(sym1));
2351   CHECK(sym1->StrictEquals(sym1));
2352   CHECK(sym2->StrictEquals(sym2));
2353   CHECK(!sym1->StrictEquals(sym2));
2354   CHECK(!sym2->StrictEquals(sym1));
2355
2356   CHECK(sym2->Name()->Equals(v8_str("my-symbol")));
2357
2358   v8::Local<v8::Value> sym_val = sym2;
2359   CHECK(sym_val->IsSymbol());
2360   CHECK(sym_val->Equals(sym2));
2361   CHECK(sym_val->StrictEquals(sym2));
2362   CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2363
2364   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2365   CHECK(sym_obj->IsSymbolObject());
2366   CHECK(!sym2->IsSymbolObject());
2367   CHECK(!obj->IsSymbolObject());
2368   CHECK(!sym_obj->Equals(sym2));
2369   CHECK(!sym_obj->StrictEquals(sym2));
2370   CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
2371   CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
2372
2373   // Make sure delete of a non-existent symbol property works.
2374   CHECK(obj->Delete(sym1));
2375   CHECK(!obj->Has(sym1));
2376
2377   CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
2378   CHECK(obj->Has(sym1));
2379   CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2380   CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
2381   CHECK(obj->Has(sym1));
2382   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2383   CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2384
2385   CHECK_EQ(0u, obj->GetOwnPropertyNames()->Length());
2386   unsigned num_props = obj->GetPropertyNames()->Length();
2387   CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2388                  v8::Integer::New(isolate, 20)));
2389   CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
2390   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2391
2392   CcTest::heap()->CollectAllGarbage();
2393
2394   CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
2395   CHECK(obj->Get(sym3)->IsUndefined());
2396   CHECK(obj->Set(sym3, v8::Integer::New(isolate, 42)));
2397   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2398   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2399             ->Equals(v8::Integer::New(isolate, 42)));
2400
2401   // Add another property and delete it afterwards to force the object in
2402   // slow case.
2403   CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
2404   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2405   CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2406   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2407   CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
2408
2409   CHECK(obj->Has(sym1));
2410   CHECK(obj->Has(sym2));
2411   CHECK(obj->Has(sym3));
2412   CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2413   CHECK(obj->Delete(sym2));
2414   CHECK(obj->Has(sym1));
2415   CHECK(!obj->Has(sym2));
2416   CHECK(obj->Has(sym3));
2417   CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2418   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2419   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2420   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2421             ->Equals(v8::Integer::New(isolate, 42)));
2422   CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
2423
2424   // Symbol properties are inherited.
2425   v8::Local<v8::Object> child = v8::Object::New(isolate);
2426   child->SetPrototype(obj);
2427   CHECK(child->Has(sym1));
2428   CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2429   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2430   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2431             ->Equals(v8::Integer::New(isolate, 42)));
2432   CHECK_EQ(0u, child->GetOwnPropertyNames()->Length());
2433 }
2434
2435
2436 THREADED_TEST(SymbolTemplateProperties) {
2437   LocalContext env;
2438   v8::Isolate* isolate = env->GetIsolate();
2439   v8::HandleScope scope(isolate);
2440   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
2441   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
2442   CHECK(!name.IsEmpty());
2443   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
2444   v8::Local<v8::Object> new_instance = foo->InstanceTemplate()->NewInstance();
2445   CHECK(!new_instance.IsEmpty());
2446   CHECK(new_instance->Has(name));
2447 }
2448
2449
2450 THREADED_TEST(GlobalSymbols) {
2451   LocalContext env;
2452   v8::Isolate* isolate = env->GetIsolate();
2453   v8::HandleScope scope(isolate);
2454
2455   v8::Local<String> name = v8_str("my-symbol");
2456   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
2457   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
2458   CHECK(glob2->SameValue(glob));
2459
2460   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
2461   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
2462   CHECK(glob_api2->SameValue(glob_api));
2463   CHECK(!glob_api->SameValue(glob));
2464
2465   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
2466   CHECK(!sym->SameValue(glob));
2467
2468   CompileRun("var sym2 = Symbol.for('my-symbol')");
2469   v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
2470   CHECK(sym2->SameValue(glob));
2471   CHECK(!sym2->SameValue(glob_api));
2472 }
2473
2474
2475 static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
2476                                  const char* name) {
2477   LocalContext env;
2478   v8::Isolate* isolate = env->GetIsolate();
2479   v8::HandleScope scope(isolate);
2480
2481   v8::Local<v8::Symbol> symbol = getter(isolate);
2482   std::string script = std::string("var sym = ") + name;
2483   CompileRun(script.c_str());
2484   v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
2485
2486   CHECK(!value.IsEmpty());
2487   CHECK(!symbol.IsEmpty());
2488   CHECK(value->SameValue(symbol));
2489 }
2490
2491
2492 THREADED_TEST(WellKnownSymbols) {
2493   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
2494   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
2495 }
2496
2497
2498 class ScopedArrayBufferContents {
2499  public:
2500   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
2501       : contents_(contents) {}
2502   ~ScopedArrayBufferContents() { free(contents_.Data()); }
2503   void* Data() const { return contents_.Data(); }
2504   size_t ByteLength() const { return contents_.ByteLength(); }
2505
2506  private:
2507   const v8::ArrayBuffer::Contents contents_;
2508 };
2509
2510 template <typename T>
2511 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2512   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2513   for (int i = 0; i < value->InternalFieldCount(); i++) {
2514     CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2515   }
2516 }
2517
2518
2519 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
2520   LocalContext env;
2521   v8::Isolate* isolate = env->GetIsolate();
2522   v8::HandleScope handle_scope(isolate);
2523
2524   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
2525   CheckInternalFieldsAreZero(ab);
2526   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2527   CHECK(!ab->IsExternal());
2528   CcTest::heap()->CollectAllGarbage();
2529
2530   ScopedArrayBufferContents ab_contents(ab->Externalize());
2531   CHECK(ab->IsExternal());
2532
2533   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2534   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2535   DCHECK(data != NULL);
2536   env->Global()->Set(v8_str("ab"), ab);
2537
2538   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2539   CHECK_EQ(1024, result->Int32Value());
2540
2541   result = CompileRun(
2542       "var u8 = new Uint8Array(ab);"
2543       "u8[0] = 0xFF;"
2544       "u8[1] = 0xAA;"
2545       "u8.length");
2546   CHECK_EQ(1024, result->Int32Value());
2547   CHECK_EQ(0xFF, data[0]);
2548   CHECK_EQ(0xAA, data[1]);
2549   data[0] = 0xCC;
2550   data[1] = 0x11;
2551   result = CompileRun("u8[0] + u8[1]");
2552   CHECK_EQ(0xDD, result->Int32Value());
2553 }
2554
2555
2556 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
2557   LocalContext env;
2558   v8::Isolate* isolate = env->GetIsolate();
2559   v8::HandleScope handle_scope(isolate);
2560
2561
2562   v8::Local<v8::Value> result = CompileRun(
2563       "var ab1 = new ArrayBuffer(2);"
2564       "var u8_a = new Uint8Array(ab1);"
2565       "u8_a[0] = 0xAA;"
2566       "u8_a[1] = 0xFF; u8_a.buffer");
2567   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
2568   CheckInternalFieldsAreZero(ab1);
2569   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
2570   CHECK(!ab1->IsExternal());
2571   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
2572   CHECK(ab1->IsExternal());
2573
2574   result = CompileRun("ab1.byteLength");
2575   CHECK_EQ(2, result->Int32Value());
2576   result = CompileRun("u8_a[0]");
2577   CHECK_EQ(0xAA, result->Int32Value());
2578   result = CompileRun("u8_a[1]");
2579   CHECK_EQ(0xFF, result->Int32Value());
2580   result = CompileRun(
2581       "var u8_b = new Uint8Array(ab1);"
2582       "u8_b[0] = 0xBB;"
2583       "u8_a[0]");
2584   CHECK_EQ(0xBB, result->Int32Value());
2585   result = CompileRun("u8_b[1]");
2586   CHECK_EQ(0xFF, result->Int32Value());
2587
2588   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2589   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2590   CHECK_EQ(0xBB, ab1_data[0]);
2591   CHECK_EQ(0xFF, ab1_data[1]);
2592   ab1_data[0] = 0xCC;
2593   ab1_data[1] = 0x11;
2594   result = CompileRun("u8_a[0] + u8_a[1]");
2595   CHECK_EQ(0xDD, result->Int32Value());
2596 }
2597
2598
2599 THREADED_TEST(ArrayBuffer_External) {
2600   LocalContext env;
2601   v8::Isolate* isolate = env->GetIsolate();
2602   v8::HandleScope handle_scope(isolate);
2603
2604   i::ScopedVector<uint8_t> my_data(100);
2605   memset(my_data.start(), 0, 100);
2606   Local<v8::ArrayBuffer> ab3 =
2607       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
2608   CheckInternalFieldsAreZero(ab3);
2609   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
2610   CHECK(ab3->IsExternal());
2611
2612   env->Global()->Set(v8_str("ab3"), ab3);
2613
2614   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2615   CHECK_EQ(100, result->Int32Value());
2616
2617   result = CompileRun(
2618       "var u8_b = new Uint8Array(ab3);"
2619       "u8_b[0] = 0xBB;"
2620       "u8_b[1] = 0xCC;"
2621       "u8_b.length");
2622   CHECK_EQ(100, result->Int32Value());
2623   CHECK_EQ(0xBB, my_data[0]);
2624   CHECK_EQ(0xCC, my_data[1]);
2625   my_data[0] = 0xCC;
2626   my_data[1] = 0x11;
2627   result = CompileRun("u8_b[0] + u8_b[1]");
2628   CHECK_EQ(0xDD, result->Int32Value());
2629 }
2630
2631
2632 THREADED_TEST(ArrayBuffer_DisableNeuter) {
2633   LocalContext env;
2634   v8::Isolate* isolate = env->GetIsolate();
2635   v8::HandleScope handle_scope(isolate);
2636
2637   i::ScopedVector<uint8_t> my_data(100);
2638   memset(my_data.start(), 0, 100);
2639   Local<v8::ArrayBuffer> ab =
2640       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
2641   CHECK(ab->IsNeuterable());
2642
2643   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
2644   buf->set_is_neuterable(false);
2645
2646   CHECK(!ab->IsNeuterable());
2647 }
2648
2649
2650 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
2651   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
2652   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
2653 }
2654
2655
2656 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
2657   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
2658   CHECK_EQ(0, static_cast<int>(ta->Length()));
2659   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
2660 }
2661
2662
2663 static void CheckIsTypedArrayVarNeutered(const char* name) {
2664   i::ScopedVector<char> source(1024);
2665   i::SNPrintF(source,
2666               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
2667               name, name, name);
2668   CHECK(CompileRun(source.start())->IsTrue());
2669   v8::Handle<v8::TypedArray> ta =
2670       v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
2671   CheckIsNeutered(ta);
2672 }
2673
2674
2675 template <typename TypedArray, int kElementSize>
2676 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
2677                                          int byteOffset, int length) {
2678   v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
2679   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
2680   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
2681   CHECK_EQ(length, static_cast<int>(ta->Length()));
2682   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
2683   return ta;
2684 }
2685
2686
2687 THREADED_TEST(ArrayBuffer_NeuteringApi) {
2688   LocalContext env;
2689   v8::Isolate* isolate = env->GetIsolate();
2690   v8::HandleScope handle_scope(isolate);
2691
2692   v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
2693
2694   v8::Handle<v8::Uint8Array> u8a =
2695       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
2696   v8::Handle<v8::Uint8ClampedArray> u8c =
2697       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
2698   v8::Handle<v8::Int8Array> i8a =
2699       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
2700
2701   v8::Handle<v8::Uint16Array> u16a =
2702       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
2703   v8::Handle<v8::Int16Array> i16a =
2704       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
2705
2706   v8::Handle<v8::Uint32Array> u32a =
2707       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
2708   v8::Handle<v8::Int32Array> i32a =
2709       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
2710
2711   v8::Handle<v8::Float32Array> f32a =
2712       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
2713   v8::Handle<v8::Float64Array> f64a =
2714       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
2715
2716   v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
2717   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
2718   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
2719   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
2720
2721   ScopedArrayBufferContents contents(buffer->Externalize());
2722   buffer->Neuter();
2723   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
2724   CheckIsNeutered(u8a);
2725   CheckIsNeutered(u8c);
2726   CheckIsNeutered(i8a);
2727   CheckIsNeutered(u16a);
2728   CheckIsNeutered(i16a);
2729   CheckIsNeutered(u32a);
2730   CheckIsNeutered(i32a);
2731   CheckIsNeutered(f32a);
2732   CheckIsNeutered(f64a);
2733   CheckDataViewIsNeutered(dv);
2734 }
2735
2736
2737 THREADED_TEST(ArrayBuffer_NeuteringScript) {
2738   LocalContext env;
2739   v8::Isolate* isolate = env->GetIsolate();
2740   v8::HandleScope handle_scope(isolate);
2741
2742   CompileRun(
2743       "var ab = new ArrayBuffer(1024);"
2744       "var u8a = new Uint8Array(ab, 1, 1023);"
2745       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
2746       "var i8a = new Int8Array(ab, 1, 1023);"
2747       "var u16a = new Uint16Array(ab, 2, 511);"
2748       "var i16a = new Int16Array(ab, 2, 511);"
2749       "var u32a = new Uint32Array(ab, 4, 255);"
2750       "var i32a = new Int32Array(ab, 4, 255);"
2751       "var f32a = new Float32Array(ab, 4, 255);"
2752       "var f64a = new Float64Array(ab, 8, 127);"
2753       "var dv = new DataView(ab, 1, 1023);");
2754
2755   v8::Handle<v8::ArrayBuffer> ab =
2756       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
2757
2758   v8::Handle<v8::DataView> dv =
2759       v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
2760
2761   ScopedArrayBufferContents contents(ab->Externalize());
2762   ab->Neuter();
2763   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
2764   CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
2765
2766   CheckIsTypedArrayVarNeutered("u8a");
2767   CheckIsTypedArrayVarNeutered("u8c");
2768   CheckIsTypedArrayVarNeutered("i8a");
2769   CheckIsTypedArrayVarNeutered("u16a");
2770   CheckIsTypedArrayVarNeutered("i16a");
2771   CheckIsTypedArrayVarNeutered("u32a");
2772   CheckIsTypedArrayVarNeutered("i32a");
2773   CheckIsTypedArrayVarNeutered("f32a");
2774   CheckIsTypedArrayVarNeutered("f64a");
2775
2776   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
2777   CheckDataViewIsNeutered(dv);
2778 }
2779
2780
2781 class ScopedSharedArrayBufferContents {
2782  public:
2783   explicit ScopedSharedArrayBufferContents(
2784       const v8::SharedArrayBuffer::Contents& contents)
2785       : contents_(contents) {}
2786   ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
2787   void* Data() const { return contents_.Data(); }
2788   size_t ByteLength() const { return contents_.ByteLength(); }
2789
2790  private:
2791   const v8::SharedArrayBuffer::Contents contents_;
2792 };
2793
2794
2795 THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
2796   i::FLAG_harmony_sharedarraybuffer = true;
2797   LocalContext env;
2798   v8::Isolate* isolate = env->GetIsolate();
2799   v8::HandleScope handle_scope(isolate);
2800
2801   Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
2802   CheckInternalFieldsAreZero(ab);
2803   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2804   CHECK(!ab->IsExternal());
2805   CcTest::heap()->CollectAllGarbage();
2806
2807   ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
2808   CHECK(ab->IsExternal());
2809
2810   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2811   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2812   DCHECK(data != NULL);
2813   env->Global()->Set(v8_str("ab"), ab);
2814
2815   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2816   CHECK_EQ(1024, result->Int32Value());
2817
2818   result = CompileRun(
2819       "var u8 = new Uint8Array(ab);"
2820       "u8[0] = 0xFF;"
2821       "u8[1] = 0xAA;"
2822       "u8.length");
2823   CHECK_EQ(1024, result->Int32Value());
2824   CHECK_EQ(0xFF, data[0]);
2825   CHECK_EQ(0xAA, data[1]);
2826   data[0] = 0xCC;
2827   data[1] = 0x11;
2828   result = CompileRun("u8[0] + u8[1]");
2829   CHECK_EQ(0xDD, result->Int32Value());
2830 }
2831
2832
2833 THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
2834   i::FLAG_harmony_sharedarraybuffer = true;
2835   LocalContext env;
2836   v8::Isolate* isolate = env->GetIsolate();
2837   v8::HandleScope handle_scope(isolate);
2838
2839
2840   v8::Local<v8::Value> result = CompileRun(
2841       "var ab1 = new SharedArrayBuffer(2);"
2842       "var u8_a = new Uint8Array(ab1);"
2843       "u8_a[0] = 0xAA;"
2844       "u8_a[1] = 0xFF; u8_a.buffer");
2845   Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
2846   CheckInternalFieldsAreZero(ab1);
2847   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
2848   CHECK(!ab1->IsExternal());
2849   ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
2850   CHECK(ab1->IsExternal());
2851
2852   result = CompileRun("ab1.byteLength");
2853   CHECK_EQ(2, result->Int32Value());
2854   result = CompileRun("u8_a[0]");
2855   CHECK_EQ(0xAA, result->Int32Value());
2856   result = CompileRun("u8_a[1]");
2857   CHECK_EQ(0xFF, result->Int32Value());
2858   result = CompileRun(
2859       "var u8_b = new Uint8Array(ab1);"
2860       "u8_b[0] = 0xBB;"
2861       "u8_a[0]");
2862   CHECK_EQ(0xBB, result->Int32Value());
2863   result = CompileRun("u8_b[1]");
2864   CHECK_EQ(0xFF, result->Int32Value());
2865
2866   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2867   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2868   CHECK_EQ(0xBB, ab1_data[0]);
2869   CHECK_EQ(0xFF, ab1_data[1]);
2870   ab1_data[0] = 0xCC;
2871   ab1_data[1] = 0x11;
2872   result = CompileRun("u8_a[0] + u8_a[1]");
2873   CHECK_EQ(0xDD, result->Int32Value());
2874 }
2875
2876
2877 THREADED_TEST(SharedArrayBuffer_External) {
2878   i::FLAG_harmony_sharedarraybuffer = true;
2879   LocalContext env;
2880   v8::Isolate* isolate = env->GetIsolate();
2881   v8::HandleScope handle_scope(isolate);
2882
2883   i::ScopedVector<uint8_t> my_data(100);
2884   memset(my_data.start(), 0, 100);
2885   Local<v8::SharedArrayBuffer> ab3 =
2886       v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
2887   CheckInternalFieldsAreZero(ab3);
2888   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
2889   CHECK(ab3->IsExternal());
2890
2891   env->Global()->Set(v8_str("ab3"), ab3);
2892
2893   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2894   CHECK_EQ(100, result->Int32Value());
2895
2896   result = CompileRun(
2897       "var u8_b = new Uint8Array(ab3);"
2898       "u8_b[0] = 0xBB;"
2899       "u8_b[1] = 0xCC;"
2900       "u8_b.length");
2901   CHECK_EQ(100, result->Int32Value());
2902   CHECK_EQ(0xBB, my_data[0]);
2903   CHECK_EQ(0xCC, my_data[1]);
2904   my_data[0] = 0xCC;
2905   my_data[1] = 0x11;
2906   result = CompileRun("u8_b[0] + u8_b[1]");
2907   CHECK_EQ(0xDD, result->Int32Value());
2908 }
2909
2910
2911 THREADED_TEST(HiddenProperties) {
2912   LocalContext env;
2913   v8::Isolate* isolate = env->GetIsolate();
2914   v8::HandleScope scope(isolate);
2915
2916   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
2917   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
2918   v8::Local<v8::String> empty = v8_str("");
2919   v8::Local<v8::String> prop_name = v8_str("prop_name");
2920
2921   CcTest::heap()->CollectAllGarbage();
2922
2923   // Make sure delete of a non-existent hidden value works
2924   CHECK(obj->DeleteHiddenValue(key));
2925
2926   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
2927   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
2928   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
2929   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2930
2931   CcTest::heap()->CollectAllGarbage();
2932
2933   // Make sure we do not find the hidden property.
2934   CHECK(!obj->Has(empty));
2935   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2936   CHECK(obj->Get(empty)->IsUndefined());
2937   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2938   CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
2939   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2940   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
2941
2942   CcTest::heap()->CollectAllGarbage();
2943
2944   // Add another property and delete it afterwards to force the object in
2945   // slow case.
2946   CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
2947   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2948   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
2949   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2950   CHECK(obj->Delete(prop_name));
2951   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2952
2953   CcTest::heap()->CollectAllGarbage();
2954
2955   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
2956   CHECK(obj->GetHiddenValue(key).IsEmpty());
2957
2958   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
2959   CHECK(obj->DeleteHiddenValue(key));
2960   CHECK(obj->GetHiddenValue(key).IsEmpty());
2961 }
2962
2963
2964 THREADED_TEST(Regress97784) {
2965   // Regression test for crbug.com/97784
2966   // Messing with the Object.prototype should not have effect on
2967   // hidden properties.
2968   LocalContext env;
2969   v8::HandleScope scope(env->GetIsolate());
2970
2971   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
2972   v8::Local<v8::String> key = v8_str("hidden");
2973
2974   CompileRun(
2975       "set_called = false;"
2976       "Object.defineProperty("
2977       "    Object.prototype,"
2978       "    'hidden',"
2979       "    {get: function() { return 45; },"
2980       "     set: function() { set_called = true; }})");
2981
2982   CHECK(obj->GetHiddenValue(key).IsEmpty());
2983   // Make sure that the getter and setter from Object.prototype is not invoked.
2984   // If it did we would have full access to the hidden properties in
2985   // the accessor.
2986   CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
2987   ExpectFalse("set_called");
2988   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
2989 }
2990
2991
2992 THREADED_TEST(External) {
2993   v8::HandleScope scope(CcTest::isolate());
2994   int x = 3;
2995   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
2996   LocalContext env;
2997   env->Global()->Set(v8_str("ext"), ext);
2998   Local<Value> reext_obj = CompileRun("this.ext");
2999   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
3000   int* ptr = static_cast<int*>(reext->Value());
3001   CHECK_EQ(x, 3);
3002   *ptr = 10;
3003   CHECK_EQ(x, 10);
3004
3005   // Make sure unaligned pointers are wrapped properly.
3006   char* data = i::StrDup("0123456789");
3007   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3008   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3009   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3010   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
3011
3012   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
3013   CHECK_EQ('0', *char_ptr);
3014   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
3015   CHECK_EQ('1', *char_ptr);
3016   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
3017   CHECK_EQ('2', *char_ptr);
3018   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
3019   CHECK_EQ('3', *char_ptr);
3020   i::DeleteArray(data);
3021 }
3022
3023
3024 THREADED_TEST(GlobalHandle) {
3025   v8::Isolate* isolate = CcTest::isolate();
3026   v8::Persistent<String> global;
3027   {
3028     v8::HandleScope scope(isolate);
3029     global.Reset(isolate, v8_str("str"));
3030   }
3031   {
3032     v8::HandleScope scope(isolate);
3033     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3034   }
3035   global.Reset();
3036   {
3037     v8::HandleScope scope(isolate);
3038     global.Reset(isolate, v8_str("str"));
3039   }
3040   {
3041     v8::HandleScope scope(isolate);
3042     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3043   }
3044   global.Reset();
3045 }
3046
3047
3048 THREADED_TEST(ResettingGlobalHandle) {
3049   v8::Isolate* isolate = CcTest::isolate();
3050   v8::Persistent<String> global;
3051   {
3052     v8::HandleScope scope(isolate);
3053     global.Reset(isolate, v8_str("str"));
3054   }
3055   v8::internal::GlobalHandles* global_handles =
3056       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3057   int initial_handle_count = global_handles->global_handles_count();
3058   {
3059     v8::HandleScope scope(isolate);
3060     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3061   }
3062   {
3063     v8::HandleScope scope(isolate);
3064     global.Reset(isolate, v8_str("longer"));
3065   }
3066   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3067   {
3068     v8::HandleScope scope(isolate);
3069     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3070   }
3071   global.Reset();
3072   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3073 }
3074
3075
3076 THREADED_TEST(ResettingGlobalHandleToEmpty) {
3077   v8::Isolate* isolate = CcTest::isolate();
3078   v8::Persistent<String> global;
3079   {
3080     v8::HandleScope scope(isolate);
3081     global.Reset(isolate, v8_str("str"));
3082   }
3083   v8::internal::GlobalHandles* global_handles =
3084       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3085   int initial_handle_count = global_handles->global_handles_count();
3086   {
3087     v8::HandleScope scope(isolate);
3088     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3089   }
3090   {
3091     v8::HandleScope scope(isolate);
3092     Local<String> empty;
3093     global.Reset(isolate, empty);
3094   }
3095   CHECK(global.IsEmpty());
3096   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3097 }
3098
3099
3100 template <class T>
3101 static v8::Global<T> PassUnique(v8::Global<T> unique) {
3102   return unique.Pass();
3103 }
3104
3105
3106 template <class T>
3107 static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
3108                                   const v8::Persistent<T>& global) {
3109   v8::Global<String> unique(isolate, global);
3110   return unique.Pass();
3111 }
3112
3113
3114 THREADED_TEST(Global) {
3115   v8::Isolate* isolate = CcTest::isolate();
3116   v8::Persistent<String> global;
3117   {
3118     v8::HandleScope scope(isolate);
3119     global.Reset(isolate, v8_str("str"));
3120   }
3121   v8::internal::GlobalHandles* global_handles =
3122       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3123   int initial_handle_count = global_handles->global_handles_count();
3124   {
3125     v8::Global<String> unique(isolate, global);
3126     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3127     // Test assignment via Pass
3128     {
3129       v8::Global<String> copy = unique.Pass();
3130       CHECK(unique.IsEmpty());
3131       CHECK(copy == global);
3132       CHECK_EQ(initial_handle_count + 1,
3133                global_handles->global_handles_count());
3134       unique = copy.Pass();
3135     }
3136     // Test ctor via Pass
3137     {
3138       v8::Global<String> copy(unique.Pass());
3139       CHECK(unique.IsEmpty());
3140       CHECK(copy == global);
3141       CHECK_EQ(initial_handle_count + 1,
3142                global_handles->global_handles_count());
3143       unique = copy.Pass();
3144     }
3145     // Test pass through function call
3146     {
3147       v8::Global<String> copy = PassUnique(unique.Pass());
3148       CHECK(unique.IsEmpty());
3149       CHECK(copy == global);
3150       CHECK_EQ(initial_handle_count + 1,
3151                global_handles->global_handles_count());
3152       unique = copy.Pass();
3153     }
3154     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3155   }
3156   // Test pass from function call
3157   {
3158     v8::Global<String> unique = ReturnUnique(isolate, global);
3159     CHECK(unique == global);
3160     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3161   }
3162   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3163   global.Reset();
3164 }
3165
3166
3167 namespace {
3168
3169 class TwoPassCallbackData;
3170 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3171 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3172
3173
3174 class TwoPassCallbackData {
3175  public:
3176   TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
3177       : first_pass_called_(false),
3178         second_pass_called_(false),
3179         trigger_gc_(false),
3180         instance_counter_(instance_counter) {
3181     HandleScope scope(isolate);
3182     i::ScopedVector<char> buffer(40);
3183     i::SNPrintF(buffer, "%p", static_cast<void*>(this));
3184     auto string =
3185         v8::String::NewFromUtf8(isolate, buffer.start(),
3186                                 v8::NewStringType::kNormal).ToLocalChecked();
3187     cell_.Reset(isolate, string);
3188     (*instance_counter_)++;
3189   }
3190
3191   ~TwoPassCallbackData() {
3192     CHECK(first_pass_called_);
3193     CHECK(second_pass_called_);
3194     CHECK(cell_.IsEmpty());
3195     (*instance_counter_)--;
3196   }
3197
3198   void FirstPass() {
3199     CHECK(!first_pass_called_);
3200     CHECK(!second_pass_called_);
3201     CHECK(!cell_.IsEmpty());
3202     cell_.Reset();
3203     first_pass_called_ = true;
3204   }
3205
3206   void SecondPass() {
3207     CHECK(first_pass_called_);
3208     CHECK(!second_pass_called_);
3209     CHECK(cell_.IsEmpty());
3210     second_pass_called_ = true;
3211     delete this;
3212   }
3213
3214   void SetWeak() {
3215     cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
3216   }
3217
3218   void MarkTriggerGc() { trigger_gc_ = true; }
3219   bool trigger_gc() { return trigger_gc_; }
3220
3221   int* instance_counter() { return instance_counter_; }
3222
3223  private:
3224   bool first_pass_called_;
3225   bool second_pass_called_;
3226   bool trigger_gc_;
3227   v8::Global<v8::String> cell_;
3228   int* instance_counter_;
3229 };
3230
3231
3232 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
3233   ApiTestFuzzer::Fuzz();
3234   bool trigger_gc = data.GetParameter()->trigger_gc();
3235   int* instance_counter = data.GetParameter()->instance_counter();
3236   data.GetParameter()->SecondPass();
3237   if (!trigger_gc) return;
3238   auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
3239   data_2->SetWeak();
3240   CcTest::heap()->CollectAllGarbage();
3241 }
3242
3243
3244 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
3245   data.GetParameter()->FirstPass();
3246   data.SetSecondPassCallback(SecondPassCallback);
3247 }
3248
3249 }  // namespace
3250
3251
3252 TEST(TwoPassPhantomCallbacks) {
3253   auto isolate = CcTest::isolate();
3254   const size_t kLength = 20;
3255   int instance_counter = 0;
3256   for (size_t i = 0; i < kLength; ++i) {
3257     auto data = new TwoPassCallbackData(isolate, &instance_counter);
3258     data->SetWeak();
3259   }
3260   CHECK_EQ(static_cast<int>(kLength), instance_counter);
3261   CcTest::heap()->CollectAllGarbage();
3262   EmptyMessageQueues(isolate);
3263   CHECK_EQ(0, instance_counter);
3264 }
3265
3266
3267 TEST(TwoPassPhantomCallbacksNestedGc) {
3268   auto isolate = CcTest::isolate();
3269   const size_t kLength = 20;
3270   TwoPassCallbackData* array[kLength];
3271   int instance_counter = 0;
3272   for (size_t i = 0; i < kLength; ++i) {
3273     array[i] = new TwoPassCallbackData(isolate, &instance_counter);
3274     array[i]->SetWeak();
3275   }
3276   array[5]->MarkTriggerGc();
3277   array[10]->MarkTriggerGc();
3278   array[15]->MarkTriggerGc();
3279   CHECK_EQ(static_cast<int>(kLength), instance_counter);
3280   CcTest::heap()->CollectAllGarbage();
3281   EmptyMessageQueues(isolate);
3282   CHECK_EQ(0, instance_counter);
3283 }
3284
3285
3286 namespace {
3287
3288 void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
3289
3290
3291 Local<v8::Object> NewObjectForIntKey(
3292     v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
3293     int key) {
3294   auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
3295   auto obj = local->NewInstance();
3296   obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
3297   return obj;
3298 }
3299
3300
3301 template <typename K, typename V>
3302 class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
3303  public:
3304   typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
3305   static const v8::PersistentContainerCallbackType kCallbackType =
3306       v8::kWeakWithInternalFields;
3307   struct WeakCallbackDataType {
3308     MapType* map;
3309     K key;
3310   };
3311   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
3312                                                      Local<V> value) {
3313     WeakCallbackDataType* data = new WeakCallbackDataType;
3314     data->map = map;
3315     data->key = key;
3316     return data;
3317   }
3318   static MapType* MapFromWeakCallbackInfo(
3319       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
3320     return data.GetParameter()->map;
3321   }
3322   static K KeyFromWeakCallbackInfo(
3323       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
3324     return data.GetParameter()->key;
3325   }
3326   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
3327   static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
3328     CHECK_EQ(IntKeyToVoidPointer(key),
3329              v8::Object::GetAlignedPointerFromInternalField(value, 0));
3330   }
3331   static void OnWeakCallback(
3332       const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
3333   static void DisposeWeak(
3334       const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
3335     K key = KeyFromWeakCallbackInfo(info);
3336     CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
3337     DisposeCallbackData(info.GetParameter());
3338   }
3339 };
3340
3341
3342 template <typename Map>
3343 void TestGlobalValueMap() {
3344   LocalContext env;
3345   v8::Isolate* isolate = env->GetIsolate();
3346   v8::Global<ObjectTemplate> templ;
3347   {
3348     HandleScope scope(isolate);
3349     auto t = ObjectTemplate::New(isolate);
3350     t->SetInternalFieldCount(1);
3351     templ.Reset(isolate, t);
3352   }
3353   Map map(isolate);
3354   v8::internal::GlobalHandles* global_handles =
3355       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3356   int initial_handle_count = global_handles->global_handles_count();
3357   CHECK_EQ(0, static_cast<int>(map.Size()));
3358   {
3359     HandleScope scope(isolate);
3360     Local<v8::Object> obj = map.Get(7);
3361     CHECK(obj.IsEmpty());
3362     Local<v8::Object> expected = v8::Object::New(isolate);
3363     map.Set(7, expected);
3364     CHECK_EQ(1, static_cast<int>(map.Size()));
3365     obj = map.Get(7);
3366     CHECK(expected->Equals(obj));
3367     {
3368       typename Map::PersistentValueReference ref = map.GetReference(7);
3369       CHECK(expected->Equals(ref.NewLocal(isolate)));
3370     }
3371     v8::Global<v8::Object> removed = map.Remove(7);
3372     CHECK_EQ(0, static_cast<int>(map.Size()));
3373     CHECK(expected == removed);
3374     removed = map.Remove(7);
3375     CHECK(removed.IsEmpty());
3376     map.Set(8, expected);
3377     CHECK_EQ(1, static_cast<int>(map.Size()));
3378     map.Set(8, expected);
3379     CHECK_EQ(1, static_cast<int>(map.Size()));
3380     {
3381       typename Map::PersistentValueReference ref;
3382       Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
3383       removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
3384       CHECK_EQ(1, static_cast<int>(map.Size()));
3385       CHECK(expected == removed);
3386       CHECK(expected2->Equals(ref.NewLocal(isolate)));
3387     }
3388   }
3389   CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3390   if (map.IsWeak()) {
3391     CcTest::i_isolate()->heap()->CollectAllGarbage(
3392         i::Heap::kAbortIncrementalMarkingMask);
3393   } else {
3394     map.Clear();
3395   }
3396   CHECK_EQ(0, static_cast<int>(map.Size()));
3397   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3398   {
3399     HandleScope scope(isolate);
3400     Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
3401     map.Set(9, value);
3402     map.Clear();
3403   }
3404   CHECK_EQ(0, static_cast<int>(map.Size()));
3405   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3406 }
3407
3408 }  // namespace
3409
3410
3411 TEST(GlobalValueMap) {
3412   // Default case, w/o weak callbacks:
3413   TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
3414
3415   // Custom traits with weak callbacks:
3416   typedef v8::GlobalValueMap<int, v8::Object,
3417                              PhantomStdMapTraits<int, v8::Object>> WeakMap;
3418   TestGlobalValueMap<WeakMap>();
3419 }
3420
3421
3422 TEST(PersistentValueVector) {
3423   LocalContext env;
3424   v8::Isolate* isolate = env->GetIsolate();
3425   v8::internal::GlobalHandles* global_handles =
3426       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3427   int handle_count = global_handles->global_handles_count();
3428   HandleScope scope(isolate);
3429
3430   v8::PersistentValueVector<v8::Object> vector(isolate);
3431
3432   Local<v8::Object> obj1 = v8::Object::New(isolate);
3433   Local<v8::Object> obj2 = v8::Object::New(isolate);
3434   v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
3435
3436   CHECK(vector.IsEmpty());
3437   CHECK_EQ(0, static_cast<int>(vector.Size()));
3438
3439   vector.ReserveCapacity(3);
3440   CHECK(vector.IsEmpty());
3441
3442   vector.Append(obj1);
3443   vector.Append(obj2);
3444   vector.Append(obj1);
3445   vector.Append(obj3.Pass());
3446   vector.Append(obj1);
3447
3448   CHECK(!vector.IsEmpty());
3449   CHECK_EQ(5, static_cast<int>(vector.Size()));
3450   CHECK(obj3.IsEmpty());
3451   CHECK(obj1->Equals(vector.Get(0)));
3452   CHECK(obj1->Equals(vector.Get(2)));
3453   CHECK(obj1->Equals(vector.Get(4)));
3454   CHECK(obj2->Equals(vector.Get(1)));
3455
3456   CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
3457
3458   vector.Clear();
3459   CHECK(vector.IsEmpty());
3460   CHECK_EQ(0, static_cast<int>(vector.Size()));
3461   CHECK_EQ(handle_count, global_handles->global_handles_count());
3462 }
3463
3464
3465 THREADED_TEST(GlobalHandleUpcast) {
3466   v8::Isolate* isolate = CcTest::isolate();
3467   v8::HandleScope scope(isolate);
3468   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
3469   v8::Persistent<String> global_string(isolate, local);
3470   v8::Persistent<Value>& global_value =
3471       v8::Persistent<Value>::Cast(global_string);
3472   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3473   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
3474   global_string.Reset();
3475 }
3476
3477
3478 THREADED_TEST(HandleEquality) {
3479   v8::Isolate* isolate = CcTest::isolate();
3480   v8::Persistent<String> global1;
3481   v8::Persistent<String> global2;
3482   {
3483     v8::HandleScope scope(isolate);
3484     global1.Reset(isolate, v8_str("str"));
3485     global2.Reset(isolate, v8_str("str2"));
3486   }
3487   CHECK_EQ(global1 == global1, true);
3488   CHECK_EQ(global1 != global1, false);
3489   {
3490     v8::HandleScope scope(isolate);
3491     Local<String> local1 = Local<String>::New(isolate, global1);
3492     Local<String> local2 = Local<String>::New(isolate, global2);
3493
3494     CHECK_EQ(global1 == local1, true);
3495     CHECK_EQ(global1 != local1, false);
3496     CHECK_EQ(local1 == global1, true);
3497     CHECK_EQ(local1 != global1, false);
3498
3499     CHECK_EQ(global1 == local2, false);
3500     CHECK_EQ(global1 != local2, true);
3501     CHECK_EQ(local2 == global1, false);
3502     CHECK_EQ(local2 != global1, true);
3503
3504     CHECK_EQ(local1 == local2, false);
3505     CHECK_EQ(local1 != local2, true);
3506
3507     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3508     CHECK_EQ(local1 == anotherLocal1, true);
3509     CHECK_EQ(local1 != anotherLocal1, false);
3510   }
3511   global1.Reset();
3512   global2.Reset();
3513 }
3514
3515
3516 THREADED_TEST(LocalHandle) {
3517   v8::HandleScope scope(CcTest::isolate());
3518   v8::Local<String> local =
3519       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
3520   CHECK_EQ(local->Length(), 3);
3521 }
3522
3523
3524 class WeakCallCounter {
3525  public:
3526   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
3527   int id() { return id_; }
3528   void increment() { number_of_weak_calls_++; }
3529   int NumberOfWeakCalls() { return number_of_weak_calls_; }
3530
3531  private:
3532   int id_;
3533   int number_of_weak_calls_;
3534 };
3535
3536
3537 template <typename T>
3538 struct WeakCallCounterAndPersistent {
3539   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3540       : counter(counter) {}
3541   WeakCallCounter* counter;
3542   v8::Persistent<T> handle;
3543 };
3544
3545
3546 template <typename T>
3547 static void WeakPointerCallback(
3548     const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
3549   CHECK_EQ(1234, data.GetParameter()->counter->id());
3550   data.GetParameter()->counter->increment();
3551   data.GetParameter()->handle.Reset();
3552 }
3553
3554
3555 template <typename T>
3556 static UniqueId MakeUniqueId(const Persistent<T>& p) {
3557   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3558 }
3559
3560
3561 THREADED_TEST(ApiObjectGroups) {
3562   LocalContext env;
3563   v8::Isolate* iso = env->GetIsolate();
3564   HandleScope scope(iso);
3565
3566   WeakCallCounter counter(1234);
3567
3568   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3569   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3570   WeakCallCounterAndPersistent<Value> g1c1(&counter);
3571   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3572   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3573   WeakCallCounterAndPersistent<Value> g2c1(&counter);
3574
3575   {
3576     HandleScope scope(iso);
3577     g1s1.handle.Reset(iso, Object::New(iso));
3578     g1s2.handle.Reset(iso, Object::New(iso));
3579     g1c1.handle.Reset(iso, Object::New(iso));
3580     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3581                         v8::WeakCallbackType::kParameter);
3582     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3583                         v8::WeakCallbackType::kParameter);
3584     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3585                         v8::WeakCallbackType::kParameter);
3586
3587     g2s1.handle.Reset(iso, Object::New(iso));
3588     g2s2.handle.Reset(iso, Object::New(iso));
3589     g2c1.handle.Reset(iso, Object::New(iso));
3590     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3591                         v8::WeakCallbackType::kParameter);
3592     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3593                         v8::WeakCallbackType::kParameter);
3594     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3595                         v8::WeakCallbackType::kParameter);
3596   }
3597
3598   WeakCallCounterAndPersistent<Value> root(&counter);
3599   root.handle.Reset(iso, g1s1.handle);  // make a root.
3600
3601   // Connect group 1 and 2, make a cycle.
3602   {
3603     HandleScope scope(iso);
3604     CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
3605               ->Set(0, Local<Value>::New(iso, g2s2.handle)));
3606     CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
3607               ->Set(0, Local<Value>::New(iso, g1s1.handle)));
3608   }
3609
3610   {
3611     UniqueId id1 = MakeUniqueId(g1s1.handle);
3612     UniqueId id2 = MakeUniqueId(g2s2.handle);
3613     iso->SetObjectGroupId(g1s1.handle, id1);
3614     iso->SetObjectGroupId(g1s2.handle, id1);
3615     iso->SetReferenceFromGroup(id1, g1c1.handle);
3616     iso->SetObjectGroupId(g2s1.handle, id2);
3617     iso->SetObjectGroupId(g2s2.handle, id2);
3618     iso->SetReferenceFromGroup(id2, g2c1.handle);
3619   }
3620   // Do a single full GC, ensure incremental marking is stopped.
3621   v8::internal::Heap* heap =
3622       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3623   heap->CollectAllGarbage();
3624
3625   // All object should be alive.
3626   CHECK_EQ(0, counter.NumberOfWeakCalls());
3627
3628   // Weaken the root.
3629   root.handle.SetWeak(&root, &WeakPointerCallback,
3630                       v8::WeakCallbackType::kParameter);
3631   // But make children strong roots---all the objects (except for children)
3632   // should be collectable now.
3633   g1c1.handle.ClearWeak();
3634   g2c1.handle.ClearWeak();
3635
3636   // Groups are deleted, rebuild groups.
3637   {
3638     UniqueId id1 = MakeUniqueId(g1s1.handle);
3639     UniqueId id2 = MakeUniqueId(g2s2.handle);
3640     iso->SetObjectGroupId(g1s1.handle, id1);
3641     iso->SetObjectGroupId(g1s2.handle, id1);
3642     iso->SetReferenceFromGroup(id1, g1c1.handle);
3643     iso->SetObjectGroupId(g2s1.handle, id2);
3644     iso->SetObjectGroupId(g2s2.handle, id2);
3645     iso->SetReferenceFromGroup(id2, g2c1.handle);
3646   }
3647
3648   heap->CollectAllGarbage();
3649
3650   // All objects should be gone. 5 global handles in total.
3651   CHECK_EQ(5, counter.NumberOfWeakCalls());
3652
3653   // And now make children weak again and collect them.
3654   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3655                       v8::WeakCallbackType::kParameter);
3656   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3657                       v8::WeakCallbackType::kParameter);
3658
3659   heap->CollectAllGarbage();
3660   CHECK_EQ(7, counter.NumberOfWeakCalls());
3661 }
3662
3663
3664 THREADED_TEST(ApiObjectGroupsForSubtypes) {
3665   LocalContext env;
3666   v8::Isolate* iso = env->GetIsolate();
3667   HandleScope scope(iso);
3668
3669   WeakCallCounter counter(1234);
3670
3671   WeakCallCounterAndPersistent<Object> g1s1(&counter);
3672   WeakCallCounterAndPersistent<String> g1s2(&counter);
3673   WeakCallCounterAndPersistent<String> g1c1(&counter);
3674   WeakCallCounterAndPersistent<Object> g2s1(&counter);
3675   WeakCallCounterAndPersistent<String> g2s2(&counter);
3676   WeakCallCounterAndPersistent<String> g2c1(&counter);
3677
3678   {
3679     HandleScope scope(iso);
3680     g1s1.handle.Reset(iso, Object::New(iso));
3681     g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3682     g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3683     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3684                         v8::WeakCallbackType::kParameter);
3685     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3686                         v8::WeakCallbackType::kParameter);
3687     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3688                         v8::WeakCallbackType::kParameter);
3689
3690     g2s1.handle.Reset(iso, Object::New(iso));
3691     g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3692     g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3693     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3694                         v8::WeakCallbackType::kParameter);
3695     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3696                         v8::WeakCallbackType::kParameter);
3697     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3698                         v8::WeakCallbackType::kParameter);
3699   }
3700
3701   WeakCallCounterAndPersistent<Value> root(&counter);
3702   root.handle.Reset(iso, g1s1.handle);  // make a root.
3703
3704   // Connect group 1 and 2, make a cycle.
3705   {
3706     HandleScope scope(iso);
3707     CHECK(Local<Object>::New(iso, g1s1.handle)
3708               ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3709     CHECK(Local<Object>::New(iso, g2s1.handle)
3710               ->Set(0, Local<Object>::New(iso, g1s1.handle)));
3711   }
3712
3713   {
3714     UniqueId id1 = MakeUniqueId(g1s1.handle);
3715     UniqueId id2 = MakeUniqueId(g2s2.handle);
3716     iso->SetObjectGroupId(g1s1.handle, id1);
3717     iso->SetObjectGroupId(g1s2.handle, id1);
3718     iso->SetReference(g1s1.handle, g1c1.handle);
3719     iso->SetObjectGroupId(g2s1.handle, id2);
3720     iso->SetObjectGroupId(g2s2.handle, id2);
3721     iso->SetReferenceFromGroup(id2, g2c1.handle);
3722   }
3723   // Do a single full GC, ensure incremental marking is stopped.
3724   v8::internal::Heap* heap =
3725       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3726   heap->CollectAllGarbage();
3727
3728   // All object should be alive.
3729   CHECK_EQ(0, counter.NumberOfWeakCalls());
3730
3731   // Weaken the root.
3732   root.handle.SetWeak(&root, &WeakPointerCallback,
3733                       v8::WeakCallbackType::kParameter);
3734   // But make children strong roots---all the objects (except for children)
3735   // should be collectable now.
3736   g1c1.handle.ClearWeak();
3737   g2c1.handle.ClearWeak();
3738
3739   // Groups are deleted, rebuild groups.
3740   {
3741     UniqueId id1 = MakeUniqueId(g1s1.handle);
3742     UniqueId id2 = MakeUniqueId(g2s2.handle);
3743     iso->SetObjectGroupId(g1s1.handle, id1);
3744     iso->SetObjectGroupId(g1s2.handle, id1);
3745     iso->SetReference(g1s1.handle, g1c1.handle);
3746     iso->SetObjectGroupId(g2s1.handle, id2);
3747     iso->SetObjectGroupId(g2s2.handle, id2);
3748     iso->SetReferenceFromGroup(id2, g2c1.handle);
3749   }
3750
3751   heap->CollectAllGarbage();
3752
3753   // All objects should be gone. 5 global handles in total.
3754   CHECK_EQ(5, counter.NumberOfWeakCalls());
3755
3756   // And now make children weak again and collect them.
3757   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3758                       v8::WeakCallbackType::kParameter);
3759   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3760                       v8::WeakCallbackType::kParameter);
3761
3762   heap->CollectAllGarbage();
3763   CHECK_EQ(7, counter.NumberOfWeakCalls());
3764 }
3765
3766
3767 THREADED_TEST(ApiObjectGroupsCycle) {
3768   LocalContext env;
3769   v8::Isolate* iso = env->GetIsolate();
3770   HandleScope scope(iso);
3771
3772   WeakCallCounter counter(1234);
3773
3774   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3775   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3776   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3777   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3778   WeakCallCounterAndPersistent<Value> g3s1(&counter);
3779   WeakCallCounterAndPersistent<Value> g3s2(&counter);
3780   WeakCallCounterAndPersistent<Value> g4s1(&counter);
3781   WeakCallCounterAndPersistent<Value> g4s2(&counter);
3782
3783   {
3784     HandleScope scope(iso);
3785     g1s1.handle.Reset(iso, Object::New(iso));
3786     g1s2.handle.Reset(iso, Object::New(iso));
3787     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3788                         v8::WeakCallbackType::kParameter);
3789     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3790                         v8::WeakCallbackType::kParameter);
3791     CHECK(g1s1.handle.IsWeak());
3792     CHECK(g1s2.handle.IsWeak());
3793
3794     g2s1.handle.Reset(iso, Object::New(iso));
3795     g2s2.handle.Reset(iso, Object::New(iso));
3796     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3797                         v8::WeakCallbackType::kParameter);
3798     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3799                         v8::WeakCallbackType::kParameter);
3800     CHECK(g2s1.handle.IsWeak());
3801     CHECK(g2s2.handle.IsWeak());
3802
3803     g3s1.handle.Reset(iso, Object::New(iso));
3804     g3s2.handle.Reset(iso, Object::New(iso));
3805     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
3806                         v8::WeakCallbackType::kParameter);
3807     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
3808                         v8::WeakCallbackType::kParameter);
3809     CHECK(g3s1.handle.IsWeak());
3810     CHECK(g3s2.handle.IsWeak());
3811
3812     g4s1.handle.Reset(iso, Object::New(iso));
3813     g4s2.handle.Reset(iso, Object::New(iso));
3814     g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
3815                         v8::WeakCallbackType::kParameter);
3816     g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
3817                         v8::WeakCallbackType::kParameter);
3818     CHECK(g4s1.handle.IsWeak());
3819     CHECK(g4s2.handle.IsWeak());
3820   }
3821
3822   WeakCallCounterAndPersistent<Value> root(&counter);
3823   root.handle.Reset(iso, g1s1.handle);  // make a root.
3824
3825   // Connect groups.  We're building the following cycle:
3826   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3827   // groups.
3828   {
3829     UniqueId id1 = MakeUniqueId(g1s1.handle);
3830     UniqueId id2 = MakeUniqueId(g2s1.handle);
3831     UniqueId id3 = MakeUniqueId(g3s1.handle);
3832     UniqueId id4 = MakeUniqueId(g4s1.handle);
3833     iso->SetObjectGroupId(g1s1.handle, id1);
3834     iso->SetObjectGroupId(g1s2.handle, id1);
3835     iso->SetReferenceFromGroup(id1, g2s1.handle);
3836     iso->SetObjectGroupId(g2s1.handle, id2);
3837     iso->SetObjectGroupId(g2s2.handle, id2);
3838     iso->SetReferenceFromGroup(id2, g3s1.handle);
3839     iso->SetObjectGroupId(g3s1.handle, id3);
3840     iso->SetObjectGroupId(g3s2.handle, id3);
3841     iso->SetReferenceFromGroup(id3, g4s1.handle);
3842     iso->SetObjectGroupId(g4s1.handle, id4);
3843     iso->SetObjectGroupId(g4s2.handle, id4);
3844     iso->SetReferenceFromGroup(id4, g1s1.handle);
3845   }
3846   // Do a single full GC
3847   v8::internal::Heap* heap =
3848       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3849   heap->CollectAllGarbage();
3850
3851   // All object should be alive.
3852   CHECK_EQ(0, counter.NumberOfWeakCalls());
3853
3854   // Weaken the root.
3855   root.handle.SetWeak(&root, &WeakPointerCallback,
3856                       v8::WeakCallbackType::kParameter);
3857
3858   // Groups are deleted, rebuild groups.
3859   {
3860     UniqueId id1 = MakeUniqueId(g1s1.handle);
3861     UniqueId id2 = MakeUniqueId(g2s1.handle);
3862     UniqueId id3 = MakeUniqueId(g3s1.handle);
3863     UniqueId id4 = MakeUniqueId(g4s1.handle);
3864     iso->SetObjectGroupId(g1s1.handle, id1);
3865     iso->SetObjectGroupId(g1s2.handle, id1);
3866     iso->SetReferenceFromGroup(id1, g2s1.handle);
3867     iso->SetObjectGroupId(g2s1.handle, id2);
3868     iso->SetObjectGroupId(g2s2.handle, id2);
3869     iso->SetReferenceFromGroup(id2, g3s1.handle);
3870     iso->SetObjectGroupId(g3s1.handle, id3);
3871     iso->SetObjectGroupId(g3s2.handle, id3);
3872     iso->SetReferenceFromGroup(id3, g4s1.handle);
3873     iso->SetObjectGroupId(g4s1.handle, id4);
3874     iso->SetObjectGroupId(g4s2.handle, id4);
3875     iso->SetReferenceFromGroup(id4, g1s1.handle);
3876   }
3877
3878   heap->CollectAllGarbage();
3879
3880   // All objects should be gone. 9 global handles in total.
3881   CHECK_EQ(9, counter.NumberOfWeakCalls());
3882 }
3883
3884
3885 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3886 // on the buildbots, so was made non-threaded for the time being.
3887 TEST(ApiObjectGroupsCycleForScavenger) {
3888   i::FLAG_stress_compaction = false;
3889   i::FLAG_gc_global = false;
3890   LocalContext env;
3891   v8::Isolate* iso = env->GetIsolate();
3892   HandleScope scope(iso);
3893
3894   WeakCallCounter counter(1234);
3895
3896   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3897   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3898   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3899   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3900   WeakCallCounterAndPersistent<Value> g3s1(&counter);
3901   WeakCallCounterAndPersistent<Value> g3s2(&counter);
3902
3903   {
3904     HandleScope scope(iso);
3905     g1s1.handle.Reset(iso, Object::New(iso));
3906     g1s2.handle.Reset(iso, Object::New(iso));
3907     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3908                         v8::WeakCallbackType::kParameter);
3909     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3910                         v8::WeakCallbackType::kParameter);
3911
3912     g2s1.handle.Reset(iso, Object::New(iso));
3913     g2s2.handle.Reset(iso, Object::New(iso));
3914     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3915                         v8::WeakCallbackType::kParameter);
3916     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3917                         v8::WeakCallbackType::kParameter);
3918
3919     g3s1.handle.Reset(iso, Object::New(iso));
3920     g3s2.handle.Reset(iso, Object::New(iso));
3921     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
3922                         v8::WeakCallbackType::kParameter);
3923     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
3924                         v8::WeakCallbackType::kParameter);
3925   }
3926
3927   // Make a root.
3928   WeakCallCounterAndPersistent<Value> root(&counter);
3929   root.handle.Reset(iso, g1s1.handle);
3930   root.handle.MarkPartiallyDependent();
3931
3932   // Connect groups.  We're building the following cycle:
3933   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3934   // groups.
3935   {
3936     HandleScope handle_scope(iso);
3937     g1s1.handle.MarkPartiallyDependent();
3938     g1s2.handle.MarkPartiallyDependent();
3939     g2s1.handle.MarkPartiallyDependent();
3940     g2s2.handle.MarkPartiallyDependent();
3941     g3s1.handle.MarkPartiallyDependent();
3942     g3s2.handle.MarkPartiallyDependent();
3943     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3944     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3945     Local<Object>::New(iso, g1s1.handle.As<Object>())
3946         ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3947     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3948     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3949     Local<Object>::New(iso, g2s1.handle.As<Object>())
3950         ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3951     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3952     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3953     Local<Object>::New(iso, g3s1.handle.As<Object>())
3954         ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
3955   }
3956
3957   v8::internal::Heap* heap =
3958       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3959   heap->CollectAllGarbage();
3960
3961   // All objects should be alive.
3962   CHECK_EQ(0, counter.NumberOfWeakCalls());
3963
3964   // Weaken the root.
3965   root.handle.SetWeak(&root, &WeakPointerCallback,
3966                       v8::WeakCallbackType::kParameter);
3967   root.handle.MarkPartiallyDependent();
3968
3969   // Groups are deleted, rebuild groups.
3970   {
3971     HandleScope handle_scope(iso);
3972     g1s1.handle.MarkPartiallyDependent();
3973     g1s2.handle.MarkPartiallyDependent();
3974     g2s1.handle.MarkPartiallyDependent();
3975     g2s2.handle.MarkPartiallyDependent();
3976     g3s1.handle.MarkPartiallyDependent();
3977     g3s2.handle.MarkPartiallyDependent();
3978     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3979     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3980     Local<Object>::New(iso, g1s1.handle.As<Object>())
3981         ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3982     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3983     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3984     Local<Object>::New(iso, g2s1.handle.As<Object>())
3985         ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3986     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3987     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3988     Local<Object>::New(iso, g3s1.handle.As<Object>())
3989         ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
3990   }
3991
3992   heap->CollectAllGarbage();
3993
3994   // All objects should be gone. 7 global handles in total.
3995   CHECK_EQ(7, counter.NumberOfWeakCalls());
3996 }
3997
3998
3999 THREADED_TEST(ScriptException) {
4000   LocalContext env;
4001   v8::HandleScope scope(env->GetIsolate());
4002   Local<Script> script = v8_compile("throw 'panama!';");
4003   v8::TryCatch try_catch(env->GetIsolate());
4004   Local<Value> result = script->Run();
4005   CHECK(result.IsEmpty());
4006   CHECK(try_catch.HasCaught());
4007   String::Utf8Value exception_value(try_catch.Exception());
4008   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
4009 }
4010
4011
4012 TEST(TryCatchCustomException) {
4013   LocalContext env;
4014   v8::Isolate* isolate = env->GetIsolate();
4015   v8::HandleScope scope(isolate);
4016   v8::TryCatch try_catch(isolate);
4017   CompileRun(
4018       "function CustomError() { this.a = 'b'; }"
4019       "(function f() { throw new CustomError(); })();");
4020   CHECK(try_catch.HasCaught());
4021   CHECK(try_catch.Exception()
4022             ->ToObject(isolate)
4023             ->Get(v8_str("a"))
4024             ->Equals(v8_str("b")));
4025 }
4026
4027
4028 bool message_received;
4029
4030
4031 static void check_message_0(v8::Handle<v8::Message> message,
4032                             v8::Handle<Value> data) {
4033   CHECK_EQ(5.76, data->NumberValue());
4034   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4035   CHECK(!message->IsSharedCrossOrigin());
4036   message_received = true;
4037 }
4038
4039
4040 THREADED_TEST(MessageHandler0) {
4041   message_received = false;
4042   v8::HandleScope scope(CcTest::isolate());
4043   CHECK(!message_received);
4044   LocalContext context;
4045   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
4046   v8::Handle<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4047   script->Run();
4048   CHECK(message_received);
4049   // clear out the message listener
4050   v8::V8::RemoveMessageListeners(check_message_0);
4051 }
4052
4053
4054 static void check_message_1(v8::Handle<v8::Message> message,
4055                             v8::Handle<Value> data) {
4056   CHECK(data->IsNumber());
4057   CHECK_EQ(1337, data->Int32Value());
4058   CHECK(!message->IsSharedCrossOrigin());
4059   message_received = true;
4060 }
4061
4062
4063 TEST(MessageHandler1) {
4064   message_received = false;
4065   v8::HandleScope scope(CcTest::isolate());
4066   CHECK(!message_received);
4067   v8::V8::AddMessageListener(check_message_1);
4068   LocalContext context;
4069   CompileRun("throw 1337;");
4070   CHECK(message_received);
4071   // clear out the message listener
4072   v8::V8::RemoveMessageListeners(check_message_1);
4073 }
4074
4075
4076 static void check_message_2(v8::Handle<v8::Message> message,
4077                             v8::Handle<Value> data) {
4078   LocalContext context;
4079   CHECK(data->IsObject());
4080   v8::Local<v8::Value> hidden_property =
4081       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4082   CHECK(v8_str("hidden value")->Equals(hidden_property));
4083   CHECK(!message->IsSharedCrossOrigin());
4084   message_received = true;
4085 }
4086
4087
4088 TEST(MessageHandler2) {
4089   message_received = false;
4090   v8::HandleScope scope(CcTest::isolate());
4091   CHECK(!message_received);
4092   v8::V8::AddMessageListener(check_message_2);
4093   LocalContext context;
4094   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4095   v8::Object::Cast(*error)
4096       ->SetHiddenValue(v8_str("hidden key"), v8_str("hidden value"));
4097   context->Global()->Set(v8_str("error"), error);
4098   CompileRun("throw error;");
4099   CHECK(message_received);
4100   // clear out the message listener
4101   v8::V8::RemoveMessageListeners(check_message_2);
4102 }
4103
4104
4105 static void check_message_3(v8::Handle<v8::Message> message,
4106                             v8::Handle<Value> data) {
4107   CHECK(message->IsSharedCrossOrigin());
4108   CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
4109   CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
4110   CHECK(message->GetScriptOrigin().Options().IsOpaque());
4111   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4112   CHECK_EQ(7.40, message->GetScriptOrigin().SourceMapUrl()->NumberValue());
4113   message_received = true;
4114 }
4115
4116
4117 TEST(MessageHandler3) {
4118   message_received = false;
4119   v8::Isolate* isolate = CcTest::isolate();
4120   v8::HandleScope scope(isolate);
4121   CHECK(!message_received);
4122   v8::V8::AddMessageListener(check_message_3);
4123   LocalContext context;
4124   v8::ScriptOrigin origin = v8::ScriptOrigin(
4125       v8_str("6.75"), v8::Integer::New(isolate, 1),
4126       v8::Integer::New(isolate, 2), v8::True(isolate), Handle<v8::Integer>(),
4127       v8::True(isolate), v8_str("7.40"), v8::True(isolate));
4128   v8::Handle<v8::Script> script =
4129       Script::Compile(v8_str("throw 'error'"), &origin);
4130   script->Run();
4131   CHECK(message_received);
4132   // clear out the message listener
4133   v8::V8::RemoveMessageListeners(check_message_3);
4134 }
4135
4136
4137 static void check_message_4(v8::Handle<v8::Message> message,
4138                             v8::Handle<Value> data) {
4139   CHECK(!message->IsSharedCrossOrigin());
4140   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4141   message_received = true;
4142 }
4143
4144
4145 TEST(MessageHandler4) {
4146   message_received = false;
4147   v8::Isolate* isolate = CcTest::isolate();
4148   v8::HandleScope scope(isolate);
4149   CHECK(!message_received);
4150   v8::V8::AddMessageListener(check_message_4);
4151   LocalContext context;
4152   v8::ScriptOrigin origin =
4153       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4154                        v8::Integer::New(isolate, 2), v8::False(isolate));
4155   v8::Handle<v8::Script> script =
4156       Script::Compile(v8_str("throw 'error'"), &origin);
4157   script->Run();
4158   CHECK(message_received);
4159   // clear out the message listener
4160   v8::V8::RemoveMessageListeners(check_message_4);
4161 }
4162
4163
4164 static void check_message_5a(v8::Handle<v8::Message> message,
4165                              v8::Handle<Value> data) {
4166   CHECK(message->IsSharedCrossOrigin());
4167   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4168   message_received = true;
4169 }
4170
4171
4172 static void check_message_5b(v8::Handle<v8::Message> message,
4173                              v8::Handle<Value> data) {
4174   CHECK(!message->IsSharedCrossOrigin());
4175   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4176   message_received = true;
4177 }
4178
4179
4180 TEST(MessageHandler5) {
4181   message_received = false;
4182   v8::Isolate* isolate = CcTest::isolate();
4183   v8::HandleScope scope(isolate);
4184   CHECK(!message_received);
4185   v8::V8::AddMessageListener(check_message_5a);
4186   LocalContext context;
4187   v8::ScriptOrigin origin1 =
4188       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4189                        v8::Integer::New(isolate, 2), v8::True(isolate));
4190   v8::Handle<v8::Script> script =
4191       Script::Compile(v8_str("throw 'error'"), &origin1);
4192   script->Run();
4193   CHECK(message_received);
4194   // clear out the message listener
4195   v8::V8::RemoveMessageListeners(check_message_5a);
4196
4197   message_received = false;
4198   v8::V8::AddMessageListener(check_message_5b);
4199   v8::ScriptOrigin origin2 =
4200       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4201                        v8::Integer::New(isolate, 2), v8::False(isolate));
4202   script = Script::Compile(v8_str("throw 'error'"), &origin2);
4203   script->Run();
4204   CHECK(message_received);
4205   // clear out the message listener
4206   v8::V8::RemoveMessageListeners(check_message_5b);
4207 }
4208
4209
4210 TEST(NativeWeakMap) {
4211   v8::Isolate* isolate = CcTest::isolate();
4212   HandleScope scope(isolate);
4213   Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
4214   CHECK(!weak_map.IsEmpty());
4215
4216   LocalContext env;
4217   Local<Object> value = v8::Object::New(isolate);
4218
4219   Local<Object> local1 = v8::Object::New(isolate);
4220   CHECK(!weak_map->Has(local1));
4221   CHECK(weak_map->Get(local1)->IsUndefined());
4222   weak_map->Set(local1, value);
4223   CHECK(weak_map->Has(local1));
4224   CHECK(value->Equals(weak_map->Get(local1)));
4225
4226   WeakCallCounter counter(1234);
4227   WeakCallCounterAndPersistent<Value> o1(&counter);
4228   WeakCallCounterAndPersistent<Value> o2(&counter);
4229   WeakCallCounterAndPersistent<Value> s1(&counter);
4230   {
4231     HandleScope scope(isolate);
4232     Local<v8::Object> obj1 = v8::Object::New(isolate);
4233     Local<v8::Object> obj2 = v8::Object::New(isolate);
4234     Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
4235
4236     weak_map->Set(obj1, value);
4237     weak_map->Set(obj2, value);
4238     weak_map->Set(sym1, value);
4239
4240     o1.handle.Reset(isolate, obj1);
4241     o2.handle.Reset(isolate, obj2);
4242     s1.handle.Reset(isolate, sym1);
4243
4244     CHECK(weak_map->Has(local1));
4245     CHECK(weak_map->Has(obj1));
4246     CHECK(weak_map->Has(obj2));
4247     CHECK(weak_map->Has(sym1));
4248
4249     CHECK(value->Equals(weak_map->Get(local1)));
4250     CHECK(value->Equals(weak_map->Get(obj1)));
4251     CHECK(value->Equals(weak_map->Get(obj2)));
4252     CHECK(value->Equals(weak_map->Get(sym1)));
4253   }
4254   CcTest::heap()->CollectAllGarbage();
4255   {
4256     HandleScope scope(isolate);
4257     CHECK(value->Equals(weak_map->Get(local1)));
4258     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o1.handle))));
4259     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o2.handle))));
4260     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, s1.handle))));
4261   }
4262
4263   o1.handle.SetWeak(&o1, &WeakPointerCallback,
4264                     v8::WeakCallbackType::kParameter);
4265   o2.handle.SetWeak(&o2, &WeakPointerCallback,
4266                     v8::WeakCallbackType::kParameter);
4267   s1.handle.SetWeak(&s1, &WeakPointerCallback,
4268                     v8::WeakCallbackType::kParameter);
4269
4270   CcTest::heap()->CollectAllGarbage();
4271   CHECK_EQ(3, counter.NumberOfWeakCalls());
4272
4273   CHECK(o1.handle.IsEmpty());
4274   CHECK(o2.handle.IsEmpty());
4275   CHECK(s1.handle.IsEmpty());
4276
4277   CHECK(value->Equals(weak_map->Get(local1)));
4278   CHECK(weak_map->Delete(local1));
4279   CHECK(!weak_map->Has(local1));
4280   CHECK(weak_map->Get(local1)->IsUndefined());
4281 }
4282
4283
4284 THREADED_TEST(GetSetProperty) {
4285   LocalContext context;
4286   v8::Isolate* isolate = context->GetIsolate();
4287   v8::HandleScope scope(isolate);
4288   context->Global()->Set(v8_str("foo"), v8_num(14));
4289   context->Global()->Set(v8_str("12"), v8_num(92));
4290   context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
4291   context->Global()->Set(v8_num(13), v8_num(56));
4292   Local<Value> foo = CompileRun("this.foo");
4293   CHECK_EQ(14, foo->Int32Value());
4294   Local<Value> twelve = CompileRun("this[12]");
4295   CHECK_EQ(92, twelve->Int32Value());
4296   Local<Value> sixteen = CompileRun("this[16]");
4297   CHECK_EQ(32, sixteen->Int32Value());
4298   Local<Value> thirteen = CompileRun("this[13]");
4299   CHECK_EQ(56, thirteen->Int32Value());
4300   CHECK_EQ(92,
4301            context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
4302   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4303   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
4304   CHECK_EQ(32,
4305            context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
4306   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4307   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
4308   CHECK_EQ(56,
4309            context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
4310   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4311   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4312 }
4313
4314
4315 THREADED_TEST(PropertyAttributes) {
4316   LocalContext context;
4317   v8::HandleScope scope(context->GetIsolate());
4318   // none
4319   Local<String> prop = v8_str("none");
4320   context->Global()->Set(prop, v8_num(7));
4321   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4322   // read-only
4323   prop = v8_str("read_only");
4324   context->Global()->ForceSet(prop, v8_num(7), v8::ReadOnly);
4325   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4326   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
4327   CompileRun("read_only = 9");
4328   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4329   context->Global()->Set(prop, v8_num(10));
4330   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4331   // dont-delete
4332   prop = v8_str("dont_delete");
4333   context->Global()->ForceSet(prop, v8_num(13), v8::DontDelete);
4334   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4335   CompileRun("delete dont_delete");
4336   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4337   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4338   // dont-enum
4339   prop = v8_str("dont_enum");
4340   context->Global()->ForceSet(prop, v8_num(28), v8::DontEnum);
4341   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4342   // absent
4343   prop = v8_str("absent");
4344   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4345   Local<Value> fake_prop = v8_num(1);
4346   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4347   // exception
4348   TryCatch try_catch(context->GetIsolate());
4349   Local<Value> exception =
4350       CompileRun("({ toString: function() { throw 'exception';} })");
4351   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4352   CHECK(try_catch.HasCaught());
4353   String::Utf8Value exception_value(try_catch.Exception());
4354   CHECK_EQ(0, strcmp("exception", *exception_value));
4355   try_catch.Reset();
4356 }
4357
4358
4359 THREADED_TEST(Array) {
4360   LocalContext context;
4361   v8::HandleScope scope(context->GetIsolate());
4362   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
4363   CHECK_EQ(0u, array->Length());
4364   CHECK(array->Get(0)->IsUndefined());
4365   CHECK(!array->Has(0));
4366   CHECK(array->Get(100)->IsUndefined());
4367   CHECK(!array->Has(100));
4368   array->Set(2, v8_num(7));
4369   CHECK_EQ(3u, array->Length());
4370   CHECK(!array->Has(0));
4371   CHECK(!array->Has(1));
4372   CHECK(array->Has(2));
4373   CHECK_EQ(7, array->Get(2)->Int32Value());
4374   Local<Value> obj = CompileRun("[1, 2, 3]");
4375   Local<v8::Array> arr = obj.As<v8::Array>();
4376   CHECK_EQ(3u, arr->Length());
4377   CHECK_EQ(1, arr->Get(0)->Int32Value());
4378   CHECK_EQ(2, arr->Get(1)->Int32Value());
4379   CHECK_EQ(3, arr->Get(2)->Int32Value());
4380   array = v8::Array::New(context->GetIsolate(), 27);
4381   CHECK_EQ(27u, array->Length());
4382   array = v8::Array::New(context->GetIsolate(), -27);
4383   CHECK_EQ(0u, array->Length());
4384 }
4385
4386
4387 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
4388   v8::EscapableHandleScope scope(args.GetIsolate());
4389   ApiTestFuzzer::Fuzz();
4390   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
4391   for (int i = 0; i < args.Length(); i++) result->Set(i, args[i]);
4392   args.GetReturnValue().Set(scope.Escape(result));
4393 }
4394
4395
4396 THREADED_TEST(Vector) {
4397   v8::Isolate* isolate = CcTest::isolate();
4398   v8::HandleScope scope(isolate);
4399   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
4400   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
4401   LocalContext context(0, global);
4402
4403   const char* fun = "f()";
4404   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
4405   CHECK_EQ(0u, a0->Length());
4406
4407   const char* fun2 = "f(11)";
4408   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
4409   CHECK_EQ(1u, a1->Length());
4410   CHECK_EQ(11, a1->Get(0)->Int32Value());
4411
4412   const char* fun3 = "f(12, 13)";
4413   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
4414   CHECK_EQ(2u, a2->Length());
4415   CHECK_EQ(12, a2->Get(0)->Int32Value());
4416   CHECK_EQ(13, a2->Get(1)->Int32Value());
4417
4418   const char* fun4 = "f(14, 15, 16)";
4419   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
4420   CHECK_EQ(3u, a3->Length());
4421   CHECK_EQ(14, a3->Get(0)->Int32Value());
4422   CHECK_EQ(15, a3->Get(1)->Int32Value());
4423   CHECK_EQ(16, a3->Get(2)->Int32Value());
4424
4425   const char* fun5 = "f(17, 18, 19, 20)";
4426   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
4427   CHECK_EQ(4u, a4->Length());
4428   CHECK_EQ(17, a4->Get(0)->Int32Value());
4429   CHECK_EQ(18, a4->Get(1)->Int32Value());
4430   CHECK_EQ(19, a4->Get(2)->Int32Value());
4431   CHECK_EQ(20, a4->Get(3)->Int32Value());
4432 }
4433
4434
4435 THREADED_TEST(FunctionCall) {
4436   LocalContext context;
4437   v8::Isolate* isolate = context->GetIsolate();
4438   v8::HandleScope scope(isolate);
4439   CompileRun(
4440       "function Foo() {"
4441       "  var result = [];"
4442       "  for (var i = 0; i < arguments.length; i++) {"
4443       "    result.push(arguments[i]);"
4444       "  }"
4445       "  return result;"
4446       "}"
4447       "function ReturnThisSloppy() {"
4448       "  return this;"
4449       "}"
4450       "function ReturnThisStrict() {"
4451       "  'use strict';"
4452       "  return this;"
4453       "}");
4454   Local<Function> Foo =
4455       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4456   Local<Function> ReturnThisSloppy =
4457       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4458   Local<Function> ReturnThisStrict =
4459       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
4460
4461   v8::Handle<Value>* args0 = NULL;
4462   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4463   CHECK_EQ(0u, a0->Length());
4464
4465   v8::Handle<Value> args1[] = {v8_num(1.1)};
4466   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4467   CHECK_EQ(1u, a1->Length());
4468   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4469
4470   v8::Handle<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
4471   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4472   CHECK_EQ(2u, a2->Length());
4473   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4474   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4475
4476   v8::Handle<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
4477   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4478   CHECK_EQ(3u, a3->Length());
4479   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4480   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4481   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4482
4483   v8::Handle<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
4484                                v8_num(10.11)};
4485   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4486   CHECK_EQ(4u, a4->Length());
4487   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4488   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4489   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4490   CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4491
4492   Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4493   CHECK(r1->StrictEquals(context->Global()));
4494   Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4495   CHECK(r2->StrictEquals(context->Global()));
4496   Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4497   CHECK(r3->IsNumberObject());
4498   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4499   Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4500   CHECK(r4->IsStringObject());
4501   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4502   Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4503   CHECK(r5->IsBooleanObject());
4504   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4505
4506   Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4507   CHECK(r6->IsUndefined());
4508   Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4509   CHECK(r7->IsNull());
4510   Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4511   CHECK(r8->StrictEquals(v8_num(42)));
4512   Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4513   CHECK(r9->StrictEquals(v8_str("hello")));
4514   Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4515   CHECK(r10->StrictEquals(v8::True(isolate)));
4516 }
4517
4518
4519 THREADED_TEST(ConstructCall) {
4520   LocalContext context;
4521   v8::Isolate* isolate = context->GetIsolate();
4522   v8::HandleScope scope(isolate);
4523   CompileRun(
4524       "function Foo() {"
4525       "  var result = [];"
4526       "  for (var i = 0; i < arguments.length; i++) {"
4527       "    result.push(arguments[i]);"
4528       "  }"
4529       "  return result;"
4530       "}");
4531   Local<Function> Foo =
4532       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4533
4534   v8::Handle<Value>* args0 = NULL;
4535   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4536   CHECK_EQ(0u, a0->Length());
4537
4538   v8::Handle<Value> args1[] = {v8_num(1.1)};
4539   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4540   CHECK_EQ(1u, a1->Length());
4541   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4542
4543   v8::Handle<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
4544   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4545   CHECK_EQ(2u, a2->Length());
4546   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4547   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4548
4549   v8::Handle<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
4550   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4551   CHECK_EQ(3u, a3->Length());
4552   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4553   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4554   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4555
4556   v8::Handle<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
4557                                v8_num(10.11)};
4558   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4559   CHECK_EQ(4u, a4->Length());
4560   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4561   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4562   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4563   CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4564 }
4565
4566
4567 static void CheckUncle(v8::TryCatch* try_catch) {
4568   CHECK(try_catch->HasCaught());
4569   String::Utf8Value str_value(try_catch->Exception());
4570   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
4571   try_catch->Reset();
4572 }
4573
4574
4575 THREADED_TEST(ConversionNumber) {
4576   LocalContext env;
4577   v8::Isolate* isolate = env->GetIsolate();
4578   v8::HandleScope scope(isolate);
4579   // Very large number.
4580   CompileRun("var obj = Math.pow(2,32) * 1237;");
4581   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4582   CHECK_EQ(5312874545152.0, obj->ToNumber(isolate)->Value());
4583   CHECK_EQ(0, obj->ToInt32(isolate)->Value());
4584   CHECK(0u ==
4585         obj->ToUint32(isolate)->Value());  // NOLINT - no CHECK_EQ for unsigned.
4586   // Large number.
4587   CompileRun("var obj = -1234567890123;");
4588   obj = env->Global()->Get(v8_str("obj"));
4589   CHECK_EQ(-1234567890123.0, obj->ToNumber(isolate)->Value());
4590   CHECK_EQ(-1912276171, obj->ToInt32(isolate)->Value());
4591   CHECK(2382691125u == obj->ToUint32(isolate)->Value());  // NOLINT
4592   // Small positive integer.
4593   CompileRun("var obj = 42;");
4594   obj = env->Global()->Get(v8_str("obj"));
4595   CHECK_EQ(42.0, obj->ToNumber(isolate)->Value());
4596   CHECK_EQ(42, obj->ToInt32(isolate)->Value());
4597   CHECK(42u == obj->ToUint32(isolate)->Value());  // NOLINT
4598   // Negative integer.
4599   CompileRun("var obj = -37;");
4600   obj = env->Global()->Get(v8_str("obj"));
4601   CHECK_EQ(-37.0, obj->ToNumber(isolate)->Value());
4602   CHECK_EQ(-37, obj->ToInt32(isolate)->Value());
4603   CHECK(4294967259u == obj->ToUint32(isolate)->Value());  // NOLINT
4604   // Positive non-int32 integer.
4605   CompileRun("var obj = 0x81234567;");
4606   obj = env->Global()->Get(v8_str("obj"));
4607   CHECK_EQ(2166572391.0, obj->ToNumber(isolate)->Value());
4608   CHECK_EQ(-2128394905, obj->ToInt32(isolate)->Value());
4609   CHECK(2166572391u == obj->ToUint32(isolate)->Value());  // NOLINT
4610   // Fraction.
4611   CompileRun("var obj = 42.3;");
4612   obj = env->Global()->Get(v8_str("obj"));
4613   CHECK_EQ(42.3, obj->ToNumber(isolate)->Value());
4614   CHECK_EQ(42, obj->ToInt32(isolate)->Value());
4615   CHECK(42u == obj->ToUint32(isolate)->Value());  // NOLINT
4616   // Large negative fraction.
4617   CompileRun("var obj = -5726623061.75;");
4618   obj = env->Global()->Get(v8_str("obj"));
4619   CHECK_EQ(-5726623061.75, obj->ToNumber(isolate)->Value());
4620   CHECK_EQ(-1431655765, obj->ToInt32(isolate)->Value());
4621   CHECK(2863311531u == obj->ToUint32(isolate)->Value());  // NOLINT
4622 }
4623
4624
4625 THREADED_TEST(isNumberType) {
4626   LocalContext env;
4627   v8::HandleScope scope(env->GetIsolate());
4628   // Very large number.
4629   CompileRun("var obj = Math.pow(2,32) * 1237;");
4630   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4631   CHECK(!obj->IsInt32());
4632   CHECK(!obj->IsUint32());
4633   // Large negative number.
4634   CompileRun("var obj = -1234567890123;");
4635   obj = env->Global()->Get(v8_str("obj"));
4636   CHECK(!obj->IsInt32());
4637   CHECK(!obj->IsUint32());
4638   // Small positive integer.
4639   CompileRun("var obj = 42;");
4640   obj = env->Global()->Get(v8_str("obj"));
4641   CHECK(obj->IsInt32());
4642   CHECK(obj->IsUint32());
4643   // Negative integer.
4644   CompileRun("var obj = -37;");
4645   obj = env->Global()->Get(v8_str("obj"));
4646   CHECK(obj->IsInt32());
4647   CHECK(!obj->IsUint32());
4648   // Positive non-int32 integer.
4649   CompileRun("var obj = 0x81234567;");
4650   obj = env->Global()->Get(v8_str("obj"));
4651   CHECK(!obj->IsInt32());
4652   CHECK(obj->IsUint32());
4653   // Fraction.
4654   CompileRun("var obj = 42.3;");
4655   obj = env->Global()->Get(v8_str("obj"));
4656   CHECK(!obj->IsInt32());
4657   CHECK(!obj->IsUint32());
4658   // Large negative fraction.
4659   CompileRun("var obj = -5726623061.75;");
4660   obj = env->Global()->Get(v8_str("obj"));
4661   CHECK(!obj->IsInt32());
4662   CHECK(!obj->IsUint32());
4663   // Positive zero
4664   CompileRun("var obj = 0.0;");
4665   obj = env->Global()->Get(v8_str("obj"));
4666   CHECK(obj->IsInt32());
4667   CHECK(obj->IsUint32());
4668   // Positive zero
4669   CompileRun("var obj = -0.0;");
4670   obj = env->Global()->Get(v8_str("obj"));
4671   CHECK(!obj->IsInt32());
4672   CHECK(!obj->IsUint32());
4673 }
4674
4675
4676 THREADED_TEST(ConversionException) {
4677   LocalContext env;
4678   v8::Isolate* isolate = env->GetIsolate();
4679   v8::HandleScope scope(isolate);
4680   CompileRun(
4681       "function TestClass() { };"
4682       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4683       "var obj = new TestClass();");
4684   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4685
4686   v8::TryCatch try_catch(isolate);
4687
4688   Local<Value> to_string_result = obj->ToString(isolate);
4689   CHECK(to_string_result.IsEmpty());
4690   CheckUncle(&try_catch);
4691
4692   Local<Value> to_number_result = obj->ToNumber(isolate);
4693   CHECK(to_number_result.IsEmpty());
4694   CheckUncle(&try_catch);
4695
4696   Local<Value> to_integer_result = obj->ToInteger(isolate);
4697   CHECK(to_integer_result.IsEmpty());
4698   CheckUncle(&try_catch);
4699
4700   Local<Value> to_uint32_result = obj->ToUint32(isolate);
4701   CHECK(to_uint32_result.IsEmpty());
4702   CheckUncle(&try_catch);
4703
4704   Local<Value> to_int32_result = obj->ToInt32(isolate);
4705   CHECK(to_int32_result.IsEmpty());
4706   CheckUncle(&try_catch);
4707
4708   Local<Value> to_object_result = v8::Undefined(isolate)->ToObject(isolate);
4709   CHECK(to_object_result.IsEmpty());
4710   CHECK(try_catch.HasCaught());
4711   try_catch.Reset();
4712
4713   int32_t int32_value = obj->Int32Value();
4714   CHECK_EQ(0, int32_value);
4715   CheckUncle(&try_catch);
4716
4717   uint32_t uint32_value = obj->Uint32Value();
4718   CHECK_EQ(0u, uint32_value);
4719   CheckUncle(&try_catch);
4720
4721   double number_value = obj->NumberValue();
4722   CHECK(std::isnan(number_value));
4723   CheckUncle(&try_catch);
4724
4725   int64_t integer_value = obj->IntegerValue();
4726   CHECK_EQ(0, integer_value);
4727   CheckUncle(&try_catch);
4728 }
4729
4730
4731 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
4732   ApiTestFuzzer::Fuzz();
4733   args.GetIsolate()->ThrowException(v8_str("konto"));
4734 }
4735
4736
4737 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4738   if (args.Length() < 1) {
4739     args.GetReturnValue().Set(false);
4740     return;
4741   }
4742   v8::HandleScope scope(args.GetIsolate());
4743   v8::TryCatch try_catch(args.GetIsolate());
4744   Local<Value> result = CompileRun(args[0]->ToString(args.GetIsolate()));
4745   CHECK(!try_catch.HasCaught() || result.IsEmpty());
4746   args.GetReturnValue().Set(try_catch.HasCaught());
4747 }
4748
4749
4750 THREADED_TEST(APICatch) {
4751   v8::Isolate* isolate = CcTest::isolate();
4752   v8::HandleScope scope(isolate);
4753   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4754   templ->Set(v8_str("ThrowFromC"),
4755              v8::FunctionTemplate::New(isolate, ThrowFromC));
4756   LocalContext context(0, templ);
4757   CompileRun(
4758       "var thrown = false;"
4759       "try {"
4760       "  ThrowFromC();"
4761       "} catch (e) {"
4762       "  thrown = true;"
4763       "}");
4764   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4765   CHECK(thrown->BooleanValue());
4766 }
4767
4768
4769 THREADED_TEST(APIThrowTryCatch) {
4770   v8::Isolate* isolate = CcTest::isolate();
4771   v8::HandleScope scope(isolate);
4772   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4773   templ->Set(v8_str("ThrowFromC"),
4774              v8::FunctionTemplate::New(isolate, ThrowFromC));
4775   LocalContext context(0, templ);
4776   v8::TryCatch try_catch(isolate);
4777   CompileRun("ThrowFromC();");
4778   CHECK(try_catch.HasCaught());
4779 }
4780
4781
4782 // Test that a try-finally block doesn't shadow a try-catch block
4783 // when setting up an external handler.
4784 //
4785 // BUG(271): Some of the exception propagation does not work on the
4786 // ARM simulator because the simulator separates the C++ stack and the
4787 // JS stack.  This test therefore fails on the simulator.  The test is
4788 // not threaded to allow the threading tests to run on the simulator.
4789 TEST(TryCatchInTryFinally) {
4790   v8::Isolate* isolate = CcTest::isolate();
4791   v8::HandleScope scope(isolate);
4792   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4793   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
4794   LocalContext context(0, templ);
4795   Local<Value> result = CompileRun(
4796       "try {"
4797       "  try {"
4798       "    CCatcher('throw 7;');"
4799       "  } finally {"
4800       "  }"
4801       "} catch (e) {"
4802       "}");
4803   CHECK(result->IsTrue());
4804 }
4805
4806
4807 static void check_reference_error_message(v8::Handle<v8::Message> message,
4808                                           v8::Handle<v8::Value> data) {
4809   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4810   CHECK(message->Get()->Equals(v8_str(reference_error)));
4811 }
4812
4813
4814 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
4815   ApiTestFuzzer::Fuzz();
4816   CHECK(false);
4817 }
4818
4819
4820 // Test that overwritten methods are not invoked on uncaught exception
4821 // formatting. However, they are invoked when performing normal error
4822 // string conversions.
4823 TEST(APIThrowMessageOverwrittenToString) {
4824   v8::Isolate* isolate = CcTest::isolate();
4825   v8::HandleScope scope(isolate);
4826   v8::V8::AddMessageListener(check_reference_error_message);
4827   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4828   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
4829   LocalContext context(NULL, templ);
4830   CompileRun("asdf;");
4831   CompileRun(
4832       "var limit = {};"
4833       "limit.valueOf = fail;"
4834       "Error.stackTraceLimit = limit;");
4835   CompileRun("asdf");
4836   CompileRun("Array.prototype.pop = fail;");
4837   CompileRun("Object.prototype.hasOwnProperty = fail;");
4838   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
4839   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4840   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
4841   CompileRun(
4842       "ReferenceError.prototype.toString ="
4843       "  function() { return 'Whoops' }");
4844   CompileRun("asdf;");
4845   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4846   CompileRun("asdf;");
4847   CompileRun("ReferenceError.prototype.constructor = void 0;");
4848   CompileRun("asdf;");
4849   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4850   CompileRun("asdf;");
4851   CompileRun("ReferenceError.prototype = new Object();");
4852   CompileRun("asdf;");
4853   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4854   CHECK(string->Equals(v8_str("Whoops")));
4855   CompileRun(
4856       "ReferenceError.prototype.constructor = new Object();"
4857       "ReferenceError.prototype.constructor.name = 1;"
4858       "Number.prototype.toString = function() { return 'Whoops'; };"
4859       "ReferenceError.prototype.toString = Object.prototype.toString;");
4860   CompileRun("asdf;");
4861   v8::V8::RemoveMessageListeners(check_reference_error_message);
4862 }
4863
4864
4865 static void check_custom_error_tostring(v8::Handle<v8::Message> message,
4866                                         v8::Handle<v8::Value> data) {
4867   const char* uncaught_error = "Uncaught MyError toString";
4868   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4869 }
4870
4871
4872 TEST(CustomErrorToString) {
4873   LocalContext context;
4874   v8::HandleScope scope(context->GetIsolate());
4875   v8::V8::AddMessageListener(check_custom_error_tostring);
4876   CompileRun(
4877       "function MyError(name, message) {                   "
4878       "  this.name = name;                                 "
4879       "  this.message = message;                           "
4880       "}                                                   "
4881       "MyError.prototype = Object.create(Error.prototype); "
4882       "MyError.prototype.toString = function() {           "
4883       "  return 'MyError toString';                        "
4884       "};                                                  "
4885       "throw new MyError('my name', 'my message');         ");
4886   v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4887 }
4888
4889
4890 static void check_custom_error_message(v8::Handle<v8::Message> message,
4891                                        v8::Handle<v8::Value> data) {
4892   const char* uncaught_error = "Uncaught MyError: my message";
4893   printf("%s\n", *v8::String::Utf8Value(message->Get()));
4894   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4895 }
4896
4897
4898 TEST(CustomErrorMessage) {
4899   LocalContext context;
4900   v8::HandleScope scope(context->GetIsolate());
4901   v8::V8::AddMessageListener(check_custom_error_message);
4902
4903   // Handlebars.
4904   CompileRun(
4905       "function MyError(msg) {                             "
4906       "  this.name = 'MyError';                            "
4907       "  this.message = msg;                               "
4908       "}                                                   "
4909       "MyError.prototype = new Error();                    "
4910       "throw new MyError('my message');                    ");
4911
4912   // Closure.
4913   CompileRun(
4914       "function MyError(msg) {                             "
4915       "  this.name = 'MyError';                            "
4916       "  this.message = msg;                               "
4917       "}                                                   "
4918       "inherits = function(childCtor, parentCtor) {        "
4919       "    function tempCtor() {};                         "
4920       "    tempCtor.prototype = parentCtor.prototype;      "
4921       "    childCtor.superClass_ = parentCtor.prototype;   "
4922       "    childCtor.prototype = new tempCtor();           "
4923       "    childCtor.prototype.constructor = childCtor;    "
4924       "};                                                  "
4925       "inherits(MyError, Error);                           "
4926       "throw new MyError('my message');                    ");
4927
4928   // Object.create.
4929   CompileRun(
4930       "function MyError(msg) {                             "
4931       "  this.name = 'MyError';                            "
4932       "  this.message = msg;                               "
4933       "}                                                   "
4934       "MyError.prototype = Object.create(Error.prototype); "
4935       "throw new MyError('my message');                    ");
4936
4937   v8::V8::RemoveMessageListeners(check_custom_error_message);
4938 }
4939
4940
4941 static void check_custom_rethrowing_message(v8::Handle<v8::Message> message,
4942                                             v8::Handle<v8::Value> data) {
4943   const char* uncaught_error = "Uncaught exception";
4944   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4945 }
4946
4947
4948 TEST(CustomErrorRethrowsOnToString) {
4949   LocalContext context;
4950   v8::HandleScope scope(context->GetIsolate());
4951   v8::V8::AddMessageListener(check_custom_rethrowing_message);
4952
4953   CompileRun(
4954       "var e = { toString: function() { throw e; } };"
4955       "try { throw e; } finally {}");
4956
4957   v8::V8::RemoveMessageListeners(check_custom_rethrowing_message);
4958 }
4959
4960
4961 static void receive_message(v8::Handle<v8::Message> message,
4962                             v8::Handle<v8::Value> data) {
4963   message->Get();
4964   message_received = true;
4965 }
4966
4967
4968 TEST(APIThrowMessage) {
4969   message_received = false;
4970   v8::Isolate* isolate = CcTest::isolate();
4971   v8::HandleScope scope(isolate);
4972   v8::V8::AddMessageListener(receive_message);
4973   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4974   templ->Set(v8_str("ThrowFromC"),
4975              v8::FunctionTemplate::New(isolate, ThrowFromC));
4976   LocalContext context(0, templ);
4977   CompileRun("ThrowFromC();");
4978   CHECK(message_received);
4979   v8::V8::RemoveMessageListeners(receive_message);
4980 }
4981
4982
4983 TEST(APIThrowMessageAndVerboseTryCatch) {
4984   message_received = false;
4985   v8::Isolate* isolate = CcTest::isolate();
4986   v8::HandleScope scope(isolate);
4987   v8::V8::AddMessageListener(receive_message);
4988   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4989   templ->Set(v8_str("ThrowFromC"),
4990              v8::FunctionTemplate::New(isolate, ThrowFromC));
4991   LocalContext context(0, templ);
4992   v8::TryCatch try_catch(isolate);
4993   try_catch.SetVerbose(true);
4994   Local<Value> result = CompileRun("ThrowFromC();");
4995   CHECK(try_catch.HasCaught());
4996   CHECK(result.IsEmpty());
4997   CHECK(message_received);
4998   v8::V8::RemoveMessageListeners(receive_message);
4999 }
5000
5001
5002 TEST(APIStackOverflowAndVerboseTryCatch) {
5003   message_received = false;
5004   LocalContext context;
5005   v8::HandleScope scope(context->GetIsolate());
5006   v8::V8::AddMessageListener(receive_message);
5007   v8::TryCatch try_catch(context->GetIsolate());
5008   try_catch.SetVerbose(true);
5009   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
5010   CHECK(try_catch.HasCaught());
5011   CHECK(result.IsEmpty());
5012   CHECK(message_received);
5013   v8::V8::RemoveMessageListeners(receive_message);
5014 }
5015
5016
5017 THREADED_TEST(ExternalScriptException) {
5018   v8::Isolate* isolate = CcTest::isolate();
5019   v8::HandleScope scope(isolate);
5020   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5021   templ->Set(v8_str("ThrowFromC"),
5022              v8::FunctionTemplate::New(isolate, ThrowFromC));
5023   LocalContext context(0, templ);
5024
5025   v8::TryCatch try_catch(isolate);
5026   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
5027   CHECK(result.IsEmpty());
5028   CHECK(try_catch.HasCaught());
5029   String::Utf8Value exception_value(try_catch.Exception());
5030   CHECK_EQ(0, strcmp("konto", *exception_value));
5031 }
5032
5033
5034 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
5035   ApiTestFuzzer::Fuzz();
5036   CHECK_EQ(4, args.Length());
5037   int count = args[0]->Int32Value();
5038   int cInterval = args[2]->Int32Value();
5039   if (count == 0) {
5040     args.GetIsolate()->ThrowException(v8_str("FromC"));
5041     return;
5042   } else {
5043     Local<v8::Object> global = args.GetIsolate()->GetCurrentContext()->Global();
5044     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5045     v8::Handle<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
5046     if (count % cInterval == 0) {
5047       v8::TryCatch try_catch(args.GetIsolate());
5048       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
5049       int expected = args[3]->Int32Value();
5050       if (try_catch.HasCaught()) {
5051         CHECK_EQ(expected, count);
5052         CHECK(result.IsEmpty());
5053         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
5054       } else {
5055         CHECK_NE(expected, count);
5056       }
5057       args.GetReturnValue().Set(result);
5058       return;
5059     } else {
5060       args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5061       return;
5062     }
5063   }
5064 }
5065
5066
5067 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
5068   ApiTestFuzzer::Fuzz();
5069   CHECK_EQ(3, args.Length());
5070   bool equality = args[0]->BooleanValue();
5071   int count = args[1]->Int32Value();
5072   int expected = args[2]->Int32Value();
5073   if (equality) {
5074     CHECK_EQ(count, expected);
5075   } else {
5076     CHECK_NE(count, expected);
5077   }
5078 }
5079
5080
5081 THREADED_TEST(EvalInTryFinally) {
5082   LocalContext context;
5083   v8::HandleScope scope(context->GetIsolate());
5084   v8::TryCatch try_catch(context->GetIsolate());
5085   CompileRun(
5086       "(function() {"
5087       "  try {"
5088       "    eval('asldkf (*&^&*^');"
5089       "  } finally {"
5090       "    return;"
5091       "  }"
5092       "})()");
5093   CHECK(!try_catch.HasCaught());
5094 }
5095
5096
5097 // This test works by making a stack of alternating JavaScript and C
5098 // activations.  These activations set up exception handlers with regular
5099 // intervals, one interval for C activations and another for JavaScript
5100 // activations.  When enough activations have been created an exception is
5101 // thrown and we check that the right activation catches the exception and that
5102 // no other activations do.  The right activation is always the topmost one with
5103 // a handler, regardless of whether it is in JavaScript or C.
5104 //
5105 // The notation used to describe a test case looks like this:
5106 //
5107 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
5108 //
5109 // Each entry is an activation, either JS or C.  The index is the count at that
5110 // level.  Stars identify activations with exception handlers, the @ identifies
5111 // the exception handler that should catch the exception.
5112 //
5113 // BUG(271): Some of the exception propagation does not work on the
5114 // ARM simulator because the simulator separates the C++ stack and the
5115 // JS stack.  This test therefore fails on the simulator.  The test is
5116 // not threaded to allow the threading tests to run on the simulator.
5117 TEST(ExceptionOrder) {
5118   v8::Isolate* isolate = CcTest::isolate();
5119   v8::HandleScope scope(isolate);
5120   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5121   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
5122   templ->Set(v8_str("CThrowCountDown"),
5123              v8::FunctionTemplate::New(isolate, CThrowCountDown));
5124   LocalContext context(0, templ);
5125   CompileRun(
5126       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5127       "  if (count == 0) throw 'FromJS';"
5128       "  if (count % jsInterval == 0) {"
5129       "    try {"
5130       "      var value = CThrowCountDown(count - 1,"
5131       "                                  jsInterval,"
5132       "                                  cInterval,"
5133       "                                  expected);"
5134       "      check(false, count, expected);"
5135       "      return value;"
5136       "    } catch (e) {"
5137       "      check(true, count, expected);"
5138       "    }"
5139       "  } else {"
5140       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5141       "  }"
5142       "}");
5143   Local<Function> fun =
5144       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5145
5146   const int argc = 4;
5147   //                             count      jsInterval cInterval  expected
5148
5149   // *JS[4] *C[3] @JS[2] C[1] JS[0]
5150   v8::Handle<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
5151   fun->Call(fun, argc, a0);
5152
5153   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
5154   v8::Handle<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
5155   fun->Call(fun, argc, a1);
5156
5157   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
5158   v8::Handle<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
5159   fun->Call(fun, argc, a2);
5160
5161   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
5162   v8::Handle<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
5163   fun->Call(fun, argc, a3);
5164
5165   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
5166   v8::Handle<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
5167   fun->Call(fun, argc, a4);
5168
5169   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
5170   v8::Handle<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
5171   fun->Call(fun, argc, a5);
5172 }
5173
5174
5175 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
5176   ApiTestFuzzer::Fuzz();
5177   CHECK_EQ(1, args.Length());
5178   args.GetIsolate()->ThrowException(args[0]);
5179 }
5180
5181
5182 THREADED_TEST(ThrowValues) {
5183   v8::Isolate* isolate = CcTest::isolate();
5184   v8::HandleScope scope(isolate);
5185   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5186   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
5187   LocalContext context(0, templ);
5188   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5189       "function Run(obj) {"
5190       "  try {"
5191       "    Throw(obj);"
5192       "  } catch (e) {"
5193       "    return e;"
5194       "  }"
5195       "  return 'no exception';"
5196       "}"
5197       "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5198   CHECK_EQ(5u, result->Length());
5199   CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5200   CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5201   CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5202   CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5203   CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5204   CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5205   CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
5206 }
5207
5208
5209 THREADED_TEST(CatchZero) {
5210   LocalContext context;
5211   v8::HandleScope scope(context->GetIsolate());
5212   v8::TryCatch try_catch(context->GetIsolate());
5213   CHECK(!try_catch.HasCaught());
5214   CompileRun("throw 10");
5215   CHECK(try_catch.HasCaught());
5216   CHECK_EQ(10, try_catch.Exception()->Int32Value());
5217   try_catch.Reset();
5218   CHECK(!try_catch.HasCaught());
5219   CompileRun("throw 0");
5220   CHECK(try_catch.HasCaught());
5221   CHECK_EQ(0, try_catch.Exception()->Int32Value());
5222 }
5223
5224
5225 THREADED_TEST(CatchExceptionFromWith) {
5226   LocalContext context;
5227   v8::HandleScope scope(context->GetIsolate());
5228   v8::TryCatch try_catch(context->GetIsolate());
5229   CHECK(!try_catch.HasCaught());
5230   CompileRun("var o = {}; with (o) { throw 42; }");
5231   CHECK(try_catch.HasCaught());
5232 }
5233
5234
5235 THREADED_TEST(TryCatchAndFinallyHidingException) {
5236   LocalContext context;
5237   v8::HandleScope scope(context->GetIsolate());
5238   v8::TryCatch try_catch(context->GetIsolate());
5239   CHECK(!try_catch.HasCaught());
5240   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5241   CompileRun("f({toString: function() { throw 42; }});");
5242   CHECK(!try_catch.HasCaught());
5243 }
5244
5245
5246 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
5247   v8::TryCatch try_catch(args.GetIsolate());
5248 }
5249
5250
5251 THREADED_TEST(TryCatchAndFinally) {
5252   LocalContext context;
5253   v8::Isolate* isolate = context->GetIsolate();
5254   v8::HandleScope scope(isolate);
5255   context->Global()->Set(
5256       v8_str("native_with_try_catch"),
5257       v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
5258   v8::TryCatch try_catch(isolate);
5259   CHECK(!try_catch.HasCaught());
5260   CompileRun(
5261       "try {\n"
5262       "  throw new Error('a');\n"
5263       "} finally {\n"
5264       "  native_with_try_catch();\n"
5265       "}\n");
5266   CHECK(try_catch.HasCaught());
5267 }
5268
5269
5270 static void TryCatchNested1Helper(int depth) {
5271   if (depth > 0) {
5272     v8::TryCatch try_catch(CcTest::isolate());
5273     try_catch.SetVerbose(true);
5274     TryCatchNested1Helper(depth - 1);
5275     CHECK(try_catch.HasCaught());
5276     try_catch.ReThrow();
5277   } else {
5278     CcTest::isolate()->ThrowException(v8_str("E1"));
5279   }
5280 }
5281
5282
5283 static void TryCatchNested2Helper(int depth) {
5284   if (depth > 0) {
5285     v8::TryCatch try_catch(CcTest::isolate());
5286     try_catch.SetVerbose(true);
5287     TryCatchNested2Helper(depth - 1);
5288     CHECK(try_catch.HasCaught());
5289     try_catch.ReThrow();
5290   } else {
5291     CompileRun("throw 'E2';");
5292   }
5293 }
5294
5295
5296 TEST(TryCatchNested) {
5297   v8::V8::Initialize();
5298   LocalContext context;
5299   v8::HandleScope scope(context->GetIsolate());
5300
5301   {
5302     // Test nested try-catch with a native throw in the end.
5303     v8::TryCatch try_catch(context->GetIsolate());
5304     TryCatchNested1Helper(5);
5305     CHECK(try_catch.HasCaught());
5306     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
5307   }
5308
5309   {
5310     // Test nested try-catch with a JavaScript throw in the end.
5311     v8::TryCatch try_catch(context->GetIsolate());
5312     TryCatchNested2Helper(5);
5313     CHECK(try_catch.HasCaught());
5314     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
5315   }
5316 }
5317
5318
5319 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5320   CHECK(try_catch->HasCaught());
5321   Handle<Message> message = try_catch->Message();
5322   Handle<Value> resource = message->GetScriptOrigin().ResourceName();
5323   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5324   CHECK_EQ(0,
5325            strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
5326   CHECK_EQ(1, message->GetLineNumber());
5327   CHECK_EQ(0, message->GetStartColumn());
5328 }
5329
5330
5331 void TryCatchMixedNestingHelper(
5332     const v8::FunctionCallbackInfo<v8::Value>& args) {
5333   ApiTestFuzzer::Fuzz();
5334   v8::TryCatch try_catch(args.GetIsolate());
5335   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5336   CHECK(try_catch.HasCaught());
5337   TryCatchMixedNestingCheck(&try_catch);
5338   try_catch.ReThrow();
5339 }
5340
5341
5342 // This test ensures that an outer TryCatch in the following situation:
5343 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5344 // does not clobber the Message object generated for the inner TryCatch.
5345 // This exercises the ability of TryCatch.ReThrow() to restore the
5346 // inner pending Message before throwing the exception again.
5347 TEST(TryCatchMixedNesting) {
5348   v8::Isolate* isolate = CcTest::isolate();
5349   v8::HandleScope scope(isolate);
5350   v8::V8::Initialize();
5351   v8::TryCatch try_catch(isolate);
5352   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5353   templ->Set(v8_str("TryCatchMixedNestingHelper"),
5354              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
5355   LocalContext context(0, templ);
5356   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5357   TryCatchMixedNestingCheck(&try_catch);
5358 }
5359
5360
5361 void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
5362   ApiTestFuzzer::Fuzz();
5363   v8::TryCatch try_catch(args.GetIsolate());
5364   args.GetIsolate()->ThrowException(v8_str("boom"));
5365   CHECK(try_catch.HasCaught());
5366 }
5367
5368
5369 TEST(TryCatchNative) {
5370   v8::Isolate* isolate = CcTest::isolate();
5371   v8::HandleScope scope(isolate);
5372   v8::V8::Initialize();
5373   v8::TryCatch try_catch(isolate);
5374   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5375   templ->Set(v8_str("TryCatchNativeHelper"),
5376              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
5377   LocalContext context(0, templ);
5378   CompileRun("TryCatchNativeHelper();");
5379   CHECK(!try_catch.HasCaught());
5380 }
5381
5382
5383 void TryCatchNativeResetHelper(
5384     const v8::FunctionCallbackInfo<v8::Value>& args) {
5385   ApiTestFuzzer::Fuzz();
5386   v8::TryCatch try_catch(args.GetIsolate());
5387   args.GetIsolate()->ThrowException(v8_str("boom"));
5388   CHECK(try_catch.HasCaught());
5389   try_catch.Reset();
5390   CHECK(!try_catch.HasCaught());
5391 }
5392
5393
5394 TEST(TryCatchNativeReset) {
5395   v8::Isolate* isolate = CcTest::isolate();
5396   v8::HandleScope scope(isolate);
5397   v8::V8::Initialize();
5398   v8::TryCatch try_catch(isolate);
5399   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5400   templ->Set(v8_str("TryCatchNativeResetHelper"),
5401              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
5402   LocalContext context(0, templ);
5403   CompileRun("TryCatchNativeResetHelper();");
5404   CHECK(!try_catch.HasCaught());
5405 }
5406
5407
5408 THREADED_TEST(Equality) {
5409   LocalContext context;
5410   v8::Isolate* isolate = context->GetIsolate();
5411   v8::HandleScope scope(context->GetIsolate());
5412   // Check that equality works at all before relying on CHECK_EQ
5413   CHECK(v8_str("a")->Equals(v8_str("a")));
5414   CHECK(!v8_str("a")->Equals(v8_str("b")));
5415
5416   CHECK(v8_str("a")->Equals(v8_str("a")));
5417   CHECK(!v8_str("a")->Equals(v8_str("b")));
5418   CHECK(v8_num(1)->Equals(v8_num(1)));
5419   CHECK(v8_num(1.00)->Equals(v8_num(1)));
5420   CHECK(!v8_num(1)->Equals(v8_num(2)));
5421
5422   // Assume String is not internalized.
5423   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5424   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5425   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5426   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5427   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
5428   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
5429   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
5430   CHECK(!not_a_number->StrictEquals(not_a_number));
5431   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5432   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
5433
5434   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
5435   v8::Persistent<v8::Object> alias(isolate, obj);
5436   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
5437   alias.Reset();
5438
5439   CHECK(v8_str("a")->SameValue(v8_str("a")));
5440   CHECK(!v8_str("a")->SameValue(v8_str("b")));
5441   CHECK(!v8_str("5")->SameValue(v8_num(5)));
5442   CHECK(v8_num(1)->SameValue(v8_num(1)));
5443   CHECK(!v8_num(1)->SameValue(v8_num(2)));
5444   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5445   CHECK(not_a_number->SameValue(not_a_number));
5446   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5447   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
5448 }
5449
5450
5451 THREADED_TEST(MultiRun) {
5452   LocalContext context;
5453   v8::HandleScope scope(context->GetIsolate());
5454   Local<Script> script = v8_compile("x");
5455   for (int i = 0; i < 10; i++) script->Run();
5456 }
5457
5458
5459 static void GetXValue(Local<String> name,
5460                       const v8::PropertyCallbackInfo<v8::Value>& info) {
5461   ApiTestFuzzer::Fuzz();
5462   CHECK(info.Data()->Equals(v8_str("donut")));
5463   CHECK(name->Equals(v8_str("x")));
5464   info.GetReturnValue().Set(name);
5465 }
5466
5467
5468 THREADED_TEST(SimplePropertyRead) {
5469   LocalContext context;
5470   v8::Isolate* isolate = context->GetIsolate();
5471   v8::HandleScope scope(isolate);
5472   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5473   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5474   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5475   Local<Script> script = v8_compile("obj.x");
5476   for (int i = 0; i < 10; i++) {
5477     Local<Value> result = script->Run();
5478     CHECK(result->Equals(v8_str("x")));
5479   }
5480 }
5481
5482
5483 THREADED_TEST(DefinePropertyOnAPIAccessor) {
5484   LocalContext context;
5485   v8::Isolate* isolate = context->GetIsolate();
5486   v8::HandleScope scope(isolate);
5487   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5488   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5489   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5490
5491   // Uses getOwnPropertyDescriptor to check the configurable status
5492   Local<Script> script_desc = v8_compile(
5493       "var prop = Object.getOwnPropertyDescriptor( "
5494       "obj, 'x');"
5495       "prop.configurable;");
5496   Local<Value> result = script_desc->Run();
5497   CHECK_EQ(result->BooleanValue(), true);
5498
5499   // Redefine get - but still configurable
5500   Local<Script> script_define = v8_compile(
5501       "var desc = { get: function(){return 42; },"
5502       "            configurable: true };"
5503       "Object.defineProperty(obj, 'x', desc);"
5504       "obj.x");
5505   result = script_define->Run();
5506   CHECK(result->Equals(v8_num(42)));
5507
5508   // Check that the accessor is still configurable
5509   result = script_desc->Run();
5510   CHECK_EQ(result->BooleanValue(), true);
5511
5512   // Redefine to a non-configurable
5513   script_define = v8_compile(
5514       "var desc = { get: function(){return 43; },"
5515       "             configurable: false };"
5516       "Object.defineProperty(obj, 'x', desc);"
5517       "obj.x");
5518   result = script_define->Run();
5519   CHECK(result->Equals(v8_num(43)));
5520   result = script_desc->Run();
5521   CHECK_EQ(result->BooleanValue(), false);
5522
5523   // Make sure that it is not possible to redefine again
5524   v8::TryCatch try_catch(isolate);
5525   result = script_define->Run();
5526   CHECK(try_catch.HasCaught());
5527   String::Utf8Value exception_value(try_catch.Exception());
5528   CHECK_EQ(0,
5529            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5530 }
5531
5532
5533 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
5534   v8::Isolate* isolate = CcTest::isolate();
5535   v8::HandleScope scope(isolate);
5536   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5537   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5538   LocalContext context;
5539   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5540
5541   Local<Script> script_desc = v8_compile(
5542       "var prop ="
5543       "Object.getOwnPropertyDescriptor( "
5544       "obj, 'x');"
5545       "prop.configurable;");
5546   Local<Value> result = script_desc->Run();
5547   CHECK_EQ(result->BooleanValue(), true);
5548
5549   Local<Script> script_define = v8_compile(
5550       "var desc = {get: function(){return 42; },"
5551       "            configurable: true };"
5552       "Object.defineProperty(obj, 'x', desc);"
5553       "obj.x");
5554   result = script_define->Run();
5555   CHECK(result->Equals(v8_num(42)));
5556
5557
5558   result = script_desc->Run();
5559   CHECK_EQ(result->BooleanValue(), true);
5560
5561
5562   script_define = v8_compile(
5563       "var desc = {get: function(){return 43; },"
5564       "            configurable: false };"
5565       "Object.defineProperty(obj, 'x', desc);"
5566       "obj.x");
5567   result = script_define->Run();
5568   CHECK(result->Equals(v8_num(43)));
5569   result = script_desc->Run();
5570
5571   CHECK_EQ(result->BooleanValue(), false);
5572
5573   v8::TryCatch try_catch(isolate);
5574   result = script_define->Run();
5575   CHECK(try_catch.HasCaught());
5576   String::Utf8Value exception_value(try_catch.Exception());
5577   CHECK_EQ(0,
5578            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5579 }
5580
5581
5582 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5583                                                 char const* name) {
5584   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5585 }
5586
5587
5588 THREADED_TEST(DefineAPIAccessorOnObject) {
5589   v8::Isolate* isolate = CcTest::isolate();
5590   v8::HandleScope scope(isolate);
5591   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5592   LocalContext context;
5593
5594   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5595   CompileRun("var obj2 = {};");
5596
5597   CHECK(CompileRun("obj1.x")->IsUndefined());
5598   CHECK(CompileRun("obj2.x")->IsUndefined());
5599
5600   CHECK(GetGlobalProperty(&context, "obj1")
5601             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5602
5603   ExpectString("obj1.x", "x");
5604   CHECK(CompileRun("obj2.x")->IsUndefined());
5605
5606   CHECK(GetGlobalProperty(&context, "obj2")
5607             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5608
5609   ExpectString("obj1.x", "x");
5610   ExpectString("obj2.x", "x");
5611
5612   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5613   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5614
5615   CompileRun(
5616       "Object.defineProperty(obj1, 'x',"
5617       "{ get: function() { return 'y'; }, configurable: true })");
5618
5619   ExpectString("obj1.x", "y");
5620   ExpectString("obj2.x", "x");
5621
5622   CompileRun(
5623       "Object.defineProperty(obj2, 'x',"
5624       "{ get: function() { return 'y'; }, configurable: true })");
5625
5626   ExpectString("obj1.x", "y");
5627   ExpectString("obj2.x", "y");
5628
5629   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5630   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5631
5632   CHECK(GetGlobalProperty(&context, "obj1")
5633             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5634   CHECK(GetGlobalProperty(&context, "obj2")
5635             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5636
5637   ExpectString("obj1.x", "x");
5638   ExpectString("obj2.x", "x");
5639
5640   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5641   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5642
5643   // Define getters/setters, but now make them not configurable.
5644   CompileRun(
5645       "Object.defineProperty(obj1, 'x',"
5646       "{ get: function() { return 'z'; }, configurable: false })");
5647   CompileRun(
5648       "Object.defineProperty(obj2, 'x',"
5649       "{ get: function() { return 'z'; }, configurable: false })");
5650
5651   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5652   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5653
5654   ExpectString("obj1.x", "z");
5655   ExpectString("obj2.x", "z");
5656
5657   CHECK(!GetGlobalProperty(&context, "obj1")
5658              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5659   CHECK(!GetGlobalProperty(&context, "obj2")
5660              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5661
5662   ExpectString("obj1.x", "z");
5663   ExpectString("obj2.x", "z");
5664 }
5665
5666
5667 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
5668   v8::Isolate* isolate = CcTest::isolate();
5669   v8::HandleScope scope(isolate);
5670   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5671   LocalContext context;
5672
5673   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5674   CompileRun("var obj2 = {};");
5675
5676   CHECK(GetGlobalProperty(&context, "obj1")
5677             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
5678                           v8::DEFAULT, v8::DontDelete));
5679   CHECK(GetGlobalProperty(&context, "obj2")
5680             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
5681                           v8::DEFAULT, v8::DontDelete));
5682
5683   ExpectString("obj1.x", "x");
5684   ExpectString("obj2.x", "x");
5685
5686   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5687   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5688
5689   CHECK(!GetGlobalProperty(&context, "obj1")
5690              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5691   CHECK(!GetGlobalProperty(&context, "obj2")
5692              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5693
5694   {
5695     v8::TryCatch try_catch(isolate);
5696     CompileRun(
5697         "Object.defineProperty(obj1, 'x',"
5698         "{get: function() { return 'func'; }})");
5699     CHECK(try_catch.HasCaught());
5700     String::Utf8Value exception_value(try_catch.Exception());
5701     CHECK_EQ(
5702         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5703   }
5704   {
5705     v8::TryCatch try_catch(isolate);
5706     CompileRun(
5707         "Object.defineProperty(obj2, 'x',"
5708         "{get: function() { return 'func'; }})");
5709     CHECK(try_catch.HasCaught());
5710     String::Utf8Value exception_value(try_catch.Exception());
5711     CHECK_EQ(
5712         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5713   }
5714 }
5715
5716
5717 static void Get239Value(Local<String> name,
5718                         const v8::PropertyCallbackInfo<v8::Value>& info) {
5719   ApiTestFuzzer::Fuzz();
5720   CHECK(info.Data()->Equals(v8_str("donut")));
5721   CHECK(name->Equals(v8_str("239")));
5722   info.GetReturnValue().Set(name);
5723 }
5724
5725
5726 THREADED_TEST(ElementAPIAccessor) {
5727   v8::Isolate* isolate = CcTest::isolate();
5728   v8::HandleScope scope(isolate);
5729   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5730   LocalContext context;
5731
5732   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5733   CompileRun("var obj2 = {};");
5734
5735   CHECK(GetGlobalProperty(&context, "obj1")
5736             ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
5737   CHECK(GetGlobalProperty(&context, "obj2")
5738             ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
5739
5740   ExpectString("obj1[239]", "239");
5741   ExpectString("obj2[239]", "239");
5742   ExpectString("obj1['239']", "239");
5743   ExpectString("obj2['239']", "239");
5744 }
5745
5746
5747 v8::Persistent<Value> xValue;
5748
5749
5750 static void SetXValue(Local<String> name, Local<Value> value,
5751                       const v8::PropertyCallbackInfo<void>& info) {
5752   CHECK(value->Equals(v8_num(4)));
5753   CHECK(info.Data()->Equals(v8_str("donut")));
5754   CHECK(name->Equals(v8_str("x")));
5755   CHECK(xValue.IsEmpty());
5756   xValue.Reset(info.GetIsolate(), value);
5757 }
5758
5759
5760 THREADED_TEST(SimplePropertyWrite) {
5761   v8::Isolate* isolate = CcTest::isolate();
5762   v8::HandleScope scope(isolate);
5763   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5764   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5765   LocalContext context;
5766   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5767   Local<Script> script = v8_compile("obj.x = 4");
5768   for (int i = 0; i < 10; i++) {
5769     CHECK(xValue.IsEmpty());
5770     script->Run();
5771     CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
5772     xValue.Reset();
5773   }
5774 }
5775
5776
5777 THREADED_TEST(SetterOnly) {
5778   v8::Isolate* isolate = CcTest::isolate();
5779   v8::HandleScope scope(isolate);
5780   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5781   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5782   LocalContext context;
5783   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5784   Local<Script> script = v8_compile("obj.x = 4; obj.x");
5785   for (int i = 0; i < 10; i++) {
5786     CHECK(xValue.IsEmpty());
5787     script->Run();
5788     CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
5789     xValue.Reset();
5790   }
5791 }
5792
5793
5794 THREADED_TEST(NoAccessors) {
5795   v8::Isolate* isolate = CcTest::isolate();
5796   v8::HandleScope scope(isolate);
5797   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5798   templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
5799                      NULL, v8_str("donut"));
5800   LocalContext context;
5801   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5802   Local<Script> script = v8_compile("obj.x = 4; obj.x");
5803   for (int i = 0; i < 10; i++) {
5804     script->Run();
5805   }
5806 }
5807
5808
5809 THREADED_TEST(MultiContexts) {
5810   v8::Isolate* isolate = CcTest::isolate();
5811   v8::HandleScope scope(isolate);
5812   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5813   templ->Set(v8_str("dummy"),
5814              v8::FunctionTemplate::New(isolate, DummyCallHandler));
5815
5816   Local<String> password = v8_str("Password");
5817
5818   // Create an environment
5819   LocalContext context0(0, templ);
5820   context0->SetSecurityToken(password);
5821   v8::Handle<v8::Object> global0 = context0->Global();
5822   global0->Set(v8_str("custom"), v8_num(1234));
5823   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5824
5825   // Create an independent environment
5826   LocalContext context1(0, templ);
5827   context1->SetSecurityToken(password);
5828   v8::Handle<v8::Object> global1 = context1->Global();
5829   global1->Set(v8_str("custom"), v8_num(1234));
5830   CHECK(!global0->Equals(global1));
5831   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5832   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
5833
5834   // Now create a new context with the old global
5835   LocalContext context2(0, templ, global1);
5836   context2->SetSecurityToken(password);
5837   v8::Handle<v8::Object> global2 = context2->Global();
5838   CHECK(global1->Equals(global2));
5839   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
5840   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
5841 }
5842
5843
5844 THREADED_TEST(FunctionPrototypeAcrossContexts) {
5845   // Make sure that functions created by cloning boilerplates cannot
5846   // communicate through their __proto__ field.
5847
5848   v8::HandleScope scope(CcTest::isolate());
5849
5850   LocalContext env0;
5851   v8::Handle<v8::Object> global0 = env0->Global();
5852   v8::Handle<v8::Object> object0 =
5853       global0->Get(v8_str("Object")).As<v8::Object>();
5854   v8::Handle<v8::Object> tostring0 =
5855       object0->Get(v8_str("toString")).As<v8::Object>();
5856   v8::Handle<v8::Object> proto0 =
5857       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
5858   proto0->Set(v8_str("custom"), v8_num(1234));
5859
5860   LocalContext env1;
5861   v8::Handle<v8::Object> global1 = env1->Global();
5862   v8::Handle<v8::Object> object1 =
5863       global1->Get(v8_str("Object")).As<v8::Object>();
5864   v8::Handle<v8::Object> tostring1 =
5865       object1->Get(v8_str("toString")).As<v8::Object>();
5866   v8::Handle<v8::Object> proto1 =
5867       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
5868   CHECK(!proto1->Has(v8_str("custom")));
5869 }
5870
5871
5872 THREADED_TEST(Regress892105) {
5873   // Make sure that object and array literals created by cloning
5874   // boilerplates cannot communicate through their __proto__
5875   // field. This is rather difficult to check, but we try to add stuff
5876   // to Object.prototype and Array.prototype and create a new
5877   // environment. This should succeed.
5878
5879   v8::HandleScope scope(CcTest::isolate());
5880
5881   Local<String> source = v8_str(
5882       "Object.prototype.obj = 1234;"
5883       "Array.prototype.arr = 4567;"
5884       "8901");
5885
5886   LocalContext env0;
5887   Local<Script> script0 = v8_compile(source);
5888   CHECK_EQ(8901.0, script0->Run()->NumberValue());
5889
5890   LocalContext env1;
5891   Local<Script> script1 = v8_compile(source);
5892   CHECK_EQ(8901.0, script1->Run()->NumberValue());
5893 }
5894
5895
5896 THREADED_TEST(UndetectableObject) {
5897   LocalContext env;
5898   v8::HandleScope scope(env->GetIsolate());
5899
5900   Local<v8::FunctionTemplate> desc =
5901       v8::FunctionTemplate::New(env->GetIsolate());
5902   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5903
5904   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5905   env->Global()->Set(v8_str("undetectable"), obj);
5906
5907   ExpectString("undetectable.toString()", "[object Object]");
5908   ExpectString("typeof undetectable", "undefined");
5909   ExpectString("typeof(undetectable)", "undefined");
5910   ExpectBoolean("typeof undetectable == 'undefined'", true);
5911   ExpectBoolean("typeof undetectable == 'object'", false);
5912   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
5913   ExpectBoolean("!undetectable", true);
5914
5915   ExpectObject("true&&undetectable", obj);
5916   ExpectBoolean("false&&undetectable", false);
5917   ExpectBoolean("true||undetectable", true);
5918   ExpectObject("false||undetectable", obj);
5919
5920   ExpectObject("undetectable&&true", obj);
5921   ExpectObject("undetectable&&false", obj);
5922   ExpectBoolean("undetectable||true", true);
5923   ExpectBoolean("undetectable||false", false);
5924
5925   ExpectBoolean("undetectable==null", true);
5926   ExpectBoolean("null==undetectable", true);
5927   ExpectBoolean("undetectable==undefined", true);
5928   ExpectBoolean("undefined==undetectable", true);
5929   ExpectBoolean("undetectable==undetectable", true);
5930
5931
5932   ExpectBoolean("undetectable===null", false);
5933   ExpectBoolean("null===undetectable", false);
5934   ExpectBoolean("undetectable===undefined", false);
5935   ExpectBoolean("undefined===undetectable", false);
5936   ExpectBoolean("undetectable===undetectable", true);
5937 }
5938
5939
5940 THREADED_TEST(VoidLiteral) {
5941   LocalContext env;
5942   v8::Isolate* isolate = env->GetIsolate();
5943   v8::HandleScope scope(isolate);
5944
5945   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
5946   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5947
5948   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5949   env->Global()->Set(v8_str("undetectable"), obj);
5950
5951   ExpectBoolean("undefined == void 0", true);
5952   ExpectBoolean("undetectable == void 0", true);
5953   ExpectBoolean("null == void 0", true);
5954   ExpectBoolean("undefined === void 0", true);
5955   ExpectBoolean("undetectable === void 0", false);
5956   ExpectBoolean("null === void 0", false);
5957
5958   ExpectBoolean("void 0 == undefined", true);
5959   ExpectBoolean("void 0 == undetectable", true);
5960   ExpectBoolean("void 0 == null", true);
5961   ExpectBoolean("void 0 === undefined", true);
5962   ExpectBoolean("void 0 === undetectable", false);
5963   ExpectBoolean("void 0 === null", false);
5964
5965   ExpectString(
5966       "(function() {"
5967       "  try {"
5968       "    return x === void 0;"
5969       "  } catch(e) {"
5970       "    return e.toString();"
5971       "  }"
5972       "})()",
5973       "ReferenceError: x is not defined");
5974   ExpectString(
5975       "(function() {"
5976       "  try {"
5977       "    return void 0 === x;"
5978       "  } catch(e) {"
5979       "    return e.toString();"
5980       "  }"
5981       "})()",
5982       "ReferenceError: x is not defined");
5983 }
5984
5985
5986 THREADED_TEST(ExtensibleOnUndetectable) {
5987   LocalContext env;
5988   v8::Isolate* isolate = env->GetIsolate();
5989   v8::HandleScope scope(isolate);
5990
5991   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
5992   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5993
5994   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5995   env->Global()->Set(v8_str("undetectable"), obj);
5996
5997   Local<String> source = v8_str(
5998       "undetectable.x = 42;"
5999       "undetectable.x");
6000
6001   Local<Script> script = v8_compile(source);
6002
6003   CHECK(v8::Integer::New(isolate, 42)->Equals(script->Run()));
6004
6005   ExpectBoolean("Object.isExtensible(undetectable)", true);
6006
6007   source = v8_str("Object.preventExtensions(undetectable);");
6008   script = v8_compile(source);
6009   script->Run();
6010   ExpectBoolean("Object.isExtensible(undetectable)", false);
6011
6012   source = v8_str("undetectable.y = 2000;");
6013   script = v8_compile(source);
6014   script->Run();
6015   ExpectBoolean("undetectable.y == undefined", true);
6016 }
6017
6018
6019 // The point of this test is type checking. We run it only so compilers
6020 // don't complain about an unused function.
6021 TEST(PersistentHandles) {
6022   LocalContext env;
6023   v8::Isolate* isolate = CcTest::isolate();
6024   v8::HandleScope scope(isolate);
6025   Local<String> str = v8_str("foo");
6026   v8::Persistent<String> p_str(isolate, str);
6027   p_str.Reset();
6028   Local<Script> scr = v8_compile("");
6029   v8::Persistent<Script> p_scr(isolate, scr);
6030   p_scr.Reset();
6031   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6032   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
6033   p_templ.Reset();
6034 }
6035
6036
6037 static void HandleLogDelegator(
6038     const v8::FunctionCallbackInfo<v8::Value>& args) {
6039   ApiTestFuzzer::Fuzz();
6040 }
6041
6042
6043 THREADED_TEST(GlobalObjectTemplate) {
6044   v8::Isolate* isolate = CcTest::isolate();
6045   v8::HandleScope handle_scope(isolate);
6046   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
6047   global_template->Set(v8_str("JSNI_Log"),
6048                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
6049   v8::Local<Context> context = Context::New(isolate, 0, global_template);
6050   Context::Scope context_scope(context);
6051   CompileRun("JSNI_Log('LOG')");
6052 }
6053
6054
6055 static const char* kSimpleExtensionSource =
6056     "function Foo() {"
6057     "  return 4;"
6058     "}";
6059
6060
6061 TEST(SimpleExtensions) {
6062   v8::HandleScope handle_scope(CcTest::isolate());
6063   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6064   const char* extension_names[] = {"simpletest"};
6065   v8::ExtensionConfiguration extensions(1, extension_names);
6066   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6067   Context::Scope lock(context);
6068   v8::Handle<Value> result = CompileRun("Foo()");
6069   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6070 }
6071
6072
6073 static const char* kStackTraceFromExtensionSource =
6074     "function foo() {"
6075     "  throw new Error();"
6076     "}"
6077     "function bar() {"
6078     "  foo();"
6079     "}";
6080
6081
6082 TEST(StackTraceInExtension) {
6083   v8::HandleScope handle_scope(CcTest::isolate());
6084   v8::RegisterExtension(
6085       new Extension("stacktracetest", kStackTraceFromExtensionSource));
6086   const char* extension_names[] = {"stacktracetest"};
6087   v8::ExtensionConfiguration extensions(1, extension_names);
6088   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6089   Context::Scope lock(context);
6090   CompileRun(
6091       "function user() { bar(); }"
6092       "var error;"
6093       "try{ user(); } catch (e) { error = e; }");
6094   CHECK_EQ(-1, CompileRun("error.stack.indexOf('foo')")->Int32Value());
6095   CHECK_EQ(-1, CompileRun("error.stack.indexOf('bar')")->Int32Value());
6096   CHECK_NE(-1, CompileRun("error.stack.indexOf('user')")->Int32Value());
6097 }
6098
6099
6100 TEST(NullExtensions) {
6101   v8::HandleScope handle_scope(CcTest::isolate());
6102   v8::RegisterExtension(new Extension("nulltest", NULL));
6103   const char* extension_names[] = {"nulltest"};
6104   v8::ExtensionConfiguration extensions(1, extension_names);
6105   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6106   Context::Scope lock(context);
6107   v8::Handle<Value> result = CompileRun("1+3");
6108   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6109 }
6110
6111
6112 static const char* kEmbeddedExtensionSource =
6113     "function Ret54321(){return 54321;}~~@@$"
6114     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6115 static const int kEmbeddedExtensionSourceValidLen = 34;
6116
6117
6118 TEST(ExtensionMissingSourceLength) {
6119   v8::HandleScope handle_scope(CcTest::isolate());
6120   v8::RegisterExtension(
6121       new Extension("srclentest_fail", kEmbeddedExtensionSource));
6122   const char* extension_names[] = {"srclentest_fail"};
6123   v8::ExtensionConfiguration extensions(1, extension_names);
6124   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6125   CHECK(0 == *context);
6126 }
6127
6128
6129 TEST(ExtensionWithSourceLength) {
6130   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6131        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
6132     v8::HandleScope handle_scope(CcTest::isolate());
6133     i::ScopedVector<char> extension_name(32);
6134     i::SNPrintF(extension_name, "ext #%d", source_len);
6135     v8::RegisterExtension(new Extension(
6136         extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
6137     const char* extension_names[1] = {extension_name.start()};
6138     v8::ExtensionConfiguration extensions(1, extension_names);
6139     v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6140     if (source_len == kEmbeddedExtensionSourceValidLen) {
6141       Context::Scope lock(context);
6142       v8::Handle<Value> result = CompileRun("Ret54321()");
6143       CHECK(v8::Integer::New(CcTest::isolate(), 54321)->Equals(result));
6144     } else {
6145       // Anything but exactly the right length should fail to compile.
6146       CHECK(0 == *context);
6147     }
6148   }
6149 }
6150
6151
6152 static const char* kEvalExtensionSource1 =
6153     "function UseEval1() {"
6154     "  var x = 42;"
6155     "  return eval('x');"
6156     "}";
6157
6158
6159 static const char* kEvalExtensionSource2 =
6160     "(function() {"
6161     "  var x = 42;"
6162     "  function e() {"
6163     "    return eval('x');"
6164     "  }"
6165     "  this.UseEval2 = e;"
6166     "})()";
6167
6168
6169 TEST(UseEvalFromExtension) {
6170   v8::HandleScope handle_scope(CcTest::isolate());
6171   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6172   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6173   const char* extension_names[] = {"evaltest1", "evaltest2"};
6174   v8::ExtensionConfiguration extensions(2, extension_names);
6175   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6176   Context::Scope lock(context);
6177   v8::Handle<Value> result = CompileRun("UseEval1()");
6178   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6179   result = CompileRun("UseEval2()");
6180   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6181 }
6182
6183
6184 static const char* kWithExtensionSource1 =
6185     "function UseWith1() {"
6186     "  var x = 42;"
6187     "  with({x:87}) { return x; }"
6188     "}";
6189
6190
6191 static const char* kWithExtensionSource2 =
6192     "(function() {"
6193     "  var x = 42;"
6194     "  function e() {"
6195     "    with ({x:87}) { return x; }"
6196     "  }"
6197     "  this.UseWith2 = e;"
6198     "})()";
6199
6200
6201 TEST(UseWithFromExtension) {
6202   v8::HandleScope handle_scope(CcTest::isolate());
6203   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6204   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6205   const char* extension_names[] = {"withtest1", "withtest2"};
6206   v8::ExtensionConfiguration extensions(2, extension_names);
6207   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6208   Context::Scope lock(context);
6209   v8::Handle<Value> result = CompileRun("UseWith1()");
6210   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
6211   result = CompileRun("UseWith2()");
6212   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
6213 }
6214
6215
6216 TEST(AutoExtensions) {
6217   v8::HandleScope handle_scope(CcTest::isolate());
6218   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6219   extension->set_auto_enable(true);
6220   v8::RegisterExtension(extension);
6221   v8::Handle<Context> context = Context::New(CcTest::isolate());
6222   Context::Scope lock(context);
6223   v8::Handle<Value> result = CompileRun("Foo()");
6224   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6225 }
6226
6227
6228 static const char* kSyntaxErrorInExtensionSource = "[";
6229
6230
6231 // Test that a syntax error in an extension does not cause a fatal
6232 // error but results in an empty context.
6233 TEST(SyntaxErrorExtensions) {
6234   v8::HandleScope handle_scope(CcTest::isolate());
6235   v8::RegisterExtension(
6236       new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
6237   const char* extension_names[] = {"syntaxerror"};
6238   v8::ExtensionConfiguration extensions(1, extension_names);
6239   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6240   CHECK(context.IsEmpty());
6241 }
6242
6243
6244 static const char* kExceptionInExtensionSource = "throw 42";
6245
6246
6247 // Test that an exception when installing an extension does not cause
6248 // a fatal error but results in an empty context.
6249 TEST(ExceptionExtensions) {
6250   v8::HandleScope handle_scope(CcTest::isolate());
6251   v8::RegisterExtension(
6252       new Extension("exception", kExceptionInExtensionSource));
6253   const char* extension_names[] = {"exception"};
6254   v8::ExtensionConfiguration extensions(1, extension_names);
6255   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6256   CHECK(context.IsEmpty());
6257 }
6258
6259
6260 static const char* kNativeCallInExtensionSource =
6261     "function call_runtime_last_index_of(x) {"
6262     "  return %StringLastIndexOf(x, 'bob', 10);"
6263     "}";
6264
6265
6266 static const char* kNativeCallTest =
6267     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6268
6269 // Test that a native runtime calls are supported in extensions.
6270 TEST(NativeCallInExtensions) {
6271   v8::HandleScope handle_scope(CcTest::isolate());
6272   v8::RegisterExtension(
6273       new Extension("nativecall", kNativeCallInExtensionSource));
6274   const char* extension_names[] = {"nativecall"};
6275   v8::ExtensionConfiguration extensions(1, extension_names);
6276   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6277   Context::Scope lock(context);
6278   v8::Handle<Value> result = CompileRun(kNativeCallTest);
6279   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 3)));
6280 }
6281
6282
6283 class NativeFunctionExtension : public Extension {
6284  public:
6285   NativeFunctionExtension(const char* name, const char* source,
6286                           v8::FunctionCallback fun = &Echo)
6287       : Extension(name, source), function_(fun) {}
6288
6289   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6290       v8::Isolate* isolate, v8::Handle<v8::String> name) {
6291     return v8::FunctionTemplate::New(isolate, function_);
6292   }
6293
6294   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6295     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
6296   }
6297
6298  private:
6299   v8::FunctionCallback function_;
6300 };
6301
6302
6303 TEST(NativeFunctionDeclaration) {
6304   v8::HandleScope handle_scope(CcTest::isolate());
6305   const char* name = "nativedecl";
6306   v8::RegisterExtension(
6307       new NativeFunctionExtension(name, "native function foo();"));
6308   const char* extension_names[] = {name};
6309   v8::ExtensionConfiguration extensions(1, extension_names);
6310   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6311   Context::Scope lock(context);
6312   v8::Handle<Value> result = CompileRun("foo(42);");
6313   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6314 }
6315
6316
6317 TEST(NativeFunctionDeclarationError) {
6318   v8::HandleScope handle_scope(CcTest::isolate());
6319   const char* name = "nativedeclerr";
6320   // Syntax error in extension code.
6321   v8::RegisterExtension(
6322       new NativeFunctionExtension(name, "native\nfunction foo();"));
6323   const char* extension_names[] = {name};
6324   v8::ExtensionConfiguration extensions(1, extension_names);
6325   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6326   CHECK(context.IsEmpty());
6327 }
6328
6329
6330 TEST(NativeFunctionDeclarationErrorEscape) {
6331   v8::HandleScope handle_scope(CcTest::isolate());
6332   const char* name = "nativedeclerresc";
6333   // Syntax error in extension code - escape code in "native" means that
6334   // it's not treated as a keyword.
6335   v8::RegisterExtension(
6336       new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
6337   const char* extension_names[] = {name};
6338   v8::ExtensionConfiguration extensions(1, extension_names);
6339   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6340   CHECK(context.IsEmpty());
6341 }
6342
6343
6344 static void CheckDependencies(const char* name, const char* expected) {
6345   v8::HandleScope handle_scope(CcTest::isolate());
6346   v8::ExtensionConfiguration config(1, &name);
6347   LocalContext context(&config);
6348   CHECK(String::NewFromUtf8(CcTest::isolate(), expected)
6349             ->Equals(context->Global()->Get(v8_str("loaded"))));
6350 }
6351
6352
6353 /*
6354  * Configuration:
6355  *
6356  *     /-- B <--\
6357  * A <-          -- D <-- E
6358  *     \-- C <--/
6359  */
6360 THREADED_TEST(ExtensionDependency) {
6361   static const char* kEDeps[] = {"D"};
6362   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6363   static const char* kDDeps[] = {"B", "C"};
6364   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6365   static const char* kBCDeps[] = {"A"};
6366   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6367   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6368   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6369   CheckDependencies("A", "undefinedA");
6370   CheckDependencies("B", "undefinedAB");
6371   CheckDependencies("C", "undefinedAC");
6372   CheckDependencies("D", "undefinedABCD");
6373   CheckDependencies("E", "undefinedABCDE");
6374   v8::HandleScope handle_scope(CcTest::isolate());
6375   static const char* exts[2] = {"C", "E"};
6376   v8::ExtensionConfiguration config(2, exts);
6377   LocalContext context(&config);
6378   CHECK(v8_str("undefinedACBDE")
6379             ->Equals(context->Global()->Get(v8_str("loaded"))));
6380 }
6381
6382
6383 static const char* kExtensionTestScript =
6384     "native function A();"
6385     "native function B();"
6386     "native function C();"
6387     "function Foo(i) {"
6388     "  if (i == 0) return A();"
6389     "  if (i == 1) return B();"
6390     "  if (i == 2) return C();"
6391     "}";
6392
6393
6394 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
6395   ApiTestFuzzer::Fuzz();
6396   if (args.IsConstructCall()) {
6397     args.This()->Set(v8_str("data"), args.Data());
6398     args.GetReturnValue().SetNull();
6399     return;
6400   }
6401   args.GetReturnValue().Set(args.Data());
6402 }
6403
6404
6405 class FunctionExtension : public Extension {
6406  public:
6407   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
6408   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6409       v8::Isolate* isolate, v8::Handle<String> name);
6410 };
6411
6412
6413 static int lookup_count = 0;
6414 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
6415     v8::Isolate* isolate, v8::Handle<String> name) {
6416   lookup_count++;
6417   if (name->Equals(v8_str("A"))) {
6418     return v8::FunctionTemplate::New(isolate, CallFun,
6419                                      v8::Integer::New(isolate, 8));
6420   } else if (name->Equals(v8_str("B"))) {
6421     return v8::FunctionTemplate::New(isolate, CallFun,
6422                                      v8::Integer::New(isolate, 7));
6423   } else if (name->Equals(v8_str("C"))) {
6424     return v8::FunctionTemplate::New(isolate, CallFun,
6425                                      v8::Integer::New(isolate, 6));
6426   } else {
6427     return v8::Handle<v8::FunctionTemplate>();
6428   }
6429 }
6430
6431
6432 THREADED_TEST(FunctionLookup) {
6433   v8::RegisterExtension(new FunctionExtension());
6434   v8::HandleScope handle_scope(CcTest::isolate());
6435   static const char* exts[1] = {"functiontest"};
6436   v8::ExtensionConfiguration config(1, exts);
6437   LocalContext context(&config);
6438   CHECK_EQ(3, lookup_count);
6439   CHECK(v8::Integer::New(CcTest::isolate(), 8)->Equals(CompileRun("Foo(0)")));
6440   CHECK(v8::Integer::New(CcTest::isolate(), 7)->Equals(CompileRun("Foo(1)")));
6441   CHECK(v8::Integer::New(CcTest::isolate(), 6)->Equals(CompileRun("Foo(2)")));
6442 }
6443
6444
6445 THREADED_TEST(NativeFunctionConstructCall) {
6446   v8::RegisterExtension(new FunctionExtension());
6447   v8::HandleScope handle_scope(CcTest::isolate());
6448   static const char* exts[1] = {"functiontest"};
6449   v8::ExtensionConfiguration config(1, exts);
6450   LocalContext context(&config);
6451   for (int i = 0; i < 10; i++) {
6452     // Run a few times to ensure that allocation of objects doesn't
6453     // change behavior of a constructor function.
6454     CHECK(v8::Integer::New(CcTest::isolate(), 8)
6455               ->Equals(CompileRun("(new A()).data")));
6456     CHECK(v8::Integer::New(CcTest::isolate(), 7)
6457               ->Equals(CompileRun("(new B()).data")));
6458     CHECK(v8::Integer::New(CcTest::isolate(), 6)
6459               ->Equals(CompileRun("(new C()).data")));
6460   }
6461 }
6462
6463
6464 static const char* last_location;
6465 static const char* last_message;
6466 void StoringErrorCallback(const char* location, const char* message) {
6467   if (last_location == NULL) {
6468     last_location = location;
6469     last_message = message;
6470   }
6471 }
6472
6473
6474 // ErrorReporting creates a circular extensions configuration and
6475 // tests that the fatal error handler gets called.  This renders V8
6476 // unusable and therefore this test cannot be run in parallel.
6477 TEST(ErrorReporting) {
6478   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
6479   static const char* aDeps[] = {"B"};
6480   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
6481   static const char* bDeps[] = {"A"};
6482   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
6483   last_location = NULL;
6484   v8::ExtensionConfiguration config(1, bDeps);
6485   v8::Handle<Context> context = Context::New(CcTest::isolate(), &config);
6486   CHECK(context.IsEmpty());
6487   CHECK(last_location);
6488 }
6489
6490
6491 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
6492                                              v8::Handle<Value> data) {
6493   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
6494   CHECK(v8::Undefined(CcTest::isolate())
6495             ->Equals(message->GetScriptOrigin().ResourceName()));
6496   message->GetLineNumber();
6497   message->GetSourceLine();
6498 }
6499
6500
6501 THREADED_TEST(ErrorWithMissingScriptInfo) {
6502   LocalContext context;
6503   v8::HandleScope scope(context->GetIsolate());
6504   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
6505   CompileRun("throw Error()");
6506   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
6507 }
6508
6509
6510 struct FlagAndPersistent {
6511   bool flag;
6512   v8::Global<v8::Object> handle;
6513 };
6514
6515
6516 static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6517   data.GetParameter()->flag = true;
6518   data.GetParameter()->handle.Reset();
6519 }
6520
6521
6522 static void IndependentWeakHandle(bool global_gc, bool interlinked) {
6523   v8::Isolate* iso = CcTest::isolate();
6524   v8::HandleScope scope(iso);
6525   v8::Handle<Context> context = Context::New(iso);
6526   Context::Scope context_scope(context);
6527
6528   FlagAndPersistent object_a, object_b;
6529
6530   intptr_t big_heap_size;
6531
6532   {
6533     v8::HandleScope handle_scope(iso);
6534     Local<Object> a(v8::Object::New(iso));
6535     Local<Object> b(v8::Object::New(iso));
6536     object_a.handle.Reset(iso, a);
6537     object_b.handle.Reset(iso, b);
6538     if (interlinked) {
6539       a->Set(v8_str("x"), b);
6540       b->Set(v8_str("x"), a);
6541     }
6542     if (global_gc) {
6543       CcTest::heap()->CollectAllGarbage();
6544     } else {
6545       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6546     }
6547     // We are relying on this creating a big flag array and reserving the space
6548     // up front.
6549     v8::Handle<Value> big_array = CompileRun("new Array(50000)");
6550     a->Set(v8_str("y"), big_array);
6551     big_heap_size = CcTest::heap()->SizeOfObjects();
6552   }
6553
6554   object_a.flag = false;
6555   object_b.flag = false;
6556   object_a.handle.SetWeak(&object_a, &SetFlag,
6557                           v8::WeakCallbackType::kParameter);
6558   object_b.handle.SetWeak(&object_b, &SetFlag,
6559                           v8::WeakCallbackType::kParameter);
6560   CHECK(!object_b.handle.IsIndependent());
6561   object_a.handle.MarkIndependent();
6562   object_b.handle.MarkIndependent();
6563   CHECK(object_b.handle.IsIndependent());
6564   if (global_gc) {
6565     CcTest::heap()->CollectAllGarbage();
6566   } else {
6567     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6568   }
6569   // A single GC should be enough to reclaim the memory, since we are using
6570   // phantom handles.
6571   CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 200000);
6572   CHECK(object_a.flag);
6573   CHECK(object_b.flag);
6574 }
6575
6576
6577 TEST(IndependentWeakHandle) {
6578   IndependentWeakHandle(false, false);
6579   IndependentWeakHandle(false, true);
6580   IndependentWeakHandle(true, false);
6581   IndependentWeakHandle(true, true);
6582 }
6583
6584
6585 class Trivial {
6586  public:
6587   explicit Trivial(int x) : x_(x) {}
6588
6589   int x() { return x_; }
6590   void set_x(int x) { x_ = x; }
6591
6592  private:
6593   int x_;
6594 };
6595
6596
6597 class Trivial2 {
6598  public:
6599   Trivial2(int x, int y) : y_(y), x_(x) {}
6600
6601   int x() { return x_; }
6602   void set_x(int x) { x_ = x; }
6603
6604   int y() { return y_; }
6605   void set_y(int y) { y_ = y; }
6606
6607  private:
6608   int y_;
6609   int x_;
6610 };
6611
6612
6613 void CheckInternalFields(
6614     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
6615   v8::Persistent<v8::Object>* handle = data.GetParameter();
6616   handle->Reset();
6617   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField1());
6618   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField2());
6619   CHECK_EQ(42, t1->x());
6620   CHECK_EQ(103, t2->x());
6621   t1->set_x(1729);
6622   t2->set_x(33550336);
6623 }
6624
6625
6626 void InternalFieldCallback(bool global_gc) {
6627   LocalContext env;
6628   v8::Isolate* isolate = env->GetIsolate();
6629   v8::HandleScope scope(isolate);
6630
6631   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
6632   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
6633   Trivial* t1;
6634   Trivial2* t2;
6635   instance_templ->SetInternalFieldCount(2);
6636   {
6637     v8::HandleScope scope(isolate);
6638     Local<v8::Object> obj = templ->GetFunction()->NewInstance();
6639     v8::Persistent<v8::Object> handle(isolate, obj);
6640     CHECK_EQ(2, obj->InternalFieldCount());
6641     CHECK(obj->GetInternalField(0)->IsUndefined());
6642     t1 = new Trivial(42);
6643     t2 = new Trivial2(103, 9);
6644
6645     obj->SetAlignedPointerInInternalField(0, t1);
6646     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
6647     CHECK_EQ(42, t1->x());
6648
6649     obj->SetAlignedPointerInInternalField(1, t2);
6650     t2 =
6651         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
6652     CHECK_EQ(103, t2->x());
6653
6654     handle.SetWeak<v8::Persistent<v8::Object>>(
6655         &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
6656     if (!global_gc) {
6657       handle.MarkIndependent();
6658     }
6659   }
6660   if (global_gc) {
6661     CcTest::heap()->CollectAllGarbage();
6662   } else {
6663     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6664   }
6665
6666   CHECK_EQ(1729, t1->x());
6667   CHECK_EQ(33550336, t2->x());
6668
6669   delete t1;
6670   delete t2;
6671 }
6672
6673
6674 THREADED_TEST(InternalFieldCallback) {
6675   InternalFieldCallback(false);
6676   InternalFieldCallback(true);
6677 }
6678
6679
6680 static void ResetUseValueAndSetFlag(
6681     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6682   // Blink will reset the handle, and then use the other handle, so they
6683   // can't use the same backing slot.
6684   data.GetParameter()->handle.Reset();
6685   data.GetParameter()->flag = true;
6686 }
6687
6688
6689 static void ResetWeakHandle(bool global_gc) {
6690   v8::Isolate* iso = CcTest::isolate();
6691   v8::HandleScope scope(iso);
6692   v8::Handle<Context> context = Context::New(iso);
6693   Context::Scope context_scope(context);
6694
6695   FlagAndPersistent object_a, object_b;
6696
6697   {
6698     v8::HandleScope handle_scope(iso);
6699     Local<Object> a(v8::Object::New(iso));
6700     Local<Object> b(v8::Object::New(iso));
6701     object_a.handle.Reset(iso, a);
6702     object_b.handle.Reset(iso, b);
6703     if (global_gc) {
6704       CcTest::heap()->CollectAllGarbage(
6705           TestHeap::Heap::kAbortIncrementalMarkingMask);
6706     } else {
6707       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6708     }
6709   }
6710
6711   object_a.flag = false;
6712   object_b.flag = false;
6713   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
6714                           v8::WeakCallbackType::kParameter);
6715   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
6716                           v8::WeakCallbackType::kParameter);
6717   if (!global_gc) {
6718     object_a.handle.MarkIndependent();
6719     object_b.handle.MarkIndependent();
6720     CHECK(object_b.handle.IsIndependent());
6721   }
6722   if (global_gc) {
6723     CcTest::heap()->CollectAllGarbage(
6724         TestHeap::Heap::kAbortIncrementalMarkingMask);
6725   } else {
6726     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6727   }
6728   CHECK(object_a.flag);
6729   CHECK(object_b.flag);
6730 }
6731
6732
6733 THREADED_TEST(ResetWeakHandle) {
6734   ResetWeakHandle(false);
6735   ResetWeakHandle(true);
6736 }
6737
6738
6739 static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
6740
6741
6742 static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
6743
6744
6745 static void ForceScavenge2(
6746     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6747   data.GetParameter()->flag = true;
6748   InvokeScavenge();
6749 }
6750
6751 static void ForceScavenge1(
6752     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6753   data.GetParameter()->handle.Reset();
6754   data.SetSecondPassCallback(ForceScavenge2);
6755 }
6756
6757
6758 static void ForceMarkSweep2(
6759     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6760   data.GetParameter()->flag = true;
6761   InvokeMarkSweep();
6762 }
6763
6764 static void ForceMarkSweep1(
6765     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6766   data.GetParameter()->handle.Reset();
6767   data.SetSecondPassCallback(ForceMarkSweep2);
6768 }
6769
6770
6771 THREADED_TEST(GCFromWeakCallbacks) {
6772   v8::Isolate* isolate = CcTest::isolate();
6773   v8::Locker locker(CcTest::isolate());
6774   v8::HandleScope scope(isolate);
6775   v8::Handle<Context> context = Context::New(isolate);
6776   Context::Scope context_scope(context);
6777
6778   static const int kNumberOfGCTypes = 2;
6779   typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
6780   Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
6781                                                     &ForceMarkSweep1};
6782
6783   typedef void (*GCInvoker)();
6784   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
6785
6786   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
6787     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
6788       FlagAndPersistent object;
6789       {
6790         v8::HandleScope handle_scope(isolate);
6791         object.handle.Reset(isolate, v8::Object::New(isolate));
6792       }
6793       object.flag = false;
6794       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
6795                             v8::WeakCallbackType::kParameter);
6796       object.handle.MarkIndependent();
6797       invoke_gc[outer_gc]();
6798       EmptyMessageQueues(isolate);
6799       CHECK(object.flag);
6800     }
6801   }
6802 }
6803
6804
6805 v8::Handle<Function> args_fun;
6806
6807
6808 static void ArgumentsTestCallback(
6809     const v8::FunctionCallbackInfo<v8::Value>& args) {
6810   ApiTestFuzzer::Fuzz();
6811   v8::Isolate* isolate = args.GetIsolate();
6812   CHECK(args_fun->Equals(args.Callee()));
6813   CHECK_EQ(3, args.Length());
6814   CHECK(v8::Integer::New(isolate, 1)->Equals(args[0]));
6815   CHECK(v8::Integer::New(isolate, 2)->Equals(args[1]));
6816   CHECK(v8::Integer::New(isolate, 3)->Equals(args[2]));
6817   CHECK(v8::Undefined(isolate)->Equals(args[3]));
6818   v8::HandleScope scope(args.GetIsolate());
6819   CcTest::heap()->CollectAllGarbage();
6820 }
6821
6822
6823 THREADED_TEST(Arguments) {
6824   v8::Isolate* isolate = CcTest::isolate();
6825   v8::HandleScope scope(isolate);
6826   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
6827   global->Set(v8_str("f"),
6828               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
6829   LocalContext context(NULL, global);
6830   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
6831   v8_compile("f(1, 2, 3)")->Run();
6832 }
6833
6834
6835 static int p_getter_count;
6836 static int p_getter_count2;
6837
6838
6839 static void PGetter(Local<String> name,
6840                     const v8::PropertyCallbackInfo<v8::Value>& info) {
6841   ApiTestFuzzer::Fuzz();
6842   p_getter_count++;
6843   v8::Handle<v8::Object> global =
6844       info.GetIsolate()->GetCurrentContext()->Global();
6845   CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
6846   if (name->Equals(v8_str("p1"))) {
6847     CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
6848   } else if (name->Equals(v8_str("p2"))) {
6849     CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
6850   } else if (name->Equals(v8_str("p3"))) {
6851     CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
6852   } else if (name->Equals(v8_str("p4"))) {
6853     CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
6854   }
6855 }
6856
6857
6858 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
6859   ApiTestFuzzer::Fuzz();
6860   LocalContext context;
6861   context->Global()->Set(v8_str("o1"), obj->NewInstance());
6862   CompileRun(
6863     "o1.__proto__ = { };"
6864     "var o2 = { __proto__: o1 };"
6865     "var o3 = { __proto__: o2 };"
6866     "var o4 = { __proto__: o3 };"
6867     "for (var i = 0; i < 10; i++) o4.p4;"
6868     "for (var i = 0; i < 10; i++) o3.p3;"
6869     "for (var i = 0; i < 10; i++) o2.p2;"
6870     "for (var i = 0; i < 10; i++) o1.p1;");
6871 }
6872
6873
6874 static void PGetter2(Local<Name> name,
6875                      const v8::PropertyCallbackInfo<v8::Value>& info) {
6876   ApiTestFuzzer::Fuzz();
6877   p_getter_count2++;
6878   v8::Handle<v8::Object> global =
6879       info.GetIsolate()->GetCurrentContext()->Global();
6880   CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
6881   if (name->Equals(v8_str("p1"))) {
6882     CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
6883   } else if (name->Equals(v8_str("p2"))) {
6884     CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
6885   } else if (name->Equals(v8_str("p3"))) {
6886     CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
6887   } else if (name->Equals(v8_str("p4"))) {
6888     CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
6889   }
6890 }
6891
6892
6893 THREADED_TEST(GetterHolders) {
6894   v8::Isolate* isolate = CcTest::isolate();
6895   v8::HandleScope scope(isolate);
6896   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
6897   obj->SetAccessor(v8_str("p1"), PGetter);
6898   obj->SetAccessor(v8_str("p2"), PGetter);
6899   obj->SetAccessor(v8_str("p3"), PGetter);
6900   obj->SetAccessor(v8_str("p4"), PGetter);
6901   p_getter_count = 0;
6902   RunHolderTest(obj);
6903   CHECK_EQ(40, p_getter_count);
6904 }
6905
6906
6907 THREADED_TEST(PreInterceptorHolders) {
6908   v8::Isolate* isolate = CcTest::isolate();
6909   v8::HandleScope scope(isolate);
6910   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
6911   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
6912   p_getter_count2 = 0;
6913   RunHolderTest(obj);
6914   CHECK_EQ(40, p_getter_count2);
6915 }
6916
6917
6918 THREADED_TEST(ObjectInstantiation) {
6919   v8::Isolate* isolate = CcTest::isolate();
6920   v8::HandleScope scope(isolate);
6921   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
6922   templ->SetAccessor(v8_str("t"), PGetter2);
6923   LocalContext context;
6924   context->Global()->Set(v8_str("o"), templ->NewInstance());
6925   for (int i = 0; i < 100; i++) {
6926     v8::HandleScope inner_scope(CcTest::isolate());
6927     v8::Handle<v8::Object> obj = templ->NewInstance();
6928     CHECK(!obj->Equals(context->Global()->Get(v8_str("o"))));
6929     context->Global()->Set(v8_str("o2"), obj);
6930     v8::Handle<Value> value =
6931         CompileRun("o.__proto__ === o2.__proto__");
6932     CHECK(v8::True(isolate)->Equals(value));
6933     context->Global()->Set(v8_str("o"), obj);
6934   }
6935 }
6936
6937
6938 static int StrCmp16(uint16_t* a, uint16_t* b) {
6939   while (true) {
6940     if (*a == 0 && *b == 0) return 0;
6941     if (*a != *b) return 0 + *a - *b;
6942     a++;
6943     b++;
6944   }
6945 }
6946
6947
6948 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
6949   while (true) {
6950     if (n-- == 0) return 0;
6951     if (*a == 0 && *b == 0) return 0;
6952     if (*a != *b) return 0 + *a - *b;
6953     a++;
6954     b++;
6955   }
6956 }
6957
6958
6959 int GetUtf8Length(Handle<String> str) {
6960   int len = str->Utf8Length();
6961   if (len < 0) {
6962     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
6963     i::String::Flatten(istr);
6964     len = str->Utf8Length();
6965   }
6966   return len;
6967 }
6968
6969
6970 THREADED_TEST(StringWrite) {
6971   LocalContext context;
6972   v8::HandleScope scope(context->GetIsolate());
6973   v8::Handle<String> str = v8_str("abcde");
6974   // abc<Icelandic eth><Unicode snowman>.
6975   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
6976   v8::Handle<String> str3 = v8::String::NewFromUtf8(
6977       context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
6978   // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
6979   uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
6980   v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
6981       context->GetIsolate(), orphans, v8::String::kNormalString, 8);
6982   // single lead surrogate
6983   uint16_t lead[1] = { 0xd800 };
6984   v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
6985       context->GetIsolate(), lead, v8::String::kNormalString, 1);
6986   // single trail surrogate
6987   uint16_t trail[1] = { 0xdc00 };
6988   v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
6989       context->GetIsolate(), trail, v8::String::kNormalString, 1);
6990   // surrogate pair
6991   uint16_t pair[2] = { 0xd800,  0xdc00 };
6992   v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
6993       context->GetIsolate(), pair, v8::String::kNormalString, 2);
6994   const int kStride = 4;  // Must match stride in for loops in JS below.
6995   CompileRun(
6996       "var left = '';"
6997       "for (var i = 0; i < 0xd800; i += 4) {"
6998       "  left = left + String.fromCharCode(i);"
6999       "}");
7000   CompileRun(
7001       "var right = '';"
7002       "for (var i = 0; i < 0xd800; i += 4) {"
7003       "  right = String.fromCharCode(i) + right;"
7004       "}");
7005   v8::Handle<v8::Object> global = context->Global();
7006   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7007   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
7008
7009   CHECK_EQ(5, str2->Length());
7010   CHECK_EQ(0xd800 / kStride, left_tree->Length());
7011   CHECK_EQ(0xd800 / kStride, right_tree->Length());
7012
7013   char buf[100];
7014   char utf8buf[0xd800 * 3];
7015   uint16_t wbuf[100];
7016   int len;
7017   int charlen;
7018
7019   memset(utf8buf, 0x1, 1000);
7020   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7021   CHECK_EQ(9, len);
7022   CHECK_EQ(5, charlen);
7023   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7024
7025   memset(utf8buf, 0x1, 1000);
7026   len = str2->WriteUtf8(utf8buf, 8, &charlen);
7027   CHECK_EQ(8, len);
7028   CHECK_EQ(5, charlen);
7029   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
7030
7031   memset(utf8buf, 0x1, 1000);
7032   len = str2->WriteUtf8(utf8buf, 7, &charlen);
7033   CHECK_EQ(5, len);
7034   CHECK_EQ(4, charlen);
7035   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7036
7037   memset(utf8buf, 0x1, 1000);
7038   len = str2->WriteUtf8(utf8buf, 6, &charlen);
7039   CHECK_EQ(5, len);
7040   CHECK_EQ(4, charlen);
7041   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7042
7043   memset(utf8buf, 0x1, 1000);
7044   len = str2->WriteUtf8(utf8buf, 5, &charlen);
7045   CHECK_EQ(5, len);
7046   CHECK_EQ(4, charlen);
7047   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7048
7049   memset(utf8buf, 0x1, 1000);
7050   len = str2->WriteUtf8(utf8buf, 4, &charlen);
7051   CHECK_EQ(3, len);
7052   CHECK_EQ(3, charlen);
7053   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7054
7055   memset(utf8buf, 0x1, 1000);
7056   len = str2->WriteUtf8(utf8buf, 3, &charlen);
7057   CHECK_EQ(3, len);
7058   CHECK_EQ(3, charlen);
7059   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7060
7061   memset(utf8buf, 0x1, 1000);
7062   len = str2->WriteUtf8(utf8buf, 2, &charlen);
7063   CHECK_EQ(2, len);
7064   CHECK_EQ(2, charlen);
7065   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
7066
7067   // allow orphan surrogates by default
7068   memset(utf8buf, 0x1, 1000);
7069   len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7070   CHECK_EQ(13, len);
7071   CHECK_EQ(8, charlen);
7072   CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
7073
7074   // replace orphan surrogates with unicode replacement character
7075   memset(utf8buf, 0x1, 1000);
7076   len = orphans_str->WriteUtf8(utf8buf,
7077                                sizeof(utf8buf),
7078                                &charlen,
7079                                String::REPLACE_INVALID_UTF8);
7080   CHECK_EQ(13, len);
7081   CHECK_EQ(8, charlen);
7082   CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
7083
7084   // replace single lead surrogate with unicode replacement character
7085   memset(utf8buf, 0x1, 1000);
7086   len = lead_str->WriteUtf8(utf8buf,
7087                             sizeof(utf8buf),
7088                             &charlen,
7089                             String::REPLACE_INVALID_UTF8);
7090   CHECK_EQ(4, len);
7091   CHECK_EQ(1, charlen);
7092   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7093
7094   // replace single trail surrogate with unicode replacement character
7095   memset(utf8buf, 0x1, 1000);
7096   len = trail_str->WriteUtf8(utf8buf,
7097                              sizeof(utf8buf),
7098                              &charlen,
7099                              String::REPLACE_INVALID_UTF8);
7100   CHECK_EQ(4, len);
7101   CHECK_EQ(1, charlen);
7102   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7103
7104   // do not replace / write anything if surrogate pair does not fit the buffer
7105   // space
7106   memset(utf8buf, 0x1, 1000);
7107   len = pair_str->WriteUtf8(utf8buf,
7108                              3,
7109                              &charlen,
7110                              String::REPLACE_INVALID_UTF8);
7111   CHECK_EQ(0, len);
7112   CHECK_EQ(0, charlen);
7113
7114   memset(utf8buf, 0x1, sizeof(utf8buf));
7115   len = GetUtf8Length(left_tree);
7116   int utf8_expected =
7117       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7118   CHECK_EQ(utf8_expected, len);
7119   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7120   CHECK_EQ(utf8_expected, len);
7121   CHECK_EQ(0xd800 / kStride, charlen);
7122   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7123   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7124   CHECK_EQ(0xc0 - kStride,
7125            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7126   CHECK_EQ(1, utf8buf[utf8_expected]);
7127
7128   memset(utf8buf, 0x1, sizeof(utf8buf));
7129   len = GetUtf8Length(right_tree);
7130   CHECK_EQ(utf8_expected, len);
7131   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7132   CHECK_EQ(utf8_expected, len);
7133   CHECK_EQ(0xd800 / kStride, charlen);
7134   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7135   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7136   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7137   CHECK_EQ(1, utf8buf[utf8_expected]);
7138
7139   memset(buf, 0x1, sizeof(buf));
7140   memset(wbuf, 0x1, sizeof(wbuf));
7141   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7142   CHECK_EQ(5, len);
7143   len = str->Write(wbuf);
7144   CHECK_EQ(5, len);
7145   CHECK_EQ(0, strcmp("abcde", buf));
7146   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7147   CHECK_EQ(0, StrCmp16(answer1, wbuf));
7148
7149   memset(buf, 0x1, sizeof(buf));
7150   memset(wbuf, 0x1, sizeof(wbuf));
7151   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
7152   CHECK_EQ(4, len);
7153   len = str->Write(wbuf, 0, 4);
7154   CHECK_EQ(4, len);
7155   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
7156   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
7157   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
7158
7159   memset(buf, 0x1, sizeof(buf));
7160   memset(wbuf, 0x1, sizeof(wbuf));
7161   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
7162   CHECK_EQ(5, len);
7163   len = str->Write(wbuf, 0, 5);
7164   CHECK_EQ(5, len);
7165   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
7166   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
7167   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
7168
7169   memset(buf, 0x1, sizeof(buf));
7170   memset(wbuf, 0x1, sizeof(wbuf));
7171   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
7172   CHECK_EQ(5, len);
7173   len = str->Write(wbuf, 0, 6);
7174   CHECK_EQ(5, len);
7175   CHECK_EQ(0, strcmp("abcde", buf));
7176   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7177   CHECK_EQ(0, StrCmp16(answer4, wbuf));
7178
7179   memset(buf, 0x1, sizeof(buf));
7180   memset(wbuf, 0x1, sizeof(wbuf));
7181   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
7182   CHECK_EQ(1, len);
7183   len = str->Write(wbuf, 4, -1);
7184   CHECK_EQ(1, len);
7185   CHECK_EQ(0, strcmp("e", buf));
7186   uint16_t answer5[] = {'e', '\0'};
7187   CHECK_EQ(0, StrCmp16(answer5, wbuf));
7188
7189   memset(buf, 0x1, sizeof(buf));
7190   memset(wbuf, 0x1, sizeof(wbuf));
7191   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
7192   CHECK_EQ(1, len);
7193   len = str->Write(wbuf, 4, 6);
7194   CHECK_EQ(1, len);
7195   CHECK_EQ(0, strcmp("e", buf));
7196   CHECK_EQ(0, StrCmp16(answer5, wbuf));
7197
7198   memset(buf, 0x1, sizeof(buf));
7199   memset(wbuf, 0x1, sizeof(wbuf));
7200   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
7201   CHECK_EQ(1, len);
7202   len = str->Write(wbuf, 4, 1);
7203   CHECK_EQ(1, len);
7204   CHECK_EQ(0, strncmp("e\1", buf, 2));
7205   uint16_t answer6[] = {'e', 0x101};
7206   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
7207
7208   memset(buf, 0x1, sizeof(buf));
7209   memset(wbuf, 0x1, sizeof(wbuf));
7210   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
7211   CHECK_EQ(1, len);
7212   len = str->Write(wbuf, 3, 1);
7213   CHECK_EQ(1, len);
7214   CHECK_EQ(0, strncmp("d\1", buf, 2));
7215   uint16_t answer7[] = {'d', 0x101};
7216   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
7217
7218   memset(wbuf, 0x1, sizeof(wbuf));
7219   wbuf[5] = 'X';
7220   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7221   CHECK_EQ(5, len);
7222   CHECK_EQ('X', wbuf[5]);
7223   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7224   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7225   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7226   CHECK_NE(0, StrCmp16(answer8b, wbuf));
7227   wbuf[5] = '\0';
7228   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7229
7230   memset(buf, 0x1, sizeof(buf));
7231   buf[5] = 'X';
7232   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7233                           0,
7234                           6,
7235                           String::NO_NULL_TERMINATION);
7236   CHECK_EQ(5, len);
7237   CHECK_EQ('X', buf[5]);
7238   CHECK_EQ(0, strncmp("abcde", buf, 5));
7239   CHECK_NE(0, strcmp("abcde", buf));
7240   buf[5] = '\0';
7241   CHECK_EQ(0, strcmp("abcde", buf));
7242
7243   memset(utf8buf, 0x1, sizeof(utf8buf));
7244   utf8buf[8] = 'X';
7245   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7246                         String::NO_NULL_TERMINATION);
7247   CHECK_EQ(8, len);
7248   CHECK_EQ('X', utf8buf[8]);
7249   CHECK_EQ(5, charlen);
7250   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7251   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7252   utf8buf[8] = '\0';
7253   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7254
7255   memset(utf8buf, 0x1, sizeof(utf8buf));
7256   utf8buf[5] = 'X';
7257   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7258                         String::NO_NULL_TERMINATION);
7259   CHECK_EQ(5, len);
7260   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
7261   CHECK_EQ(5, charlen);
7262   utf8buf[5] = '\0';
7263   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7264
7265   memset(buf, 0x1, sizeof(buf));
7266   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7267   CHECK_EQ(7, len);
7268   CHECK_EQ(0, strcmp("abc", buf));
7269   CHECK_EQ(0, buf[3]);
7270   CHECK_EQ(0, strcmp("def", buf + 4));
7271
7272   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
7273   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7274   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
7275 }
7276
7277
7278 static void Utf16Helper(
7279     LocalContext& context,  // NOLINT
7280     const char* name,
7281     const char* lengths_name,
7282     int len) {
7283   Local<v8::Array> a =
7284       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7285   Local<v8::Array> alens =
7286       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7287   for (int i = 0; i < len; i++) {
7288     Local<v8::String> string =
7289       Local<v8::String>::Cast(a->Get(i));
7290     Local<v8::Number> expected_len =
7291       Local<v8::Number>::Cast(alens->Get(i));
7292     int length = GetUtf8Length(string);
7293     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7294   }
7295 }
7296
7297
7298 THREADED_TEST(Utf16) {
7299   LocalContext context;
7300   v8::HandleScope scope(context->GetIsolate());
7301   CompileRun(
7302       "var pad = '01234567890123456789';"
7303       "var p = [];"
7304       "var plens = [20, 3, 3];"
7305       "p.push('01234567890123456789');"
7306       "var lead = 0xd800;"
7307       "var trail = 0xdc00;"
7308       "p.push(String.fromCharCode(0xd800));"
7309       "p.push(String.fromCharCode(0xdc00));"
7310       "var a = [];"
7311       "var b = [];"
7312       "var c = [];"
7313       "var alens = [];"
7314       "for (var i = 0; i < 3; i++) {"
7315       "  p[1] = String.fromCharCode(lead++);"
7316       "  for (var j = 0; j < 3; j++) {"
7317       "    p[2] = String.fromCharCode(trail++);"
7318       "    a.push(p[i] + p[j]);"
7319       "    b.push(p[i] + p[j]);"
7320       "    c.push(p[i] + p[j]);"
7321       "    alens.push(plens[i] + plens[j]);"
7322       "  }"
7323       "}"
7324       "alens[5] -= 2;"  // Here the surrogate pairs match up.
7325       "var a2 = [];"
7326       "var b2 = [];"
7327       "var c2 = [];"
7328       "var a2lens = [];"
7329       "for (var m = 0; m < 9; m++) {"
7330       "  for (var n = 0; n < 9; n++) {"
7331       "    a2.push(a[m] + a[n]);"
7332       "    b2.push(b[m] + b[n]);"
7333       "    var newc = 'x' + c[m] + c[n] + 'y';"
7334       "    c2.push(newc.substring(1, newc.length - 1));"
7335       "    var utf = alens[m] + alens[n];"  // And here.
7336            // The 'n's that start with 0xdc.. are 6-8
7337            // The 'm's that end with 0xd8.. are 1, 4 and 7
7338       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
7339       "    a2lens.push(utf);"
7340       "  }"
7341       "}");
7342   Utf16Helper(context, "a", "alens", 9);
7343   Utf16Helper(context, "a2", "a2lens", 81);
7344 }
7345
7346
7347 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
7348   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
7349   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
7350   return *is1 == *is2;
7351 }
7352
7353
7354 THREADED_TEST(Utf16Symbol) {
7355   LocalContext context;
7356   v8::HandleScope scope(context->GetIsolate());
7357
7358   Handle<String> symbol1 = v8::String::NewFromUtf8(
7359       context->GetIsolate(), "abc", v8::String::kInternalizedString);
7360   Handle<String> symbol2 = v8::String::NewFromUtf8(
7361       context->GetIsolate(), "abc", v8::String::kInternalizedString);
7362   CHECK(SameSymbol(symbol1, symbol2));
7363
7364   CompileRun(
7365       "var sym0 = 'benedictus';"
7366       "var sym0b = 'S\303\270ren';"
7367       "var sym1 = '\355\240\201\355\260\207';"
7368       "var sym2 = '\360\220\220\210';"
7369       "var sym3 = 'x\355\240\201\355\260\207';"
7370       "var sym4 = 'x\360\220\220\210';"
7371       "if (sym1.length != 2) throw sym1;"
7372       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
7373       "if (sym2.length != 2) throw sym2;"
7374       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
7375       "if (sym3.length != 3) throw sym3;"
7376       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
7377       "if (sym4.length != 3) throw sym4;"
7378       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
7379   Handle<String> sym0 = v8::String::NewFromUtf8(
7380       context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
7381   Handle<String> sym0b = v8::String::NewFromUtf8(
7382       context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
7383   Handle<String> sym1 =
7384       v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
7385                               v8::String::kInternalizedString);
7386   Handle<String> sym2 =
7387       v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
7388                               v8::String::kInternalizedString);
7389   Handle<String> sym3 = v8::String::NewFromUtf8(
7390       context->GetIsolate(), "x\355\240\201\355\260\207",
7391       v8::String::kInternalizedString);
7392   Handle<String> sym4 =
7393       v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
7394                               v8::String::kInternalizedString);
7395   v8::Local<v8::Object> global = context->Global();
7396   Local<Value> s0 = global->Get(v8_str("sym0"));
7397   Local<Value> s0b = global->Get(v8_str("sym0b"));
7398   Local<Value> s1 = global->Get(v8_str("sym1"));
7399   Local<Value> s2 = global->Get(v8_str("sym2"));
7400   Local<Value> s3 = global->Get(v8_str("sym3"));
7401   Local<Value> s4 = global->Get(v8_str("sym4"));
7402   CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
7403   CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
7404   CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
7405   CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
7406   CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
7407   CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
7408 }
7409
7410
7411 THREADED_TEST(Utf16MissingTrailing) {
7412   LocalContext context;
7413   v8::HandleScope scope(context->GetIsolate());
7414
7415   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
7416   int size = 1024 * 64;
7417   uint8_t* buffer = new uint8_t[size];
7418   for (int i = 0; i < size; i += 4) {
7419     buffer[i] = 0xf0;
7420     buffer[i + 1] = 0x9d;
7421     buffer[i + 2] = 0x80;
7422     buffer[i + 3] = 0x9e;
7423   }
7424
7425   // Now invoke the decoder without last 3 bytes
7426   v8::Local<v8::String> str =
7427       v8::String::NewFromUtf8(
7428           context->GetIsolate(), reinterpret_cast<char*>(buffer),
7429           v8::NewStringType::kNormal, size - 3).ToLocalChecked();
7430   USE(str);
7431   delete[] buffer;
7432 }
7433
7434
7435 THREADED_TEST(Utf16Trailing3Byte) {
7436   LocalContext context;
7437   v8::HandleScope scope(context->GetIsolate());
7438
7439   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
7440   int size = 1024 * 63;
7441   uint8_t* buffer = new uint8_t[size];
7442   for (int i = 0; i < size; i += 3) {
7443     buffer[i] = 0xe2;
7444     buffer[i + 1] = 0x80;
7445     buffer[i + 2] = 0xa6;
7446   }
7447
7448   // Now invoke the decoder without last 3 bytes
7449   v8::Local<v8::String> str =
7450       v8::String::NewFromUtf8(
7451           context->GetIsolate(), reinterpret_cast<char*>(buffer),
7452           v8::NewStringType::kNormal, size).ToLocalChecked();
7453
7454   v8::String::Value value(str);
7455   CHECK_EQ(value.length(), size / 3);
7456   CHECK_EQ((*value)[value.length() - 1], 0x2026);
7457
7458   delete[] buffer;
7459 }
7460
7461
7462 THREADED_TEST(ToArrayIndex) {
7463   LocalContext context;
7464   v8::Isolate* isolate = context->GetIsolate();
7465   v8::HandleScope scope(isolate);
7466
7467   v8::Handle<String> str = v8_str("42");
7468   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
7469   CHECK(!index.IsEmpty());
7470   CHECK_EQ(42.0, index->Uint32Value());
7471   str = v8_str("42asdf");
7472   index = str->ToArrayIndex();
7473   CHECK(index.IsEmpty());
7474   str = v8_str("-42");
7475   index = str->ToArrayIndex();
7476   CHECK(index.IsEmpty());
7477   str = v8_str("4294967294");
7478   index = str->ToArrayIndex();
7479   CHECK(!index.IsEmpty());
7480   CHECK_EQ(4294967294.0, index->Uint32Value());
7481   v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
7482   index = num->ToArrayIndex();
7483   CHECK(!index.IsEmpty());
7484   CHECK_EQ(1.0, index->Uint32Value());
7485   num = v8::Number::New(isolate, -1);
7486   index = num->ToArrayIndex();
7487   CHECK(index.IsEmpty());
7488   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
7489   index = obj->ToArrayIndex();
7490   CHECK(index.IsEmpty());
7491 }
7492
7493
7494 THREADED_TEST(ErrorConstruction) {
7495   LocalContext context;
7496   v8::HandleScope scope(context->GetIsolate());
7497
7498   v8::Handle<String> foo = v8_str("foo");
7499   v8::Handle<String> message = v8_str("message");
7500   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
7501   CHECK(range_error->IsObject());
7502   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
7503   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
7504   CHECK(reference_error->IsObject());
7505   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
7506   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
7507   CHECK(syntax_error->IsObject());
7508   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
7509   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
7510   CHECK(type_error->IsObject());
7511   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
7512   v8::Handle<Value> error = v8::Exception::Error(foo);
7513   CHECK(error->IsObject());
7514   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7515 }
7516
7517
7518 static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
7519   ApiTestFuzzer::Fuzz();
7520   v8::Handle<String> foo = v8_str("foo");
7521   v8::Handle<String> message = v8_str("message");
7522   v8::Handle<Value> error = v8::Exception::Error(foo);
7523   CHECK(error->IsObject());
7524   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7525   info.GetIsolate()->ThrowException(error);
7526   info.GetReturnValue().SetUndefined();
7527 }
7528
7529
7530 THREADED_TEST(ExceptionCreateMessage) {
7531   LocalContext context;
7532   v8::HandleScope scope(context->GetIsolate());
7533   v8::Handle<String> foo_str = v8_str("foo");
7534   v8::Handle<String> message_str = v8_str("message");
7535
7536   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
7537
7538   Local<v8::FunctionTemplate> fun =
7539       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
7540   v8::Local<v8::Object> global = context->Global();
7541   global->Set(v8_str("throwV8Exception"), fun->GetFunction());
7542
7543   TryCatch try_catch(context->GetIsolate());
7544   CompileRun(
7545       "function f1() {\n"
7546       "  throwV8Exception();\n"
7547       "};\n"
7548       "f1();");
7549   CHECK(try_catch.HasCaught());
7550
7551   v8::Handle<v8::Value> error = try_catch.Exception();
7552   CHECK(error->IsObject());
7553   CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
7554
7555   v8::Handle<v8::Message> message = v8::Exception::CreateMessage(error);
7556   CHECK(!message.IsEmpty());
7557   CHECK_EQ(2, message->GetLineNumber());
7558   CHECK_EQ(2, message->GetStartColumn());
7559
7560   v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace();
7561   CHECK(!stackTrace.IsEmpty());
7562   CHECK_EQ(2, stackTrace->GetFrameCount());
7563
7564   stackTrace = v8::Exception::GetStackTrace(error);
7565   CHECK(!stackTrace.IsEmpty());
7566   CHECK_EQ(2, stackTrace->GetFrameCount());
7567
7568   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
7569
7570   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
7571   // is false.
7572   try_catch.Reset();
7573
7574   CompileRun(
7575       "function f2() {\n"
7576       "  return throwV8Exception();\n"
7577       "};\n"
7578       "f2();");
7579   CHECK(try_catch.HasCaught());
7580
7581   error = try_catch.Exception();
7582   CHECK(error->IsObject());
7583   CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
7584
7585   message = v8::Exception::CreateMessage(error);
7586   CHECK(!message.IsEmpty());
7587   CHECK_EQ(2, message->GetLineNumber());
7588   CHECK_EQ(9, message->GetStartColumn());
7589
7590   // Should be empty stack trace.
7591   stackTrace = message->GetStackTrace();
7592   CHECK(stackTrace.IsEmpty());
7593   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
7594 }
7595
7596
7597 THREADED_TEST(ExceptionCreateMessageLength) {
7598   LocalContext context;
7599   v8::HandleScope scope(context->GetIsolate());
7600
7601   // Test that the message is not truncated.
7602   TryCatch try_catch(context->GetIsolate());
7603   CompileRun(
7604       "var message = 'm';"
7605       "while (message.length < 1000) message += message;"
7606       "throw message;");
7607   CHECK(try_catch.HasCaught());
7608
7609   CHECK_LT(1000, try_catch.Message()->Get()->Length());
7610 }
7611
7612
7613 static void YGetter(Local<String> name,
7614                     const v8::PropertyCallbackInfo<v8::Value>& info) {
7615   ApiTestFuzzer::Fuzz();
7616   info.GetReturnValue().Set(v8_num(10));
7617 }
7618
7619
7620 static void YSetter(Local<String> name,
7621                     Local<Value> value,
7622                     const v8::PropertyCallbackInfo<void>& info) {
7623   Local<Object> this_obj = Local<Object>::Cast(info.This());
7624   if (this_obj->Has(name)) this_obj->Delete(name);
7625   this_obj->Set(name, value);
7626 }
7627
7628
7629 THREADED_TEST(DeleteAccessor) {
7630   v8::Isolate* isolate = CcTest::isolate();
7631   v8::HandleScope scope(isolate);
7632   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7633   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
7634   LocalContext context;
7635   v8::Handle<v8::Object> holder = obj->NewInstance();
7636   context->Global()->Set(v8_str("holder"), holder);
7637   v8::Handle<Value> result = CompileRun(
7638       "holder.y = 11; holder.y = 12; holder.y");
7639   CHECK_EQ(12u, result->Uint32Value());
7640 }
7641
7642
7643 THREADED_TEST(TypeSwitch) {
7644   v8::Isolate* isolate = CcTest::isolate();
7645   v8::HandleScope scope(isolate);
7646   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
7647   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
7648   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
7649   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
7650   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
7651   LocalContext context;
7652   v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
7653   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
7654   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
7655   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
7656   for (int i = 0; i < 10; i++) {
7657     CHECK_EQ(0, type_switch->match(obj0));
7658     CHECK_EQ(1, type_switch->match(obj1));
7659     CHECK_EQ(2, type_switch->match(obj2));
7660     CHECK_EQ(3, type_switch->match(obj3));
7661     CHECK_EQ(3, type_switch->match(obj3));
7662     CHECK_EQ(2, type_switch->match(obj2));
7663     CHECK_EQ(1, type_switch->match(obj1));
7664     CHECK_EQ(0, type_switch->match(obj0));
7665   }
7666 }
7667
7668
7669 static int trouble_nesting = 0;
7670 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
7671   ApiTestFuzzer::Fuzz();
7672   trouble_nesting++;
7673
7674   // Call a JS function that throws an uncaught exception.
7675   Local<v8::Object> arg_this =
7676       args.GetIsolate()->GetCurrentContext()->Global();
7677   Local<Value> trouble_callee = (trouble_nesting == 3) ?
7678     arg_this->Get(v8_str("trouble_callee")) :
7679     arg_this->Get(v8_str("trouble_caller"));
7680   CHECK(trouble_callee->IsFunction());
7681   args.GetReturnValue().Set(
7682       Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
7683 }
7684
7685
7686 static int report_count = 0;
7687 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
7688                                              v8::Handle<Value>) {
7689   report_count++;
7690 }
7691
7692
7693 // Counts uncaught exceptions, but other tests running in parallel
7694 // also have uncaught exceptions.
7695 TEST(ApiUncaughtException) {
7696   report_count = 0;
7697   LocalContext env;
7698   v8::Isolate* isolate = env->GetIsolate();
7699   v8::HandleScope scope(isolate);
7700   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7701
7702   Local<v8::FunctionTemplate> fun =
7703       v8::FunctionTemplate::New(isolate, TroubleCallback);
7704   v8::Local<v8::Object> global = env->Global();
7705   global->Set(v8_str("trouble"), fun->GetFunction());
7706
7707   CompileRun(
7708       "function trouble_callee() {"
7709       "  var x = null;"
7710       "  return x.foo;"
7711       "};"
7712       "function trouble_caller() {"
7713       "  trouble();"
7714       "};");
7715   Local<Value> trouble = global->Get(v8_str("trouble"));
7716   CHECK(trouble->IsFunction());
7717   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
7718   CHECK(trouble_callee->IsFunction());
7719   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
7720   CHECK(trouble_caller->IsFunction());
7721   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
7722   CHECK_EQ(1, report_count);
7723   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7724 }
7725
7726
7727 TEST(ApiUncaughtExceptionInObjectObserve) {
7728   v8::internal::FLAG_stack_size = 150;
7729   report_count = 0;
7730   LocalContext env;
7731   v8::Isolate* isolate = env->GetIsolate();
7732   v8::HandleScope scope(isolate);
7733   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7734   CompileRun(
7735       "var obj = {};"
7736       "var observe_count = 0;"
7737       "function observer1() { ++observe_count; };"
7738       "function observer2() { ++observe_count; };"
7739       "function observer_throws() { throw new Error(); };"
7740       "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
7741       "Object.observe(obj, observer_throws.bind());"
7742       "Object.observe(obj, observer1);"
7743       "Object.observe(obj, stack_overflow);"
7744       "Object.observe(obj, observer2);"
7745       "Object.observe(obj, observer_throws.bind());"
7746       "obj.foo = 'bar';");
7747   CHECK_EQ(3, report_count);
7748   ExpectInt32("observe_count", 2);
7749   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7750 }
7751
7752
7753 static const char* script_resource_name = "ExceptionInNativeScript.js";
7754 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
7755                                                 v8::Handle<Value>) {
7756   v8::Handle<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
7757   CHECK(!name_val.IsEmpty() && name_val->IsString());
7758   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
7759   CHECK_EQ(0, strcmp(script_resource_name, *name));
7760   CHECK_EQ(3, message->GetLineNumber());
7761   v8::String::Utf8Value source_line(message->GetSourceLine());
7762   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
7763 }
7764
7765
7766 TEST(ExceptionInNativeScript) {
7767   LocalContext env;
7768   v8::Isolate* isolate = env->GetIsolate();
7769   v8::HandleScope scope(isolate);
7770   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
7771
7772   Local<v8::FunctionTemplate> fun =
7773       v8::FunctionTemplate::New(isolate, TroubleCallback);
7774   v8::Local<v8::Object> global = env->Global();
7775   global->Set(v8_str("trouble"), fun->GetFunction());
7776
7777   CompileRunWithOrigin(
7778       "function trouble() {\n"
7779       "  var o = {};\n"
7780       "  new o.foo();\n"
7781       "};",
7782       script_resource_name);
7783   Local<Value> trouble = global->Get(v8_str("trouble"));
7784   CHECK(trouble->IsFunction());
7785   Function::Cast(*trouble)->Call(global, 0, NULL);
7786   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
7787 }
7788
7789
7790 TEST(CompilationErrorUsingTryCatchHandler) {
7791   LocalContext env;
7792   v8::HandleScope scope(env->GetIsolate());
7793   v8::TryCatch try_catch(env->GetIsolate());
7794   v8_compile("This doesn't &*&@#$&*^ compile.");
7795   CHECK(*try_catch.Exception());
7796   CHECK(try_catch.HasCaught());
7797 }
7798
7799
7800 TEST(TryCatchFinallyUsingTryCatchHandler) {
7801   LocalContext env;
7802   v8::HandleScope scope(env->GetIsolate());
7803   v8::TryCatch try_catch(env->GetIsolate());
7804   CompileRun("try { throw ''; } catch (e) {}");
7805   CHECK(!try_catch.HasCaught());
7806   CompileRun("try { throw ''; } finally {}");
7807   CHECK(try_catch.HasCaught());
7808   try_catch.Reset();
7809   CompileRun(
7810       "(function() {"
7811       "try { throw ''; } finally { return; }"
7812       "})()");
7813   CHECK(!try_catch.HasCaught());
7814   CompileRun(
7815       "(function()"
7816       "  { try { throw ''; } finally { throw 0; }"
7817       "})()");
7818   CHECK(try_catch.HasCaught());
7819 }
7820
7821
7822 void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
7823   v8::HandleScope scope(args.GetIsolate());
7824   CompileRun(args[0]->ToString(args.GetIsolate()));
7825 }
7826
7827
7828 TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
7829   v8::Isolate* isolate = CcTest::isolate();
7830   v8::HandleScope scope(isolate);
7831   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
7832   templ->Set(v8_str("CEvaluate"),
7833              v8::FunctionTemplate::New(isolate, CEvaluate));
7834   LocalContext context(0, templ);
7835   v8::TryCatch try_catch(isolate);
7836   CompileRun("try {"
7837              "  CEvaluate('throw 1;');"
7838              "} finally {"
7839              "}");
7840   CHECK(try_catch.HasCaught());
7841   CHECK(!try_catch.Message().IsEmpty());
7842   String::Utf8Value exception_value(try_catch.Exception());
7843   CHECK_EQ(0, strcmp(*exception_value, "1"));
7844   try_catch.Reset();
7845   CompileRun("try {"
7846              "  CEvaluate('throw 1;');"
7847              "} finally {"
7848              "  throw 2;"
7849              "}");
7850   CHECK(try_catch.HasCaught());
7851   CHECK(!try_catch.Message().IsEmpty());
7852   String::Utf8Value finally_exception_value(try_catch.Exception());
7853   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
7854 }
7855
7856
7857 // For use within the TestSecurityHandler() test.
7858 static bool g_security_callback_result = false;
7859 static bool SecurityTestCallback(Local<v8::Object> global, Local<Value> name,
7860                                  v8::AccessType type, Local<Value> data) {
7861   printf("a\n");
7862   return g_security_callback_result;
7863 }
7864
7865
7866 // SecurityHandler can't be run twice
7867 TEST(SecurityHandler) {
7868   v8::Isolate* isolate = CcTest::isolate();
7869   v8::HandleScope scope0(isolate);
7870   v8::Handle<v8::ObjectTemplate> global_template =
7871       v8::ObjectTemplate::New(isolate);
7872   global_template->SetAccessCheckCallbacks(SecurityTestCallback, NULL);
7873   // Create an environment
7874   v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
7875   context0->Enter();
7876
7877   v8::Handle<v8::Object> global0 = context0->Global();
7878   v8::Handle<Script> script0 = v8_compile("foo = 111");
7879   script0->Run();
7880   global0->Set(v8_str("0"), v8_num(999));
7881   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
7882   CHECK_EQ(111, foo0->Int32Value());
7883   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
7884   CHECK_EQ(999, z0->Int32Value());
7885
7886   // Create another environment, should fail security checks.
7887   v8::HandleScope scope1(isolate);
7888
7889   v8::Handle<Context> context1 =
7890     Context::New(isolate, NULL, global_template);
7891   context1->Enter();
7892
7893   v8::Handle<v8::Object> global1 = context1->Global();
7894   global1->Set(v8_str("othercontext"), global0);
7895   // This set will fail the security check.
7896   v8::Handle<Script> script1 =
7897     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
7898   script1->Run();
7899   g_security_callback_result = true;
7900   // This read will pass the security check.
7901   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
7902   CHECK_EQ(111, foo1->Int32Value());
7903   // This read will pass the security check.
7904   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
7905   CHECK_EQ(999, z1->Int32Value());
7906
7907   // Create another environment, should pass security checks.
7908   {
7909     v8::HandleScope scope2(isolate);
7910     LocalContext context2;
7911     v8::Handle<v8::Object> global2 = context2->Global();
7912     global2->Set(v8_str("othercontext"), global0);
7913     v8::Handle<Script> script2 =
7914         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
7915     script2->Run();
7916     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
7917     CHECK_EQ(333, foo2->Int32Value());
7918     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
7919     CHECK_EQ(888, z2->Int32Value());
7920   }
7921
7922   context1->Exit();
7923   context0->Exit();
7924 }
7925
7926
7927 THREADED_TEST(SecurityChecks) {
7928   LocalContext env1;
7929   v8::HandleScope handle_scope(env1->GetIsolate());
7930   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
7931
7932   Local<Value> foo = v8_str("foo");
7933   Local<Value> bar = v8_str("bar");
7934
7935   // Set to the same domain.
7936   env1->SetSecurityToken(foo);
7937
7938   // Create a function in env1.
7939   CompileRun("spy=function(){return spy;}");
7940   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
7941   CHECK(spy->IsFunction());
7942
7943   // Create another function accessing global objects.
7944   CompileRun("spy2=function(){return new this.Array();}");
7945   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
7946   CHECK(spy2->IsFunction());
7947
7948   // Switch to env2 in the same domain and invoke spy on env2.
7949   {
7950     env2->SetSecurityToken(foo);
7951     // Enter env2
7952     Context::Scope scope_env2(env2);
7953     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
7954     CHECK(result->IsFunction());
7955   }
7956
7957   {
7958     env2->SetSecurityToken(bar);
7959     Context::Scope scope_env2(env2);
7960
7961     // Call cross_domain_call, it should throw an exception
7962     v8::TryCatch try_catch(env1->GetIsolate());
7963     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
7964     CHECK(try_catch.HasCaught());
7965   }
7966 }
7967
7968
7969 // Regression test case for issue 1183439.
7970 THREADED_TEST(SecurityChecksForPrototypeChain) {
7971   LocalContext current;
7972   v8::HandleScope scope(current->GetIsolate());
7973   v8::Handle<Context> other = Context::New(current->GetIsolate());
7974
7975   // Change context to be able to get to the Object function in the
7976   // other context without hitting the security checks.
7977   v8::Local<Value> other_object;
7978   { Context::Scope scope(other);
7979     other_object = other->Global()->Get(v8_str("Object"));
7980     other->Global()->Set(v8_num(42), v8_num(87));
7981   }
7982
7983   current->Global()->Set(v8_str("other"), other->Global());
7984   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
7985
7986   // Make sure the security check fails here and we get an undefined
7987   // result instead of getting the Object function. Repeat in a loop
7988   // to make sure to exercise the IC code.
7989   v8::Local<Script> access_other0 = v8_compile("other.Object");
7990   v8::Local<Script> access_other1 = v8_compile("other[42]");
7991   for (int i = 0; i < 5; i++) {
7992     CHECK(access_other0->Run().IsEmpty());
7993     CHECK(access_other1->Run().IsEmpty());
7994   }
7995
7996   // Create an object that has 'other' in its prototype chain and make
7997   // sure we cannot access the Object function indirectly through
7998   // that. Repeat in a loop to make sure to exercise the IC code.
7999   v8_compile("function F() { };"
8000              "F.prototype = other;"
8001              "var f = new F();")->Run();
8002   v8::Local<Script> access_f0 = v8_compile("f.Object");
8003   v8::Local<Script> access_f1 = v8_compile("f[42]");
8004   for (int j = 0; j < 5; j++) {
8005     CHECK(access_f0->Run().IsEmpty());
8006     CHECK(access_f1->Run().IsEmpty());
8007   }
8008
8009   // Now it gets hairy: Set the prototype for the other global object
8010   // to be the current global object. The prototype chain for 'f' now
8011   // goes through 'other' but ends up in the current global object.
8012   { Context::Scope scope(other);
8013     other->Global()->Set(v8_str("__proto__"), current->Global());
8014   }
8015   // Set a named and an index property on the current global
8016   // object. To force the lookup to go through the other global object,
8017   // the properties must not exist in the other global object.
8018   current->Global()->Set(v8_str("foo"), v8_num(100));
8019   current->Global()->Set(v8_num(99), v8_num(101));
8020   // Try to read the properties from f and make sure that the access
8021   // gets stopped by the security checks on the other global object.
8022   Local<Script> access_f2 = v8_compile("f.foo");
8023   Local<Script> access_f3 = v8_compile("f[99]");
8024   for (int k = 0; k < 5; k++) {
8025     CHECK(access_f2->Run().IsEmpty());
8026     CHECK(access_f3->Run().IsEmpty());
8027   }
8028 }
8029
8030
8031 static bool security_check_with_gc_called;
8032
8033 static bool SecurityTestCallbackWithGC(Local<v8::Object> global,
8034                                        Local<v8::Value> name,
8035                                        v8::AccessType type, Local<Value> data) {
8036   CcTest::heap()->CollectAllGarbage();
8037   security_check_with_gc_called = true;
8038   return true;
8039 }
8040
8041
8042 TEST(SecurityTestGCAllowed) {
8043   v8::Isolate* isolate = CcTest::isolate();
8044   v8::HandleScope handle_scope(isolate);
8045   v8::Handle<v8::ObjectTemplate> object_template =
8046       v8::ObjectTemplate::New(isolate);
8047   object_template->SetAccessCheckCallbacks(SecurityTestCallbackWithGC, NULL);
8048
8049   v8::Handle<Context> context = Context::New(isolate);
8050   v8::Context::Scope context_scope(context);
8051
8052   context->Global()->Set(v8_str("obj"), object_template->NewInstance());
8053
8054   security_check_with_gc_called = false;
8055   CompileRun("obj[0] = new String(1002);");
8056   CHECK(security_check_with_gc_called);
8057
8058   security_check_with_gc_called = false;
8059   CHECK(CompileRun("obj[0]")->ToString(isolate)->Equals(v8_str("1002")));
8060   CHECK(security_check_with_gc_called);
8061 }
8062
8063
8064 THREADED_TEST(CrossDomainDelete) {
8065   LocalContext env1;
8066   v8::HandleScope handle_scope(env1->GetIsolate());
8067   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8068
8069   Local<Value> foo = v8_str("foo");
8070   Local<Value> bar = v8_str("bar");
8071
8072   // Set to the same domain.
8073   env1->SetSecurityToken(foo);
8074   env2->SetSecurityToken(foo);
8075
8076   env1->Global()->Set(v8_str("prop"), v8_num(3));
8077   env2->Global()->Set(v8_str("env1"), env1->Global());
8078
8079   // Change env2 to a different domain and delete env1.prop.
8080   env2->SetSecurityToken(bar);
8081   {
8082     Context::Scope scope_env2(env2);
8083     Local<Value> result =
8084         CompileRun("delete env1.prop");
8085     CHECK(result.IsEmpty());
8086   }
8087
8088   // Check that env1.prop still exists.
8089   Local<Value> v = env1->Global()->Get(v8_str("prop"));
8090   CHECK(v->IsNumber());
8091   CHECK_EQ(3, v->Int32Value());
8092 }
8093
8094
8095 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
8096   LocalContext env1;
8097   v8::HandleScope handle_scope(env1->GetIsolate());
8098   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8099
8100   Local<Value> foo = v8_str("foo");
8101   Local<Value> bar = v8_str("bar");
8102
8103   // Set to the same domain.
8104   env1->SetSecurityToken(foo);
8105   env2->SetSecurityToken(foo);
8106
8107   env1->Global()->Set(v8_str("prop"), v8_num(3));
8108   env2->Global()->Set(v8_str("env1"), env1->Global());
8109
8110   // env1.prop is enumerable in env2.
8111   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8112   {
8113     Context::Scope scope_env2(env2);
8114     Local<Value> result = CompileRun(test);
8115     CHECK(result->IsTrue());
8116   }
8117
8118   // Change env2 to a different domain and test again.
8119   env2->SetSecurityToken(bar);
8120   {
8121     Context::Scope scope_env2(env2);
8122     Local<Value> result = CompileRun(test);
8123     CHECK(result.IsEmpty());
8124   }
8125 }
8126
8127
8128 THREADED_TEST(CrossDomainFor) {
8129   LocalContext env1;
8130   v8::HandleScope handle_scope(env1->GetIsolate());
8131   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8132
8133   Local<Value> foo = v8_str("foo");
8134   Local<Value> bar = v8_str("bar");
8135
8136   // Set to the same domain.
8137   env1->SetSecurityToken(foo);
8138   env2->SetSecurityToken(foo);
8139
8140   env1->Global()->Set(v8_str("prop"), v8_num(3));
8141   env2->Global()->Set(v8_str("env1"), env1->Global());
8142
8143   // Change env2 to a different domain and set env1's global object
8144   // as the __proto__ of an object in env2 and enumerate properties
8145   // in for-in. It shouldn't enumerate properties on env1's global
8146   // object.
8147   env2->SetSecurityToken(bar);
8148   {
8149     Context::Scope scope_env2(env2);
8150     Local<Value> result = CompileRun(
8151         "(function() {"
8152         "  try {"
8153         "    for (var p in env1) {"
8154         "      if (p == 'prop') return false;"
8155         "    }"
8156         "    return true;"
8157         "  } catch (e) {"
8158         "    return false;"
8159         "  }"
8160         "})()");
8161     CHECK(result->IsTrue());
8162   }
8163 }
8164
8165
8166 THREADED_TEST(CrossDomainForInOnPrototype) {
8167   LocalContext env1;
8168   v8::HandleScope handle_scope(env1->GetIsolate());
8169   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8170
8171   Local<Value> foo = v8_str("foo");
8172   Local<Value> bar = v8_str("bar");
8173
8174   // Set to the same domain.
8175   env1->SetSecurityToken(foo);
8176   env2->SetSecurityToken(foo);
8177
8178   env1->Global()->Set(v8_str("prop"), v8_num(3));
8179   env2->Global()->Set(v8_str("env1"), env1->Global());
8180
8181   // Change env2 to a different domain and set env1's global object
8182   // as the __proto__ of an object in env2 and enumerate properties
8183   // in for-in. It shouldn't enumerate properties on env1's global
8184   // object.
8185   env2->SetSecurityToken(bar);
8186   {
8187     Context::Scope scope_env2(env2);
8188     Local<Value> result = CompileRun(
8189         "(function() {"
8190         "  var obj = { '__proto__': env1 };"
8191         "  try {"
8192         "    for (var p in obj) {"
8193         "      if (p == 'prop') return false;"
8194         "    }"
8195         "    return false;"
8196         "  } catch (e) {"
8197         "    return true;"
8198         "  }"
8199         "})()");
8200     CHECK(result->IsTrue());
8201   }
8202 }
8203
8204
8205 TEST(ContextDetachGlobal) {
8206   LocalContext env1;
8207   v8::HandleScope handle_scope(env1->GetIsolate());
8208   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8209
8210   Local<v8::Object> global1 = env1->Global();
8211
8212   Local<Value> foo = v8_str("foo");
8213
8214   // Set to the same domain.
8215   env1->SetSecurityToken(foo);
8216   env2->SetSecurityToken(foo);
8217
8218   // Enter env2
8219   env2->Enter();
8220
8221   // Create a function in env2 and add a reference to it in env1.
8222   Local<v8::Object> global2 = env2->Global();
8223   global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
8224   CompileRun("function getProp() {return prop;}");
8225
8226   env1->Global()->Set(v8_str("getProp"),
8227                       global2->Get(v8_str("getProp")));
8228
8229   // Detach env2's global, and reuse the global object of env2
8230   env2->Exit();
8231   env2->DetachGlobal();
8232
8233   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8234                                           0,
8235                                           v8::Handle<v8::ObjectTemplate>(),
8236                                           global2);
8237   env3->SetSecurityToken(v8_str("bar"));
8238   env3->Enter();
8239
8240   Local<v8::Object> global3 = env3->Global();
8241   CHECK(global2->Equals(global3));
8242   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8243   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
8244   global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8245   global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
8246   env3->Exit();
8247
8248   // Call getProp in env1, and it should return the value 1
8249   {
8250     Local<Value> get_prop = global1->Get(v8_str("getProp"));
8251     CHECK(get_prop->IsFunction());
8252     v8::TryCatch try_catch(env1->GetIsolate());
8253     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8254     CHECK(!try_catch.HasCaught());
8255     CHECK_EQ(1, r->Int32Value());
8256   }
8257
8258   // Check that env3 is not accessible from env1
8259   {
8260     Local<Value> r = global3->Get(v8_str("prop2"));
8261     CHECK(r.IsEmpty());
8262   }
8263 }
8264
8265
8266 TEST(DetachGlobal) {
8267   LocalContext env1;
8268   v8::HandleScope scope(env1->GetIsolate());
8269
8270   // Create second environment.
8271   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8272
8273   Local<Value> foo = v8_str("foo");
8274
8275   // Set same security token for env1 and env2.
8276   env1->SetSecurityToken(foo);
8277   env2->SetSecurityToken(foo);
8278
8279   // Create a property on the global object in env2.
8280   {
8281     v8::Context::Scope scope(env2);
8282     env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
8283   }
8284
8285   // Create a reference to env2 global from env1 global.
8286   env1->Global()->Set(v8_str("other"), env2->Global());
8287
8288   // Check that we have access to other.p in env2 from env1.
8289   Local<Value> result = CompileRun("other.p");
8290   CHECK(result->IsInt32());
8291   CHECK_EQ(42, result->Int32Value());
8292
8293   // Hold on to global from env2 and detach global from env2.
8294   Local<v8::Object> global2 = env2->Global();
8295   env2->DetachGlobal();
8296
8297   // Check that the global has been detached. No other.p property can
8298   // be found.
8299   result = CompileRun("other.p");
8300   CHECK(result.IsEmpty());
8301
8302   // Reuse global2 for env3.
8303   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8304                                           0,
8305                                           v8::Handle<v8::ObjectTemplate>(),
8306                                           global2);
8307   CHECK(global2->Equals(env3->Global()));
8308
8309   // Start by using the same security token for env3 as for env1 and env2.
8310   env3->SetSecurityToken(foo);
8311
8312   // Create a property on the global object in env3.
8313   {
8314     v8::Context::Scope scope(env3);
8315     env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
8316   }
8317
8318   // Check that other.p is now the property in env3 and that we have access.
8319   result = CompileRun("other.p");
8320   CHECK(result->IsInt32());
8321   CHECK_EQ(24, result->Int32Value());
8322
8323   // Change security token for env3 to something different from env1 and env2.
8324   env3->SetSecurityToken(v8_str("bar"));
8325
8326   // Check that we do not have access to other.p in env1. |other| is now
8327   // the global object for env3 which has a different security token,
8328   // so access should be blocked.
8329   result = CompileRun("other.p");
8330   CHECK(result.IsEmpty());
8331 }
8332
8333
8334 void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
8335   info.GetReturnValue().Set(
8336       info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8337 }
8338
8339
8340 TEST(DetachedAccesses) {
8341   LocalContext env1;
8342   v8::HandleScope scope(env1->GetIsolate());
8343
8344   // Create second environment.
8345   Local<ObjectTemplate> inner_global_template =
8346       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8347   inner_global_template ->SetAccessorProperty(
8348       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8349   v8::Local<Context> env2 =
8350       Context::New(env1->GetIsolate(), NULL, inner_global_template);
8351
8352   Local<Value> foo = v8_str("foo");
8353
8354   // Set same security token for env1 and env2.
8355   env1->SetSecurityToken(foo);
8356   env2->SetSecurityToken(foo);
8357
8358   env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8359
8360   {
8361     v8::Context::Scope scope(env2);
8362     env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
8363     CompileRun(
8364         "function bound_x() { return x; }"
8365         "function get_x()   { return this.x; }"
8366         "function get_x_w() { return (function() {return this.x;})(); }");
8367     env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
8368     env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8369     env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
8370     env1->Global()->Set(
8371         v8_str("this_x"),
8372         CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
8373   }
8374
8375   Local<Object> env2_global = env2->Global();
8376   env2->DetachGlobal();
8377
8378   Local<Value> result;
8379   result = CompileRun("bound_x()");
8380   CHECK(v8_str("env2_x")->Equals(result));
8381   result = CompileRun("get_x()");
8382   CHECK(result.IsEmpty());
8383   result = CompileRun("get_x_w()");
8384   CHECK(result.IsEmpty());
8385   result = CompileRun("this_x()");
8386   CHECK(v8_str("env2_x")->Equals(result));
8387
8388   // Reattach env2's proxy
8389   env2 = Context::New(env1->GetIsolate(),
8390                       0,
8391                       v8::Handle<v8::ObjectTemplate>(),
8392                       env2_global);
8393   env2->SetSecurityToken(foo);
8394   {
8395     v8::Context::Scope scope(env2);
8396     env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8397     env2->Global()->Set(v8_str("env1"), env1->Global());
8398     result = CompileRun(
8399         "results = [];"
8400         "for (var i = 0; i < 4; i++ ) {"
8401         "  results.push(env1.bound_x());"
8402         "  results.push(env1.get_x());"
8403         "  results.push(env1.get_x_w());"
8404         "  results.push(env1.this_x());"
8405         "}"
8406         "results");
8407     Local<v8::Array> results = Local<v8::Array>::Cast(result);
8408     CHECK_EQ(16u, results->Length());
8409     for (int i = 0; i < 16; i += 4) {
8410       CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8411       CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
8412       CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8413       CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8414     }
8415   }
8416
8417   result = CompileRun(
8418       "results = [];"
8419       "for (var i = 0; i < 4; i++ ) {"
8420       "  results.push(bound_x());"
8421       "  results.push(get_x());"
8422       "  results.push(get_x_w());"
8423       "  results.push(this_x());"
8424       "}"
8425       "results");
8426   Local<v8::Array> results = Local<v8::Array>::Cast(result);
8427   CHECK_EQ(16u, results->Length());
8428   for (int i = 0; i < 16; i += 4) {
8429     CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8430     CHECK(v8_str("env3_x")->Equals(results->Get(i + 1)));
8431     CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8432     CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8433   }
8434
8435   result = CompileRun(
8436       "results = [];"
8437       "for (var i = 0; i < 4; i++ ) {"
8438       "  results.push(this.bound_x());"
8439       "  results.push(this.get_x());"
8440       "  results.push(this.get_x_w());"
8441       "  results.push(this.this_x());"
8442       "}"
8443       "results");
8444   results = Local<v8::Array>::Cast(result);
8445   CHECK_EQ(16u, results->Length());
8446   for (int i = 0; i < 16; i += 4) {
8447     CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8448     CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
8449     CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8450     CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8451   }
8452 }
8453
8454
8455 static bool allowed_access = false;
8456 static bool AccessBlocker(Local<v8::Object> global, Local<Value> name,
8457                           v8::AccessType type, Local<Value> data) {
8458   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
8459          allowed_access;
8460 }
8461
8462
8463 static int g_echo_value = -1;
8464
8465
8466 static void EchoGetter(
8467     Local<String> name,
8468     const v8::PropertyCallbackInfo<v8::Value>& info) {
8469   info.GetReturnValue().Set(v8_num(g_echo_value));
8470 }
8471
8472
8473 static void EchoSetter(Local<String> name,
8474                        Local<Value> value,
8475                        const v8::PropertyCallbackInfo<void>&) {
8476   if (value->IsNumber())
8477     g_echo_value = value->Int32Value();
8478 }
8479
8480
8481 static void UnreachableGetter(
8482     Local<String> name,
8483     const v8::PropertyCallbackInfo<v8::Value>& info) {
8484   CHECK(false);  // This function should not be called..
8485 }
8486
8487
8488 static void UnreachableSetter(Local<String>,
8489                               Local<Value>,
8490                               const v8::PropertyCallbackInfo<void>&) {
8491   CHECK(false);  // This function should nto be called.
8492 }
8493
8494
8495 static void UnreachableFunction(
8496     const v8::FunctionCallbackInfo<v8::Value>& info) {
8497   CHECK(false);  // This function should not be called..
8498 }
8499
8500
8501 TEST(AccessControl) {
8502   v8::Isolate* isolate = CcTest::isolate();
8503   v8::HandleScope handle_scope(isolate);
8504   v8::Handle<v8::ObjectTemplate> global_template =
8505       v8::ObjectTemplate::New(isolate);
8506
8507   global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
8508
8509   // Add an accessor accessible by cross-domain JS code.
8510   global_template->SetAccessor(
8511       v8_str("accessible_prop"),
8512       EchoGetter, EchoSetter,
8513       v8::Handle<Value>(),
8514       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8515
8516
8517   // Add an accessor that is not accessible by cross-domain JS code.
8518   global_template->SetAccessor(v8_str("blocked_prop"),
8519                                UnreachableGetter, UnreachableSetter,
8520                                v8::Handle<Value>(),
8521                                v8::DEFAULT);
8522
8523   global_template->SetAccessorProperty(
8524       v8_str("blocked_js_prop"),
8525       v8::FunctionTemplate::New(isolate, UnreachableFunction),
8526       v8::FunctionTemplate::New(isolate, UnreachableFunction),
8527       v8::None,
8528       v8::DEFAULT);
8529
8530   // Create an environment
8531   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8532   context0->Enter();
8533
8534   v8::Handle<v8::Object> global0 = context0->Global();
8535
8536   // Define a property with JS getter and setter.
8537   CompileRun(
8538       "function getter() { return 'getter'; };\n"
8539       "function setter() { return 'setter'; }\n"
8540       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8541
8542   Local<Value> getter = global0->Get(v8_str("getter"));
8543   Local<Value> setter = global0->Get(v8_str("setter"));
8544
8545   // And define normal element.
8546   global0->Set(239, v8_str("239"));
8547
8548   // Define an element with JS getter and setter.
8549   CompileRun(
8550       "function el_getter() { return 'el_getter'; };\n"
8551       "function el_setter() { return 'el_setter'; };\n"
8552       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
8553
8554   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
8555   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
8556
8557   v8::HandleScope scope1(isolate);
8558
8559   v8::Local<Context> context1 = Context::New(isolate);
8560   context1->Enter();
8561
8562   v8::Handle<v8::Object> global1 = context1->Global();
8563   global1->Set(v8_str("other"), global0);
8564
8565   // Access blocked property.
8566   CompileRun("other.blocked_prop = 1");
8567
8568   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8569   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
8570             .IsEmpty());
8571   CHECK(
8572       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
8573
8574   // Access blocked element.
8575   CHECK(CompileRun("other[239] = 1").IsEmpty());
8576
8577   CHECK(CompileRun("other[239]").IsEmpty());
8578   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
8579   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
8580
8581   allowed_access = true;
8582   // Now we can enumerate the property.
8583   ExpectTrue("propertyIsEnumerable.call(other, '239')");
8584   allowed_access = false;
8585
8586   // Access a property with JS accessor.
8587   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
8588
8589   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
8590   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
8591             .IsEmpty());
8592
8593   allowed_access = true;
8594
8595   ExpectString("other.js_accessor_p", "getter");
8596   ExpectObject(
8597       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
8598   ExpectObject(
8599       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
8600   ExpectUndefined(
8601       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8602
8603   allowed_access = false;
8604
8605   // Access an element with JS accessor.
8606   CHECK(CompileRun("other[42] = 2").IsEmpty());
8607
8608   CHECK(CompileRun("other[42]").IsEmpty());
8609   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
8610
8611   allowed_access = true;
8612
8613   ExpectString("other[42]", "el_getter");
8614   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
8615   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
8616   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8617
8618   allowed_access = false;
8619
8620   v8::Handle<Value> value;
8621
8622   // Access accessible property
8623   value = CompileRun("other.accessible_prop = 3");
8624   CHECK(value->IsNumber());
8625   CHECK_EQ(3, value->Int32Value());
8626   CHECK_EQ(3, g_echo_value);
8627
8628   value = CompileRun("other.accessible_prop");
8629   CHECK(value->IsNumber());
8630   CHECK_EQ(3, value->Int32Value());
8631
8632   value = CompileRun(
8633       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
8634   CHECK(value->IsNumber());
8635   CHECK_EQ(3, value->Int32Value());
8636
8637   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
8638   CHECK(value->IsTrue());
8639
8640   // Enumeration doesn't enumerate accessors from inaccessible objects in
8641   // the prototype chain even if the accessors are in themselves accessible.
8642   value = CompileRun(
8643       "(function() {"
8644       "  var obj = { '__proto__': other };"
8645       "  try {"
8646       "    for (var p in obj) {"
8647       "      if (p == 'accessible_prop' ||"
8648       "          p == 'blocked_js_prop' ||"
8649       "          p == 'blocked_js_prop') {"
8650       "        return false;"
8651       "      }"
8652       "    }"
8653       "    return false;"
8654       "  } catch (e) {"
8655       "    return true;"
8656       "  }"
8657       "})()");
8658   CHECK(value->IsTrue());
8659
8660   context1->Exit();
8661   context0->Exit();
8662 }
8663
8664
8665 TEST(AccessControlES5) {
8666   v8::Isolate* isolate = CcTest::isolate();
8667   v8::HandleScope handle_scope(isolate);
8668   v8::Handle<v8::ObjectTemplate> global_template =
8669       v8::ObjectTemplate::New(isolate);
8670
8671   global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
8672
8673   // Add accessible accessor.
8674   global_template->SetAccessor(
8675       v8_str("accessible_prop"),
8676       EchoGetter, EchoSetter,
8677       v8::Handle<Value>(),
8678       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8679
8680
8681   // Add an accessor that is not accessible by cross-domain JS code.
8682   global_template->SetAccessor(v8_str("blocked_prop"),
8683                                UnreachableGetter, UnreachableSetter,
8684                                v8::Handle<Value>(),
8685                                v8::DEFAULT);
8686
8687   // Create an environment
8688   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8689   context0->Enter();
8690
8691   v8::Handle<v8::Object> global0 = context0->Global();
8692
8693   v8::Local<Context> context1 = Context::New(isolate);
8694   context1->Enter();
8695   v8::Handle<v8::Object> global1 = context1->Global();
8696   global1->Set(v8_str("other"), global0);
8697
8698   // Regression test for issue 1154.
8699   CHECK(CompileRun("Object.keys(other).length == 0")->BooleanValue());
8700   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8701
8702   // Regression test for issue 1027.
8703   CompileRun("Object.defineProperty(\n"
8704              "  other, 'blocked_prop', {configurable: false})");
8705   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8706   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
8707             .IsEmpty());
8708
8709   // Regression test for issue 1171.
8710   ExpectTrue("Object.isExtensible(other)");
8711   CompileRun("Object.preventExtensions(other)");
8712   ExpectTrue("Object.isExtensible(other)");
8713
8714   // Object.seal and Object.freeze.
8715   CompileRun("Object.freeze(other)");
8716   ExpectTrue("Object.isExtensible(other)");
8717
8718   CompileRun("Object.seal(other)");
8719   ExpectTrue("Object.isExtensible(other)");
8720
8721   // Regression test for issue 1250.
8722   // Make sure that we can set the accessible accessors value using normal
8723   // assignment.
8724   CompileRun("other.accessible_prop = 42");
8725   CHECK_EQ(42, g_echo_value);
8726
8727   v8::Handle<Value> value;
8728   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
8729   value = CompileRun("other.accessible_prop == 42");
8730   CHECK(value->IsTrue());
8731 }
8732
8733
8734 static bool AccessAlwaysBlocked(Local<v8::Object> global, Local<Value> name,
8735                                 v8::AccessType type, Local<Value> data) {
8736   i::PrintF("Access blocked.\n");
8737   return false;
8738 }
8739
8740
8741 THREADED_TEST(AccessControlGetOwnPropertyNames) {
8742   v8::Isolate* isolate = CcTest::isolate();
8743   v8::HandleScope handle_scope(isolate);
8744   v8::Handle<v8::ObjectTemplate> obj_template =
8745       v8::ObjectTemplate::New(isolate);
8746
8747   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
8748   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8749
8750   // Add an accessor accessible by cross-domain JS code.
8751   obj_template->SetAccessor(
8752       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Handle<Value>(),
8753       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8754
8755   // Create an environment
8756   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
8757   context0->Enter();
8758
8759   v8::Handle<v8::Object> global0 = context0->Global();
8760
8761   v8::HandleScope scope1(CcTest::isolate());
8762
8763   v8::Local<Context> context1 = Context::New(isolate);
8764   context1->Enter();
8765
8766   v8::Handle<v8::Object> global1 = context1->Global();
8767   global1->Set(v8_str("other"), global0);
8768   global1->Set(v8_str("object"), obj_template->NewInstance());
8769
8770   v8::Handle<Value> value;
8771
8772   // Attempt to get the property names of the other global object and
8773   // of an object that requires access checks.  Accessing the other
8774   // global object should be blocked by access checks on the global
8775   // proxy object.  Accessing the object that requires access checks
8776   // is blocked by the access checks on the object itself.
8777   value = CompileRun(
8778       "var names = Object.getOwnPropertyNames(other);"
8779       "names.length == 1 && names[0] == 'accessible_prop';");
8780   CHECK(value->BooleanValue());
8781
8782   value = CompileRun(
8783       "var names = Object.getOwnPropertyNames(object);"
8784       "names.length == 1 && names[0] == 'accessible_prop';");
8785   CHECK(value->BooleanValue());
8786
8787   context1->Exit();
8788   context0->Exit();
8789 }
8790
8791
8792 TEST(SuperAccessControl) {
8793   i::FLAG_allow_natives_syntax = true;
8794   v8::Isolate* isolate = CcTest::isolate();
8795   v8::HandleScope handle_scope(isolate);
8796   v8::Handle<v8::ObjectTemplate> obj_template =
8797       v8::ObjectTemplate::New(isolate);
8798   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8799   LocalContext env;
8800   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
8801
8802   {
8803     v8::TryCatch try_catch(isolate);
8804     CompileRun(
8805         "var f = { m() { return super.hasOwnProperty; } }.m;"
8806         "var m = %ToMethod(f, prohibited);"
8807         "m();");
8808     CHECK(try_catch.HasCaught());
8809   }
8810
8811   {
8812     v8::TryCatch try_catch(isolate);
8813     CompileRun(
8814         "var f = {m() { return super[42]; } }.m;"
8815         "var m = %ToMethod(f, prohibited);"
8816         "m();");
8817     CHECK(try_catch.HasCaught());
8818   }
8819
8820   {
8821     v8::TryCatch try_catch(isolate);
8822     CompileRun(
8823         "var f = {m() { super.hasOwnProperty = function () {}; } }.m;"
8824         "var m = %ToMethod(f, prohibited);"
8825         "m();");
8826     CHECK(try_catch.HasCaught());
8827   }
8828
8829   {
8830     v8::TryCatch try_catch(isolate);
8831     CompileRun(
8832         "Object.defineProperty(Object.prototype, 'x', { set : function(){}});"
8833         "var f = {"
8834         "  m() { "
8835         "    'use strict';"
8836         "    super.x = function () {};"
8837         "  }"
8838         "}.m;"
8839         "var m = %ToMethod(f, prohibited);"
8840         "m();");
8841     CHECK(try_catch.HasCaught());
8842   }
8843 }
8844
8845
8846 TEST(Regress470113) {
8847   v8::Isolate* isolate = CcTest::isolate();
8848   v8::HandleScope handle_scope(isolate);
8849   v8::Handle<v8::ObjectTemplate> obj_template =
8850       v8::ObjectTemplate::New(isolate);
8851   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8852   LocalContext env;
8853   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
8854
8855   {
8856     v8::TryCatch try_catch(isolate);
8857     CompileRun(
8858         "'use strict';\n"
8859         "class C extends Object {\n"
8860         "   m() { super.powned = 'Powned!'; }\n"
8861         "}\n"
8862         "let c = new C();\n"
8863         "c.m.call(prohibited)");
8864
8865     CHECK(try_catch.HasCaught());
8866   }
8867 }
8868
8869
8870 static void ConstTenGetter(Local<String> name,
8871                            const v8::PropertyCallbackInfo<v8::Value>& info) {
8872   info.GetReturnValue().Set(v8_num(10));
8873 }
8874
8875
8876 THREADED_TEST(CrossDomainAccessors) {
8877   v8::Isolate* isolate = CcTest::isolate();
8878   v8::HandleScope handle_scope(isolate);
8879
8880   v8::Handle<v8::FunctionTemplate> func_template =
8881       v8::FunctionTemplate::New(isolate);
8882
8883   v8::Handle<v8::ObjectTemplate> global_template =
8884       func_template->InstanceTemplate();
8885
8886   v8::Handle<v8::ObjectTemplate> proto_template =
8887       func_template->PrototypeTemplate();
8888
8889   // Add an accessor to proto that's accessible by cross-domain JS code.
8890   proto_template->SetAccessor(v8_str("accessible"),
8891                               ConstTenGetter, 0,
8892                               v8::Handle<Value>(),
8893                               v8::ALL_CAN_READ);
8894
8895   // Add an accessor that is not accessible by cross-domain JS code.
8896   global_template->SetAccessor(v8_str("unreachable"),
8897                                UnreachableGetter, 0,
8898                                v8::Handle<Value>(),
8899                                v8::DEFAULT);
8900
8901   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8902   context0->Enter();
8903
8904   Local<v8::Object> global = context0->Global();
8905   // Add a normal property that shadows 'accessible'
8906   global->Set(v8_str("accessible"), v8_num(11));
8907
8908   // Enter a new context.
8909   v8::HandleScope scope1(CcTest::isolate());
8910   v8::Local<Context> context1 = Context::New(isolate);
8911   context1->Enter();
8912
8913   v8::Handle<v8::Object> global1 = context1->Global();
8914   global1->Set(v8_str("other"), global);
8915
8916   // Should return 10, instead of 11
8917   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
8918   CHECK(value->IsNumber());
8919   CHECK_EQ(10, value->Int32Value());
8920
8921   value = v8_compile("other.unreachable")->Run();
8922   CHECK(value.IsEmpty());
8923
8924   context1->Exit();
8925   context0->Exit();
8926 }
8927
8928
8929 static int access_count = 0;
8930
8931 static bool AccessCounter(Local<v8::Object> global, Local<Value> name,
8932                           v8::AccessType type, Local<Value> data) {
8933   access_count++;
8934   return true;
8935 }
8936
8937
8938 // This one is too easily disturbed by other tests.
8939 TEST(AccessControlIC) {
8940   access_count = 0;
8941
8942   v8::Isolate* isolate = CcTest::isolate();
8943   v8::HandleScope handle_scope(isolate);
8944
8945   // Create an environment.
8946   v8::Local<Context> context0 = Context::New(isolate);
8947   context0->Enter();
8948
8949   // Create an object that requires access-check functions to be
8950   // called for cross-domain access.
8951   v8::Handle<v8::ObjectTemplate> object_template =
8952       v8::ObjectTemplate::New(isolate);
8953   object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
8954   Local<v8::Object> object = object_template->NewInstance();
8955
8956   v8::HandleScope scope1(isolate);
8957
8958   // Create another environment.
8959   v8::Local<Context> context1 = Context::New(isolate);
8960   context1->Enter();
8961
8962   // Make easy access to the object from the other environment.
8963   v8::Handle<v8::Object> global1 = context1->Global();
8964   global1->Set(v8_str("obj"), object);
8965
8966   v8::Handle<Value> value;
8967
8968   // Check that the named access-control function is called every time.
8969   CompileRun("function testProp(obj) {"
8970              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
8971              "  for (var j = 0; j < 10; j++) obj.prop;"
8972              "  return obj.prop"
8973              "}");
8974   value = CompileRun("testProp(obj)");
8975   CHECK(value->IsNumber());
8976   CHECK_EQ(1, value->Int32Value());
8977   CHECK_EQ(21, access_count);
8978
8979   // Check that the named access-control function is called every time.
8980   CompileRun("var p = 'prop';"
8981              "function testKeyed(obj) {"
8982              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
8983              "  for (var j = 0; j < 10; j++) obj[p];"
8984              "  return obj[p];"
8985              "}");
8986   // Use obj which requires access checks.  No inline caching is used
8987   // in that case.
8988   value = CompileRun("testKeyed(obj)");
8989   CHECK(value->IsNumber());
8990   CHECK_EQ(1, value->Int32Value());
8991   CHECK_EQ(42, access_count);
8992   // Force the inline caches into generic state and try again.
8993   CompileRun("testKeyed({ a: 0 })");
8994   CompileRun("testKeyed({ b: 0 })");
8995   value = CompileRun("testKeyed(obj)");
8996   CHECK(value->IsNumber());
8997   CHECK_EQ(1, value->Int32Value());
8998   CHECK_EQ(63, access_count);
8999
9000   // Check that the indexed access-control function is called every time.
9001   access_count = 0;
9002
9003   CompileRun("function testIndexed(obj) {"
9004              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
9005              "  for (var j = 0; j < 10; j++) obj[0];"
9006              "  return obj[0]"
9007              "}");
9008   value = CompileRun("testIndexed(obj)");
9009   CHECK(value->IsNumber());
9010   CHECK_EQ(1, value->Int32Value());
9011   CHECK_EQ(21, access_count);
9012   // Force the inline caches into generic state.
9013   CompileRun("testIndexed(new Array(1))");
9014   // Test that the indexed access check is called.
9015   value = CompileRun("testIndexed(obj)");
9016   CHECK(value->IsNumber());
9017   CHECK_EQ(1, value->Int32Value());
9018   CHECK_EQ(42, access_count);
9019
9020   access_count = 0;
9021   // Check that the named access check is called when invoking
9022   // functions on an object that requires access checks.
9023   CompileRun("obj.f = function() {}");
9024   CompileRun("function testCallNormal(obj) {"
9025              "  for (var i = 0; i < 10; i++) obj.f();"
9026              "}");
9027   CompileRun("testCallNormal(obj)");
9028   printf("%i\n", access_count);
9029   CHECK_EQ(11, access_count);
9030
9031   // Force obj into slow case.
9032   value = CompileRun("delete obj.prop");
9033   CHECK(value->BooleanValue());
9034   // Force inline caches into dictionary probing mode.
9035   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9036   // Test that the named access check is called.
9037   value = CompileRun("testProp(obj);");
9038   CHECK(value->IsNumber());
9039   CHECK_EQ(1, value->Int32Value());
9040   CHECK_EQ(33, access_count);
9041
9042   // Force the call inline cache into dictionary probing mode.
9043   CompileRun("o.f = function() {}; testCallNormal(o)");
9044   // Test that the named access check is still called for each
9045   // invocation of the function.
9046   value = CompileRun("testCallNormal(obj)");
9047   CHECK_EQ(43, access_count);
9048
9049   context1->Exit();
9050   context0->Exit();
9051 }
9052
9053
9054 THREADED_TEST(Version) { v8::V8::GetVersion(); }
9055
9056
9057 static void InstanceFunctionCallback(
9058     const v8::FunctionCallbackInfo<v8::Value>& args) {
9059   ApiTestFuzzer::Fuzz();
9060   args.GetReturnValue().Set(v8_num(12));
9061 }
9062
9063
9064 THREADED_TEST(InstanceProperties) {
9065   LocalContext context;
9066   v8::Isolate* isolate = context->GetIsolate();
9067   v8::HandleScope handle_scope(isolate);
9068
9069   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9070   Local<ObjectTemplate> instance = t->InstanceTemplate();
9071
9072   instance->Set(v8_str("x"), v8_num(42));
9073   instance->Set(v8_str("f"),
9074                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
9075
9076   Local<Value> o = t->GetFunction()->NewInstance();
9077
9078   context->Global()->Set(v8_str("i"), o);
9079   Local<Value> value = CompileRun("i.x");
9080   CHECK_EQ(42, value->Int32Value());
9081
9082   value = CompileRun("i.f()");
9083   CHECK_EQ(12, value->Int32Value());
9084 }
9085
9086
9087 static void GlobalObjectInstancePropertiesGet(
9088     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
9089   ApiTestFuzzer::Fuzz();
9090 }
9091
9092
9093 THREADED_TEST(GlobalObjectInstanceProperties) {
9094   v8::Isolate* isolate = CcTest::isolate();
9095   v8::HandleScope handle_scope(isolate);
9096
9097   Local<Value> global_object;
9098
9099   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9100   t->InstanceTemplate()->SetHandler(
9101       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
9102   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9103   instance_template->Set(v8_str("x"), v8_num(42));
9104   instance_template->Set(v8_str("f"),
9105                          v8::FunctionTemplate::New(isolate,
9106                                                    InstanceFunctionCallback));
9107
9108   // The script to check how Crankshaft compiles missing global function
9109   // invocations.  function g is not defined and should throw on call.
9110   const char* script =
9111       "function wrapper(call) {"
9112       "  var x = 0, y = 1;"
9113       "  for (var i = 0; i < 1000; i++) {"
9114       "    x += i * 100;"
9115       "    y += i * 100;"
9116       "  }"
9117       "  if (call) g();"
9118       "}"
9119       "for (var i = 0; i < 17; i++) wrapper(false);"
9120       "var thrown = 0;"
9121       "try { wrapper(true); } catch (e) { thrown = 1; };"
9122       "thrown";
9123
9124   {
9125     LocalContext env(NULL, instance_template);
9126     // Hold on to the global object so it can be used again in another
9127     // environment initialization.
9128     global_object = env->Global();
9129
9130     Local<Value> value = CompileRun("x");
9131     CHECK_EQ(42, value->Int32Value());
9132     value = CompileRun("f()");
9133     CHECK_EQ(12, value->Int32Value());
9134     value = CompileRun(script);
9135     CHECK_EQ(1, value->Int32Value());
9136   }
9137
9138   {
9139     // Create new environment reusing the global object.
9140     LocalContext env(NULL, instance_template, global_object);
9141     Local<Value> value = CompileRun("x");
9142     CHECK_EQ(42, value->Int32Value());
9143     value = CompileRun("f()");
9144     CHECK_EQ(12, value->Int32Value());
9145     value = CompileRun(script);
9146     CHECK_EQ(1, value->Int32Value());
9147   }
9148 }
9149
9150
9151 THREADED_TEST(CallKnownGlobalReceiver) {
9152   v8::Isolate* isolate = CcTest::isolate();
9153   v8::HandleScope handle_scope(isolate);
9154
9155   Local<Value> global_object;
9156
9157   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9158   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9159
9160   // The script to check that we leave global object not
9161   // global object proxy on stack when we deoptimize from inside
9162   // arguments evaluation.
9163   // To provoke error we need to both force deoptimization
9164   // from arguments evaluation and to force CallIC to take
9165   // CallIC_Miss code path that can't cope with global proxy.
9166   const char* script =
9167       "function bar(x, y) { try { } finally { } }"
9168       "function baz(x) { try { } finally { } }"
9169       "function bom(x) { try { } finally { } }"
9170       "function foo(x) { bar([x], bom(2)); }"
9171       "for (var i = 0; i < 10000; i++) foo(1);"
9172       "foo";
9173
9174   Local<Value> foo;
9175   {
9176     LocalContext env(NULL, instance_template);
9177     // Hold on to the global object so it can be used again in another
9178     // environment initialization.
9179     global_object = env->Global();
9180     foo = CompileRun(script);
9181   }
9182
9183   {
9184     // Create new environment reusing the global object.
9185     LocalContext env(NULL, instance_template, global_object);
9186     env->Global()->Set(v8_str("foo"), foo);
9187     CompileRun("foo()");
9188   }
9189 }
9190
9191
9192 static void ShadowFunctionCallback(
9193     const v8::FunctionCallbackInfo<v8::Value>& args) {
9194   ApiTestFuzzer::Fuzz();
9195   args.GetReturnValue().Set(v8_num(42));
9196 }
9197
9198
9199 static int shadow_y;
9200 static int shadow_y_setter_call_count;
9201 static int shadow_y_getter_call_count;
9202
9203
9204 static void ShadowYSetter(Local<String>,
9205                           Local<Value>,
9206                           const v8::PropertyCallbackInfo<void>&) {
9207   shadow_y_setter_call_count++;
9208   shadow_y = 42;
9209 }
9210
9211
9212 static void ShadowYGetter(Local<String> name,
9213                           const v8::PropertyCallbackInfo<v8::Value>& info) {
9214   ApiTestFuzzer::Fuzz();
9215   shadow_y_getter_call_count++;
9216   info.GetReturnValue().Set(v8_num(shadow_y));
9217 }
9218
9219
9220 static void ShadowIndexedGet(uint32_t index,
9221                              const v8::PropertyCallbackInfo<v8::Value>&) {
9222 }
9223
9224
9225 static void ShadowNamedGet(Local<Name> key,
9226                            const v8::PropertyCallbackInfo<v8::Value>&) {}
9227
9228
9229 THREADED_TEST(ShadowObject) {
9230   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
9231   v8::Isolate* isolate = CcTest::isolate();
9232   v8::HandleScope handle_scope(isolate);
9233
9234   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
9235   LocalContext context(NULL, global_template);
9236
9237   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9238   t->InstanceTemplate()->SetHandler(
9239       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
9240   t->InstanceTemplate()->SetHandler(
9241       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
9242   Local<ObjectTemplate> proto = t->PrototypeTemplate();
9243   Local<ObjectTemplate> instance = t->InstanceTemplate();
9244
9245   proto->Set(v8_str("f"),
9246              v8::FunctionTemplate::New(isolate,
9247                                        ShadowFunctionCallback,
9248                                        Local<Value>()));
9249   proto->Set(v8_str("x"), v8_num(12));
9250
9251   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9252
9253   Local<Value> o = t->GetFunction()->NewInstance();
9254   context->Global()->Set(v8_str("__proto__"), o);
9255
9256   Local<Value> value =
9257       CompileRun("this.propertyIsEnumerable(0)");
9258   CHECK(value->IsBoolean());
9259   CHECK(!value->BooleanValue());
9260
9261   value = CompileRun("x");
9262   CHECK_EQ(12, value->Int32Value());
9263
9264   value = CompileRun("f()");
9265   CHECK_EQ(42, value->Int32Value());
9266
9267   CompileRun("y = 43");
9268   CHECK_EQ(1, shadow_y_setter_call_count);
9269   value = CompileRun("y");
9270   CHECK_EQ(1, shadow_y_getter_call_count);
9271   CHECK_EQ(42, value->Int32Value());
9272 }
9273
9274
9275 THREADED_TEST(HiddenPrototype) {
9276   LocalContext context;
9277   v8::Isolate* isolate = context->GetIsolate();
9278   v8::HandleScope handle_scope(isolate);
9279
9280   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9281   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9282   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9283   t1->SetHiddenPrototype(true);
9284   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9285   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9286   t2->SetHiddenPrototype(true);
9287   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9288   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9289   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9290
9291   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9292   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9293   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9294   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9295
9296   // Setting the prototype on an object skips hidden prototypes.
9297   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9298   o0->Set(v8_str("__proto__"), o1);
9299   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9300   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9301   o0->Set(v8_str("__proto__"), o2);
9302   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9303   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9304   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9305   o0->Set(v8_str("__proto__"), o3);
9306   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9307   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9308   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9309   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9310
9311   // Getting the prototype of o0 should get the first visible one
9312   // which is o3.  Therefore, z should not be defined on the prototype
9313   // object.
9314   Local<Value> proto = o0->Get(v8_str("__proto__"));
9315   CHECK(proto->IsObject());
9316   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
9317 }
9318
9319
9320 THREADED_TEST(HiddenPrototypeSet) {
9321   LocalContext context;
9322   v8::Isolate* isolate = context->GetIsolate();
9323   v8::HandleScope handle_scope(isolate);
9324
9325   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
9326   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
9327   ht->SetHiddenPrototype(true);
9328   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
9329   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9330
9331   Local<v8::Object> o = ot->GetFunction()->NewInstance();
9332   Local<v8::Object> h = ht->GetFunction()->NewInstance();
9333   Local<v8::Object> p = pt->GetFunction()->NewInstance();
9334   o->Set(v8_str("__proto__"), h);
9335   h->Set(v8_str("__proto__"), p);
9336
9337   // Setting a property that exists on the hidden prototype goes there.
9338   o->Set(v8_str("x"), v8_num(7));
9339   CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
9340   CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
9341   CHECK(p->Get(v8_str("x"))->IsUndefined());
9342
9343   // Setting a new property should not be forwarded to the hidden prototype.
9344   o->Set(v8_str("y"), v8_num(6));
9345   CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
9346   CHECK(h->Get(v8_str("y"))->IsUndefined());
9347   CHECK(p->Get(v8_str("y"))->IsUndefined());
9348
9349   // Setting a property that only exists on a prototype of the hidden prototype
9350   // is treated normally again.
9351   p->Set(v8_str("z"), v8_num(8));
9352   CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
9353   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9354   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9355   o->Set(v8_str("z"), v8_num(9));
9356   CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
9357   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9358   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9359 }
9360
9361
9362 // Regression test for issue 2457.
9363 THREADED_TEST(HiddenPrototypeIdentityHash) {
9364   LocalContext context;
9365   v8::HandleScope handle_scope(context->GetIsolate());
9366
9367   Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
9368   t->SetHiddenPrototype(true);
9369   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
9370   Handle<Object> p = t->GetFunction()->NewInstance();
9371   Handle<Object> o = Object::New(context->GetIsolate());
9372   o->SetPrototype(p);
9373
9374   int hash = o->GetIdentityHash();
9375   USE(hash);
9376   o->Set(v8_str("foo"), v8_num(42));
9377   DCHECK_EQ(hash, o->GetIdentityHash());
9378 }
9379
9380
9381 THREADED_TEST(SetPrototype) {
9382   LocalContext context;
9383   v8::Isolate* isolate = context->GetIsolate();
9384   v8::HandleScope handle_scope(isolate);
9385
9386   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9387   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9388   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9389   t1->SetHiddenPrototype(true);
9390   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9391   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9392   t2->SetHiddenPrototype(true);
9393   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9394   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9395   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9396
9397   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9398   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9399   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9400   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9401
9402   // Setting the prototype on an object does not skip hidden prototypes.
9403   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9404   CHECK(o0->SetPrototype(o1));
9405   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9406   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9407   CHECK(o1->SetPrototype(o2));
9408   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9409   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9410   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9411   CHECK(o2->SetPrototype(o3));
9412   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9413   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9414   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9415   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9416
9417   // Getting the prototype of o0 should get the first visible one
9418   // which is o3.  Therefore, z should not be defined on the prototype
9419   // object.
9420   Local<Value> proto = o0->Get(v8_str("__proto__"));
9421   CHECK(proto->IsObject());
9422   CHECK(proto.As<v8::Object>()->Equals(o3));
9423
9424   // However, Object::GetPrototype ignores hidden prototype.
9425   Local<Value> proto0 = o0->GetPrototype();
9426   CHECK(proto0->IsObject());
9427   CHECK(proto0.As<v8::Object>()->Equals(o1));
9428
9429   Local<Value> proto1 = o1->GetPrototype();
9430   CHECK(proto1->IsObject());
9431   CHECK(proto1.As<v8::Object>()->Equals(o2));
9432
9433   Local<Value> proto2 = o2->GetPrototype();
9434   CHECK(proto2->IsObject());
9435   CHECK(proto2.As<v8::Object>()->Equals(o3));
9436 }
9437
9438
9439 // Getting property names of an object with a prototype chain that
9440 // triggers dictionary elements in GetOwnPropertyNames() shouldn't
9441 // crash the runtime.
9442 THREADED_TEST(Regress91517) {
9443   i::FLAG_allow_natives_syntax = true;
9444   LocalContext context;
9445   v8::Isolate* isolate = context->GetIsolate();
9446   v8::HandleScope handle_scope(isolate);
9447
9448   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9449   t1->SetHiddenPrototype(true);
9450   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
9451   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9452   t2->SetHiddenPrototype(true);
9453   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
9454   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
9455   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
9456   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9457   t3->SetHiddenPrototype(true);
9458   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
9459   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
9460   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
9461
9462   // Force dictionary-based properties.
9463   i::ScopedVector<char> name_buf(1024);
9464   for (int i = 1; i <= 1000; i++) {
9465     i::SNPrintF(name_buf, "sdf%d", i);
9466     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
9467   }
9468
9469   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9470   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9471   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9472   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
9473
9474   // Create prototype chain of hidden prototypes.
9475   CHECK(o4->SetPrototype(o3));
9476   CHECK(o3->SetPrototype(o2));
9477   CHECK(o2->SetPrototype(o1));
9478
9479   // Call the runtime version of GetOwnPropertyNames() on the natively
9480   // created object through JavaScript.
9481   context->Global()->Set(v8_str("obj"), o4);
9482   // PROPERTY_ATTRIBUTES_NONE = 0
9483   CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
9484
9485   ExpectInt32("names.length", 1006);
9486   ExpectTrue("names.indexOf(\"baz\") >= 0");
9487   ExpectTrue("names.indexOf(\"boo\") >= 0");
9488   ExpectTrue("names.indexOf(\"foo\") >= 0");
9489   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
9490   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
9491   ExpectFalse("names[1005] == undefined");
9492 }
9493
9494
9495 // Getting property names of an object with a hidden and inherited
9496 // prototype should not duplicate the accessor properties inherited.
9497 THREADED_TEST(Regress269562) {
9498   i::FLAG_allow_natives_syntax = true;
9499   LocalContext context;
9500   v8::HandleScope handle_scope(context->GetIsolate());
9501
9502   Local<v8::FunctionTemplate> t1 =
9503       v8::FunctionTemplate::New(context->GetIsolate());
9504   t1->SetHiddenPrototype(true);
9505
9506   Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
9507   i1->SetAccessor(v8_str("foo"),
9508                   SimpleAccessorGetter, SimpleAccessorSetter);
9509   i1->SetAccessor(v8_str("bar"),
9510                   SimpleAccessorGetter, SimpleAccessorSetter);
9511   i1->SetAccessor(v8_str("baz"),
9512                   SimpleAccessorGetter, SimpleAccessorSetter);
9513   i1->Set(v8_str("n1"), v8_num(1));
9514   i1->Set(v8_str("n2"), v8_num(2));
9515
9516   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9517   Local<v8::FunctionTemplate> t2 =
9518       v8::FunctionTemplate::New(context->GetIsolate());
9519   t2->SetHiddenPrototype(true);
9520
9521   // Inherit from t1 and mark prototype as hidden.
9522   t2->Inherit(t1);
9523   t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
9524
9525   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9526   CHECK(o2->SetPrototype(o1));
9527
9528   v8::Local<v8::Symbol> sym =
9529       v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
9530   o1->Set(sym, v8_num(3));
9531   o1->SetHiddenValue(
9532       v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
9533
9534   // Call the runtime version of GetOwnPropertyNames() on
9535   // the natively created object through JavaScript.
9536   context->Global()->Set(v8_str("obj"), o2);
9537   context->Global()->Set(v8_str("sym"), sym);
9538   // PROPERTY_ATTRIBUTES_NONE = 0
9539   CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
9540
9541   ExpectInt32("names.length", 7);
9542   ExpectTrue("names.indexOf(\"foo\") >= 0");
9543   ExpectTrue("names.indexOf(\"bar\") >= 0");
9544   ExpectTrue("names.indexOf(\"baz\") >= 0");
9545   ExpectTrue("names.indexOf(\"n1\") >= 0");
9546   ExpectTrue("names.indexOf(\"n2\") >= 0");
9547   ExpectTrue("names.indexOf(sym) >= 0");
9548   ExpectTrue("names.indexOf(\"mine\") >= 0");
9549 }
9550
9551
9552 THREADED_TEST(FunctionReadOnlyPrototype) {
9553   LocalContext context;
9554   v8::Isolate* isolate = context->GetIsolate();
9555   v8::HandleScope handle_scope(isolate);
9556
9557   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9558   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9559   t1->ReadOnlyPrototype();
9560   context->Global()->Set(v8_str("func1"), t1->GetFunction());
9561   // Configured value of ReadOnly flag.
9562   CHECK(CompileRun(
9563       "(function() {"
9564       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
9565       "  return (descriptor['writable'] == false);"
9566       "})()")->BooleanValue());
9567   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
9568   CHECK_EQ(42,
9569            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
9570
9571   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9572   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9573   context->Global()->Set(v8_str("func2"), t2->GetFunction());
9574   // Default value of ReadOnly flag.
9575   CHECK(CompileRun(
9576       "(function() {"
9577       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
9578       "  return (descriptor['writable'] == true);"
9579       "})()")->BooleanValue());
9580   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
9581 }
9582
9583
9584 THREADED_TEST(SetPrototypeThrows) {
9585   LocalContext context;
9586   v8::Isolate* isolate = context->GetIsolate();
9587   v8::HandleScope handle_scope(isolate);
9588
9589   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9590
9591   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
9592   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
9593
9594   CHECK(o0->SetPrototype(o1));
9595   // If setting the prototype leads to the cycle, SetPrototype should
9596   // return false and keep VM in sane state.
9597   v8::TryCatch try_catch(isolate);
9598   CHECK(!o1->SetPrototype(o0));
9599   CHECK(!try_catch.HasCaught());
9600   DCHECK(!CcTest::i_isolate()->has_pending_exception());
9601
9602   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
9603 }
9604
9605
9606 THREADED_TEST(FunctionRemovePrototype) {
9607   LocalContext context;
9608   v8::Isolate* isolate = context->GetIsolate();
9609   v8::HandleScope handle_scope(isolate);
9610
9611   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9612   t1->RemovePrototype();
9613   Local<v8::Function> fun = t1->GetFunction();
9614   context->Global()->Set(v8_str("fun"), fun);
9615   CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
9616
9617   v8::TryCatch try_catch(isolate);
9618   CompileRun("new fun()");
9619   CHECK(try_catch.HasCaught());
9620
9621   try_catch.Reset();
9622   fun->NewInstance();
9623   CHECK(try_catch.HasCaught());
9624 }
9625
9626
9627 THREADED_TEST(GetterSetterExceptions) {
9628   LocalContext context;
9629   v8::Isolate* isolate = context->GetIsolate();
9630   v8::HandleScope handle_scope(isolate);
9631   CompileRun(
9632       "function Foo() { };"
9633       "function Throw() { throw 5; };"
9634       "var x = { };"
9635       "x.__defineSetter__('set', Throw);"
9636       "x.__defineGetter__('get', Throw);");
9637   Local<v8::Object> x =
9638       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
9639   v8::TryCatch try_catch(isolate);
9640   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9641   x->Get(v8_str("get"));
9642   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9643   x->Get(v8_str("get"));
9644   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9645   x->Get(v8_str("get"));
9646   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9647   x->Get(v8_str("get"));
9648 }
9649
9650
9651 THREADED_TEST(Constructor) {
9652   LocalContext context;
9653   v8::Isolate* isolate = context->GetIsolate();
9654   v8::HandleScope handle_scope(isolate);
9655   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
9656   templ->SetClassName(v8_str("Fun"));
9657   Local<Function> cons = templ->GetFunction();
9658   context->Global()->Set(v8_str("Fun"), cons);
9659   Local<v8::Object> inst = cons->NewInstance();
9660   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
9661   CHECK(obj->IsJSObject());
9662   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
9663   CHECK(value->BooleanValue());
9664 }
9665
9666
9667 static void ConstructorCallback(
9668     const v8::FunctionCallbackInfo<v8::Value>& args) {
9669   ApiTestFuzzer::Fuzz();
9670   Local<Object> This;
9671
9672   if (args.IsConstructCall()) {
9673     Local<Object> Holder = args.Holder();
9674     This = Object::New(args.GetIsolate());
9675     Local<Value> proto = Holder->GetPrototype();
9676     if (proto->IsObject()) {
9677       This->SetPrototype(proto);
9678     }
9679   } else {
9680     This = args.This();
9681   }
9682
9683   This->Set(v8_str("a"), args[0]);
9684   args.GetReturnValue().Set(This);
9685 }
9686
9687
9688 static void FakeConstructorCallback(
9689     const v8::FunctionCallbackInfo<v8::Value>& args) {
9690   ApiTestFuzzer::Fuzz();
9691   args.GetReturnValue().Set(args[0]);
9692 }
9693
9694
9695 THREADED_TEST(ConstructorForObject) {
9696   LocalContext context;
9697   v8::Isolate* isolate = context->GetIsolate();
9698   v8::HandleScope handle_scope(isolate);
9699
9700   {
9701     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9702     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
9703     Local<Object> instance = instance_template->NewInstance();
9704     context->Global()->Set(v8_str("obj"), instance);
9705     v8::TryCatch try_catch(isolate);
9706     Local<Value> value;
9707     CHECK(!try_catch.HasCaught());
9708
9709     // Call the Object's constructor with a 32-bit signed integer.
9710     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
9711     CHECK(!try_catch.HasCaught());
9712     CHECK(value->IsInt32());
9713     CHECK_EQ(28, value->Int32Value());
9714
9715     Local<Value> args1[] = {v8_num(28)};
9716     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
9717     CHECK(value_obj1->IsObject());
9718     Local<Object> object1 = Local<Object>::Cast(value_obj1);
9719     value = object1->Get(v8_str("a"));
9720     CHECK(value->IsInt32());
9721     CHECK(!try_catch.HasCaught());
9722     CHECK_EQ(28, value->Int32Value());
9723
9724     // Call the Object's constructor with a String.
9725     value =
9726         CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
9727     CHECK(!try_catch.HasCaught());
9728     CHECK(value->IsString());
9729     String::Utf8Value string_value1(value->ToString(isolate));
9730     CHECK_EQ(0, strcmp("tipli", *string_value1));
9731
9732     Local<Value> args2[] = {v8_str("tipli")};
9733     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
9734     CHECK(value_obj2->IsObject());
9735     Local<Object> object2 = Local<Object>::Cast(value_obj2);
9736     value = object2->Get(v8_str("a"));
9737     CHECK(!try_catch.HasCaught());
9738     CHECK(value->IsString());
9739     String::Utf8Value string_value2(value->ToString(isolate));
9740     CHECK_EQ(0, strcmp("tipli", *string_value2));
9741
9742     // Call the Object's constructor with a Boolean.
9743     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
9744     CHECK(!try_catch.HasCaught());
9745     CHECK(value->IsBoolean());
9746     CHECK_EQ(true, value->BooleanValue());
9747
9748     Handle<Value> args3[] = {v8::True(isolate)};
9749     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
9750     CHECK(value_obj3->IsObject());
9751     Local<Object> object3 = Local<Object>::Cast(value_obj3);
9752     value = object3->Get(v8_str("a"));
9753     CHECK(!try_catch.HasCaught());
9754     CHECK(value->IsBoolean());
9755     CHECK_EQ(true, value->BooleanValue());
9756
9757     // Call the Object's constructor with undefined.
9758     Handle<Value> args4[] = {v8::Undefined(isolate)};
9759     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
9760     CHECK(value_obj4->IsObject());
9761     Local<Object> object4 = Local<Object>::Cast(value_obj4);
9762     value = object4->Get(v8_str("a"));
9763     CHECK(!try_catch.HasCaught());
9764     CHECK(value->IsUndefined());
9765
9766     // Call the Object's constructor with null.
9767     Handle<Value> args5[] = {v8::Null(isolate)};
9768     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
9769     CHECK(value_obj5->IsObject());
9770     Local<Object> object5 = Local<Object>::Cast(value_obj5);
9771     value = object5->Get(v8_str("a"));
9772     CHECK(!try_catch.HasCaught());
9773     CHECK(value->IsNull());
9774   }
9775
9776   // Check exception handling when there is no constructor set for the Object.
9777   {
9778     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9779     Local<Object> instance = instance_template->NewInstance();
9780     context->Global()->Set(v8_str("obj2"), instance);
9781     v8::TryCatch try_catch(isolate);
9782     Local<Value> value;
9783     CHECK(!try_catch.HasCaught());
9784
9785     value = CompileRun("new obj2(28)");
9786     CHECK(try_catch.HasCaught());
9787     String::Utf8Value exception_value1(try_catch.Exception());
9788     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
9789     try_catch.Reset();
9790
9791     Local<Value> args[] = {v8_num(29)};
9792     value = instance->CallAsConstructor(1, args);
9793     CHECK(try_catch.HasCaught());
9794     String::Utf8Value exception_value2(try_catch.Exception());
9795     CHECK_EQ(
9796         0, strcmp("TypeError: #<Object> is not a function", *exception_value2));
9797     try_catch.Reset();
9798   }
9799
9800   // Check the case when constructor throws exception.
9801   {
9802     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9803     instance_template->SetCallAsFunctionHandler(ThrowValue);
9804     Local<Object> instance = instance_template->NewInstance();
9805     context->Global()->Set(v8_str("obj3"), instance);
9806     v8::TryCatch try_catch(isolate);
9807     Local<Value> value;
9808     CHECK(!try_catch.HasCaught());
9809
9810     value = CompileRun("new obj3(22)");
9811     CHECK(try_catch.HasCaught());
9812     String::Utf8Value exception_value1(try_catch.Exception());
9813     CHECK_EQ(0, strcmp("22", *exception_value1));
9814     try_catch.Reset();
9815
9816     Local<Value> args[] = {v8_num(23)};
9817     value = instance->CallAsConstructor(1, args);
9818     CHECK(try_catch.HasCaught());
9819     String::Utf8Value exception_value2(try_catch.Exception());
9820     CHECK_EQ(0, strcmp("23", *exception_value2));
9821     try_catch.Reset();
9822   }
9823
9824   // Check whether constructor returns with an object or non-object.
9825   {
9826     Local<FunctionTemplate> function_template =
9827         FunctionTemplate::New(isolate, FakeConstructorCallback);
9828     Local<Function> function = function_template->GetFunction();
9829     Local<Object> instance1 = function;
9830     context->Global()->Set(v8_str("obj4"), instance1);
9831     v8::TryCatch try_catch(isolate);
9832     Local<Value> value;
9833     CHECK(!try_catch.HasCaught());
9834
9835     CHECK(instance1->IsObject());
9836     CHECK(instance1->IsFunction());
9837
9838     value = CompileRun("new obj4(28)");
9839     CHECK(!try_catch.HasCaught());
9840     CHECK(value->IsObject());
9841
9842     Local<Value> args1[] = {v8_num(28)};
9843     value = instance1->CallAsConstructor(1, args1);
9844     CHECK(!try_catch.HasCaught());
9845     CHECK(value->IsObject());
9846
9847     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9848     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
9849     Local<Object> instance2 = instance_template->NewInstance();
9850     context->Global()->Set(v8_str("obj5"), instance2);
9851     CHECK(!try_catch.HasCaught());
9852
9853     CHECK(instance2->IsObject());
9854     CHECK(!instance2->IsFunction());
9855
9856     value = CompileRun("new obj5(28)");
9857     CHECK(!try_catch.HasCaught());
9858     CHECK(!value->IsObject());
9859
9860     Local<Value> args2[] = {v8_num(28)};
9861     value = instance2->CallAsConstructor(1, args2);
9862     CHECK(!try_catch.HasCaught());
9863     CHECK(!value->IsObject());
9864   }
9865 }
9866
9867
9868 THREADED_TEST(FunctionDescriptorException) {
9869   LocalContext context;
9870   v8::Isolate* isolate = context->GetIsolate();
9871   v8::HandleScope handle_scope(isolate);
9872   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
9873   templ->SetClassName(v8_str("Fun"));
9874   Local<Function> cons = templ->GetFunction();
9875   context->Global()->Set(v8_str("Fun"), cons);
9876   Local<Value> value = CompileRun(
9877       "function test() {"
9878       "  try {"
9879       "    (new Fun()).blah()"
9880       "  } catch (e) {"
9881       "    var str = String(e);"
9882       // "    if (str.indexOf('TypeError') == -1) return 1;"
9883       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
9884       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
9885       "    return 0;"
9886       "  }"
9887       "  return 4;"
9888       "}"
9889       "test();");
9890   CHECK_EQ(0, value->Int32Value());
9891 }
9892
9893
9894 THREADED_TEST(EvalAliasedDynamic) {
9895   LocalContext current;
9896   v8::HandleScope scope(current->GetIsolate());
9897
9898   // Tests where aliased eval can only be resolved dynamically.
9899   Local<Script> script = v8_compile(
9900       "function f(x) { "
9901       "  var foo = 2;"
9902       "  with (x) { return eval('foo'); }"
9903       "}"
9904       "foo = 0;"
9905       "result1 = f(new Object());"
9906       "result2 = f(this);"
9907       "var x = new Object();"
9908       "x.eval = function(x) { return 1; };"
9909       "result3 = f(x);");
9910   script->Run();
9911   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
9912   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
9913   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
9914
9915   v8::TryCatch try_catch(current->GetIsolate());
9916   script = v8_compile(
9917       "function f(x) { "
9918       "  var bar = 2;"
9919       "  with (x) { return eval('bar'); }"
9920       "}"
9921       "result4 = f(this)");
9922   script->Run();
9923   CHECK(!try_catch.HasCaught());
9924   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
9925
9926   try_catch.Reset();
9927 }
9928
9929
9930 THREADED_TEST(CrossEval) {
9931   v8::HandleScope scope(CcTest::isolate());
9932   LocalContext other;
9933   LocalContext current;
9934
9935   Local<String> token = v8_str("<security token>");
9936   other->SetSecurityToken(token);
9937   current->SetSecurityToken(token);
9938
9939   // Set up reference from current to other.
9940   current->Global()->Set(v8_str("other"), other->Global());
9941
9942   // Check that new variables are introduced in other context.
9943   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
9944   script->Run();
9945   Local<Value> foo = other->Global()->Get(v8_str("foo"));
9946   CHECK_EQ(1234, foo->Int32Value());
9947   CHECK(!current->Global()->Has(v8_str("foo")));
9948
9949   // Check that writing to non-existing properties introduces them in
9950   // the other context.
9951   script = v8_compile("other.eval('na = 1234')");
9952   script->Run();
9953   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
9954   CHECK(!current->Global()->Has(v8_str("na")));
9955
9956   // Check that global variables in current context are not visible in other
9957   // context.
9958   v8::TryCatch try_catch(CcTest::isolate());
9959   script = v8_compile("var bar = 42; other.eval('bar');");
9960   Local<Value> result = script->Run();
9961   CHECK(try_catch.HasCaught());
9962   try_catch.Reset();
9963
9964   // Check that local variables in current context are not visible in other
9965   // context.
9966   script = v8_compile(
9967       "(function() { "
9968       "  var baz = 87;"
9969       "  return other.eval('baz');"
9970       "})();");
9971   result = script->Run();
9972   CHECK(try_catch.HasCaught());
9973   try_catch.Reset();
9974
9975   // Check that global variables in the other environment are visible
9976   // when evaluting code.
9977   other->Global()->Set(v8_str("bis"), v8_num(1234));
9978   script = v8_compile("other.eval('bis')");
9979   CHECK_EQ(1234, script->Run()->Int32Value());
9980   CHECK(!try_catch.HasCaught());
9981
9982   // Check that the 'this' pointer points to the global object evaluating
9983   // code.
9984   other->Global()->Set(v8_str("t"), other->Global());
9985   script = v8_compile("other.eval('this == t')");
9986   result = script->Run();
9987   CHECK(result->IsTrue());
9988   CHECK(!try_catch.HasCaught());
9989
9990   // Check that variables introduced in with-statement are not visible in
9991   // other context.
9992   script = v8_compile("with({x:2}){other.eval('x')}");
9993   result = script->Run();
9994   CHECK(try_catch.HasCaught());
9995   try_catch.Reset();
9996
9997   // Check that you cannot use 'eval.call' with another object than the
9998   // current global object.
9999   script = v8_compile("other.y = 1; eval.call(other, 'y')");
10000   result = script->Run();
10001   CHECK(try_catch.HasCaught());
10002 }
10003
10004
10005 // Test that calling eval in a context which has been detached from
10006 // its global proxy works.
10007 THREADED_TEST(EvalInDetachedGlobal) {
10008   v8::Isolate* isolate = CcTest::isolate();
10009   v8::HandleScope scope(isolate);
10010
10011   v8::Local<Context> context0 = Context::New(isolate);
10012   v8::Local<Context> context1 = Context::New(isolate);
10013
10014   // Set up function in context0 that uses eval from context0.
10015   context0->Enter();
10016   v8::Handle<v8::Value> fun = CompileRun(
10017       "var x = 42;"
10018       "(function() {"
10019       "  var e = eval;"
10020       "  return function(s) { return e(s); }"
10021       "})()");
10022   context0->Exit();
10023
10024   // Put the function into context1 and call it before and after
10025   // detaching the global.  Before detaching, the call succeeds and
10026   // after detaching and exception is thrown.
10027   context1->Enter();
10028   context1->Global()->Set(v8_str("fun"), fun);
10029   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10030   CHECK_EQ(42, x_value->Int32Value());
10031   context0->DetachGlobal();
10032   v8::TryCatch catcher(isolate);
10033   x_value = CompileRun("fun('x')");
10034   CHECK_EQ(42, x_value->Int32Value());
10035   context1->Exit();
10036 }
10037
10038
10039 THREADED_TEST(CrossLazyLoad) {
10040   v8::HandleScope scope(CcTest::isolate());
10041   LocalContext other;
10042   LocalContext current;
10043
10044   Local<String> token = v8_str("<security token>");
10045   other->SetSecurityToken(token);
10046   current->SetSecurityToken(token);
10047
10048   // Set up reference from current to other.
10049   current->Global()->Set(v8_str("other"), other->Global());
10050
10051   // Trigger lazy loading in other context.
10052   Local<Script> script = v8_compile("other.eval('new Date(42)')");
10053   Local<Value> value = script->Run();
10054   CHECK_EQ(42.0, value->NumberValue());
10055 }
10056
10057
10058 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
10059   ApiTestFuzzer::Fuzz();
10060   if (args.IsConstructCall()) {
10061     if (args[0]->IsInt32()) {
10062       args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10063       return;
10064     }
10065   }
10066
10067   args.GetReturnValue().Set(args[0]);
10068 }
10069
10070
10071 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10072   args.GetReturnValue().Set(args.This());
10073 }
10074
10075
10076 // Test that a call handler can be set for objects which will allow
10077 // non-function objects created through the API to be called as
10078 // functions.
10079 THREADED_TEST(CallAsFunction) {
10080   LocalContext context;
10081   v8::Isolate* isolate = context->GetIsolate();
10082   v8::HandleScope scope(isolate);
10083
10084   {
10085     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10086     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10087     instance_template->SetCallAsFunctionHandler(call_as_function);
10088     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10089     context->Global()->Set(v8_str("obj"), instance);
10090     v8::TryCatch try_catch(isolate);
10091     Local<Value> value;
10092     CHECK(!try_catch.HasCaught());
10093
10094     value = CompileRun("obj(42)");
10095     CHECK(!try_catch.HasCaught());
10096     CHECK_EQ(42, value->Int32Value());
10097
10098     value = CompileRun("(function(o){return o(49)})(obj)");
10099     CHECK(!try_catch.HasCaught());
10100     CHECK_EQ(49, value->Int32Value());
10101
10102     // test special case of call as function
10103     value = CompileRun("[obj]['0'](45)");
10104     CHECK(!try_catch.HasCaught());
10105     CHECK_EQ(45, value->Int32Value());
10106
10107     value = CompileRun(
10108         "obj.call = Function.prototype.call;"
10109         "obj.call(null, 87)");
10110     CHECK(!try_catch.HasCaught());
10111     CHECK_EQ(87, value->Int32Value());
10112
10113     // Regression tests for bug #1116356: Calling call through call/apply
10114     // must work for non-function receivers.
10115     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10116     value = CompileRun(apply_99);
10117     CHECK(!try_catch.HasCaught());
10118     CHECK_EQ(99, value->Int32Value());
10119
10120     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10121     value = CompileRun(call_17);
10122     CHECK(!try_catch.HasCaught());
10123     CHECK_EQ(17, value->Int32Value());
10124
10125     // Check that the call-as-function handler can be called through
10126     // new.
10127     value = CompileRun("new obj(43)");
10128     CHECK(!try_catch.HasCaught());
10129     CHECK_EQ(-43, value->Int32Value());
10130
10131     // Check that the call-as-function handler can be called through
10132     // the API.
10133     v8::Handle<Value> args[] = {v8_num(28)};
10134     value = instance->CallAsFunction(instance, 1, args);
10135     CHECK(!try_catch.HasCaught());
10136     CHECK_EQ(28, value->Int32Value());
10137   }
10138
10139   {
10140     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10141     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
10142     USE(instance_template);
10143     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10144     context->Global()->Set(v8_str("obj2"), instance);
10145     v8::TryCatch try_catch(isolate);
10146     Local<Value> value;
10147     CHECK(!try_catch.HasCaught());
10148
10149     // Call an object without call-as-function handler through the JS
10150     value = CompileRun("obj2(28)");
10151     CHECK(value.IsEmpty());
10152     CHECK(try_catch.HasCaught());
10153     String::Utf8Value exception_value1(try_catch.Exception());
10154     // TODO(verwaest): Better message
10155     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
10156     try_catch.Reset();
10157
10158     // Call an object without call-as-function handler through the API
10159     value = CompileRun("obj2(28)");
10160     v8::Handle<Value> args[] = {v8_num(28)};
10161     value = instance->CallAsFunction(instance, 1, args);
10162     CHECK(value.IsEmpty());
10163     CHECK(try_catch.HasCaught());
10164     String::Utf8Value exception_value2(try_catch.Exception());
10165     CHECK_EQ(0, strcmp("TypeError: [object Object] is not a function",
10166                        *exception_value2));
10167     try_catch.Reset();
10168   }
10169
10170   {
10171     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10172     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10173     instance_template->SetCallAsFunctionHandler(ThrowValue);
10174     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10175     context->Global()->Set(v8_str("obj3"), instance);
10176     v8::TryCatch try_catch(isolate);
10177     Local<Value> value;
10178     CHECK(!try_catch.HasCaught());
10179
10180     // Catch the exception which is thrown by call-as-function handler
10181     value = CompileRun("obj3(22)");
10182     CHECK(try_catch.HasCaught());
10183     String::Utf8Value exception_value1(try_catch.Exception());
10184     CHECK_EQ(0, strcmp("22", *exception_value1));
10185     try_catch.Reset();
10186
10187     v8::Handle<Value> args[] = {v8_num(23)};
10188     value = instance->CallAsFunction(instance, 1, args);
10189     CHECK(try_catch.HasCaught());
10190     String::Utf8Value exception_value2(try_catch.Exception());
10191     CHECK_EQ(0, strcmp("23", *exception_value2));
10192     try_catch.Reset();
10193   }
10194
10195   {
10196     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10197     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10198     instance_template->SetCallAsFunctionHandler(ReturnThis);
10199     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10200
10201     Local<v8::Value> a1 =
10202         instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10203     CHECK(a1->StrictEquals(instance));
10204     Local<v8::Value> a2 = instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10205     CHECK(a2->StrictEquals(instance));
10206     Local<v8::Value> a3 = instance->CallAsFunction(v8_num(42), 0, NULL);
10207     CHECK(a3->StrictEquals(instance));
10208     Local<v8::Value> a4 = instance->CallAsFunction(v8_str("hello"), 0, NULL);
10209     CHECK(a4->StrictEquals(instance));
10210     Local<v8::Value> a5 = instance->CallAsFunction(v8::True(isolate), 0, NULL);
10211     CHECK(a5->StrictEquals(instance));
10212   }
10213
10214   {
10215     CompileRun(
10216         "function ReturnThisSloppy() {"
10217         "  return this;"
10218         "}"
10219         "function ReturnThisStrict() {"
10220         "  'use strict';"
10221         "  return this;"
10222         "}");
10223     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
10224         context->Global()->Get(v8_str("ReturnThisSloppy")));
10225     Local<Function> ReturnThisStrict = Local<Function>::Cast(
10226         context->Global()->Get(v8_str("ReturnThisStrict")));
10227
10228     Local<v8::Value> a1 =
10229         ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10230     CHECK(a1->StrictEquals(context->Global()));
10231     Local<v8::Value> a2 =
10232         ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10233     CHECK(a2->StrictEquals(context->Global()));
10234     Local<v8::Value> a3 = ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10235     CHECK(a3->IsNumberObject());
10236     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10237     Local<v8::Value> a4 =
10238         ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10239     CHECK(a4->IsStringObject());
10240     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10241     Local<v8::Value> a5 =
10242         ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10243     CHECK(a5->IsBooleanObject());
10244     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10245
10246     Local<v8::Value> a6 =
10247         ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10248     CHECK(a6->IsUndefined());
10249     Local<v8::Value> a7 =
10250         ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10251     CHECK(a7->IsNull());
10252     Local<v8::Value> a8 = ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10253     CHECK(a8->StrictEquals(v8_num(42)));
10254     Local<v8::Value> a9 =
10255         ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10256     CHECK(a9->StrictEquals(v8_str("hello")));
10257     Local<v8::Value> a10 =
10258         ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10259     CHECK(a10->StrictEquals(v8::True(isolate)));
10260   }
10261 }
10262
10263
10264 // Check whether a non-function object is callable.
10265 THREADED_TEST(CallableObject) {
10266   LocalContext context;
10267   v8::Isolate* isolate = context->GetIsolate();
10268   v8::HandleScope scope(isolate);
10269
10270   {
10271     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10272     instance_template->SetCallAsFunctionHandler(call_as_function);
10273     Local<Object> instance = instance_template->NewInstance();
10274     v8::TryCatch try_catch(isolate);
10275
10276     CHECK(instance->IsCallable());
10277     CHECK(!try_catch.HasCaught());
10278   }
10279
10280   {
10281     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10282     Local<Object> instance = instance_template->NewInstance();
10283     v8::TryCatch try_catch(isolate);
10284
10285     CHECK(!instance->IsCallable());
10286     CHECK(!try_catch.HasCaught());
10287   }
10288
10289   {
10290     Local<FunctionTemplate> function_template =
10291         FunctionTemplate::New(isolate, call_as_function);
10292     Local<Function> function = function_template->GetFunction();
10293     Local<Object> instance = function;
10294     v8::TryCatch try_catch(isolate);
10295
10296     CHECK(instance->IsCallable());
10297     CHECK(!try_catch.HasCaught());
10298   }
10299
10300   {
10301     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
10302     Local<Function> function = function_template->GetFunction();
10303     Local<Object> instance = function;
10304     v8::TryCatch try_catch(isolate);
10305
10306     CHECK(instance->IsCallable());
10307     CHECK(!try_catch.HasCaught());
10308   }
10309 }
10310
10311
10312 static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
10313   v8::HandleScope scope(isolate);
10314   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
10315   for (int i = 0; i < iterations; i++) {
10316     Local<v8::Number> n(v8::Integer::New(isolate, 42));
10317   }
10318   return Recurse(isolate, depth - 1, iterations);
10319 }
10320
10321
10322 THREADED_TEST(HandleIteration) {
10323   static const int kIterations = 500;
10324   static const int kNesting = 200;
10325   LocalContext context;
10326   v8::Isolate* isolate = context->GetIsolate();
10327   v8::HandleScope scope0(isolate);
10328   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10329   {
10330     v8::HandleScope scope1(isolate);
10331     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10332     for (int i = 0; i < kIterations; i++) {
10333       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
10334       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
10335     }
10336
10337     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
10338     {
10339       v8::HandleScope scope2(CcTest::isolate());
10340       for (int j = 0; j < kIterations; j++) {
10341         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
10342         CHECK_EQ(j + 1 + kIterations,
10343                  v8::HandleScope::NumberOfHandles(isolate));
10344       }
10345     }
10346     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
10347   }
10348   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10349   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
10350 }
10351
10352
10353 static void InterceptorCallICFastApi(
10354     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
10355   ApiTestFuzzer::Fuzz();
10356   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
10357   int* call_count =
10358       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
10359   ++(*call_count);
10360   if ((*call_count) % 20 == 0) {
10361     CcTest::heap()->CollectAllGarbage();
10362   }
10363 }
10364
10365 static void FastApiCallback_TrivialSignature(
10366     const v8::FunctionCallbackInfo<v8::Value>& args) {
10367   ApiTestFuzzer::Fuzz();
10368   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
10369   v8::Isolate* isolate = CcTest::isolate();
10370   CHECK_EQ(isolate, args.GetIsolate());
10371   CHECK(args.This()->Equals(args.Holder()));
10372   CHECK(args.Data()->Equals(v8_str("method_data")));
10373   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
10374 }
10375
10376 static void FastApiCallback_SimpleSignature(
10377     const v8::FunctionCallbackInfo<v8::Value>& args) {
10378   ApiTestFuzzer::Fuzz();
10379   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
10380   v8::Isolate* isolate = CcTest::isolate();
10381   CHECK_EQ(isolate, args.GetIsolate());
10382   CHECK(args.This()->GetPrototype()->Equals(args.Holder()));
10383   CHECK(args.Data()->Equals(v8_str("method_data")));
10384   // Note, we're using HasRealNamedProperty instead of Has to avoid
10385   // invoking the interceptor again.
10386   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
10387   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
10388 }
10389
10390
10391 // Helper to maximize the odds of object moving.
10392 static void GenerateSomeGarbage() {
10393   CompileRun(
10394       "var garbage;"
10395       "for (var i = 0; i < 1000; i++) {"
10396       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
10397       "}"
10398       "garbage = undefined;");
10399 }
10400
10401
10402 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
10403   static int count = 0;
10404   if (count++ % 3 == 0) {
10405     CcTest::heap()->CollectAllGarbage();
10406         // This should move the stub
10407     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
10408   }
10409 }
10410
10411
10412 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
10413   LocalContext context;
10414   v8::Isolate* isolate = context->GetIsolate();
10415   v8::HandleScope scope(isolate);
10416   v8::Handle<v8::ObjectTemplate> nativeobject_templ =
10417       v8::ObjectTemplate::New(isolate);
10418   nativeobject_templ->Set(isolate, "callback",
10419                           v8::FunctionTemplate::New(isolate,
10420                                                     DirectApiCallback));
10421   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10422   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10423   // call the api function multiple times to ensure direct call stub creation.
10424   CompileRun(
10425         "function f() {"
10426         "  for (var i = 1; i <= 30; i++) {"
10427         "    nativeobject.callback();"
10428         "  }"
10429         "}"
10430         "f();");
10431 }
10432
10433
10434 void ThrowingDirectApiCallback(
10435     const v8::FunctionCallbackInfo<v8::Value>& args) {
10436   args.GetIsolate()->ThrowException(v8_str("g"));
10437 }
10438
10439
10440 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
10441   LocalContext context;
10442   v8::Isolate* isolate = context->GetIsolate();
10443   v8::HandleScope scope(isolate);
10444   v8::Handle<v8::ObjectTemplate> nativeobject_templ =
10445       v8::ObjectTemplate::New(isolate);
10446   nativeobject_templ->Set(isolate, "callback",
10447                           v8::FunctionTemplate::New(isolate,
10448                                                     ThrowingDirectApiCallback));
10449   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10450   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10451   // call the api function multiple times to ensure direct call stub creation.
10452   v8::Handle<Value> result = CompileRun(
10453       "var result = '';"
10454       "function f() {"
10455       "  for (var i = 1; i <= 5; i++) {"
10456       "    try { nativeobject.callback(); } catch (e) { result += e; }"
10457       "  }"
10458       "}"
10459       "f(); result;");
10460   CHECK(v8_str("ggggg")->Equals(result));
10461 }
10462
10463
10464 static int p_getter_count_3;
10465
10466
10467 static Handle<Value> DoDirectGetter() {
10468   if (++p_getter_count_3 % 3 == 0) {
10469     CcTest::heap()->CollectAllGarbage();
10470     GenerateSomeGarbage();
10471   }
10472   return v8_str("Direct Getter Result");
10473 }
10474
10475
10476 static void DirectGetterCallback(
10477     Local<String> name,
10478     const v8::PropertyCallbackInfo<v8::Value>& info) {
10479   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
10480   info.GetReturnValue().Set(DoDirectGetter());
10481 }
10482
10483
10484 template<typename Accessor>
10485 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
10486   LocalContext context;
10487   v8::Isolate* isolate = context->GetIsolate();
10488   v8::HandleScope scope(isolate);
10489   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
10490   obj->SetAccessor(v8_str("p1"), accessor);
10491   context->Global()->Set(v8_str("o1"), obj->NewInstance());
10492   p_getter_count_3 = 0;
10493   v8::Handle<v8::Value> result = CompileRun(
10494       "function f() {"
10495       "  for (var i = 0; i < 30; i++) o1.p1;"
10496       "  return o1.p1"
10497       "}"
10498       "f();");
10499   CHECK(v8_str("Direct Getter Result")->Equals(result));
10500   CHECK_EQ(31, p_getter_count_3);
10501 }
10502
10503
10504 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
10505   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
10506 }
10507
10508
10509 void ThrowingDirectGetterCallback(
10510     Local<String> name,
10511     const v8::PropertyCallbackInfo<v8::Value>& info) {
10512   info.GetIsolate()->ThrowException(v8_str("g"));
10513 }
10514
10515
10516 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
10517   LocalContext context;
10518   v8::Isolate* isolate = context->GetIsolate();
10519   v8::HandleScope scope(isolate);
10520   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
10521   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
10522   context->Global()->Set(v8_str("o1"), obj->NewInstance());
10523   v8::Handle<Value> result = CompileRun(
10524       "var result = '';"
10525       "for (var i = 0; i < 5; i++) {"
10526       "    try { o1.p1; } catch (e) { result += e; }"
10527       "}"
10528       "result;");
10529   CHECK(v8_str("ggggg")->Equals(result));
10530 }
10531
10532
10533 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
10534   int interceptor_call_count = 0;
10535   v8::Isolate* isolate = CcTest::isolate();
10536   v8::HandleScope scope(isolate);
10537   v8::Handle<v8::FunctionTemplate> fun_templ =
10538       v8::FunctionTemplate::New(isolate);
10539   v8::Handle<v8::FunctionTemplate> method_templ =
10540       v8::FunctionTemplate::New(isolate,
10541                                 FastApiCallback_TrivialSignature,
10542                                 v8_str("method_data"),
10543                                 v8::Handle<v8::Signature>());
10544   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10545   proto_templ->Set(v8_str("method"), method_templ);
10546   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10547   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10548       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10549       v8::External::New(isolate, &interceptor_call_count)));
10550   LocalContext context;
10551   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10552   GenerateSomeGarbage();
10553   context->Global()->Set(v8_str("o"), fun->NewInstance());
10554   CompileRun(
10555       "var result = 0;"
10556       "for (var i = 0; i < 100; i++) {"
10557       "  result = o.method(41);"
10558       "}");
10559   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10560   CHECK_EQ(100, interceptor_call_count);
10561 }
10562
10563
10564 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
10565   int interceptor_call_count = 0;
10566   v8::Isolate* isolate = CcTest::isolate();
10567   v8::HandleScope scope(isolate);
10568   v8::Handle<v8::FunctionTemplate> fun_templ =
10569       v8::FunctionTemplate::New(isolate);
10570   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10571       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10572       v8::Signature::New(isolate, fun_templ));
10573   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10574   proto_templ->Set(v8_str("method"), method_templ);
10575   fun_templ->SetHiddenPrototype(true);
10576   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10577   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10578       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10579       v8::External::New(isolate, &interceptor_call_count)));
10580   LocalContext context;
10581   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10582   GenerateSomeGarbage();
10583   context->Global()->Set(v8_str("o"), fun->NewInstance());
10584   CompileRun(
10585       "o.foo = 17;"
10586       "var receiver = {};"
10587       "receiver.__proto__ = o;"
10588       "var result = 0;"
10589       "for (var i = 0; i < 100; i++) {"
10590       "  result = receiver.method(41);"
10591       "}");
10592   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10593   CHECK_EQ(100, interceptor_call_count);
10594 }
10595
10596
10597 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
10598   int interceptor_call_count = 0;
10599   v8::Isolate* isolate = CcTest::isolate();
10600   v8::HandleScope scope(isolate);
10601   v8::Handle<v8::FunctionTemplate> fun_templ =
10602       v8::FunctionTemplate::New(isolate);
10603   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10604       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10605       v8::Signature::New(isolate, fun_templ));
10606   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10607   proto_templ->Set(v8_str("method"), method_templ);
10608   fun_templ->SetHiddenPrototype(true);
10609   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10610   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10611       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10612       v8::External::New(isolate, &interceptor_call_count)));
10613   LocalContext context;
10614   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10615   GenerateSomeGarbage();
10616   context->Global()->Set(v8_str("o"), fun->NewInstance());
10617   CompileRun(
10618       "o.foo = 17;"
10619       "var receiver = {};"
10620       "receiver.__proto__ = o;"
10621       "var result = 0;"
10622       "var saved_result = 0;"
10623       "for (var i = 0; i < 100; i++) {"
10624       "  result = receiver.method(41);"
10625       "  if (i == 50) {"
10626       "    saved_result = result;"
10627       "    receiver = {method: function(x) { return x - 1 }};"
10628       "  }"
10629       "}");
10630   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10631   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10632   CHECK_GE(interceptor_call_count, 50);
10633 }
10634
10635
10636 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
10637   int interceptor_call_count = 0;
10638   v8::Isolate* isolate = CcTest::isolate();
10639   v8::HandleScope scope(isolate);
10640   v8::Handle<v8::FunctionTemplate> fun_templ =
10641       v8::FunctionTemplate::New(isolate);
10642   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10643       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10644       v8::Signature::New(isolate, fun_templ));
10645   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10646   proto_templ->Set(v8_str("method"), method_templ);
10647   fun_templ->SetHiddenPrototype(true);
10648   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10649   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10650       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10651       v8::External::New(isolate, &interceptor_call_count)));
10652   LocalContext context;
10653   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10654   GenerateSomeGarbage();
10655   context->Global()->Set(v8_str("o"), fun->NewInstance());
10656   CompileRun(
10657       "o.foo = 17;"
10658       "var receiver = {};"
10659       "receiver.__proto__ = o;"
10660       "var result = 0;"
10661       "var saved_result = 0;"
10662       "for (var i = 0; i < 100; i++) {"
10663       "  result = receiver.method(41);"
10664       "  if (i == 50) {"
10665       "    saved_result = result;"
10666       "    o.method = function(x) { return x - 1 };"
10667       "  }"
10668       "}");
10669   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10670   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10671   CHECK_GE(interceptor_call_count, 50);
10672 }
10673
10674
10675 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
10676   int interceptor_call_count = 0;
10677   v8::Isolate* isolate = CcTest::isolate();
10678   v8::HandleScope scope(isolate);
10679   v8::Handle<v8::FunctionTemplate> fun_templ =
10680       v8::FunctionTemplate::New(isolate);
10681   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10682       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10683       v8::Signature::New(isolate, fun_templ));
10684   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10685   proto_templ->Set(v8_str("method"), method_templ);
10686   fun_templ->SetHiddenPrototype(true);
10687   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10688   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10689       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10690       v8::External::New(isolate, &interceptor_call_count)));
10691   LocalContext context;
10692   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10693   GenerateSomeGarbage();
10694   context->Global()->Set(v8_str("o"), fun->NewInstance());
10695   v8::TryCatch try_catch(isolate);
10696   CompileRun(
10697       "o.foo = 17;"
10698       "var receiver = {};"
10699       "receiver.__proto__ = o;"
10700       "var result = 0;"
10701       "var saved_result = 0;"
10702       "for (var i = 0; i < 100; i++) {"
10703       "  result = receiver.method(41);"
10704       "  if (i == 50) {"
10705       "    saved_result = result;"
10706       "    receiver = 333;"
10707       "  }"
10708       "}");
10709   CHECK(try_catch.HasCaught());
10710   // TODO(verwaest): Adjust message.
10711   CHECK(v8_str("TypeError: receiver.method is not a function")
10712             ->Equals(try_catch.Exception()->ToString(isolate)));
10713   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10714   CHECK_GE(interceptor_call_count, 50);
10715 }
10716
10717
10718 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
10719   int interceptor_call_count = 0;
10720   v8::Isolate* isolate = CcTest::isolate();
10721   v8::HandleScope scope(isolate);
10722   v8::Handle<v8::FunctionTemplate> fun_templ =
10723       v8::FunctionTemplate::New(isolate);
10724   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10725       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10726       v8::Signature::New(isolate, fun_templ));
10727   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10728   proto_templ->Set(v8_str("method"), method_templ);
10729   fun_templ->SetHiddenPrototype(true);
10730   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10731   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10732       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10733       v8::External::New(isolate, &interceptor_call_count)));
10734   LocalContext context;
10735   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10736   GenerateSomeGarbage();
10737   context->Global()->Set(v8_str("o"), fun->NewInstance());
10738   v8::TryCatch try_catch(isolate);
10739   CompileRun(
10740       "o.foo = 17;"
10741       "var receiver = {};"
10742       "receiver.__proto__ = o;"
10743       "var result = 0;"
10744       "var saved_result = 0;"
10745       "for (var i = 0; i < 100; i++) {"
10746       "  result = receiver.method(41);"
10747       "  if (i == 50) {"
10748       "    saved_result = result;"
10749       "    receiver = {method: receiver.method};"
10750       "  }"
10751       "}");
10752   CHECK(try_catch.HasCaught());
10753   CHECK(v8_str("TypeError: Illegal invocation")
10754             ->Equals(try_catch.Exception()->ToString(isolate)));
10755   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10756   CHECK_GE(interceptor_call_count, 50);
10757 }
10758
10759
10760 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
10761   v8::Isolate* isolate = CcTest::isolate();
10762   v8::HandleScope scope(isolate);
10763   v8::Handle<v8::FunctionTemplate> fun_templ =
10764       v8::FunctionTemplate::New(isolate);
10765   v8::Handle<v8::FunctionTemplate> method_templ =
10766       v8::FunctionTemplate::New(isolate,
10767                                 FastApiCallback_TrivialSignature,
10768                                 v8_str("method_data"),
10769                                 v8::Handle<v8::Signature>());
10770   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10771   proto_templ->Set(v8_str("method"), method_templ);
10772   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10773   USE(templ);
10774   LocalContext context;
10775   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10776   GenerateSomeGarbage();
10777   context->Global()->Set(v8_str("o"), fun->NewInstance());
10778   CompileRun(
10779       "var result = 0;"
10780       "for (var i = 0; i < 100; i++) {"
10781       "  result = o.method(41);"
10782       "}");
10783
10784   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10785 }
10786
10787
10788 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
10789   v8::Isolate* isolate = CcTest::isolate();
10790   v8::HandleScope scope(isolate);
10791   v8::Handle<v8::FunctionTemplate> fun_templ =
10792       v8::FunctionTemplate::New(isolate);
10793   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10794       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10795       v8::Signature::New(isolate, fun_templ));
10796   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10797   proto_templ->Set(v8_str("method"), method_templ);
10798   fun_templ->SetHiddenPrototype(true);
10799   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10800   CHECK(!templ.IsEmpty());
10801   LocalContext context;
10802   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10803   GenerateSomeGarbage();
10804   context->Global()->Set(v8_str("o"), fun->NewInstance());
10805   CompileRun(
10806       "o.foo = 17;"
10807       "var receiver = {};"
10808       "receiver.__proto__ = o;"
10809       "var result = 0;"
10810       "for (var i = 0; i < 100; i++) {"
10811       "  result = receiver.method(41);"
10812       "}");
10813
10814   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10815 }
10816
10817
10818 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
10819   v8::Isolate* isolate = CcTest::isolate();
10820   v8::HandleScope scope(isolate);
10821   v8::Handle<v8::FunctionTemplate> fun_templ =
10822       v8::FunctionTemplate::New(isolate);
10823   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10824       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10825       v8::Signature::New(isolate, fun_templ));
10826   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10827   proto_templ->Set(v8_str("method"), method_templ);
10828   fun_templ->SetHiddenPrototype(true);
10829   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10830   CHECK(!templ.IsEmpty());
10831   LocalContext context;
10832   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10833   GenerateSomeGarbage();
10834   context->Global()->Set(v8_str("o"), fun->NewInstance());
10835   CompileRun(
10836       "o.foo = 17;"
10837       "var receiver = {};"
10838       "receiver.__proto__ = o;"
10839       "var result = 0;"
10840       "var saved_result = 0;"
10841       "for (var i = 0; i < 100; i++) {"
10842       "  result = receiver.method(41);"
10843       "  if (i == 50) {"
10844       "    saved_result = result;"
10845       "    receiver = {method: function(x) { return x - 1 }};"
10846       "  }"
10847       "}");
10848   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10849   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10850 }
10851
10852
10853 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
10854   v8::Isolate* isolate = CcTest::isolate();
10855   v8::HandleScope scope(isolate);
10856   v8::Handle<v8::FunctionTemplate> fun_templ =
10857       v8::FunctionTemplate::New(isolate);
10858   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10859       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10860       v8::Signature::New(isolate, fun_templ));
10861   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10862   proto_templ->Set(v8_str("method"), method_templ);
10863   fun_templ->SetHiddenPrototype(true);
10864   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10865   CHECK(!templ.IsEmpty());
10866   LocalContext context;
10867   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10868   GenerateSomeGarbage();
10869   context->Global()->Set(v8_str("o"), fun->NewInstance());
10870   v8::TryCatch try_catch(isolate);
10871   CompileRun(
10872       "o.foo = 17;"
10873       "var receiver = {};"
10874       "receiver.__proto__ = o;"
10875       "var result = 0;"
10876       "var saved_result = 0;"
10877       "for (var i = 0; i < 100; i++) {"
10878       "  result = receiver.method(41);"
10879       "  if (i == 50) {"
10880       "    saved_result = result;"
10881       "    receiver = 333;"
10882       "  }"
10883       "}");
10884   CHECK(try_catch.HasCaught());
10885   // TODO(verwaest): Adjust message.
10886   CHECK(v8_str("TypeError: receiver.method is not a function")
10887             ->Equals(try_catch.Exception()->ToString(isolate)));
10888   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10889 }
10890
10891
10892 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
10893   v8::Isolate* isolate = CcTest::isolate();
10894   v8::HandleScope scope(isolate);
10895   v8::Handle<v8::FunctionTemplate> fun_templ =
10896       v8::FunctionTemplate::New(isolate);
10897   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10898       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10899       v8::Signature::New(isolate, fun_templ));
10900   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10901   proto_templ->Set(v8_str("method"), method_templ);
10902   fun_templ->SetHiddenPrototype(true);
10903   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10904   CHECK(!templ.IsEmpty());
10905   LocalContext context;
10906   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10907   GenerateSomeGarbage();
10908   context->Global()->Set(v8_str("o"), fun->NewInstance());
10909   v8::TryCatch try_catch(isolate);
10910   CompileRun(
10911       "o.foo = 17;"
10912       "var receiver = {};"
10913       "receiver.__proto__ = o;"
10914       "var result = 0;"
10915       "var saved_result = 0;"
10916       "for (var i = 0; i < 100; i++) {"
10917       "  result = receiver.method(41);"
10918       "  if (i == 50) {"
10919       "    saved_result = result;"
10920       "    receiver = Object.create(receiver);"
10921       "  }"
10922       "}");
10923   CHECK(try_catch.HasCaught());
10924   CHECK(v8_str("TypeError: Illegal invocation")
10925             ->Equals(try_catch.Exception()->ToString(isolate)));
10926   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10927 }
10928
10929
10930 static void ThrowingGetter(Local<String> name,
10931                            const v8::PropertyCallbackInfo<v8::Value>& info) {
10932   ApiTestFuzzer::Fuzz();
10933   info.GetIsolate()->ThrowException(Handle<Value>());
10934   info.GetReturnValue().SetUndefined();
10935 }
10936
10937
10938 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
10939   LocalContext context;
10940   HandleScope scope(context->GetIsolate());
10941
10942   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
10943   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
10944   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
10945
10946   Local<Object> instance = templ->GetFunction()->NewInstance();
10947
10948   Local<Object> another = Object::New(context->GetIsolate());
10949   another->SetPrototype(instance);
10950
10951   Local<Object> with_js_getter = CompileRun(
10952       "o = {};\n"
10953       "o.__defineGetter__('f', function() { throw undefined; });\n"
10954       "o\n").As<Object>();
10955   CHECK(!with_js_getter.IsEmpty());
10956
10957   TryCatch try_catch(context->GetIsolate());
10958
10959   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
10960   CHECK(try_catch.HasCaught());
10961   try_catch.Reset();
10962   CHECK(result.IsEmpty());
10963
10964   Maybe<PropertyAttribute> attr =
10965       instance->GetRealNamedPropertyAttributes(v8_str("f"));
10966   CHECK(!try_catch.HasCaught());
10967   CHECK(Just(None) == attr);
10968
10969   result = another->GetRealNamedProperty(v8_str("f"));
10970   CHECK(try_catch.HasCaught());
10971   try_catch.Reset();
10972   CHECK(result.IsEmpty());
10973
10974   attr = another->GetRealNamedPropertyAttributes(v8_str("f"));
10975   CHECK(!try_catch.HasCaught());
10976   CHECK(Just(None) == attr);
10977
10978   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
10979   CHECK(try_catch.HasCaught());
10980   try_catch.Reset();
10981   CHECK(result.IsEmpty());
10982
10983   attr = another->GetRealNamedPropertyAttributesInPrototypeChain(v8_str("f"));
10984   CHECK(!try_catch.HasCaught());
10985   CHECK(Just(None) == attr);
10986
10987   result = another->Get(v8_str("f"));
10988   CHECK(try_catch.HasCaught());
10989   try_catch.Reset();
10990   CHECK(result.IsEmpty());
10991
10992   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
10993   CHECK(try_catch.HasCaught());
10994   try_catch.Reset();
10995   CHECK(result.IsEmpty());
10996
10997   attr = with_js_getter->GetRealNamedPropertyAttributes(v8_str("f"));
10998   CHECK(!try_catch.HasCaught());
10999   CHECK(Just(None) == attr);
11000
11001   result = with_js_getter->Get(v8_str("f"));
11002   CHECK(try_catch.HasCaught());
11003   try_catch.Reset();
11004   CHECK(result.IsEmpty());
11005 }
11006
11007
11008 static void ThrowingCallbackWithTryCatch(
11009     const v8::FunctionCallbackInfo<v8::Value>& args) {
11010   TryCatch try_catch(args.GetIsolate());
11011   // Verboseness is important: it triggers message delivery which can call into
11012   // external code.
11013   try_catch.SetVerbose(true);
11014   CompileRun("throw 'from JS';");
11015   CHECK(try_catch.HasCaught());
11016   CHECK(!CcTest::i_isolate()->has_pending_exception());
11017   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
11018 }
11019
11020
11021 static int call_depth;
11022
11023
11024 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
11025   TryCatch try_catch(CcTest::isolate());
11026 }
11027
11028
11029 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
11030   if (--call_depth) CompileRun("throw 'ThrowInJS';");
11031 }
11032
11033
11034 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
11035   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
11036 }
11037
11038
11039 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
11040   Handle<String> errorMessageString = message->Get();
11041   CHECK(!errorMessageString.IsEmpty());
11042   message->GetStackTrace();
11043   message->GetScriptOrigin().ResourceName();
11044 }
11045
11046
11047 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
11048   LocalContext context;
11049   v8::Isolate* isolate = context->GetIsolate();
11050   HandleScope scope(isolate);
11051
11052   Local<Function> func =
11053       FunctionTemplate::New(isolate,
11054                             ThrowingCallbackWithTryCatch)->GetFunction();
11055   context->Global()->Set(v8_str("func"), func);
11056
11057   MessageCallback callbacks[] =
11058       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
11059   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
11060     MessageCallback callback = callbacks[i];
11061     if (callback != NULL) {
11062       V8::AddMessageListener(callback);
11063     }
11064     // Some small number to control number of times message handler should
11065     // throw an exception.
11066     call_depth = 5;
11067     ExpectFalse(
11068         "var thrown = false;\n"
11069         "try { func(); } catch(e) { thrown = true; }\n"
11070         "thrown\n");
11071     if (callback != NULL) {
11072       V8::RemoveMessageListeners(callback);
11073     }
11074   }
11075 }
11076
11077
11078 static void ParentGetter(Local<String> name,
11079                          const v8::PropertyCallbackInfo<v8::Value>& info) {
11080   ApiTestFuzzer::Fuzz();
11081   info.GetReturnValue().Set(v8_num(1));
11082 }
11083
11084
11085 static void ChildGetter(Local<String> name,
11086                         const v8::PropertyCallbackInfo<v8::Value>& info) {
11087   ApiTestFuzzer::Fuzz();
11088   info.GetReturnValue().Set(v8_num(42));
11089 }
11090
11091
11092 THREADED_TEST(Overriding) {
11093   LocalContext context;
11094   v8::Isolate* isolate = context->GetIsolate();
11095   v8::HandleScope scope(isolate);
11096
11097   // Parent template.
11098   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
11099   Local<ObjectTemplate> parent_instance_templ =
11100       parent_templ->InstanceTemplate();
11101   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
11102
11103   // Template that inherits from the parent template.
11104   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
11105   Local<ObjectTemplate> child_instance_templ =
11106       child_templ->InstanceTemplate();
11107   child_templ->Inherit(parent_templ);
11108   // Override 'f'.  The child version of 'f' should get called for child
11109   // instances.
11110   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
11111   // Add 'g' twice.  The 'g' added last should get called for instances.
11112   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
11113   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
11114
11115   // Add 'h' as an accessor to the proto template with ReadOnly attributes
11116   // so 'h' can be shadowed on the instance object.
11117   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
11118   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
11119       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
11120
11121   // Add 'i' as an accessor to the instance template with ReadOnly attributes
11122   // but the attribute does not have effect because it is duplicated with
11123   // NULL setter.
11124   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
11125       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
11126
11127
11128
11129   // Instantiate the child template.
11130   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
11131
11132   // Check that the child function overrides the parent one.
11133   context->Global()->Set(v8_str("o"), instance);
11134   Local<Value> value = v8_compile("o.f")->Run();
11135   // Check that the 'g' that was added last is hit.
11136   CHECK_EQ(42, value->Int32Value());
11137   value = v8_compile("o.g")->Run();
11138   CHECK_EQ(42, value->Int32Value());
11139
11140   // Check that 'h' cannot be shadowed.
11141   value = v8_compile("o.h = 3; o.h")->Run();
11142   CHECK_EQ(1, value->Int32Value());
11143
11144   // Check that 'i' cannot be shadowed or changed.
11145   value = v8_compile("o.i = 3; o.i")->Run();
11146   CHECK_EQ(42, value->Int32Value());
11147 }
11148
11149
11150 static void IsConstructHandler(
11151     const v8::FunctionCallbackInfo<v8::Value>& args) {
11152   ApiTestFuzzer::Fuzz();
11153   args.GetReturnValue().Set(args.IsConstructCall());
11154 }
11155
11156
11157 THREADED_TEST(IsConstructCall) {
11158   v8::Isolate* isolate = CcTest::isolate();
11159   v8::HandleScope scope(isolate);
11160
11161   // Function template with call handler.
11162   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11163   templ->SetCallHandler(IsConstructHandler);
11164
11165   LocalContext context;
11166
11167   context->Global()->Set(v8_str("f"), templ->GetFunction());
11168   Local<Value> value = v8_compile("f()")->Run();
11169   CHECK(!value->BooleanValue());
11170   value = v8_compile("new f()")->Run();
11171   CHECK(value->BooleanValue());
11172 }
11173
11174
11175 THREADED_TEST(ObjectProtoToString) {
11176   v8::Isolate* isolate = CcTest::isolate();
11177   v8::HandleScope scope(isolate);
11178   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11179   templ->SetClassName(v8_str("MyClass"));
11180
11181   LocalContext context;
11182
11183   Local<String> customized_tostring = v8_str("customized toString");
11184
11185   // Replace Object.prototype.toString
11186   v8_compile("Object.prototype.toString = function() {"
11187                   "  return 'customized toString';"
11188                   "}")->Run();
11189
11190   // Normal ToString call should call replaced Object.prototype.toString
11191   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
11192   Local<String> value = instance->ToString(isolate);
11193   CHECK(value->IsString() && value->Equals(customized_tostring));
11194
11195   // ObjectProtoToString should not call replace toString function.
11196   value = instance->ObjectProtoToString();
11197   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
11198
11199   // Check global
11200   value = context->Global()->ObjectProtoToString();
11201   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
11202
11203   // Check ordinary object
11204   Local<Value> object = v8_compile("new Object()")->Run();
11205   value = object.As<v8::Object>()->ObjectProtoToString();
11206   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11207 }
11208
11209
11210 TEST(ObjectProtoToStringES6) {
11211   // TODO(dslomov, caitp): merge into ObjectProtoToString test once shipped.
11212   i::FLAG_harmony_tostring = true;
11213   LocalContext context;
11214   v8::Isolate* isolate = CcTest::isolate();
11215   v8::HandleScope scope(isolate);
11216   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11217   templ->SetClassName(v8_str("MyClass"));
11218
11219   Local<String> customized_tostring = v8_str("customized toString");
11220
11221   // Replace Object.prototype.toString
11222   CompileRun(
11223       "Object.prototype.toString = function() {"
11224       "  return 'customized toString';"
11225       "}");
11226
11227   // Normal ToString call should call replaced Object.prototype.toString
11228   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
11229   Local<String> value = instance->ToString(isolate);
11230   CHECK(value->IsString() && value->Equals(customized_tostring));
11231
11232   // ObjectProtoToString should not call replace toString function.
11233   value = instance->ObjectProtoToString();
11234   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
11235
11236   // Check global
11237   value = context->Global()->ObjectProtoToString();
11238   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
11239
11240   // Check ordinary object
11241   Local<Value> object = CompileRun("new Object()");
11242   value = object.As<v8::Object>()->ObjectProtoToString();
11243   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11244
11245   // Check that ES6 semantics using @@toStringTag work
11246   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
11247
11248 #define TEST_TOSTRINGTAG(type, tag, expected)                \
11249   do {                                                       \
11250     object = CompileRun("new " #type "()");                  \
11251     object.As<v8::Object>()->Set(toStringTag, v8_str(#tag)); \
11252     value = object.As<v8::Object>()->ObjectProtoToString();  \
11253     CHECK(value->IsString() &&                               \
11254           value->Equals(v8_str("[object " #expected "]")));  \
11255   } while (0)
11256
11257   TEST_TOSTRINGTAG(Array, Object, Object);
11258   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
11259   TEST_TOSTRINGTAG(Object, Array, Array);
11260   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
11261   TEST_TOSTRINGTAG(Object, Date, Date);
11262   TEST_TOSTRINGTAG(Object, Error, Error);
11263   TEST_TOSTRINGTAG(Object, Function, Function);
11264   TEST_TOSTRINGTAG(Object, Number, Number);
11265   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
11266   TEST_TOSTRINGTAG(Object, String, String);
11267   TEST_TOSTRINGTAG(Object, Foo, Foo);
11268
11269 #undef TEST_TOSTRINGTAG
11270
11271   Local<v8::RegExp> valueRegExp = v8::RegExp::New(v8_str("^$"),
11272                                                   v8::RegExp::kNone);
11273   Local<Value> valueNumber = v8_num(123);
11274   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
11275   Local<v8::Function> valueFunction =
11276       CompileRun("(function fn() {})").As<v8::Function>();
11277   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
11278   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
11279   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
11280
11281 #define TEST_TOSTRINGTAG(type, tagValue, expected)          \
11282   do {                                                      \
11283     object = CompileRun("new " #type "()");                 \
11284     object.As<v8::Object>()->Set(toStringTag, tagValue);    \
11285     value = object.As<v8::Object>()->ObjectProtoToString(); \
11286     CHECK(value->IsString() &&                              \
11287           value->Equals(v8_str("[object " #expected "]"))); \
11288   } while (0)
11289
11290 #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
11291   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
11292   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
11293   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
11294   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
11295   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
11296   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
11297
11298   // Test non-String-valued @@toStringTag
11299   TEST_TOSTRINGTAG_TYPES(valueRegExp);
11300   TEST_TOSTRINGTAG_TYPES(valueNumber);
11301   TEST_TOSTRINGTAG_TYPES(valueSymbol);
11302   TEST_TOSTRINGTAG_TYPES(valueFunction);
11303   TEST_TOSTRINGTAG_TYPES(valueObject);
11304   TEST_TOSTRINGTAG_TYPES(valueNull);
11305   TEST_TOSTRINGTAG_TYPES(valueUndef);
11306
11307 #undef TEST_TOSTRINGTAG
11308 #undef TEST_TOSTRINGTAG_TYPES
11309
11310   // @@toStringTag getter throws
11311   Local<Value> obj = v8::Object::New(isolate);
11312   obj.As<v8::Object>()->SetAccessor(toStringTag, ThrowingSymbolAccessorGetter);
11313   {
11314     TryCatch try_catch(isolate);
11315     value = obj.As<v8::Object>()->ObjectProtoToString();
11316     CHECK(value.IsEmpty());
11317     CHECK(try_catch.HasCaught());
11318   }
11319
11320   // @@toStringTag getter does not throw
11321   obj = v8::Object::New(isolate);
11322   obj.As<v8::Object>()->SetAccessor(
11323       toStringTag, SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"));
11324   {
11325     TryCatch try_catch(isolate);
11326     value = obj.As<v8::Object>()->ObjectProtoToString();
11327     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11328     CHECK(!try_catch.HasCaught());
11329   }
11330
11331   // JS @@toStringTag value
11332   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
11333   {
11334     TryCatch try_catch(isolate);
11335     value = obj.As<v8::Object>()->ObjectProtoToString();
11336     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11337     CHECK(!try_catch.HasCaught());
11338   }
11339
11340   // JS @@toStringTag getter throws
11341   obj = CompileRun(
11342       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
11343       "  get: function() { throw 'Test'; }"
11344       "}); obj");
11345   {
11346     TryCatch try_catch(isolate);
11347     value = obj.As<v8::Object>()->ObjectProtoToString();
11348     CHECK(value.IsEmpty());
11349     CHECK(try_catch.HasCaught());
11350   }
11351
11352   // JS @@toStringTag getter does not throw
11353   obj = CompileRun(
11354       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
11355       "  get: function() { return 'Test'; }"
11356       "}); obj");
11357   {
11358     TryCatch try_catch(isolate);
11359     value = obj.As<v8::Object>()->ObjectProtoToString();
11360     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11361     CHECK(!try_catch.HasCaught());
11362   }
11363 }
11364
11365
11366 THREADED_TEST(ObjectGetConstructorName) {
11367   v8::Isolate* isolate = CcTest::isolate();
11368   LocalContext context;
11369   v8::HandleScope scope(isolate);
11370   v8_compile(
11371       "function Parent() {};"
11372       "function Child() {};"
11373       "Child.prototype = new Parent();"
11374       "var outer = { inner: function() { } };"
11375       "var p = new Parent();"
11376       "var c = new Child();"
11377       "var x = new outer.inner();"
11378       "var proto = Child.prototype;")->Run();
11379
11380   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
11381   CHECK(p->IsObject() &&
11382         p->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Parent")));
11383
11384   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
11385   CHECK(c->IsObject() &&
11386         c->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Child")));
11387
11388   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
11389   CHECK(x->IsObject() &&
11390         x->ToObject(isolate)->GetConstructorName()->Equals(
11391             v8_str("outer.inner")));
11392
11393   Local<v8::Value> child_prototype = context->Global()->Get(v8_str("proto"));
11394   CHECK(child_prototype->IsObject() &&
11395         child_prototype->ToObject(isolate)->GetConstructorName()->Equals(
11396             v8_str("Parent")));
11397 }
11398
11399
11400 bool ApiTestFuzzer::fuzzing_ = false;
11401 v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
11402 int ApiTestFuzzer::active_tests_;
11403 int ApiTestFuzzer::tests_being_run_;
11404 int ApiTestFuzzer::current_;
11405
11406
11407 // We are in a callback and want to switch to another thread (if we
11408 // are currently running the thread fuzzing test).
11409 void ApiTestFuzzer::Fuzz() {
11410   if (!fuzzing_) return;
11411   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
11412   test->ContextSwitch();
11413 }
11414
11415
11416 // Let the next thread go.  Since it is also waiting on the V8 lock it may
11417 // not start immediately.
11418 bool ApiTestFuzzer::NextThread() {
11419   int test_position = GetNextTestNumber();
11420   const char* test_name = RegisterThreadedTest::nth(current_)->name();
11421   if (test_position == current_) {
11422     if (kLogThreading)
11423       printf("Stay with %s\n", test_name);
11424     return false;
11425   }
11426   if (kLogThreading) {
11427     printf("Switch from %s to %s\n",
11428            test_name,
11429            RegisterThreadedTest::nth(test_position)->name());
11430   }
11431   current_ = test_position;
11432   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
11433   return true;
11434 }
11435
11436
11437 void ApiTestFuzzer::Run() {
11438   // When it is our turn...
11439   gate_.Wait();
11440   {
11441     // ... get the V8 lock and start running the test.
11442     v8::Locker locker(CcTest::isolate());
11443     CallTest();
11444   }
11445   // This test finished.
11446   active_ = false;
11447   active_tests_--;
11448   // If it was the last then signal that fact.
11449   if (active_tests_ == 0) {
11450     all_tests_done_.Signal();
11451   } else {
11452     // Otherwise select a new test and start that.
11453     NextThread();
11454   }
11455 }
11456
11457
11458 static unsigned linear_congruential_generator;
11459
11460
11461 void ApiTestFuzzer::SetUp(PartOfTest part) {
11462   linear_congruential_generator = i::FLAG_testing_prng_seed;
11463   fuzzing_ = true;
11464   int count = RegisterThreadedTest::count();
11465   int start =  count * part / (LAST_PART + 1);
11466   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
11467   active_tests_ = tests_being_run_ = end - start + 1;
11468   for (int i = 0; i < tests_being_run_; i++) {
11469     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
11470   }
11471   for (int i = 0; i < active_tests_; i++) {
11472     RegisterThreadedTest::nth(i)->fuzzer_->Start();
11473   }
11474 }
11475
11476
11477 static void CallTestNumber(int test_number) {
11478   (RegisterThreadedTest::nth(test_number)->callback())();
11479 }
11480
11481
11482 void ApiTestFuzzer::RunAllTests() {
11483   // Set off the first test.
11484   current_ = -1;
11485   NextThread();
11486   // Wait till they are all done.
11487   all_tests_done_.Wait();
11488 }
11489
11490
11491 int ApiTestFuzzer::GetNextTestNumber() {
11492   int next_test;
11493   do {
11494     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
11495     linear_congruential_generator *= 1664525u;
11496     linear_congruential_generator += 1013904223u;
11497   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
11498   return next_test;
11499 }
11500
11501
11502 void ApiTestFuzzer::ContextSwitch() {
11503   // If the new thread is the same as the current thread there is nothing to do.
11504   if (NextThread()) {
11505     // Now it can start.
11506     v8::Unlocker unlocker(CcTest::isolate());
11507     // Wait till someone starts us again.
11508     gate_.Wait();
11509     // And we're off.
11510   }
11511 }
11512
11513
11514 void ApiTestFuzzer::TearDown() {
11515   fuzzing_ = false;
11516   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
11517     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
11518     if (fuzzer != NULL) fuzzer->Join();
11519   }
11520 }
11521
11522
11523 // Lets not be needlessly self-referential.
11524 TEST(Threading1) {
11525   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
11526   ApiTestFuzzer::RunAllTests();
11527   ApiTestFuzzer::TearDown();
11528 }
11529
11530
11531 TEST(Threading2) {
11532   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
11533   ApiTestFuzzer::RunAllTests();
11534   ApiTestFuzzer::TearDown();
11535 }
11536
11537
11538 TEST(Threading3) {
11539   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
11540   ApiTestFuzzer::RunAllTests();
11541   ApiTestFuzzer::TearDown();
11542 }
11543
11544
11545 TEST(Threading4) {
11546   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
11547   ApiTestFuzzer::RunAllTests();
11548   ApiTestFuzzer::TearDown();
11549 }
11550
11551
11552 void ApiTestFuzzer::CallTest() {
11553   v8::Isolate::Scope scope(CcTest::isolate());
11554   if (kLogThreading)
11555     printf("Start test %d\n", test_number_);
11556   CallTestNumber(test_number_);
11557   if (kLogThreading)
11558     printf("End test %d\n", test_number_);
11559 }
11560
11561
11562 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
11563   v8::Isolate* isolate = args.GetIsolate();
11564   CHECK(v8::Locker::IsLocked(isolate));
11565   ApiTestFuzzer::Fuzz();
11566   v8::Unlocker unlocker(isolate);
11567   const char* code = "throw 7;";
11568   {
11569     v8::Locker nested_locker(isolate);
11570     v8::HandleScope scope(isolate);
11571     v8::Handle<Value> exception;
11572     {
11573       v8::TryCatch try_catch(isolate);
11574       v8::Handle<Value> value = CompileRun(code);
11575       CHECK(value.IsEmpty());
11576       CHECK(try_catch.HasCaught());
11577       // Make sure to wrap the exception in a new handle because
11578       // the handle returned from the TryCatch is destroyed
11579       // when the TryCatch is destroyed.
11580       exception = Local<Value>::New(isolate, try_catch.Exception());
11581     }
11582     args.GetIsolate()->ThrowException(exception);
11583   }
11584 }
11585
11586
11587 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
11588   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
11589   ApiTestFuzzer::Fuzz();
11590   v8::Unlocker unlocker(CcTest::isolate());
11591   const char* code = "throw 7;";
11592   {
11593     v8::Locker nested_locker(CcTest::isolate());
11594     v8::HandleScope scope(args.GetIsolate());
11595     v8::Handle<Value> value = CompileRun(code);
11596     CHECK(value.IsEmpty());
11597     args.GetReturnValue().Set(v8_str("foo"));
11598   }
11599 }
11600
11601
11602 // These are locking tests that don't need to be run again
11603 // as part of the locking aggregation tests.
11604 TEST(NestedLockers) {
11605   v8::Isolate* isolate = CcTest::isolate();
11606   v8::Locker locker(isolate);
11607   CHECK(v8::Locker::IsLocked(isolate));
11608   LocalContext env;
11609   v8::HandleScope scope(env->GetIsolate());
11610   Local<v8::FunctionTemplate> fun_templ =
11611       v8::FunctionTemplate::New(isolate, ThrowInJS);
11612   Local<Function> fun = fun_templ->GetFunction();
11613   env->Global()->Set(v8_str("throw_in_js"), fun);
11614   Local<Script> script = v8_compile("(function () {"
11615                                     "  try {"
11616                                     "    throw_in_js();"
11617                                     "    return 42;"
11618                                     "  } catch (e) {"
11619                                     "    return e * 13;"
11620                                     "  }"
11621                                     "})();");
11622   CHECK_EQ(91, script->Run()->Int32Value());
11623 }
11624
11625
11626 // These are locking tests that don't need to be run again
11627 // as part of the locking aggregation tests.
11628 TEST(NestedLockersNoTryCatch) {
11629   v8::Locker locker(CcTest::isolate());
11630   LocalContext env;
11631   v8::HandleScope scope(env->GetIsolate());
11632   Local<v8::FunctionTemplate> fun_templ =
11633       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
11634   Local<Function> fun = fun_templ->GetFunction();
11635   env->Global()->Set(v8_str("throw_in_js"), fun);
11636   Local<Script> script = v8_compile("(function () {"
11637                                     "  try {"
11638                                     "    throw_in_js();"
11639                                     "    return 42;"
11640                                     "  } catch (e) {"
11641                                     "    return e * 13;"
11642                                     "  }"
11643                                     "})();");
11644   CHECK_EQ(91, script->Run()->Int32Value());
11645 }
11646
11647
11648 THREADED_TEST(RecursiveLocking) {
11649   v8::Locker locker(CcTest::isolate());
11650   {
11651     v8::Locker locker2(CcTest::isolate());
11652     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
11653   }
11654 }
11655
11656
11657 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
11658   ApiTestFuzzer::Fuzz();
11659   v8::Unlocker unlocker(CcTest::isolate());
11660 }
11661
11662
11663 THREADED_TEST(LockUnlockLock) {
11664   {
11665     v8::Locker locker(CcTest::isolate());
11666     v8::HandleScope scope(CcTest::isolate());
11667     LocalContext env;
11668     Local<v8::FunctionTemplate> fun_templ =
11669         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
11670     Local<Function> fun = fun_templ->GetFunction();
11671     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11672     Local<Script> script = v8_compile("(function () {"
11673                                       "  unlock_for_a_moment();"
11674                                       "  return 42;"
11675                                       "})();");
11676     CHECK_EQ(42, script->Run()->Int32Value());
11677   }
11678   {
11679     v8::Locker locker(CcTest::isolate());
11680     v8::HandleScope scope(CcTest::isolate());
11681     LocalContext env;
11682     Local<v8::FunctionTemplate> fun_templ =
11683         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
11684     Local<Function> fun = fun_templ->GetFunction();
11685     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11686     Local<Script> script = v8_compile("(function () {"
11687                                       "  unlock_for_a_moment();"
11688                                       "  return 42;"
11689                                       "})();");
11690     CHECK_EQ(42, script->Run()->Int32Value());
11691   }
11692 }
11693
11694
11695 static int GetGlobalObjectsCount() {
11696   int count = 0;
11697   i::HeapIterator it(CcTest::heap());
11698   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
11699     if (object->IsJSGlobalObject()) count++;
11700   // Subtract one to compensate for the code stub context that is always present
11701   return count - 1;
11702 }
11703
11704
11705 static void CheckSurvivingGlobalObjectsCount(int expected) {
11706   // We need to collect all garbage twice to be sure that everything
11707   // has been collected.  This is because inline caches are cleared in
11708   // the first garbage collection but some of the maps have already
11709   // been marked at that point.  Therefore some of the maps are not
11710   // collected until the second garbage collection.
11711   CcTest::heap()->CollectAllGarbage();
11712   CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
11713   int count = GetGlobalObjectsCount();
11714 #ifdef DEBUG
11715   if (count != expected) CcTest::heap()->TracePathToGlobal();
11716 #endif
11717   CHECK_EQ(expected, count);
11718 }
11719
11720
11721 TEST(DontLeakGlobalObjects) {
11722   // Regression test for issues 1139850 and 1174891.
11723
11724   i::FLAG_expose_gc = true;
11725   v8::V8::Initialize();
11726
11727   for (int i = 0; i < 5; i++) {
11728     { v8::HandleScope scope(CcTest::isolate());
11729       LocalContext context;
11730     }
11731     CcTest::isolate()->ContextDisposedNotification();
11732     CheckSurvivingGlobalObjectsCount(0);
11733
11734     { v8::HandleScope scope(CcTest::isolate());
11735       LocalContext context;
11736       v8_compile("Date")->Run();
11737     }
11738     CcTest::isolate()->ContextDisposedNotification();
11739     CheckSurvivingGlobalObjectsCount(0);
11740
11741     { v8::HandleScope scope(CcTest::isolate());
11742       LocalContext context;
11743       v8_compile("/aaa/")->Run();
11744     }
11745     CcTest::isolate()->ContextDisposedNotification();
11746     CheckSurvivingGlobalObjectsCount(0);
11747
11748     { v8::HandleScope scope(CcTest::isolate());
11749       const char* extension_list[] = { "v8/gc" };
11750       v8::ExtensionConfiguration extensions(1, extension_list);
11751       LocalContext context(&extensions);
11752       v8_compile("gc();")->Run();
11753     }
11754     CcTest::isolate()->ContextDisposedNotification();
11755     CheckSurvivingGlobalObjectsCount(0);
11756   }
11757 }
11758
11759
11760 TEST(CopyablePersistent) {
11761   LocalContext context;
11762   v8::Isolate* isolate = context->GetIsolate();
11763   i::GlobalHandles* globals =
11764       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
11765   int initial_handles = globals->global_handles_count();
11766   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
11767       CopyableObject;
11768   {
11769     CopyableObject handle1;
11770     {
11771       v8::HandleScope scope(isolate);
11772       handle1.Reset(isolate, v8::Object::New(isolate));
11773     }
11774     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
11775     CopyableObject  handle2;
11776     handle2 = handle1;
11777     CHECK(handle1 == handle2);
11778     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
11779     CopyableObject handle3(handle2);
11780     CHECK(handle1 == handle3);
11781     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
11782   }
11783   // Verify autodispose
11784   CHECK_EQ(initial_handles, globals->global_handles_count());
11785 }
11786
11787
11788 static void WeakApiCallback(
11789     const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
11790   data.GetParameter()->Reset();
11791   delete data.GetParameter();
11792 }
11793
11794
11795 TEST(WeakCallbackApi) {
11796   LocalContext context;
11797   v8::Isolate* isolate = context->GetIsolate();
11798   i::GlobalHandles* globals =
11799       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
11800   int initial_handles = globals->global_handles_count();
11801   {
11802     v8::HandleScope scope(isolate);
11803     v8::Local<v8::Object> obj = v8::Object::New(isolate);
11804     obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
11805     v8::Persistent<v8::Object>* handle =
11806         new v8::Persistent<v8::Object>(isolate, obj);
11807     handle->SetWeak<v8::Persistent<v8::Object>>(
11808         handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
11809   }
11810   reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
11811       i::Heap::kAbortIncrementalMarkingMask);
11812   // Verify disposed.
11813   CHECK_EQ(initial_handles, globals->global_handles_count());
11814 }
11815
11816
11817 v8::Persistent<v8::Object> some_object;
11818 v8::Persistent<v8::Object> bad_handle;
11819
11820
11821 void NewPersistentHandleCallback2(
11822     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11823   v8::HandleScope scope(data.GetIsolate());
11824   bad_handle.Reset(data.GetIsolate(), some_object);
11825 }
11826
11827
11828 void NewPersistentHandleCallback1(
11829     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11830   data.GetParameter()->Reset();
11831   data.SetSecondPassCallback(NewPersistentHandleCallback2);
11832 }
11833
11834
11835 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
11836   LocalContext context;
11837   v8::Isolate* isolate = context->GetIsolate();
11838
11839   v8::Persistent<v8::Object> handle1, handle2;
11840   {
11841     v8::HandleScope scope(isolate);
11842     some_object.Reset(isolate, v8::Object::New(isolate));
11843     handle1.Reset(isolate, v8::Object::New(isolate));
11844     handle2.Reset(isolate, v8::Object::New(isolate));
11845   }
11846   // Note: order is implementation dependent alas: currently
11847   // global handle nodes are processed by PostGarbageCollectionProcessing
11848   // in reverse allocation order, so if second allocated handle is deleted,
11849   // weak callback of the first handle would be able to 'reallocate' it.
11850   handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
11851                   v8::WeakCallbackType::kParameter);
11852   handle2.Reset();
11853   CcTest::heap()->CollectAllGarbage();
11854 }
11855
11856
11857 v8::Persistent<v8::Object> to_be_disposed;
11858
11859
11860 void DisposeAndForceGcCallback2(
11861     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11862   to_be_disposed.Reset();
11863   CcTest::heap()->CollectAllGarbage();
11864 }
11865
11866
11867 void DisposeAndForceGcCallback1(
11868     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11869   data.GetParameter()->Reset();
11870   data.SetSecondPassCallback(DisposeAndForceGcCallback2);
11871 }
11872
11873
11874 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
11875   LocalContext context;
11876   v8::Isolate* isolate = context->GetIsolate();
11877
11878   v8::Persistent<v8::Object> handle1, handle2;
11879   {
11880     v8::HandleScope scope(isolate);
11881     handle1.Reset(isolate, v8::Object::New(isolate));
11882     handle2.Reset(isolate, v8::Object::New(isolate));
11883   }
11884   handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
11885                   v8::WeakCallbackType::kParameter);
11886   to_be_disposed.Reset(isolate, handle2);
11887   CcTest::heap()->CollectAllGarbage();
11888 }
11889
11890 void DisposingCallback(
11891     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11892   data.GetParameter()->Reset();
11893 }
11894
11895 void HandleCreatingCallback2(
11896     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11897   v8::HandleScope scope(data.GetIsolate());
11898   v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
11899 }
11900
11901
11902 void HandleCreatingCallback1(
11903     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11904   data.GetParameter()->Reset();
11905   data.SetSecondPassCallback(HandleCreatingCallback2);
11906 }
11907
11908
11909 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
11910   v8::Locker locker(CcTest::isolate());
11911   LocalContext context;
11912   v8::Isolate* isolate = context->GetIsolate();
11913
11914   v8::Persistent<v8::Object> handle1, handle2, handle3;
11915   {
11916     v8::HandleScope scope(isolate);
11917     handle3.Reset(isolate, v8::Object::New(isolate));
11918     handle2.Reset(isolate, v8::Object::New(isolate));
11919     handle1.Reset(isolate, v8::Object::New(isolate));
11920   }
11921   handle2.SetWeak(&handle2, DisposingCallback,
11922                   v8::WeakCallbackType::kParameter);
11923   handle3.SetWeak(&handle3, HandleCreatingCallback1,
11924                   v8::WeakCallbackType::kParameter);
11925   CcTest::heap()->CollectAllGarbage();
11926   EmptyMessageQueues(isolate);
11927 }
11928
11929
11930 THREADED_TEST(CheckForCrossContextObjectLiterals) {
11931   v8::V8::Initialize();
11932
11933   const int nof = 2;
11934   const char* sources[nof] = {
11935     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
11936     "Object()"
11937   };
11938
11939   for (int i = 0; i < nof; i++) {
11940     const char* source = sources[i];
11941     { v8::HandleScope scope(CcTest::isolate());
11942       LocalContext context;
11943       CompileRun(source);
11944     }
11945     { v8::HandleScope scope(CcTest::isolate());
11946       LocalContext context;
11947       CompileRun(source);
11948     }
11949   }
11950 }
11951
11952
11953 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
11954   v8::EscapableHandleScope inner(env->GetIsolate());
11955   env->Enter();
11956   v8::Local<Value> three = v8_num(3);
11957   v8::Local<Value> value = inner.Escape(three);
11958   env->Exit();
11959   return value;
11960 }
11961
11962
11963 THREADED_TEST(NestedHandleScopeAndContexts) {
11964   v8::Isolate* isolate = CcTest::isolate();
11965   v8::HandleScope outer(isolate);
11966   v8::Local<Context> env = Context::New(isolate);
11967   env->Enter();
11968   v8::Handle<Value> value = NestedScope(env);
11969   v8::Handle<String> str(value->ToString(isolate));
11970   CHECK(!str.IsEmpty());
11971   env->Exit();
11972 }
11973
11974
11975 static bool MatchPointers(void* key1, void* key2) {
11976   return key1 == key2;
11977 }
11978
11979
11980 struct SymbolInfo {
11981   size_t id;
11982   size_t size;
11983   std::string name;
11984 };
11985
11986
11987 class SetFunctionEntryHookTest {
11988  public:
11989   SetFunctionEntryHookTest() {
11990     CHECK(instance_ == NULL);
11991     instance_ = this;
11992   }
11993   ~SetFunctionEntryHookTest() {
11994     CHECK(instance_ == this);
11995     instance_ = NULL;
11996   }
11997   void Reset() {
11998     symbols_.clear();
11999     symbol_locations_.clear();
12000     invocations_.clear();
12001   }
12002   void RunTest();
12003   void OnJitEvent(const v8::JitCodeEvent* event);
12004   static void JitEvent(const v8::JitCodeEvent* event) {
12005     CHECK(instance_ != NULL);
12006     instance_->OnJitEvent(event);
12007   }
12008
12009   void OnEntryHook(uintptr_t function,
12010                    uintptr_t return_addr_location);
12011   static void EntryHook(uintptr_t function,
12012                         uintptr_t return_addr_location) {
12013     CHECK(instance_ != NULL);
12014     instance_->OnEntryHook(function, return_addr_location);
12015   }
12016
12017   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
12018     CHECK(instance_ != NULL);
12019     args.GetReturnValue().Set(v8_num(42));
12020   }
12021   void RunLoopInNewEnv(v8::Isolate* isolate);
12022
12023   // Records addr as location of symbol.
12024   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
12025
12026   // Finds the symbol containing addr
12027   SymbolInfo* FindSymbolForAddr(i::Address addr);
12028   // Returns the number of invocations where the caller name contains
12029   // \p caller_name and the function name contains \p function_name.
12030   int CountInvocations(const char* caller_name,
12031                        const char* function_name);
12032
12033   i::Handle<i::JSFunction> foo_func_;
12034   i::Handle<i::JSFunction> bar_func_;
12035
12036   typedef std::map<size_t, SymbolInfo> SymbolMap;
12037   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
12038   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
12039   SymbolMap symbols_;
12040   SymbolLocationMap symbol_locations_;
12041   InvocationMap invocations_;
12042
12043   static SetFunctionEntryHookTest* instance_;
12044 };
12045 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
12046
12047
12048 // Returns true if addr is in the range [start, start+len).
12049 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
12050   if (start <= addr && start + len > addr)
12051     return true;
12052
12053   return false;
12054 }
12055
12056 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
12057                                               SymbolInfo* symbol) {
12058   // Insert the symbol at the new location.
12059   SymbolLocationMap::iterator it =
12060       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
12061   // Now erase symbols to the left and right that overlap this one.
12062   while (it != symbol_locations_.begin()) {
12063     SymbolLocationMap::iterator left = it;
12064     --left;
12065     if (!Overlaps(left->first, left->second->size, addr))
12066       break;
12067     symbol_locations_.erase(left);
12068   }
12069
12070   // Now erase symbols to the left and right that overlap this one.
12071   while (true) {
12072     SymbolLocationMap::iterator right = it;
12073     ++right;
12074     if (right == symbol_locations_.end())
12075         break;
12076     if (!Overlaps(addr, symbol->size, right->first))
12077       break;
12078     symbol_locations_.erase(right);
12079   }
12080 }
12081
12082
12083 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
12084   switch (event->type) {
12085     case v8::JitCodeEvent::CODE_ADDED: {
12086         CHECK(event->code_start != NULL);
12087         CHECK_NE(0, static_cast<int>(event->code_len));
12088         CHECK(event->name.str != NULL);
12089         size_t symbol_id = symbols_.size();
12090
12091         // Record the new symbol.
12092         SymbolInfo& info = symbols_[symbol_id];
12093         info.id = symbol_id;
12094         info.size = event->code_len;
12095         info.name.assign(event->name.str, event->name.str + event->name.len);
12096
12097         // And record it's location.
12098         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
12099       }
12100       break;
12101
12102     case v8::JitCodeEvent::CODE_MOVED: {
12103         // We would like to never see code move that we haven't seen before,
12104         // but the code creation event does not happen until the line endings
12105         // have been calculated (this is so that we can report the line in the
12106         // script at which the function source is found, see
12107         // Compiler::RecordFunctionCompilation) and the line endings
12108         // calculations can cause a GC, which can move the newly created code
12109         // before its existence can be logged.
12110         SymbolLocationMap::iterator it(
12111             symbol_locations_.find(
12112                 reinterpret_cast<i::Address>(event->code_start)));
12113         if (it != symbol_locations_.end()) {
12114           // Found a symbol at this location, move it.
12115           SymbolInfo* info = it->second;
12116           symbol_locations_.erase(it);
12117           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
12118                          info);
12119         }
12120       }
12121     default:
12122       break;
12123   }
12124 }
12125
12126 void SetFunctionEntryHookTest::OnEntryHook(
12127     uintptr_t function, uintptr_t return_addr_location) {
12128   // Get the function's code object.
12129   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
12130       reinterpret_cast<i::Address>(function));
12131   CHECK(function_code != NULL);
12132
12133   // Then try and look up the caller's code object.
12134   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
12135
12136   // Count the invocation.
12137   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
12138   SymbolInfo* function_symbol =
12139       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
12140   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
12141
12142   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
12143     // Check that we have a symbol for the "bar" function at the right location.
12144     SymbolLocationMap::iterator it(
12145         symbol_locations_.find(function_code->instruction_start()));
12146     CHECK(it != symbol_locations_.end());
12147   }
12148
12149   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
12150     // Check that we have a symbol for "foo" at the right location.
12151     SymbolLocationMap::iterator it(
12152         symbol_locations_.find(function_code->instruction_start()));
12153     CHECK(it != symbol_locations_.end());
12154   }
12155 }
12156
12157
12158 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
12159   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
12160   // Do we have a direct hit on a symbol?
12161   if (it != symbol_locations_.end()) {
12162     if (it->first == addr)
12163       return it->second;
12164   }
12165
12166   // If not a direct hit, it'll have to be the previous symbol.
12167   if (it == symbol_locations_.begin())
12168     return NULL;
12169
12170   --it;
12171   size_t offs = addr - it->first;
12172   if (offs < it->second->size)
12173     return it->second;
12174
12175   return NULL;
12176 }
12177
12178
12179 int SetFunctionEntryHookTest::CountInvocations(
12180     const char* caller_name, const char* function_name) {
12181   InvocationMap::iterator it(invocations_.begin());
12182   int invocations = 0;
12183   for (; it != invocations_.end(); ++it) {
12184     SymbolInfo* caller = it->first.first;
12185     SymbolInfo* function = it->first.second;
12186
12187     // Filter out non-matching functions.
12188     if (function_name != NULL) {
12189       if (function->name.find(function_name) == std::string::npos)
12190         continue;
12191     }
12192
12193     // Filter out non-matching callers.
12194     if (caller_name != NULL) {
12195       if (caller == NULL)
12196         continue;
12197       if (caller->name.find(caller_name) == std::string::npos)
12198         continue;
12199     }
12200
12201     // It matches add the invocation count to the tally.
12202     invocations += it->second;
12203   }
12204
12205   return invocations;
12206 }
12207
12208
12209 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
12210   v8::HandleScope outer(isolate);
12211   v8::Local<Context> env = Context::New(isolate);
12212   env->Enter();
12213
12214   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
12215   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
12216   env->Global()->Set(v8_str("obj"), t->NewInstance());
12217
12218   const char* script =
12219       "function bar() {\n"
12220       "  var sum = 0;\n"
12221       "  for (i = 0; i < 100; ++i)\n"
12222       "    sum = foo(i);\n"
12223       "  return sum;\n"
12224       "}\n"
12225       "function foo(i) { return i * i; }\n"
12226       "// Invoke on the runtime function.\n"
12227       "obj.asdf()";
12228   CompileRun(script);
12229   bar_func_ = i::Handle<i::JSFunction>::cast(
12230           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
12231   DCHECK(!bar_func_.is_null());
12232
12233   foo_func_ =
12234       i::Handle<i::JSFunction>::cast(
12235            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
12236   DCHECK(!foo_func_.is_null());
12237
12238   v8::Handle<v8::Value> value = CompileRun("bar();");
12239   CHECK(value->IsNumber());
12240   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
12241
12242   // Test the optimized codegen path.
12243   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
12244                      "bar();");
12245   CHECK(value->IsNumber());
12246   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
12247
12248   env->Exit();
12249 }
12250
12251
12252 void SetFunctionEntryHookTest::RunTest() {
12253   // Work in a new isolate throughout.
12254   v8::Isolate::CreateParams create_params;
12255   create_params.entry_hook = EntryHook;
12256   create_params.code_event_handler = JitEvent;
12257   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12258   v8::Isolate* isolate = v8::Isolate::New(create_params);
12259
12260   {
12261     v8::Isolate::Scope scope(isolate);
12262
12263     RunLoopInNewEnv(isolate);
12264
12265     // Check the exepected invocation counts.
12266     CHECK_EQ(2, CountInvocations(NULL, "bar"));
12267     CHECK_EQ(200, CountInvocations("bar", "foo"));
12268     CHECK_EQ(200, CountInvocations(NULL, "foo"));
12269
12270     // Verify that we have an entry hook on some specific stubs.
12271     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
12272     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
12273     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
12274   }
12275   isolate->Dispose();
12276
12277   Reset();
12278
12279   // Make sure a second isolate is unaffected by the previous entry hook.
12280   create_params = v8::Isolate::CreateParams();
12281   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12282   isolate = v8::Isolate::New(create_params);
12283   {
12284     v8::Isolate::Scope scope(isolate);
12285
12286     // Reset the entry count to zero and set the entry hook.
12287     RunLoopInNewEnv(isolate);
12288
12289     // We should record no invocations in this isolate.
12290     CHECK_EQ(0, static_cast<int>(invocations_.size()));
12291   }
12292
12293   isolate->Dispose();
12294 }
12295
12296
12297 TEST(SetFunctionEntryHook) {
12298   // FunctionEntryHook does not work well with experimental natives.
12299   // Experimental natives are compiled during snapshot deserialization.
12300   // This test breaks because InstallGetter (function from snapshot that
12301   // only gets called from experimental natives) is compiled with entry hooks.
12302   i::FLAG_allow_natives_syntax = true;
12303   i::FLAG_use_inlining = false;
12304
12305   SetFunctionEntryHookTest test;
12306   test.RunTest();
12307 }
12308
12309
12310 static i::HashMap* code_map = NULL;
12311 static i::HashMap* jitcode_line_info = NULL;
12312 static int saw_bar = 0;
12313 static int move_events = 0;
12314
12315
12316 static bool FunctionNameIs(const char* expected,
12317                            const v8::JitCodeEvent* event) {
12318   // Log lines for functions are of the general form:
12319   // "LazyCompile:<type><function_name>", where the type is one of
12320   // "*", "~" or "".
12321   static const char kPreamble[] = "LazyCompile:";
12322   static size_t kPreambleLen = sizeof(kPreamble) - 1;
12323
12324   if (event->name.len < sizeof(kPreamble) - 1 ||
12325       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
12326     return false;
12327   }
12328
12329   const char* tail = event->name.str + kPreambleLen;
12330   size_t tail_len = event->name.len - kPreambleLen;
12331   size_t expected_len = strlen(expected);
12332   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
12333     --tail_len;
12334     ++tail;
12335   }
12336
12337   // Check for tails like 'bar :1'.
12338   if (tail_len > expected_len + 2 &&
12339       tail[expected_len] == ' ' &&
12340       tail[expected_len + 1] == ':' &&
12341       tail[expected_len + 2] &&
12342       !strncmp(tail, expected, expected_len)) {
12343     return true;
12344   }
12345
12346   if (tail_len != expected_len)
12347     return false;
12348
12349   return strncmp(tail, expected, expected_len) == 0;
12350 }
12351
12352
12353 static void event_handler(const v8::JitCodeEvent* event) {
12354   CHECK(event != NULL);
12355   CHECK(code_map != NULL);
12356   CHECK(jitcode_line_info != NULL);
12357
12358   class DummyJitCodeLineInfo {
12359   };
12360
12361   switch (event->type) {
12362     case v8::JitCodeEvent::CODE_ADDED: {
12363         CHECK(event->code_start != NULL);
12364         CHECK_NE(0, static_cast<int>(event->code_len));
12365         CHECK(event->name.str != NULL);
12366         i::HashMap::Entry* entry = code_map->LookupOrInsert(
12367             event->code_start, i::ComputePointerHash(event->code_start));
12368         entry->value = reinterpret_cast<void*>(event->code_len);
12369
12370         if (FunctionNameIs("bar", event)) {
12371           ++saw_bar;
12372         }
12373       }
12374       break;
12375
12376     case v8::JitCodeEvent::CODE_MOVED: {
12377         uint32_t hash = i::ComputePointerHash(event->code_start);
12378         // We would like to never see code move that we haven't seen before,
12379         // but the code creation event does not happen until the line endings
12380         // have been calculated (this is so that we can report the line in the
12381         // script at which the function source is found, see
12382         // Compiler::RecordFunctionCompilation) and the line endings
12383         // calculations can cause a GC, which can move the newly created code
12384         // before its existence can be logged.
12385         i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
12386         if (entry != NULL) {
12387           ++move_events;
12388
12389           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
12390           code_map->Remove(event->code_start, hash);
12391
12392           entry = code_map->LookupOrInsert(
12393               event->new_code_start,
12394               i::ComputePointerHash(event->new_code_start));
12395           entry->value = reinterpret_cast<void*>(event->code_len);
12396         }
12397       }
12398       break;
12399
12400     case v8::JitCodeEvent::CODE_REMOVED:
12401       // Object/code removal events are currently not dispatched from the GC.
12402       CHECK(false);
12403       break;
12404
12405     // For CODE_START_LINE_INFO_RECORDING event, we will create one
12406     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
12407     // record it in jitcode_line_info.
12408     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
12409         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
12410         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
12411         temp_event->user_data = line_info;
12412         i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
12413             line_info, i::ComputePointerHash(line_info));
12414         entry->value = reinterpret_cast<void*>(line_info);
12415       }
12416       break;
12417     // For these two events, we will check whether the event->user_data
12418     // data structure is created before during CODE_START_LINE_INFO_RECORDING
12419     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
12420     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
12421         CHECK(event->user_data != NULL);
12422         uint32_t hash = i::ComputePointerHash(event->user_data);
12423         i::HashMap::Entry* entry =
12424             jitcode_line_info->Lookup(event->user_data, hash);
12425         CHECK(entry != NULL);
12426         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
12427       }
12428       break;
12429
12430     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
12431         CHECK(event->user_data != NULL);
12432         uint32_t hash = i::ComputePointerHash(event->user_data);
12433         i::HashMap::Entry* entry =
12434             jitcode_line_info->Lookup(event->user_data, hash);
12435         CHECK(entry != NULL);
12436       }
12437       break;
12438
12439     default:
12440       // Impossible event.
12441       CHECK(false);
12442       break;
12443   }
12444 }
12445
12446
12447 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
12448   i::FLAG_stress_compaction = true;
12449   i::FLAG_incremental_marking = false;
12450   if (i::FLAG_never_compact) return;
12451   const char* script =
12452       "function bar() {"
12453       "  var sum = 0;"
12454       "  for (i = 0; i < 10; ++i)"
12455       "    sum = foo(i);"
12456       "  return sum;"
12457       "}"
12458       "function foo(i) { return i; };"
12459       "bar();";
12460
12461   // Run this test in a new isolate to make sure we don't
12462   // have remnants of state from other code.
12463   v8::Isolate::CreateParams create_params;
12464   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12465   v8::Isolate* isolate = v8::Isolate::New(create_params);
12466   isolate->Enter();
12467   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
12468   i::Heap* heap = i_isolate->heap();
12469
12470   // Start with a clean slate.
12471   heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
12472
12473   {
12474     v8::HandleScope scope(isolate);
12475     i::HashMap code(MatchPointers);
12476     code_map = &code;
12477
12478     i::HashMap lineinfo(MatchPointers);
12479     jitcode_line_info = &lineinfo;
12480
12481     saw_bar = 0;
12482     move_events = 0;
12483
12484     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
12485
12486     // Generate new code objects sparsely distributed across several
12487     // different fragmented code-space pages.
12488     const int kIterations = 10;
12489     for (int i = 0; i < kIterations; ++i) {
12490       LocalContext env(isolate);
12491       i::AlwaysAllocateScope always_allocate(i_isolate);
12492       SimulateFullSpace(heap->code_space());
12493       CompileRun(script);
12494
12495       // Keep a strong reference to the code object in the handle scope.
12496       i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
12497           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
12498       i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
12499           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
12500
12501       // Clear the compilation cache to get more wastage.
12502       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
12503     }
12504
12505     // Force code movement.
12506     heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
12507
12508     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
12509
12510     CHECK_LE(kIterations, saw_bar);
12511     CHECK_LT(0, move_events);
12512
12513     code_map = NULL;
12514     jitcode_line_info = NULL;
12515   }
12516
12517   isolate->Exit();
12518   isolate->Dispose();
12519
12520   // Do this in a new isolate.
12521   isolate = v8::Isolate::New(create_params);
12522   isolate->Enter();
12523
12524   // Verify that we get callbacks for existing code objects when we
12525   // request enumeration of existing code.
12526   {
12527     v8::HandleScope scope(isolate);
12528     LocalContext env(isolate);
12529     CompileRun(script);
12530
12531     // Now get code through initial iteration.
12532     i::HashMap code(MatchPointers);
12533     code_map = &code;
12534
12535     i::HashMap lineinfo(MatchPointers);
12536     jitcode_line_info = &lineinfo;
12537
12538     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
12539                                     event_handler);
12540     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
12541
12542     jitcode_line_info = NULL;
12543     // We expect that we got some events. Note that if we could get code removal
12544     // notifications, we could compare two collections, one created by listening
12545     // from the time of creation of an isolate, and the other by subscribing
12546     // with EnumExisting.
12547     CHECK_LT(0u, code.occupancy());
12548
12549     code_map = NULL;
12550   }
12551
12552   isolate->Exit();
12553   isolate->Dispose();
12554 }
12555
12556
12557 THREADED_TEST(ExternalAllocatedMemory) {
12558   v8::Isolate* isolate = CcTest::isolate();
12559   v8::HandleScope outer(isolate);
12560   v8::Local<Context> env(Context::New(isolate));
12561   CHECK(!env.IsEmpty());
12562   const int64_t kSize = 1024*1024;
12563   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
12564   CHECK_EQ(baseline + kSize,
12565            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
12566   CHECK_EQ(baseline,
12567            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
12568   const int64_t kTriggerGCSize =
12569       v8::internal::Internals::kExternalAllocationLimit + 1;
12570   CHECK_EQ(baseline + kTriggerGCSize,
12571            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
12572   CHECK_EQ(baseline,
12573            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
12574 }
12575
12576
12577 TEST(Regress51719) {
12578   i::FLAG_incremental_marking = false;
12579   CcTest::InitializeVM();
12580
12581   const int64_t kTriggerGCSize =
12582       v8::internal::Internals::kExternalAllocationLimit + 1;
12583   v8::Isolate* isolate = CcTest::isolate();
12584   isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
12585 }
12586
12587
12588 // Regression test for issue 54, object templates with internal fields
12589 // but no accessors or interceptors did not get their internal field
12590 // count set on instances.
12591 THREADED_TEST(Regress54) {
12592   LocalContext context;
12593   v8::Isolate* isolate = context->GetIsolate();
12594   v8::HandleScope outer(isolate);
12595   static v8::Persistent<v8::ObjectTemplate> templ;
12596   if (templ.IsEmpty()) {
12597     v8::EscapableHandleScope inner(isolate);
12598     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
12599     local->SetInternalFieldCount(1);
12600     templ.Reset(isolate, inner.Escape(local));
12601   }
12602   v8::Handle<v8::Object> result =
12603       v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
12604   CHECK_EQ(1, result->InternalFieldCount());
12605 }
12606
12607
12608 // If part of the threaded tests, this test makes ThreadingTest fail
12609 // on mac.
12610 TEST(CatchStackOverflow) {
12611   LocalContext context;
12612   v8::HandleScope scope(context->GetIsolate());
12613   v8::TryCatch try_catch(context->GetIsolate());
12614   v8::Handle<v8::Value> result = CompileRun(
12615     "function f() {"
12616     "  return f();"
12617     "}"
12618     ""
12619     "f();");
12620   CHECK(result.IsEmpty());
12621 }
12622
12623
12624 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
12625                                     const char* resource_name,
12626                                     int line_offset) {
12627   v8::HandleScope scope(CcTest::isolate());
12628   v8::TryCatch try_catch(CcTest::isolate());
12629   v8::Handle<v8::Value> result = script->Run();
12630   CHECK(result.IsEmpty());
12631   CHECK(try_catch.HasCaught());
12632   v8::Handle<v8::Message> message = try_catch.Message();
12633   CHECK(!message.IsEmpty());
12634   CHECK_EQ(10 + line_offset, message->GetLineNumber());
12635   CHECK_EQ(91, message->GetStartPosition());
12636   CHECK_EQ(92, message->GetEndPosition());
12637   CHECK_EQ(2, message->GetStartColumn());
12638   CHECK_EQ(3, message->GetEndColumn());
12639   v8::String::Utf8Value line(message->GetSourceLine());
12640   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
12641   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
12642   CHECK_EQ(0, strcmp(resource_name, *name));
12643 }
12644
12645
12646 THREADED_TEST(TryCatchSourceInfo) {
12647   LocalContext context;
12648   v8::HandleScope scope(context->GetIsolate());
12649   v8::Local<v8::String> source = v8_str(
12650       "function Foo() {\n"
12651       "  return Bar();\n"
12652       "}\n"
12653       "\n"
12654       "function Bar() {\n"
12655       "  return Baz();\n"
12656       "}\n"
12657       "\n"
12658       "function Baz() {\n"
12659       "  throw 'nirk';\n"
12660       "}\n"
12661       "\n"
12662       "Foo();\n");
12663
12664   const char* resource_name;
12665   v8::Handle<v8::Script> script;
12666   resource_name = "test.js";
12667   script = CompileWithOrigin(source, resource_name);
12668   CheckTryCatchSourceInfo(script, resource_name, 0);
12669
12670   resource_name = "test1.js";
12671   v8::ScriptOrigin origin1(
12672       v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
12673   script = v8::Script::Compile(source, &origin1);
12674   CheckTryCatchSourceInfo(script, resource_name, 0);
12675
12676   resource_name = "test2.js";
12677   v8::ScriptOrigin origin2(
12678       v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
12679       v8::Integer::New(context->GetIsolate(), 7));
12680   script = v8::Script::Compile(source, &origin2);
12681   CheckTryCatchSourceInfo(script, resource_name, 7);
12682 }
12683
12684
12685 THREADED_TEST(TryCatchSourceInfoForEOSError) {
12686   LocalContext context;
12687   v8::HandleScope scope(context->GetIsolate());
12688   v8::TryCatch try_catch(context->GetIsolate());
12689   v8::Script::Compile(v8_str("!\n"));
12690   CHECK(try_catch.HasCaught());
12691   v8::Handle<v8::Message> message = try_catch.Message();
12692   CHECK_EQ(1, message->GetLineNumber());
12693   CHECK_EQ(0, message->GetStartColumn());
12694 }
12695
12696
12697 THREADED_TEST(CompilationCache) {
12698   LocalContext context;
12699   v8::HandleScope scope(context->GetIsolate());
12700   v8::Handle<v8::String> source0 =
12701       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
12702   v8::Handle<v8::String> source1 =
12703       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
12704   v8::Handle<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
12705   v8::Handle<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
12706   v8::Handle<v8::Script> script2 =
12707       v8::Script::Compile(source0);  // different origin
12708   CHECK_EQ(1234, script0->Run()->Int32Value());
12709   CHECK_EQ(1234, script1->Run()->Int32Value());
12710   CHECK_EQ(1234, script2->Run()->Int32Value());
12711 }
12712
12713
12714 static void FunctionNameCallback(
12715     const v8::FunctionCallbackInfo<v8::Value>& args) {
12716   ApiTestFuzzer::Fuzz();
12717   args.GetReturnValue().Set(v8_num(42));
12718 }
12719
12720
12721 THREADED_TEST(CallbackFunctionName) {
12722   LocalContext context;
12723   v8::Isolate* isolate = context->GetIsolate();
12724   v8::HandleScope scope(isolate);
12725   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
12726   t->Set(v8_str("asdf"),
12727          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
12728   context->Global()->Set(v8_str("obj"), t->NewInstance());
12729   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
12730   CHECK(value->IsString());
12731   v8::String::Utf8Value name(value);
12732   CHECK_EQ(0, strcmp("asdf", *name));
12733 }
12734
12735
12736 THREADED_TEST(DateAccess) {
12737   LocalContext context;
12738   v8::HandleScope scope(context->GetIsolate());
12739   v8::Handle<v8::Value> date =
12740       v8::Date::New(context->GetIsolate(), 1224744689038.0);
12741   CHECK(date->IsDate());
12742   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
12743 }
12744
12745
12746 void CheckProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
12747                      unsigned elmc, const char* elmv[]) {
12748   v8::Handle<v8::Object> obj = val.As<v8::Object>();
12749   v8::Handle<v8::Array> props = obj->GetPropertyNames();
12750   CHECK_EQ(elmc, props->Length());
12751   for (unsigned i = 0; i < elmc; i++) {
12752     v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
12753     CHECK_EQ(0, strcmp(elmv[i], *elm));
12754   }
12755 }
12756
12757
12758 void CheckOwnProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
12759                         unsigned elmc, const char* elmv[]) {
12760   v8::Handle<v8::Object> obj = val.As<v8::Object>();
12761   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
12762   CHECK_EQ(elmc, props->Length());
12763   for (unsigned i = 0; i < elmc; i++) {
12764     v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
12765     CHECK_EQ(0, strcmp(elmv[i], *elm));
12766   }
12767 }
12768
12769
12770 THREADED_TEST(PropertyEnumeration) {
12771   LocalContext context;
12772   v8::Isolate* isolate = context->GetIsolate();
12773   v8::HandleScope scope(isolate);
12774   v8::Handle<v8::Value> obj = CompileRun(
12775       "var result = [];"
12776       "result[0] = {};"
12777       "result[1] = {a: 1, b: 2};"
12778       "result[2] = [1, 2, 3];"
12779       "var proto = {x: 1, y: 2, z: 3};"
12780       "var x = { __proto__: proto, w: 0, z: 1 };"
12781       "result[3] = x;"
12782       "result;");
12783   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12784   CHECK_EQ(4u, elms->Length());
12785   int elmc0 = 0;
12786   const char** elmv0 = NULL;
12787   CheckProperties(
12788       isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12789   CheckOwnProperties(
12790       isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12791   int elmc1 = 2;
12792   const char* elmv1[] = {"a", "b"};
12793   CheckProperties(
12794       isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
12795   CheckOwnProperties(
12796       isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
12797   int elmc2 = 3;
12798   const char* elmv2[] = {"0", "1", "2"};
12799   CheckProperties(
12800       isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
12801   CheckOwnProperties(
12802       isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
12803   int elmc3 = 4;
12804   const char* elmv3[] = {"w", "z", "x", "y"};
12805   CheckProperties(
12806       isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
12807   int elmc4 = 2;
12808   const char* elmv4[] = {"w", "z"};
12809   CheckOwnProperties(
12810       isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
12811 }
12812
12813
12814 THREADED_TEST(PropertyEnumeration2) {
12815   LocalContext context;
12816   v8::Isolate* isolate = context->GetIsolate();
12817   v8::HandleScope scope(isolate);
12818   v8::Handle<v8::Value> obj = CompileRun(
12819       "var result = [];"
12820       "result[0] = {};"
12821       "result[1] = {a: 1, b: 2};"
12822       "result[2] = [1, 2, 3];"
12823       "var proto = {x: 1, y: 2, z: 3};"
12824       "var x = { __proto__: proto, w: 0, z: 1 };"
12825       "result[3] = x;"
12826       "result;");
12827   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12828   CHECK_EQ(4u, elms->Length());
12829   int elmc0 = 0;
12830   const char** elmv0 = NULL;
12831   CheckProperties(isolate,
12832                   elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12833
12834   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
12835   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
12836   CHECK_EQ(0u, props->Length());
12837   for (uint32_t i = 0; i < props->Length(); i++) {
12838     printf("p[%u]\n", i);
12839   }
12840 }
12841
12842
12843 THREADED_TEST(AccessChecksReenabledCorrectly) {
12844   LocalContext context;
12845   v8::Isolate* isolate = context->GetIsolate();
12846   v8::HandleScope scope(isolate);
12847   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
12848   templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
12849   templ->Set(v8_str("a"), v8_str("a"));
12850   // Add more than 8 (see kMaxFastProperties) properties
12851   // so that the constructor will force copying map.
12852   // Cannot sprintf, gcc complains unsafety.
12853   char buf[4];
12854   for (char i = '0'; i <= '9' ; i++) {
12855     buf[0] = i;
12856     for (char j = '0'; j <= '9'; j++) {
12857       buf[1] = j;
12858       for (char k = '0'; k <= '9'; k++) {
12859         buf[2] = k;
12860         buf[3] = 0;
12861         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
12862       }
12863     }
12864   }
12865
12866   Local<v8::Object> instance_1 = templ->NewInstance();
12867   context->Global()->Set(v8_str("obj_1"), instance_1);
12868
12869   Local<Value> value_1 = CompileRun("obj_1.a");
12870   CHECK(value_1.IsEmpty());
12871
12872   Local<v8::Object> instance_2 = templ->NewInstance();
12873   context->Global()->Set(v8_str("obj_2"), instance_2);
12874
12875   Local<Value> value_2 = CompileRun("obj_2.a");
12876   CHECK(value_2.IsEmpty());
12877 }
12878
12879
12880 // Tests that ScriptData can be serialized and deserialized.
12881 TEST(PreCompileSerialization) {
12882   v8::V8::Initialize();
12883   LocalContext env;
12884   v8::Isolate* isolate = env->GetIsolate();
12885   HandleScope handle_scope(isolate);
12886
12887   i::FLAG_min_preparse_length = 0;
12888   const char* script = "function foo(a) { return a+1; }";
12889   v8::ScriptCompiler::Source source(v8_str(script));
12890   v8::ScriptCompiler::Compile(isolate, &source,
12891                               v8::ScriptCompiler::kProduceParserCache);
12892   // Serialize.
12893   const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
12894   i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
12895   i::MemCopy(serialized_data, cd->data, cd->length);
12896
12897   // Deserialize.
12898   i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
12899
12900   // Verify that the original is the same as the deserialized.
12901   CHECK_EQ(cd->length, deserialized->length());
12902   CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
12903
12904   delete deserialized;
12905   i::DeleteArray(serialized_data);
12906 }
12907
12908
12909 // This tests that we do not allow dictionary load/call inline caches
12910 // to use functions that have not yet been compiled.  The potential
12911 // problem of loading a function that has not yet been compiled can
12912 // arise because we share code between contexts via the compilation
12913 // cache.
12914 THREADED_TEST(DictionaryICLoadedFunction) {
12915   v8::HandleScope scope(CcTest::isolate());
12916   // Test LoadIC.
12917   for (int i = 0; i < 2; i++) {
12918     LocalContext context;
12919     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
12920     context->Global()->Delete(v8_str("tmp"));
12921     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
12922   }
12923   // Test CallIC.
12924   for (int i = 0; i < 2; i++) {
12925     LocalContext context;
12926     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
12927     context->Global()->Delete(v8_str("tmp"));
12928     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
12929   }
12930 }
12931
12932
12933 // Test that cross-context new calls use the context of the callee to
12934 // create the new JavaScript object.
12935 THREADED_TEST(CrossContextNew) {
12936   v8::Isolate* isolate = CcTest::isolate();
12937   v8::HandleScope scope(isolate);
12938   v8::Local<Context> context0 = Context::New(isolate);
12939   v8::Local<Context> context1 = Context::New(isolate);
12940
12941   // Allow cross-domain access.
12942   Local<String> token = v8_str("<security token>");
12943   context0->SetSecurityToken(token);
12944   context1->SetSecurityToken(token);
12945
12946   // Set an 'x' property on the Object prototype and define a
12947   // constructor function in context0.
12948   context0->Enter();
12949   CompileRun("Object.prototype.x = 42; function C() {};");
12950   context0->Exit();
12951
12952   // Call the constructor function from context0 and check that the
12953   // result has the 'x' property.
12954   context1->Enter();
12955   context1->Global()->Set(v8_str("other"), context0->Global());
12956   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
12957   CHECK(value->IsInt32());
12958   CHECK_EQ(42, value->Int32Value());
12959   context1->Exit();
12960 }
12961
12962
12963 // Verify that we can clone an object
12964 TEST(ObjectClone) {
12965   LocalContext env;
12966   v8::Isolate* isolate = env->GetIsolate();
12967   v8::HandleScope scope(isolate);
12968
12969   const char* sample =
12970     "var rv = {};"      \
12971     "rv.alpha = 'hello';" \
12972     "rv.beta = 123;"     \
12973     "rv;";
12974
12975   // Create an object, verify basics.
12976   Local<Value> val = CompileRun(sample);
12977   CHECK(val->IsObject());
12978   Local<v8::Object> obj = val.As<v8::Object>();
12979   obj->Set(v8_str("gamma"), v8_str("cloneme"));
12980
12981   CHECK(v8_str("hello")->Equals(obj->Get(v8_str("alpha"))));
12982   CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
12983   CHECK(v8_str("cloneme")->Equals(obj->Get(v8_str("gamma"))));
12984
12985   // Clone it.
12986   Local<v8::Object> clone = obj->Clone();
12987   CHECK(v8_str("hello")->Equals(clone->Get(v8_str("alpha"))));
12988   CHECK(v8::Integer::New(isolate, 123)->Equals(clone->Get(v8_str("beta"))));
12989   CHECK(v8_str("cloneme")->Equals(clone->Get(v8_str("gamma"))));
12990
12991   // Set a property on the clone, verify each object.
12992   clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
12993   CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
12994   CHECK(v8::Integer::New(isolate, 456)->Equals(clone->Get(v8_str("beta"))));
12995 }
12996
12997
12998 class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
12999  public:
13000   explicit OneByteVectorResource(i::Vector<const char> vector)
13001       : data_(vector) {}
13002   virtual ~OneByteVectorResource() {}
13003   virtual size_t length() const { return data_.length(); }
13004   virtual const char* data() const { return data_.start(); }
13005  private:
13006   i::Vector<const char> data_;
13007 };
13008
13009
13010 class UC16VectorResource : public v8::String::ExternalStringResource {
13011  public:
13012   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
13013       : data_(vector) {}
13014   virtual ~UC16VectorResource() {}
13015   virtual size_t length() const { return data_.length(); }
13016   virtual const i::uc16* data() const { return data_.start(); }
13017  private:
13018   i::Vector<const i::uc16> data_;
13019 };
13020
13021
13022 static void MorphAString(i::String* string,
13023                          OneByteVectorResource* one_byte_resource,
13024                          UC16VectorResource* uc16_resource) {
13025   CHECK(i::StringShape(string).IsExternal());
13026   if (string->IsOneByteRepresentation()) {
13027     // Check old map is not internalized or long.
13028     CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
13029     // Morph external string to be TwoByte string.
13030     string->set_map(CcTest::heap()->external_string_map());
13031     i::ExternalTwoByteString* morphed =
13032          i::ExternalTwoByteString::cast(string);
13033     morphed->set_resource(uc16_resource);
13034   } else {
13035     // Check old map is not internalized or long.
13036     CHECK(string->map() == CcTest::heap()->external_string_map());
13037     // Morph external string to be one-byte string.
13038     string->set_map(CcTest::heap()->external_one_byte_string_map());
13039     i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
13040     morphed->set_resource(one_byte_resource);
13041   }
13042 }
13043
13044
13045 // Test that we can still flatten a string if the components it is built up
13046 // from have been turned into 16 bit strings in the mean time.
13047 THREADED_TEST(MorphCompositeStringTest) {
13048   char utf_buffer[129];
13049   const char* c_string = "Now is the time for all good men"
13050                          " to come to the aid of the party";
13051   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
13052   {
13053     LocalContext env;
13054     i::Factory* factory = CcTest::i_isolate()->factory();
13055     v8::HandleScope scope(env->GetIsolate());
13056     OneByteVectorResource one_byte_resource(
13057         i::Vector<const char>(c_string, i::StrLength(c_string)));
13058     UC16VectorResource uc16_resource(
13059         i::Vector<const uint16_t>(two_byte_string,
13060                                   i::StrLength(c_string)));
13061
13062     Local<String> lhs(
13063         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
13064                                         &one_byte_resource).ToHandleChecked()));
13065     Local<String> rhs(
13066         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
13067                                         &one_byte_resource).ToHandleChecked()));
13068
13069     env->Global()->Set(v8_str("lhs"), lhs);
13070     env->Global()->Set(v8_str("rhs"), rhs);
13071
13072     CompileRun(
13073         "var cons = lhs + rhs;"
13074         "var slice = lhs.substring(1, lhs.length - 1);"
13075         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
13076
13077     CHECK(lhs->IsOneByte());
13078     CHECK(rhs->IsOneByte());
13079
13080     MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
13081                  &uc16_resource);
13082     MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
13083                  &uc16_resource);
13084
13085     // This should UTF-8 without flattening, since everything is ASCII.
13086     Handle<String> cons = v8_compile("cons")->Run().As<String>();
13087     CHECK_EQ(128, cons->Utf8Length());
13088     int nchars = -1;
13089     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
13090     CHECK_EQ(128, nchars);
13091     CHECK_EQ(0, strcmp(
13092         utf_buffer,
13093         "Now is the time for all good men to come to the aid of the party"
13094         "Now is the time for all good men to come to the aid of the party"));
13095
13096     // Now do some stuff to make sure the strings are flattened, etc.
13097     CompileRun(
13098         "/[^a-z]/.test(cons);"
13099         "/[^a-z]/.test(slice);"
13100         "/[^a-z]/.test(slice_on_cons);");
13101     const char* expected_cons =
13102         "Now is the time for all good men to come to the aid of the party"
13103         "Now is the time for all good men to come to the aid of the party";
13104     const char* expected_slice =
13105         "ow is the time for all good men to come to the aid of the part";
13106     const char* expected_slice_on_cons =
13107         "ow is the time for all good men to come to the aid of the party"
13108         "Now is the time for all good men to come to the aid of the part";
13109     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_cons)
13110               ->Equals(env->Global()->Get(v8_str("cons"))));
13111     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice)
13112               ->Equals(env->Global()->Get(v8_str("slice"))));
13113     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons)
13114               ->Equals(env->Global()->Get(v8_str("slice_on_cons"))));
13115   }
13116   i::DeleteArray(two_byte_string);
13117 }
13118
13119
13120 TEST(CompileExternalTwoByteSource) {
13121   LocalContext context;
13122   v8::HandleScope scope(context->GetIsolate());
13123
13124   // This is a very short list of sources, which currently is to check for a
13125   // regression caused by r2703.
13126   const char* one_byte_sources[] = {
13127       "0.5",
13128       "-0.5",   // This mainly testes PushBack in the Scanner.
13129       "--0.5",  // This mainly testes PushBack in the Scanner.
13130       NULL};
13131
13132   // Compile the sources as external two byte strings.
13133   for (int i = 0; one_byte_sources[i] != NULL; i++) {
13134     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
13135     TestResource* uc16_resource = new TestResource(two_byte_string);
13136     v8::Local<v8::String> source =
13137         v8::String::NewExternal(context->GetIsolate(), uc16_resource);
13138     v8::Script::Compile(source);
13139   }
13140 }
13141
13142
13143 #ifndef V8_INTERPRETED_REGEXP
13144
13145 struct RegExpInterruptionData {
13146   v8::base::Atomic32 loop_count;
13147   UC16VectorResource* string_resource;
13148   v8::Persistent<v8::String> string;
13149 } regexp_interruption_data;
13150
13151
13152 class RegExpInterruptionThread : public v8::base::Thread {
13153  public:
13154   explicit RegExpInterruptionThread(v8::Isolate* isolate)
13155       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
13156
13157   virtual void Run() {
13158     for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
13159          v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
13160          v8::base::NoBarrier_AtomicIncrement(
13161              &regexp_interruption_data.loop_count, 1)) {
13162       // Wait a bit before requesting GC.
13163       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
13164       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
13165     }
13166     // Wait a bit before terminating.
13167     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
13168     v8::V8::TerminateExecution(isolate_);
13169   }
13170
13171  private:
13172   v8::Isolate* isolate_;
13173 };
13174
13175
13176 void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
13177   if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
13178     return;
13179   }
13180   v8::HandleScope scope(CcTest::isolate());
13181   v8::Local<v8::String> string = v8::Local<v8::String>::New(
13182       CcTest::isolate(), regexp_interruption_data.string);
13183   string->MakeExternal(regexp_interruption_data.string_resource);
13184 }
13185
13186
13187 // Test that RegExp execution can be interrupted.  Specifically, we test
13188 // * interrupting with GC
13189 // * turn the subject string from one-byte internal to two-byte external string
13190 // * force termination
13191 TEST(RegExpInterruption) {
13192   v8::HandleScope scope(CcTest::isolate());
13193   LocalContext env;
13194
13195   RegExpInterruptionThread timeout_thread(CcTest::isolate());
13196
13197   v8::V8::AddGCPrologueCallback(RunBeforeGC);
13198   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
13199   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
13200   v8::Local<v8::String> string = v8_str(one_byte_content);
13201
13202   CcTest::global()->Set(v8_str("a"), string);
13203   regexp_interruption_data.string.Reset(CcTest::isolate(), string);
13204   regexp_interruption_data.string_resource = new UC16VectorResource(
13205       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
13206
13207   v8::TryCatch try_catch(CcTest::isolate());
13208   timeout_thread.Start();
13209
13210   CompileRun("/((a*)*)*b/.exec(a)");
13211   CHECK(try_catch.HasTerminated());
13212
13213   timeout_thread.Join();
13214
13215   regexp_interruption_data.string.Reset();
13216   i::DeleteArray(uc16_content);
13217 }
13218
13219 #endif  // V8_INTERPRETED_REGEXP
13220
13221
13222 // Test that we cannot set a property on the global object if there
13223 // is a read-only property in the prototype chain.
13224 TEST(ReadOnlyPropertyInGlobalProto) {
13225   v8::Isolate* isolate = CcTest::isolate();
13226   v8::HandleScope scope(isolate);
13227   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13228   LocalContext context(0, templ);
13229   v8::Handle<v8::Object> global = context->Global();
13230   v8::Handle<v8::Object> global_proto =
13231       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
13232   global_proto->ForceSet(v8_str("x"), v8::Integer::New(isolate, 0),
13233                          v8::ReadOnly);
13234   global_proto->ForceSet(v8_str("y"), v8::Integer::New(isolate, 0),
13235                          v8::ReadOnly);
13236   // Check without 'eval' or 'with'.
13237   v8::Handle<v8::Value> res =
13238       CompileRun("function f() { x = 42; return x; }; f()");
13239   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13240   // Check with 'eval'.
13241   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
13242   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13243   // Check with 'with'.
13244   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
13245   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13246 }
13247
13248 static int force_set_set_count = 0;
13249 static int force_set_get_count = 0;
13250 bool pass_on_get = false;
13251
13252 static void ForceSetGetter(v8::Local<v8::String> name,
13253                            const v8::PropertyCallbackInfo<v8::Value>& info) {
13254   force_set_get_count++;
13255   if (pass_on_get) {
13256     return;
13257   }
13258   info.GetReturnValue().Set(3);
13259 }
13260
13261 static void ForceSetSetter(v8::Local<v8::String> name,
13262                            v8::Local<v8::Value> value,
13263                            const v8::PropertyCallbackInfo<void>& info) {
13264   force_set_set_count++;
13265 }
13266
13267 static void ForceSetInterceptGetter(
13268     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
13269   CHECK(name->IsString());
13270   ForceSetGetter(Local<String>::Cast(name), info);
13271 }
13272
13273 static void ForceSetInterceptSetter(
13274     v8::Local<v8::Name> name, v8::Local<v8::Value> value,
13275     const v8::PropertyCallbackInfo<v8::Value>& info) {
13276   force_set_set_count++;
13277   info.GetReturnValue().SetUndefined();
13278 }
13279
13280
13281 TEST(ForceSet) {
13282   force_set_get_count = 0;
13283   force_set_set_count = 0;
13284   pass_on_get = false;
13285
13286   v8::Isolate* isolate = CcTest::isolate();
13287   v8::HandleScope scope(isolate);
13288   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13289   v8::Handle<v8::String> access_property =
13290       v8::String::NewFromUtf8(isolate, "a");
13291   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
13292   LocalContext context(NULL, templ);
13293   v8::Handle<v8::Object> global = context->Global();
13294
13295   // Ordinary properties
13296   v8::Handle<v8::String> simple_property =
13297       v8::String::NewFromUtf8(isolate, "p");
13298   global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
13299   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13300   // This should fail because the property is read-only
13301   global->Set(simple_property, v8::Int32::New(isolate, 5));
13302   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13303   // This should succeed even though the property is read-only
13304   global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
13305   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
13306
13307   // Accessors
13308   CHECK_EQ(0, force_set_set_count);
13309   CHECK_EQ(0, force_set_get_count);
13310   CHECK_EQ(3, global->Get(access_property)->Int32Value());
13311   // CHECK_EQ the property shouldn't override it, just call the setter
13312   // which in this case does nothing.
13313   global->Set(access_property, v8::Int32::New(isolate, 7));
13314   CHECK_EQ(3, global->Get(access_property)->Int32Value());
13315   CHECK_EQ(1, force_set_set_count);
13316   CHECK_EQ(2, force_set_get_count);
13317   // ForceSet doesn't call the accessors for now.
13318   // TODO(verwaest): Update once blink doesn't rely on ForceSet to delete api
13319   // accessors.
13320   global->ForceSet(access_property, v8::Int32::New(isolate, 8));
13321   CHECK_EQ(8, global->Get(access_property)->Int32Value());
13322   CHECK_EQ(1, force_set_set_count);
13323   CHECK_EQ(2, force_set_get_count);
13324 }
13325
13326
13327 TEST(ForceSetWithInterceptor) {
13328   v8::Isolate* isolate = CcTest::isolate();
13329   v8::HandleScope scope(isolate);
13330   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13331   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
13332       ForceSetInterceptGetter, ForceSetInterceptSetter));
13333   pass_on_get = true;
13334   LocalContext context(NULL, templ);
13335   v8::Handle<v8::Object> global = context->Global();
13336
13337   force_set_get_count = 0;
13338   force_set_set_count = 0;
13339   pass_on_get = false;
13340
13341   v8::Handle<v8::String> some_property =
13342       v8::String::NewFromUtf8(isolate, "a");
13343   CHECK_EQ(0, force_set_set_count);
13344   CHECK_EQ(0, force_set_get_count);
13345   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13346   // Setting the property shouldn't override it, just call the setter
13347   // which in this case does nothing.
13348   global->Set(some_property, v8::Int32::New(isolate, 7));
13349   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13350   CHECK_EQ(1, force_set_set_count);
13351   CHECK_EQ(2, force_set_get_count);
13352   // Getting the property when the interceptor returns an empty handle
13353   // should yield undefined, since the property isn't present on the
13354   // object itself yet.
13355   pass_on_get = true;
13356   CHECK(global->Get(some_property)->IsUndefined());
13357   CHECK_EQ(1, force_set_set_count);
13358   CHECK_EQ(3, force_set_get_count);
13359   // Forcing the property to be set should cause the value to be
13360   // set locally without calling the interceptor.
13361   global->ForceSet(some_property, v8::Int32::New(isolate, 8));
13362   CHECK_EQ(8, global->Get(some_property)->Int32Value());
13363   CHECK_EQ(1, force_set_set_count);
13364   CHECK_EQ(4, force_set_get_count);
13365   // Reenabling the interceptor should cause it to take precedence over
13366   // the property
13367   pass_on_get = false;
13368   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13369   CHECK_EQ(1, force_set_set_count);
13370   CHECK_EQ(5, force_set_get_count);
13371   // The interceptor should also work for other properties
13372   CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
13373                   ->Int32Value());
13374   CHECK_EQ(1, force_set_set_count);
13375   CHECK_EQ(6, force_set_get_count);
13376 }
13377
13378
13379 TEST(CreateDataProperty) {
13380   LocalContext env;
13381   v8::Isolate* isolate = env->GetIsolate();
13382   v8::HandleScope handle_scope(isolate);
13383
13384   CompileRun(
13385       "var a = {};"
13386       "var b = [];"
13387       "Object.defineProperty(a, 'foo', {value: 23});"
13388       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
13389
13390   v8::Local<v8::Object> obj =
13391       v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
13392   v8::Local<v8::Array> arr =
13393       v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
13394   {
13395     // Can't change a non-configurable properties.
13396     v8::TryCatch try_catch(isolate);
13397     CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
13398                                    v8::Integer::New(isolate, 42)).FromJust());
13399     CHECK(!try_catch.HasCaught());
13400     CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
13401                                   v8::Integer::New(isolate, 42)).FromJust());
13402     CHECK(!try_catch.HasCaught());
13403     v8::Local<v8::Value> val =
13404         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
13405     CHECK(val->IsNumber());
13406     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13407   }
13408
13409   {
13410     // Set a regular property.
13411     v8::TryCatch try_catch(isolate);
13412     CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
13413                                   v8::Integer::New(isolate, 42)).FromJust());
13414     CHECK(!try_catch.HasCaught());
13415     v8::Local<v8::Value> val =
13416         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
13417     CHECK(val->IsNumber());
13418     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13419   }
13420
13421   {
13422     // Set an indexed property.
13423     v8::TryCatch try_catch(isolate);
13424     CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
13425                                   v8::Integer::New(isolate, 42)).FromJust());
13426     CHECK(!try_catch.HasCaught());
13427     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
13428     CHECK(val->IsNumber());
13429     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13430   }
13431
13432   {
13433     // Special cases for arrays.
13434     v8::TryCatch try_catch(isolate);
13435     CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
13436                                    v8::Integer::New(isolate, 1)).FromJust());
13437     CHECK(!try_catch.HasCaught());
13438   }
13439   {
13440     // Special cases for arrays: index exceeds the array's length
13441     v8::TryCatch try_catch(isolate);
13442     CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
13443               .FromJust());
13444     CHECK(!try_catch.HasCaught());
13445     CHECK_EQ(2U, arr->Length());
13446     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
13447     CHECK(val->IsNumber());
13448     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
13449
13450     // Set an existing entry.
13451     CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
13452               .FromJust());
13453     CHECK(!try_catch.HasCaught());
13454     val = arr->Get(env.local(), 0).ToLocalChecked();
13455     CHECK(val->IsNumber());
13456     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13457   }
13458
13459   CompileRun("Object.freeze(a);");
13460   {
13461     // Can't change non-extensible objects.
13462     v8::TryCatch try_catch(isolate);
13463     CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
13464                                    v8::Integer::New(isolate, 42)).FromJust());
13465     CHECK(!try_catch.HasCaught());
13466   }
13467
13468   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13469   templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
13470   v8::Local<v8::Object> access_checked =
13471       templ->NewInstance(env.local()).ToLocalChecked();
13472   {
13473     v8::TryCatch try_catch(isolate);
13474     CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
13475                                              v8::Integer::New(isolate, 42))
13476               .IsNothing());
13477     CHECK(try_catch.HasCaught());
13478   }
13479 }
13480
13481
13482 TEST(DefineOwnProperty) {
13483   LocalContext env;
13484   v8::Isolate* isolate = env->GetIsolate();
13485   v8::HandleScope handle_scope(isolate);
13486
13487   CompileRun(
13488       "var a = {};"
13489       "var b = [];"
13490       "Object.defineProperty(a, 'foo', {value: 23});"
13491       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
13492
13493   v8::Local<v8::Object> obj =
13494       v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
13495   v8::Local<v8::Array> arr =
13496       v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
13497   {
13498     // Can't change a non-configurable properties.
13499     v8::TryCatch try_catch(isolate);
13500     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
13501                                   v8::Integer::New(isolate, 42)).FromJust());
13502     CHECK(!try_catch.HasCaught());
13503     CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
13504                                  v8::Integer::New(isolate, 42)).FromJust());
13505     CHECK(!try_catch.HasCaught());
13506     v8::Local<v8::Value> val =
13507         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
13508     CHECK(val->IsNumber());
13509     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13510   }
13511
13512   {
13513     // Set a regular property.
13514     v8::TryCatch try_catch(isolate);
13515     CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
13516                                  v8::Integer::New(isolate, 42)).FromJust());
13517     CHECK(!try_catch.HasCaught());
13518     v8::Local<v8::Value> val =
13519         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
13520     CHECK(val->IsNumber());
13521     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13522   }
13523
13524   {
13525     // Set an indexed property.
13526     v8::TryCatch try_catch(isolate);
13527     CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
13528                                  v8::Integer::New(isolate, 42)).FromJust());
13529     CHECK(!try_catch.HasCaught());
13530     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
13531     CHECK(val->IsNumber());
13532     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13533   }
13534
13535   {
13536     // Special cases for arrays.
13537     v8::TryCatch try_catch(isolate);
13538     CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
13539                                   v8::Integer::New(isolate, 1)).FromJust());
13540     CHECK(!try_catch.HasCaught());
13541   }
13542   {
13543     // Special cases for arrays: index exceeds the array's length
13544     v8::TryCatch try_catch(isolate);
13545     CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
13546                                  v8::Integer::New(isolate, 23)).FromJust());
13547     CHECK(!try_catch.HasCaught());
13548     CHECK_EQ(2U, arr->Length());
13549     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
13550     CHECK(val->IsNumber());
13551     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
13552
13553     // Set an existing entry.
13554     CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
13555                                  v8::Integer::New(isolate, 42)).FromJust());
13556     CHECK(!try_catch.HasCaught());
13557     val = arr->Get(env.local(), 0).ToLocalChecked();
13558     CHECK(val->IsNumber());
13559     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13560   }
13561
13562   {
13563     // Set a non-writable property.
13564     v8::TryCatch try_catch(isolate);
13565     CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
13566                                  v8::Integer::New(isolate, 42),
13567                                  v8::ReadOnly).FromJust());
13568     CHECK(!try_catch.HasCaught());
13569     v8::Local<v8::Value> val =
13570         obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
13571     CHECK(val->IsNumber());
13572     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13573     CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
13574                                     env.local(), v8_str("lala")).FromJust());
13575     CHECK(!try_catch.HasCaught());
13576   }
13577
13578   CompileRun("Object.freeze(a);");
13579   {
13580     // Can't change non-extensible objects.
13581     v8::TryCatch try_catch(isolate);
13582     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
13583                                   v8::Integer::New(isolate, 42)).FromJust());
13584     CHECK(!try_catch.HasCaught());
13585   }
13586
13587   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13588   templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
13589   v8::Local<v8::Object> access_checked =
13590       templ->NewInstance(env.local()).ToLocalChecked();
13591   {
13592     v8::TryCatch try_catch(isolate);
13593     CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
13594                                             v8::Integer::New(isolate, 42))
13595               .IsNothing());
13596     CHECK(try_catch.HasCaught());
13597   }
13598 }
13599
13600
13601 static v8::Local<Context> calling_context0;
13602 static v8::Local<Context> calling_context1;
13603 static v8::Local<Context> calling_context2;
13604
13605
13606 // Check that the call to the callback is initiated in
13607 // calling_context2, the directly calling context is calling_context1
13608 // and the callback itself is in calling_context0.
13609 static void GetCallingContextCallback(
13610     const v8::FunctionCallbackInfo<v8::Value>& args) {
13611   ApiTestFuzzer::Fuzz();
13612   CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
13613   CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
13614   CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
13615   args.GetReturnValue().Set(42);
13616 }
13617
13618
13619 THREADED_TEST(GetCurrentContextWhenNotInContext) {
13620   i::Isolate* isolate = CcTest::i_isolate();
13621   CHECK(isolate != NULL);
13622   CHECK(isolate->context() == NULL);
13623   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
13624   v8::HandleScope scope(v8_isolate);
13625   // The following should not crash, but return an empty handle.
13626   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
13627   CHECK(current.IsEmpty());
13628 }
13629
13630
13631 THREADED_TEST(GetCallingContext) {
13632   v8::Isolate* isolate = CcTest::isolate();
13633   v8::HandleScope scope(isolate);
13634
13635   Local<Context> calling_context0(Context::New(isolate));
13636   Local<Context> calling_context1(Context::New(isolate));
13637   Local<Context> calling_context2(Context::New(isolate));
13638   ::calling_context0 = calling_context0;
13639   ::calling_context1 = calling_context1;
13640   ::calling_context2 = calling_context2;
13641
13642   // Allow cross-domain access.
13643   Local<String> token = v8_str("<security token>");
13644   calling_context0->SetSecurityToken(token);
13645   calling_context1->SetSecurityToken(token);
13646   calling_context2->SetSecurityToken(token);
13647
13648   // Create an object with a C++ callback in context0.
13649   calling_context0->Enter();
13650   Local<v8::FunctionTemplate> callback_templ =
13651       v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
13652   calling_context0->Global()->Set(v8_str("callback"),
13653                                   callback_templ->GetFunction());
13654   calling_context0->Exit();
13655
13656   // Expose context0 in context1 and set up a function that calls the
13657   // callback function.
13658   calling_context1->Enter();
13659   calling_context1->Global()->Set(v8_str("context0"),
13660                                   calling_context0->Global());
13661   CompileRun("function f() { context0.callback() }");
13662   calling_context1->Exit();
13663
13664   // Expose context1 in context2 and call the callback function in
13665   // context0 indirectly through f in context1.
13666   calling_context2->Enter();
13667   calling_context2->Global()->Set(v8_str("context1"),
13668                                   calling_context1->Global());
13669   CompileRun("context1.f()");
13670   calling_context2->Exit();
13671   ::calling_context0.Clear();
13672   ::calling_context1.Clear();
13673   ::calling_context2.Clear();
13674 }
13675
13676
13677 // Check that a variable declaration with no explicit initialization
13678 // value does shadow an existing property in the prototype chain.
13679 THREADED_TEST(InitGlobalVarInProtoChain) {
13680   LocalContext context;
13681   v8::HandleScope scope(context->GetIsolate());
13682   // Introduce a variable in the prototype chain.
13683   CompileRun("__proto__.x = 42");
13684   v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
13685   CHECK(!result->IsUndefined());
13686   CHECK_EQ(43, result->Int32Value());
13687 }
13688
13689
13690 // Regression test for issue 398.
13691 // If a function is added to an object, creating a constant function
13692 // field, and the result is cloned, replacing the constant function on the
13693 // original should not affect the clone.
13694 // See http://code.google.com/p/v8/issues/detail?id=398
13695 THREADED_TEST(ReplaceConstantFunction) {
13696   LocalContext context;
13697   v8::Isolate* isolate = context->GetIsolate();
13698   v8::HandleScope scope(isolate);
13699   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
13700   v8::Handle<v8::FunctionTemplate> func_templ =
13701       v8::FunctionTemplate::New(isolate);
13702   v8::Handle<v8::String> foo_string =
13703       v8::String::NewFromUtf8(isolate, "foo");
13704   obj->Set(foo_string, func_templ->GetFunction());
13705   v8::Handle<v8::Object> obj_clone = obj->Clone();
13706   obj_clone->Set(foo_string,
13707                  v8::String::NewFromUtf8(isolate, "Hello"));
13708   CHECK(!obj->Get(foo_string)->IsUndefined());
13709 }
13710
13711
13712 static void CheckElementValue(i::Isolate* isolate,
13713                               int expected,
13714                               i::Handle<i::Object> obj,
13715                               int offset) {
13716   i::Object* element =
13717       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
13718   CHECK_EQ(expected, i::Smi::cast(element)->value());
13719 }
13720
13721
13722 template <class ExternalArrayClass, class ElementType>
13723 static void ObjectWithExternalArrayTestHelper(Handle<Context> context,
13724                                               v8::Handle<Object> obj,
13725                                               int element_count,
13726                                               i::ExternalArrayType array_type,
13727                                               int64_t low, int64_t high) {
13728   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
13729   i::Isolate* isolate = jsobj->GetIsolate();
13730   obj->Set(v8_str("field"),
13731            v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
13732   context->Global()->Set(v8_str("ext_array"), obj);
13733   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
13734   CHECK_EQ(1503, result->Int32Value());
13735   result = CompileRun("ext_array[1]");
13736   CHECK_EQ(1, result->Int32Value());
13737
13738   // Check assigned smis
13739   result = CompileRun("for (var i = 0; i < 8; i++) {"
13740                       "  ext_array[i] = i;"
13741                       "}"
13742                       "var sum = 0;"
13743                       "for (var i = 0; i < 8; i++) {"
13744                       "  sum += ext_array[i];"
13745                       "}"
13746                       "sum;");
13747
13748   CHECK_EQ(28, result->Int32Value());
13749   // Check pass through of assigned smis
13750   result = CompileRun("var sum = 0;"
13751                       "for (var i = 0; i < 8; i++) {"
13752                       "  sum += ext_array[i] = ext_array[i] = -i;"
13753                       "}"
13754                       "sum;");
13755   CHECK_EQ(-28, result->Int32Value());
13756
13757
13758   // Check assigned smis in reverse order
13759   result = CompileRun("for (var i = 8; --i >= 0; ) {"
13760                       "  ext_array[i] = i;"
13761                       "}"
13762                       "var sum = 0;"
13763                       "for (var i = 0; i < 8; i++) {"
13764                       "  sum += ext_array[i];"
13765                       "}"
13766                       "sum;");
13767   CHECK_EQ(28, result->Int32Value());
13768
13769   // Check pass through of assigned HeapNumbers
13770   result = CompileRun("var sum = 0;"
13771                       "for (var i = 0; i < 16; i+=2) {"
13772                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
13773                       "}"
13774                       "sum;");
13775   CHECK_EQ(-28, result->Int32Value());
13776
13777   // Check assigned HeapNumbers
13778   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
13779                       "  ext_array[i] = (i * 0.5);"
13780                       "}"
13781                       "var sum = 0;"
13782                       "for (var i = 0; i < 16; i+=2) {"
13783                       "  sum += ext_array[i];"
13784                       "}"
13785                       "sum;");
13786   CHECK_EQ(28, result->Int32Value());
13787
13788   // Check assigned HeapNumbers in reverse order
13789   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
13790                       "  ext_array[i] = (i * 0.5);"
13791                       "}"
13792                       "var sum = 0;"
13793                       "for (var i = 0; i < 16; i+=2) {"
13794                       "  sum += ext_array[i];"
13795                       "}"
13796                       "sum;");
13797   CHECK_EQ(28, result->Int32Value());
13798
13799   i::ScopedVector<char> test_buf(1024);
13800
13801   // Check legal boundary conditions.
13802   // The repeated loads and stores ensure the ICs are exercised.
13803   const char* boundary_program =
13804       "var res = 0;"
13805       "for (var i = 0; i < 16; i++) {"
13806       "  ext_array[i] = %lld;"
13807       "  if (i > 8) {"
13808       "    res = ext_array[i];"
13809       "  }"
13810       "}"
13811       "res;";
13812   i::SNPrintF(test_buf,
13813               boundary_program,
13814               low);
13815   result = CompileRun(test_buf.start());
13816   CHECK_EQ(low, result->IntegerValue());
13817
13818   i::SNPrintF(test_buf,
13819               boundary_program,
13820               high);
13821   result = CompileRun(test_buf.start());
13822   CHECK_EQ(high, result->IntegerValue());
13823
13824   // Check misprediction of type in IC.
13825   result = CompileRun("var tmp_array = ext_array;"
13826                       "var sum = 0;"
13827                       "for (var i = 0; i < 8; i++) {"
13828                       "  tmp_array[i] = i;"
13829                       "  sum += tmp_array[i];"
13830                       "  if (i == 4) {"
13831                       "    tmp_array = {};"
13832                       "  }"
13833                       "}"
13834                       "sum;");
13835   // Force GC to trigger verification.
13836   CcTest::heap()->CollectAllGarbage();
13837   CHECK_EQ(28, result->Int32Value());
13838
13839   // Make sure out-of-range loads do not throw.
13840   i::SNPrintF(test_buf,
13841               "var caught_exception = false;"
13842               "try {"
13843               "  ext_array[%d];"
13844               "} catch (e) {"
13845               "  caught_exception = true;"
13846               "}"
13847               "caught_exception;",
13848               element_count);
13849   result = CompileRun(test_buf.start());
13850   CHECK_EQ(false, result->BooleanValue());
13851
13852   // Make sure out-of-range stores do not throw.
13853   i::SNPrintF(test_buf,
13854               "var caught_exception = false;"
13855               "try {"
13856               "  ext_array[%d] = 1;"
13857               "} catch (e) {"
13858               "  caught_exception = true;"
13859               "}"
13860               "caught_exception;",
13861               element_count);
13862   result = CompileRun(test_buf.start());
13863   CHECK_EQ(false, result->BooleanValue());
13864
13865   // Check other boundary conditions, values and operations.
13866   result = CompileRun("for (var i = 0; i < 8; i++) {"
13867                       "  ext_array[7] = undefined;"
13868                       "}"
13869                       "ext_array[7];");
13870   CHECK_EQ(0, result->Int32Value());
13871   if (array_type == i::kExternalFloat64Array ||
13872       array_type == i::kExternalFloat32Array) {
13873     CHECK(std::isnan(
13874         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
13875   } else {
13876     CheckElementValue(isolate, 0, jsobj, 7);
13877   }
13878
13879   result = CompileRun("for (var i = 0; i < 8; i++) {"
13880                       "  ext_array[6] = '2.3';"
13881                       "}"
13882                       "ext_array[6];");
13883   CHECK_EQ(2, result->Int32Value());
13884   CHECK_EQ(2,
13885            static_cast<int>(
13886                i::Object::GetElement(
13887                    isolate, jsobj, 6).ToHandleChecked()->Number()));
13888
13889   if (array_type != i::kExternalFloat32Array &&
13890       array_type != i::kExternalFloat64Array) {
13891     // Though the specification doesn't state it, be explicit about
13892     // converting NaNs and +/-Infinity to zero.
13893     result = CompileRun("for (var i = 0; i < 8; i++) {"
13894                         "  ext_array[i] = 5;"
13895                         "}"
13896                         "for (var i = 0; i < 8; i++) {"
13897                         "  ext_array[i] = NaN;"
13898                         "}"
13899                         "ext_array[5];");
13900     CHECK_EQ(0, result->Int32Value());
13901     CheckElementValue(isolate, 0, jsobj, 5);
13902
13903     result = CompileRun("for (var i = 0; i < 8; i++) {"
13904                         "  ext_array[i] = 5;"
13905                         "}"
13906                         "for (var i = 0; i < 8; i++) {"
13907                         "  ext_array[i] = Infinity;"
13908                         "}"
13909                         "ext_array[5];");
13910     int expected_value =
13911         (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
13912     CHECK_EQ(expected_value, result->Int32Value());
13913     CheckElementValue(isolate, expected_value, jsobj, 5);
13914
13915     result = CompileRun("for (var i = 0; i < 8; i++) {"
13916                         "  ext_array[i] = 5;"
13917                         "}"
13918                         "for (var i = 0; i < 8; i++) {"
13919                         "  ext_array[i] = -Infinity;"
13920                         "}"
13921                         "ext_array[5];");
13922     CHECK_EQ(0, result->Int32Value());
13923     CheckElementValue(isolate, 0, jsobj, 5);
13924
13925     // Check truncation behavior of integral arrays.
13926     const char* unsigned_data =
13927         "var source_data = [0.6, 10.6];"
13928         "var expected_results = [0, 10];";
13929     const char* signed_data =
13930         "var source_data = [0.6, 10.6, -0.6, -10.6];"
13931         "var expected_results = [0, 10, 0, -10];";
13932     const char* pixel_data =
13933         "var source_data = [0.6, 10.6];"
13934         "var expected_results = [1, 11];";
13935     bool is_unsigned = (array_type == i::kExternalUint8Array ||
13936                         array_type == i::kExternalUint16Array ||
13937                         array_type == i::kExternalUint32Array);
13938     bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
13939
13940     i::SNPrintF(test_buf,
13941                 "%s"
13942                 "var all_passed = true;"
13943                 "for (var i = 0; i < source_data.length; i++) {"
13944                 "  for (var j = 0; j < 8; j++) {"
13945                 "    ext_array[j] = source_data[i];"
13946                 "  }"
13947                 "  all_passed = all_passed &&"
13948                 "               (ext_array[5] == expected_results[i]);"
13949                 "}"
13950                 "all_passed;",
13951                 (is_unsigned ?
13952                      unsigned_data :
13953                      (is_pixel_data ? pixel_data : signed_data)));
13954     result = CompileRun(test_buf.start());
13955     CHECK_EQ(true, result->BooleanValue());
13956   }
13957
13958   i::Handle<ExternalArrayClass> array(
13959       ExternalArrayClass::cast(jsobj->elements()));
13960   for (int i = 0; i < element_count; i++) {
13961     array->set(i, static_cast<ElementType>(i));
13962   }
13963
13964   // Test complex assignments
13965   result = CompileRun("function ee_op_test_complex_func(sum) {"
13966                       " for (var i = 0; i < 40; ++i) {"
13967                       "   sum += (ext_array[i] += 1);"
13968                       "   sum += (ext_array[i] -= 1);"
13969                       " } "
13970                       " return sum;"
13971                       "}"
13972                       "sum=0;"
13973                       "for (var i=0;i<10000;++i) {"
13974                       "  sum=ee_op_test_complex_func(sum);"
13975                       "}"
13976                       "sum;");
13977   CHECK_EQ(16000000, result->Int32Value());
13978
13979   // Test count operations
13980   result = CompileRun("function ee_op_test_count_func(sum) {"
13981                       " for (var i = 0; i < 40; ++i) {"
13982                       "   sum += (++ext_array[i]);"
13983                       "   sum += (--ext_array[i]);"
13984                       " } "
13985                       " return sum;"
13986                       "}"
13987                       "sum=0;"
13988                       "for (var i=0;i<10000;++i) {"
13989                       "  sum=ee_op_test_count_func(sum);"
13990                       "}"
13991                       "sum;");
13992   CHECK_EQ(16000000, result->Int32Value());
13993
13994   result = CompileRun("ext_array[3] = 33;"
13995                       "delete ext_array[3];"
13996                       "ext_array[3];");
13997   CHECK_EQ(33, result->Int32Value());
13998
13999   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
14000                       "ext_array[2] = 12; ext_array[3] = 13;"
14001                       "ext_array.__defineGetter__('2',"
14002                       "function() { return 120; });"
14003                       "ext_array[2];");
14004   CHECK_EQ(12, result->Int32Value());
14005
14006   result = CompileRun("var js_array = new Array(40);"
14007                       "js_array[0] = 77;"
14008                       "js_array;");
14009   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
14010
14011   result = CompileRun("ext_array[1] = 23;"
14012                       "ext_array.__proto__ = [];"
14013                       "js_array.__proto__ = ext_array;"
14014                       "js_array.concat(ext_array);");
14015   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
14016   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
14017
14018   result = CompileRun("ext_array[1] = 23;");
14019   CHECK_EQ(23, result->Int32Value());
14020 }
14021
14022
14023 template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
14024           class ElementType>
14025 static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
14026                                       ElementType low, ElementType high) {
14027   i::FLAG_allow_natives_syntax = true;
14028   LocalContext context;
14029   i::Isolate* isolate = CcTest::i_isolate();
14030   i::Factory* factory = isolate->factory();
14031   v8::HandleScope scope(context->GetIsolate());
14032   const int kElementCount = 260;
14033   i::Handle<i::JSTypedArray> jsobj =
14034       factory->NewJSTypedArray(elements_kind, kElementCount);
14035   i::Handle<FixedTypedArrayClass> fixed_array(
14036       FixedTypedArrayClass::cast(jsobj->elements()));
14037   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
14038            fixed_array->map()->instance_type());
14039   CHECK_EQ(kElementCount, fixed_array->length());
14040   CcTest::heap()->CollectAllGarbage();
14041   for (int i = 0; i < kElementCount; i++) {
14042     fixed_array->set(i, static_cast<ElementType>(i));
14043   }
14044   // Force GC to trigger verification.
14045   CcTest::heap()->CollectAllGarbage();
14046   for (int i = 0; i < kElementCount; i++) {
14047     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
14048              static_cast<int64_t>(fixed_array->get_scalar(i)));
14049   }
14050   v8::Handle<v8::Object> obj = v8::Utils::ToLocal(jsobj);
14051
14052   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
14053       context.local(), obj, kElementCount, array_type,
14054       static_cast<int64_t>(low),
14055       static_cast<int64_t>(high));
14056 }
14057
14058
14059 THREADED_TEST(FixedUint8Array) {
14060   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
14061       i::kExternalUint8Array, 0x0, 0xFF);
14062 }
14063
14064
14065 THREADED_TEST(FixedUint8ClampedArray) {
14066   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
14067                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
14068       i::kExternalUint8ClampedArray, 0x0, 0xFF);
14069 }
14070
14071
14072 THREADED_TEST(FixedInt8Array) {
14073   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
14074       i::kExternalInt8Array, -0x80, 0x7F);
14075 }
14076
14077
14078 THREADED_TEST(FixedUint16Array) {
14079   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
14080       i::kExternalUint16Array, 0x0, 0xFFFF);
14081 }
14082
14083
14084 THREADED_TEST(FixedInt16Array) {
14085   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
14086       i::kExternalInt16Array, -0x8000, 0x7FFF);
14087 }
14088
14089
14090 THREADED_TEST(FixedUint32Array) {
14091   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
14092       i::kExternalUint32Array, 0x0, UINT_MAX);
14093 }
14094
14095
14096 THREADED_TEST(FixedInt32Array) {
14097   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
14098       i::kExternalInt32Array, INT_MIN, INT_MAX);
14099 }
14100
14101
14102 THREADED_TEST(FixedFloat32Array) {
14103   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
14104       i::kExternalFloat32Array, -500, 500);
14105 }
14106
14107
14108 THREADED_TEST(FixedFloat64Array) {
14109   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
14110       i::kExternalFloat64Array, -500, 500);
14111 }
14112
14113
14114 template <typename ElementType, typename TypedArray, class ExternalArrayClass,
14115           class ArrayBufferType>
14116 void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
14117                           int64_t high) {
14118   const int kElementCount = 50;
14119
14120   i::ScopedVector<ElementType> backing_store(kElementCount+2);
14121
14122   LocalContext env;
14123   v8::Isolate* isolate = env->GetIsolate();
14124   v8::HandleScope handle_scope(isolate);
14125
14126   Local<ArrayBufferType> ab =
14127       ArrayBufferType::New(isolate, backing_store.start(),
14128                            (kElementCount + 2) * sizeof(ElementType));
14129   Local<TypedArray> ta =
14130       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
14131   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
14132   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
14133   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
14134   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
14135   CHECK(ab->Equals(ta->Buffer()));
14136
14137   ElementType* data = backing_store.start() + 2;
14138   for (int i = 0; i < kElementCount; i++) {
14139     data[i] = static_cast<ElementType>(i);
14140   }
14141
14142   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
14143       env.local(), ta, kElementCount, array_type, low, high);
14144 }
14145
14146
14147 THREADED_TEST(Uint8Array) {
14148   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
14149                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
14150 }
14151
14152
14153 THREADED_TEST(Int8Array) {
14154   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
14155                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
14156 }
14157
14158
14159 THREADED_TEST(Uint16Array) {
14160   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
14161                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
14162 }
14163
14164
14165 THREADED_TEST(Int16Array) {
14166   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
14167                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
14168                                         0x7FFF);
14169 }
14170
14171
14172 THREADED_TEST(Uint32Array) {
14173   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
14174                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
14175 }
14176
14177
14178 THREADED_TEST(Int32Array) {
14179   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
14180                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
14181                                         INT_MAX);
14182 }
14183
14184
14185 THREADED_TEST(Float32Array) {
14186   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
14187                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
14188 }
14189
14190
14191 THREADED_TEST(Float64Array) {
14192   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
14193                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
14194 }
14195
14196
14197 THREADED_TEST(Uint8ClampedArray) {
14198   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
14199                        i::FixedUint8ClampedArray, v8::ArrayBuffer>(
14200       i::kExternalUint8ClampedArray, 0, 0xFF);
14201 }
14202
14203
14204 THREADED_TEST(DataView) {
14205   const int kSize = 50;
14206
14207   i::ScopedVector<uint8_t> backing_store(kSize+2);
14208
14209   LocalContext env;
14210   v8::Isolate* isolate = env->GetIsolate();
14211   v8::HandleScope handle_scope(isolate);
14212
14213   Local<v8::ArrayBuffer> ab =
14214       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
14215   Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
14216   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
14217   CHECK_EQ(2u, dv->ByteOffset());
14218   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
14219   CHECK(ab->Equals(dv->Buffer()));
14220 }
14221
14222
14223 THREADED_TEST(SharedUint8Array) {
14224   i::FLAG_harmony_sharedarraybuffer = true;
14225   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
14226                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
14227 }
14228
14229
14230 THREADED_TEST(SharedInt8Array) {
14231   i::FLAG_harmony_sharedarraybuffer = true;
14232   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
14233                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
14234                                               0x7F);
14235 }
14236
14237
14238 THREADED_TEST(SharedUint16Array) {
14239   i::FLAG_harmony_sharedarraybuffer = true;
14240   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
14241                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
14242                                               0xFFFF);
14243 }
14244
14245
14246 THREADED_TEST(SharedInt16Array) {
14247   i::FLAG_harmony_sharedarraybuffer = true;
14248   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
14249                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
14250                                               0x7FFF);
14251 }
14252
14253
14254 THREADED_TEST(SharedUint32Array) {
14255   i::FLAG_harmony_sharedarraybuffer = true;
14256   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
14257                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
14258                                               UINT_MAX);
14259 }
14260
14261
14262 THREADED_TEST(SharedInt32Array) {
14263   i::FLAG_harmony_sharedarraybuffer = true;
14264   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
14265                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
14266                                               INT_MAX);
14267 }
14268
14269
14270 THREADED_TEST(SharedFloat32Array) {
14271   i::FLAG_harmony_sharedarraybuffer = true;
14272   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
14273                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
14274                                               500);
14275 }
14276
14277
14278 THREADED_TEST(SharedFloat64Array) {
14279   i::FLAG_harmony_sharedarraybuffer = true;
14280   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
14281                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
14282                                               500);
14283 }
14284
14285
14286 THREADED_TEST(SharedUint8ClampedArray) {
14287   i::FLAG_harmony_sharedarraybuffer = true;
14288   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
14289                        i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
14290       i::kExternalUint8ClampedArray, 0, 0xFF);
14291 }
14292
14293
14294 THREADED_TEST(SharedDataView) {
14295   i::FLAG_harmony_sharedarraybuffer = true;
14296   const int kSize = 50;
14297
14298   i::ScopedVector<uint8_t> backing_store(kSize + 2);
14299
14300   LocalContext env;
14301   v8::Isolate* isolate = env->GetIsolate();
14302   v8::HandleScope handle_scope(isolate);
14303
14304   Local<v8::SharedArrayBuffer> ab =
14305       v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
14306   Local<v8::DataView> dv =
14307       v8::DataView::New(ab, 2, kSize);
14308   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
14309   CHECK_EQ(2u, dv->ByteOffset());
14310   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
14311   CHECK(ab->Equals(dv->Buffer()));
14312 }
14313
14314
14315 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
14316   THREADED_TEST(Is##View) {                                                   \
14317     LocalContext env;                                                         \
14318     v8::Isolate* isolate = env->GetIsolate();                                 \
14319     v8::HandleScope handle_scope(isolate);                                    \
14320                                                                               \
14321     Handle<Value> result = CompileRun(                                        \
14322         "var ab = new ArrayBuffer(128);"                                      \
14323         "new " #View "(ab)");                                                 \
14324     CHECK(result->IsArrayBufferView());                                       \
14325     CHECK(result->Is##View());                                                \
14326     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
14327   }
14328
14329 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
14330 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
14331 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
14332 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
14333 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
14334 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
14335 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
14336 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
14337 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
14338 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
14339
14340 #undef IS_ARRAY_BUFFER_VIEW_TEST
14341
14342
14343
14344 THREADED_TEST(ScriptContextDependence) {
14345   LocalContext c1;
14346   v8::HandleScope scope(c1->GetIsolate());
14347   const char *source = "foo";
14348   v8::Handle<v8::Script> dep = v8_compile(source);
14349   v8::ScriptCompiler::Source script_source(v8::String::NewFromUtf8(
14350       c1->GetIsolate(), source));
14351   v8::Handle<v8::UnboundScript> indep =
14352       v8::ScriptCompiler::CompileUnbound(c1->GetIsolate(), &script_source);
14353   c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
14354                     v8::Integer::New(c1->GetIsolate(), 100));
14355   CHECK_EQ(dep->Run()->Int32Value(), 100);
14356   CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 100);
14357   LocalContext c2;
14358   c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
14359                     v8::Integer::New(c2->GetIsolate(), 101));
14360   CHECK_EQ(dep->Run()->Int32Value(), 100);
14361   CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 101);
14362 }
14363
14364
14365 THREADED_TEST(StackTrace) {
14366   LocalContext context;
14367   v8::HandleScope scope(context->GetIsolate());
14368   v8::TryCatch try_catch(context->GetIsolate());
14369   const char *source = "function foo() { FAIL.FAIL; }; foo();";
14370   v8::Handle<v8::String> src =
14371       v8::String::NewFromUtf8(context->GetIsolate(), source);
14372   v8::Handle<v8::String> origin =
14373       v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
14374   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
14375   v8::ScriptCompiler::CompileUnbound(context->GetIsolate(), &script_source)
14376       ->BindToCurrentContext()
14377       ->Run();
14378   CHECK(try_catch.HasCaught());
14379   v8::String::Utf8Value stack(try_catch.StackTrace());
14380   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
14381 }
14382
14383
14384 // Checks that a StackFrame has certain expected values.
14385 void checkStackFrame(const char* expected_script_name,
14386     const char* expected_func_name, int expected_line_number,
14387     int expected_column, bool is_eval, bool is_constructor,
14388     v8::Handle<v8::StackFrame> frame) {
14389   v8::HandleScope scope(CcTest::isolate());
14390   v8::String::Utf8Value func_name(frame->GetFunctionName());
14391   v8::String::Utf8Value script_name(frame->GetScriptName());
14392   if (*script_name == NULL) {
14393     // The situation where there is no associated script, like for evals.
14394     CHECK(expected_script_name == NULL);
14395   } else {
14396     CHECK(strstr(*script_name, expected_script_name) != NULL);
14397   }
14398   CHECK(strstr(*func_name, expected_func_name) != NULL);
14399   CHECK_EQ(expected_line_number, frame->GetLineNumber());
14400   CHECK_EQ(expected_column, frame->GetColumn());
14401   CHECK_EQ(is_eval, frame->IsEval());
14402   CHECK_EQ(is_constructor, frame->IsConstructor());
14403 }
14404
14405
14406 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
14407   v8::HandleScope scope(args.GetIsolate());
14408   const char* origin = "capture-stack-trace-test";
14409   const int kOverviewTest = 1;
14410   const int kDetailedTest = 2;
14411
14412   DCHECK(args.Length() == 1);
14413
14414   int testGroup = args[0]->Int32Value();
14415   if (testGroup == kOverviewTest) {
14416     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
14417         args.GetIsolate(), 10, v8::StackTrace::kOverview);
14418     CHECK_EQ(4, stackTrace->GetFrameCount());
14419     checkStackFrame(origin, "bar", 2, 10, false, false,
14420                     stackTrace->GetFrame(0));
14421     checkStackFrame(origin, "foo", 6, 3, false, false,
14422                     stackTrace->GetFrame(1));
14423     // This is the source string inside the eval which has the call to foo.
14424     checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
14425     // The last frame is an anonymous function which has the initial eval call.
14426     checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
14427
14428     CHECK(stackTrace->AsArray()->IsArray());
14429   } else if (testGroup == kDetailedTest) {
14430     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
14431         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
14432     CHECK_EQ(4, stackTrace->GetFrameCount());
14433     checkStackFrame(origin, "bat", 4, 22, false, false,
14434                     stackTrace->GetFrame(0));
14435     checkStackFrame(origin, "baz", 8, 3, false, true,
14436                     stackTrace->GetFrame(1));
14437     bool is_eval = true;
14438     // This is the source string inside the eval which has the call to baz.
14439     checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
14440     // The last frame is an anonymous function which has the initial eval call.
14441     checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
14442
14443     CHECK(stackTrace->AsArray()->IsArray());
14444   }
14445 }
14446
14447
14448 // Tests the C++ StackTrace API.
14449 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
14450 // THREADED_TEST(CaptureStackTrace) {
14451 TEST(CaptureStackTrace) {
14452   v8::Isolate* isolate = CcTest::isolate();
14453   v8::HandleScope scope(isolate);
14454   v8::Handle<v8::String> origin =
14455       v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
14456   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
14457   templ->Set(v8_str("AnalyzeStackInNativeCode"),
14458              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
14459   LocalContext context(0, templ);
14460
14461   // Test getting OVERVIEW information. Should ignore information that is not
14462   // script name, function name, line number, and column offset.
14463   const char *overview_source =
14464     "function bar() {\n"
14465     "  var y; AnalyzeStackInNativeCode(1);\n"
14466     "}\n"
14467     "function foo() {\n"
14468     "\n"
14469     "  bar();\n"
14470     "}\n"
14471     "var x;eval('new foo();');";
14472   v8::Handle<v8::String> overview_src =
14473       v8::String::NewFromUtf8(isolate, overview_source);
14474   v8::ScriptCompiler::Source script_source(overview_src,
14475                                            v8::ScriptOrigin(origin));
14476   v8::Handle<Value> overview_result(
14477       v8::ScriptCompiler::CompileUnbound(isolate, &script_source)
14478           ->BindToCurrentContext()
14479           ->Run());
14480   CHECK(!overview_result.IsEmpty());
14481   CHECK(overview_result->IsObject());
14482
14483   // Test getting DETAILED information.
14484   const char *detailed_source =
14485     "function bat() {AnalyzeStackInNativeCode(2);\n"
14486     "}\n"
14487     "\n"
14488     "function baz() {\n"
14489     "  bat();\n"
14490     "}\n"
14491     "eval('new baz();');";
14492   v8::Handle<v8::String> detailed_src =
14493       v8::String::NewFromUtf8(isolate, detailed_source);
14494   // Make the script using a non-zero line and column offset.
14495   v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
14496   v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
14497   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
14498   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
14499   v8::Handle<v8::UnboundScript> detailed_script(
14500       v8::ScriptCompiler::CompileUnbound(isolate, &script_source2));
14501   v8::Handle<Value> detailed_result(
14502       detailed_script->BindToCurrentContext()->Run());
14503   CHECK(!detailed_result.IsEmpty());
14504   CHECK(detailed_result->IsObject());
14505 }
14506
14507
14508 static void StackTraceForUncaughtExceptionListener(
14509     v8::Handle<v8::Message> message,
14510     v8::Handle<Value>) {
14511   report_count++;
14512   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14513   CHECK_EQ(2, stack_trace->GetFrameCount());
14514   checkStackFrame("origin", "foo", 2, 3, false, false,
14515                   stack_trace->GetFrame(0));
14516   checkStackFrame("origin", "bar", 5, 3, false, false,
14517                   stack_trace->GetFrame(1));
14518 }
14519
14520
14521 TEST(CaptureStackTraceForUncaughtException) {
14522   report_count = 0;
14523   LocalContext env;
14524   v8::HandleScope scope(env->GetIsolate());
14525   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
14526   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14527
14528   CompileRunWithOrigin(
14529       "function foo() {\n"
14530       "  throw 1;\n"
14531       "};\n"
14532       "function bar() {\n"
14533       "  foo();\n"
14534       "};",
14535       "origin");
14536   v8::Local<v8::Object> global = env->Global();
14537   Local<Value> trouble = global->Get(v8_str("bar"));
14538   CHECK(trouble->IsFunction());
14539   Function::Cast(*trouble)->Call(global, 0, NULL);
14540   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14541   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
14542   CHECK_EQ(1, report_count);
14543 }
14544
14545
14546 TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
14547   report_count = 0;
14548   LocalContext env;
14549   v8::HandleScope scope(env->GetIsolate());
14550
14551   // Create an Error object first.
14552   CompileRunWithOrigin(
14553       "function foo() {\n"
14554       "e=new Error('err');\n"
14555       "};\n"
14556       "function bar() {\n"
14557       "  foo();\n"
14558       "};\n"
14559       "var e;",
14560       "origin");
14561   v8::Local<v8::Object> global = env->Global();
14562   Local<Value> trouble = global->Get(v8_str("bar"));
14563   CHECK(trouble->IsFunction());
14564   Function::Cast(*trouble)->Call(global, 0, NULL);
14565
14566   // Enable capturing detailed stack trace late, and throw the exception.
14567   // The detailed stack trace should be extracted from the simple stack.
14568   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
14569   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14570   CompileRunWithOrigin("throw e", "origin");
14571   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14572   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
14573   CHECK_EQ(1, report_count);
14574 }
14575
14576
14577 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
14578   LocalContext env;
14579   v8::HandleScope scope(env->GetIsolate());
14580   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
14581                                                     1024,
14582                                                     v8::StackTrace::kDetailed);
14583
14584   CompileRun(
14585       "var setters = ['column', 'lineNumber', 'scriptName',\n"
14586       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
14587       "    'isConstructor'];\n"
14588       "for (var i = 0; i < setters.length; i++) {\n"
14589       "  var prop = setters[i];\n"
14590       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
14591       "}\n");
14592   CompileRun("throw 'exception';");
14593   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14594 }
14595
14596
14597 static void StackTraceFunctionNameListener(v8::Handle<v8::Message> message,
14598                                            v8::Handle<Value>) {
14599   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14600   CHECK_EQ(5, stack_trace->GetFrameCount());
14601   checkStackFrame("origin", "foo:0", 4, 7, false, false,
14602                   stack_trace->GetFrame(0));
14603   checkStackFrame("origin", "foo:1", 5, 27, false, false,
14604                   stack_trace->GetFrame(1));
14605   checkStackFrame("origin", "foo", 5, 27, false, false,
14606                   stack_trace->GetFrame(2));
14607   checkStackFrame("origin", "foo", 5, 27, false, false,
14608                   stack_trace->GetFrame(3));
14609   checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
14610 }
14611
14612
14613 TEST(GetStackTraceContainsFunctionsWithFunctionName) {
14614   LocalContext env;
14615   v8::HandleScope scope(env->GetIsolate());
14616
14617   CompileRunWithOrigin(
14618       "function gen(name, counter) {\n"
14619       "  var f = function foo() {\n"
14620       "    if (counter === 0)\n"
14621       "      throw 1;\n"
14622       "    gen(name, counter - 1)();\n"
14623       "  };\n"
14624       "  if (counter == 3) {\n"
14625       "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
14626       "  } else {\n"
14627       "    Object.defineProperty(f, 'name', {writable:true});\n"
14628       "    if (counter == 2)\n"
14629       "      f.name = 42;\n"
14630       "    else\n"
14631       "      f.name = name + ':' + counter;\n"
14632       "  }\n"
14633       "  return f;\n"
14634       "};",
14635       "origin");
14636
14637   v8::V8::AddMessageListener(StackTraceFunctionNameListener);
14638   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14639   CompileRunWithOrigin("gen('foo', 3)();", "origin");
14640   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14641   v8::V8::RemoveMessageListeners(StackTraceFunctionNameListener);
14642 }
14643
14644
14645 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
14646                                      v8::Handle<v8::Value> data) {
14647   // Use the frame where JavaScript is called from.
14648   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14649   CHECK(!stack_trace.IsEmpty());
14650   int frame_count = stack_trace->GetFrameCount();
14651   CHECK_EQ(3, frame_count);
14652   int line_number[] = {1, 2, 5};
14653   for (int i = 0; i < frame_count; i++) {
14654     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14655   }
14656 }
14657
14658
14659 // Test that we only return the stack trace at the site where the exception
14660 // is first thrown (not where it is rethrown).
14661 TEST(RethrowStackTrace) {
14662   LocalContext env;
14663   v8::HandleScope scope(env->GetIsolate());
14664   // We make sure that
14665   // - the stack trace of the ReferenceError in g() is reported.
14666   // - the stack trace is not overwritten when e1 is rethrown by t().
14667   // - the stack trace of e2 does not overwrite that of e1.
14668   const char* source =
14669       "function g() { error; }          \n"
14670       "function f() { g(); }            \n"
14671       "function t(e) { throw e; }       \n"
14672       "try {                            \n"
14673       "  f();                           \n"
14674       "} catch (e1) {                   \n"
14675       "  try {                          \n"
14676       "    error;                       \n"
14677       "  } catch (e2) {                 \n"
14678       "    t(e1);                       \n"
14679       "  }                              \n"
14680       "}                                \n";
14681   v8::V8::AddMessageListener(RethrowStackTraceHandler);
14682   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14683   CompileRun(source);
14684   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14685   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
14686 }
14687
14688
14689 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
14690                                               v8::Handle<v8::Value> data) {
14691   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14692   CHECK(!stack_trace.IsEmpty());
14693   int frame_count = stack_trace->GetFrameCount();
14694   CHECK_EQ(2, frame_count);
14695   int line_number[] = {3, 7};
14696   for (int i = 0; i < frame_count; i++) {
14697     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14698   }
14699 }
14700
14701
14702 // Test that we do not recognize identity for primitive exceptions.
14703 TEST(RethrowPrimitiveStackTrace) {
14704   LocalContext env;
14705   v8::HandleScope scope(env->GetIsolate());
14706   // We do not capture stack trace for non Error objects on creation time.
14707   // Instead, we capture the stack trace on last throw.
14708   const char* source =
14709       "function g() { throw 404; }      \n"
14710       "function f() { g(); }            \n"
14711       "function t(e) { throw e; }       \n"
14712       "try {                            \n"
14713       "  f();                           \n"
14714       "} catch (e1) {                   \n"
14715       "  t(e1)                          \n"
14716       "}                                \n";
14717   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
14718   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14719   CompileRun(source);
14720   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14721   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
14722 }
14723
14724
14725 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
14726                                               v8::Handle<v8::Value> data) {
14727   // Use the frame where JavaScript is called from.
14728   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14729   CHECK(!stack_trace.IsEmpty());
14730   CHECK_EQ(1, stack_trace->GetFrameCount());
14731   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
14732 }
14733
14734
14735 // Test that the stack trace is captured when the error object is created and
14736 // not where it is thrown.
14737 TEST(RethrowExistingStackTrace) {
14738   LocalContext env;
14739   v8::HandleScope scope(env->GetIsolate());
14740   const char* source =
14741       "var e = new Error();           \n"
14742       "throw e;                       \n";
14743   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
14744   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14745   CompileRun(source);
14746   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14747   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
14748 }
14749
14750
14751 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
14752                                                v8::Handle<v8::Value> data) {
14753   // Use the frame where JavaScript is called from.
14754   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14755   CHECK(!stack_trace.IsEmpty());
14756   CHECK_EQ(1, stack_trace->GetFrameCount());
14757   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
14758 }
14759
14760
14761 // Test that the stack trace is captured where the bogus Error object is thrown.
14762 TEST(RethrowBogusErrorStackTrace) {
14763   LocalContext env;
14764   v8::HandleScope scope(env->GetIsolate());
14765   const char* source =
14766       "var e = {__proto__: new Error()} \n"
14767       "throw e;                         \n";
14768   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
14769   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14770   CompileRun(source);
14771   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14772   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
14773 }
14774
14775
14776 v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
14777 int promise_reject_counter = 0;
14778 int promise_revoke_counter = 0;
14779 int promise_reject_msg_line_number = -1;
14780 int promise_reject_msg_column_number = -1;
14781 int promise_reject_line_number = -1;
14782 int promise_reject_column_number = -1;
14783 int promise_reject_frame_count = -1;
14784
14785 void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
14786   if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
14787     promise_reject_counter++;
14788     CcTest::global()->Set(v8_str("rejected"), reject_message.GetPromise());
14789     CcTest::global()->Set(v8_str("value"), reject_message.GetValue());
14790     v8::Handle<v8::Message> message =
14791         v8::Exception::CreateMessage(reject_message.GetValue());
14792     v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14793
14794     promise_reject_msg_line_number = message->GetLineNumber();
14795     promise_reject_msg_column_number = message->GetStartColumn() + 1;
14796
14797     if (!stack_trace.IsEmpty()) {
14798       promise_reject_frame_count = stack_trace->GetFrameCount();
14799       if (promise_reject_frame_count > 0) {
14800         CHECK(stack_trace->GetFrame(0)->GetScriptName()->Equals(v8_str("pro")));
14801         promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
14802         promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
14803       } else {
14804         promise_reject_line_number = -1;
14805         promise_reject_column_number = -1;
14806       }
14807     }
14808   } else {
14809     promise_revoke_counter++;
14810     CcTest::global()->Set(v8_str("revoked"), reject_message.GetPromise());
14811     CHECK(reject_message.GetValue().IsEmpty());
14812   }
14813 }
14814
14815
14816 v8::Handle<v8::Promise> GetPromise(const char* name) {
14817   return v8::Handle<v8::Promise>::Cast(CcTest::global()->Get(v8_str(name)));
14818 }
14819
14820
14821 v8::Handle<v8::Value> RejectValue() {
14822   return CcTest::global()->Get(v8_str("value"));
14823 }
14824
14825
14826 void ResetPromiseStates() {
14827   promise_reject_counter = 0;
14828   promise_revoke_counter = 0;
14829   promise_reject_msg_line_number = -1;
14830   promise_reject_msg_column_number = -1;
14831   promise_reject_line_number = -1;
14832   promise_reject_column_number = -1;
14833   promise_reject_frame_count = -1;
14834   CcTest::global()->Set(v8_str("rejected"), v8_str(""));
14835   CcTest::global()->Set(v8_str("value"), v8_str(""));
14836   CcTest::global()->Set(v8_str("revoked"), v8_str(""));
14837 }
14838
14839
14840 TEST(PromiseRejectCallback) {
14841   LocalContext env;
14842   v8::Isolate* isolate = env->GetIsolate();
14843   v8::HandleScope scope(isolate);
14844
14845   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
14846
14847   ResetPromiseStates();
14848
14849   // Create promise p0.
14850   CompileRun(
14851       "var reject;            \n"
14852       "var p0 = new Promise(  \n"
14853       "  function(res, rej) { \n"
14854       "    reject = rej;      \n"
14855       "  }                    \n"
14856       ");                     \n");
14857   CHECK(!GetPromise("p0")->HasHandler());
14858   CHECK_EQ(0, promise_reject_counter);
14859   CHECK_EQ(0, promise_revoke_counter);
14860
14861   // Add resolve handler (and default reject handler) to p0.
14862   CompileRun("var p1 = p0.then(function(){});");
14863   CHECK(GetPromise("p0")->HasHandler());
14864   CHECK(!GetPromise("p1")->HasHandler());
14865   CHECK_EQ(0, promise_reject_counter);
14866   CHECK_EQ(0, promise_revoke_counter);
14867
14868   // Reject p0.
14869   CompileRun("reject('ppp');");
14870   CHECK(GetPromise("p0")->HasHandler());
14871   CHECK(!GetPromise("p1")->HasHandler());
14872   CHECK_EQ(1, promise_reject_counter);
14873   CHECK_EQ(0, promise_revoke_counter);
14874   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
14875   CHECK(GetPromise("rejected")->Equals(GetPromise("p1")));
14876   CHECK(RejectValue()->Equals(v8_str("ppp")));
14877
14878   // Reject p0 again. Callback is not triggered again.
14879   CompileRun("reject();");
14880   CHECK(GetPromise("p0")->HasHandler());
14881   CHECK(!GetPromise("p1")->HasHandler());
14882   CHECK_EQ(1, promise_reject_counter);
14883   CHECK_EQ(0, promise_revoke_counter);
14884
14885   // Add resolve handler to p1.
14886   CompileRun("var p2 = p1.then(function(){});");
14887   CHECK(GetPromise("p0")->HasHandler());
14888   CHECK(GetPromise("p1")->HasHandler());
14889   CHECK(!GetPromise("p2")->HasHandler());
14890   CHECK_EQ(2, promise_reject_counter);
14891   CHECK_EQ(1, promise_revoke_counter);
14892   CHECK(GetPromise("rejected")->Equals(GetPromise("p2")));
14893   CHECK(RejectValue()->Equals(v8_str("ppp")));
14894   CHECK(GetPromise("revoked")->Equals(GetPromise("p1")));
14895
14896   ResetPromiseStates();
14897
14898   // Create promise q0.
14899   CompileRun(
14900       "var q0 = new Promise(  \n"
14901       "  function(res, rej) { \n"
14902       "    reject = rej;      \n"
14903       "  }                    \n"
14904       ");                     \n");
14905   CHECK(!GetPromise("q0")->HasHandler());
14906   CHECK_EQ(0, promise_reject_counter);
14907   CHECK_EQ(0, promise_revoke_counter);
14908
14909   // Add reject handler to q0.
14910   CompileRun("var q1 = q0.catch(function() {});");
14911   CHECK(GetPromise("q0")->HasHandler());
14912   CHECK(!GetPromise("q1")->HasHandler());
14913   CHECK_EQ(0, promise_reject_counter);
14914   CHECK_EQ(0, promise_revoke_counter);
14915
14916   // Reject q0.
14917   CompileRun("reject('qq')");
14918   CHECK(GetPromise("q0")->HasHandler());
14919   CHECK(!GetPromise("q1")->HasHandler());
14920   CHECK_EQ(0, promise_reject_counter);
14921   CHECK_EQ(0, promise_revoke_counter);
14922
14923   // Add a new reject handler, which rejects by returning Promise.reject().
14924   // The returned promise q_ triggers a reject callback at first, only to
14925   // revoke it when returning it causes q2 to be rejected.
14926   CompileRun(
14927       "var q_;"
14928       "var q2 = q0.catch(               \n"
14929       "   function() {                  \n"
14930       "     q_ = Promise.reject('qqq'); \n"
14931       "     return q_;                  \n"
14932       "   }                             \n"
14933       ");                               \n");
14934   CHECK(GetPromise("q0")->HasHandler());
14935   CHECK(!GetPromise("q1")->HasHandler());
14936   CHECK(!GetPromise("q2")->HasHandler());
14937   CHECK(GetPromise("q_")->HasHandler());
14938   CHECK_EQ(2, promise_reject_counter);
14939   CHECK_EQ(1, promise_revoke_counter);
14940   CHECK(GetPromise("rejected")->Equals(GetPromise("q2")));
14941   CHECK(GetPromise("revoked")->Equals(GetPromise("q_")));
14942   CHECK(RejectValue()->Equals(v8_str("qqq")));
14943
14944   // Add a reject handler to the resolved q1, which rejects by throwing.
14945   CompileRun(
14946       "var q3 = q1.then(  \n"
14947       "   function() {    \n"
14948       "     throw 'qqqq'; \n"
14949       "   }               \n"
14950       ");                 \n");
14951   CHECK(GetPromise("q0")->HasHandler());
14952   CHECK(GetPromise("q1")->HasHandler());
14953   CHECK(!GetPromise("q2")->HasHandler());
14954   CHECK(!GetPromise("q3")->HasHandler());
14955   CHECK_EQ(3, promise_reject_counter);
14956   CHECK_EQ(1, promise_revoke_counter);
14957   CHECK(GetPromise("rejected")->Equals(GetPromise("q3")));
14958   CHECK(RejectValue()->Equals(v8_str("qqqq")));
14959
14960   ResetPromiseStates();
14961
14962   // Create promise r0, which has three handlers, two of which handle rejects.
14963   CompileRun(
14964       "var r0 = new Promise(             \n"
14965       "  function(res, rej) {            \n"
14966       "    reject = rej;                 \n"
14967       "  }                               \n"
14968       ");                                \n"
14969       "var r1 = r0.catch(function() {}); \n"
14970       "var r2 = r0.then(function() {});  \n"
14971       "var r3 = r0.then(function() {},   \n"
14972       "                 function() {});  \n");
14973   CHECK(GetPromise("r0")->HasHandler());
14974   CHECK(!GetPromise("r1")->HasHandler());
14975   CHECK(!GetPromise("r2")->HasHandler());
14976   CHECK(!GetPromise("r3")->HasHandler());
14977   CHECK_EQ(0, promise_reject_counter);
14978   CHECK_EQ(0, promise_revoke_counter);
14979
14980   // Reject r0.
14981   CompileRun("reject('rrr')");
14982   CHECK(GetPromise("r0")->HasHandler());
14983   CHECK(!GetPromise("r1")->HasHandler());
14984   CHECK(!GetPromise("r2")->HasHandler());
14985   CHECK(!GetPromise("r3")->HasHandler());
14986   CHECK_EQ(1, promise_reject_counter);
14987   CHECK_EQ(0, promise_revoke_counter);
14988   CHECK(GetPromise("rejected")->Equals(GetPromise("r2")));
14989   CHECK(RejectValue()->Equals(v8_str("rrr")));
14990
14991   // Add reject handler to r2.
14992   CompileRun("var r4 = r2.catch(function() {});");
14993   CHECK(GetPromise("r0")->HasHandler());
14994   CHECK(!GetPromise("r1")->HasHandler());
14995   CHECK(GetPromise("r2")->HasHandler());
14996   CHECK(!GetPromise("r3")->HasHandler());
14997   CHECK(!GetPromise("r4")->HasHandler());
14998   CHECK_EQ(1, promise_reject_counter);
14999   CHECK_EQ(1, promise_revoke_counter);
15000   CHECK(GetPromise("revoked")->Equals(GetPromise("r2")));
15001   CHECK(RejectValue()->Equals(v8_str("rrr")));
15002
15003   // Add reject handlers to r4.
15004   CompileRun("var r5 = r4.then(function() {}, function() {});");
15005   CHECK(GetPromise("r0")->HasHandler());
15006   CHECK(!GetPromise("r1")->HasHandler());
15007   CHECK(GetPromise("r2")->HasHandler());
15008   CHECK(!GetPromise("r3")->HasHandler());
15009   CHECK(GetPromise("r4")->HasHandler());
15010   CHECK(!GetPromise("r5")->HasHandler());
15011   CHECK_EQ(1, promise_reject_counter);
15012   CHECK_EQ(1, promise_revoke_counter);
15013
15014   ResetPromiseStates();
15015
15016   // Create promise s0, which has three handlers, none of which handle rejects.
15017   CompileRun(
15018       "var s0 = new Promise(            \n"
15019       "  function(res, rej) {           \n"
15020       "    reject = rej;                \n"
15021       "  }                              \n"
15022       ");                               \n"
15023       "var s1 = s0.then(function() {}); \n"
15024       "var s2 = s0.then(function() {}); \n"
15025       "var s3 = s0.then(function() {}); \n");
15026   CHECK(GetPromise("s0")->HasHandler());
15027   CHECK(!GetPromise("s1")->HasHandler());
15028   CHECK(!GetPromise("s2")->HasHandler());
15029   CHECK(!GetPromise("s3")->HasHandler());
15030   CHECK_EQ(0, promise_reject_counter);
15031   CHECK_EQ(0, promise_revoke_counter);
15032
15033   // Reject s0.
15034   CompileRun("reject('sss')");
15035   CHECK(GetPromise("s0")->HasHandler());
15036   CHECK(!GetPromise("s1")->HasHandler());
15037   CHECK(!GetPromise("s2")->HasHandler());
15038   CHECK(!GetPromise("s3")->HasHandler());
15039   CHECK_EQ(3, promise_reject_counter);
15040   CHECK_EQ(0, promise_revoke_counter);
15041   CHECK(RejectValue()->Equals(v8_str("sss")));
15042
15043   // Test stack frames.
15044   V8::SetCaptureStackTraceForUncaughtExceptions(true);
15045
15046   ResetPromiseStates();
15047
15048   // Create promise t0, which is rejected in the constructor with an error.
15049   CompileRunWithOrigin(
15050       "var t0 = new Promise(  \n"
15051       "  function(res, rej) { \n"
15052       "    reference_error;   \n"
15053       "  }                    \n"
15054       ");                     \n",
15055       "pro", 0, 0);
15056   CHECK(!GetPromise("t0")->HasHandler());
15057   CHECK_EQ(1, promise_reject_counter);
15058   CHECK_EQ(0, promise_revoke_counter);
15059   CHECK_EQ(2, promise_reject_frame_count);
15060   CHECK_EQ(3, promise_reject_line_number);
15061   CHECK_EQ(5, promise_reject_column_number);
15062   CHECK_EQ(3, promise_reject_msg_line_number);
15063   CHECK_EQ(5, promise_reject_msg_column_number);
15064
15065   ResetPromiseStates();
15066
15067   // Create promise u0 and chain u1 to it, which is rejected via throw.
15068   CompileRunWithOrigin(
15069       "var u0 = Promise.resolve();        \n"
15070       "var u1 = u0.then(                  \n"
15071       "           function() {            \n"
15072       "             (function() {         \n"
15073       "                throw new Error(); \n"
15074       "              })();                \n"
15075       "           }                       \n"
15076       "         );                        \n",
15077       "pro", 0, 0);
15078   CHECK(GetPromise("u0")->HasHandler());
15079   CHECK(!GetPromise("u1")->HasHandler());
15080   CHECK_EQ(1, promise_reject_counter);
15081   CHECK_EQ(0, promise_revoke_counter);
15082   CHECK_EQ(2, promise_reject_frame_count);
15083   CHECK_EQ(5, promise_reject_line_number);
15084   CHECK_EQ(23, promise_reject_column_number);
15085   CHECK_EQ(5, promise_reject_msg_line_number);
15086   CHECK_EQ(23, promise_reject_msg_column_number);
15087
15088   // Throw in u3, which handles u1's rejection.
15089   CompileRunWithOrigin(
15090       "function f() {                \n"
15091       "  return (function() {        \n"
15092       "    return new Error();       \n"
15093       "  })();                       \n"
15094       "}                             \n"
15095       "var u2 = Promise.reject(f()); \n"
15096       "var u3 = u1.catch(            \n"
15097       "           function() {       \n"
15098       "             return u2;       \n"
15099       "           }                  \n"
15100       "         );                   \n",
15101       "pro", 0, 0);
15102   CHECK(GetPromise("u0")->HasHandler());
15103   CHECK(GetPromise("u1")->HasHandler());
15104   CHECK(GetPromise("u2")->HasHandler());
15105   CHECK(!GetPromise("u3")->HasHandler());
15106   CHECK_EQ(3, promise_reject_counter);
15107   CHECK_EQ(2, promise_revoke_counter);
15108   CHECK_EQ(3, promise_reject_frame_count);
15109   CHECK_EQ(3, promise_reject_line_number);
15110   CHECK_EQ(12, promise_reject_column_number);
15111   CHECK_EQ(3, promise_reject_msg_line_number);
15112   CHECK_EQ(12, promise_reject_msg_column_number);
15113
15114   ResetPromiseStates();
15115
15116   // Create promise rejected promise v0, which is incorrectly handled by v1
15117   // via chaining cycle.
15118   CompileRunWithOrigin(
15119       "var v0 = Promise.reject(); \n"
15120       "var v1 = v0.catch(         \n"
15121       "           function() {    \n"
15122       "             return v1;    \n"
15123       "           }               \n"
15124       "         );                \n",
15125       "pro", 0, 0);
15126   CHECK(GetPromise("v0")->HasHandler());
15127   CHECK(!GetPromise("v1")->HasHandler());
15128   CHECK_EQ(2, promise_reject_counter);
15129   CHECK_EQ(1, promise_revoke_counter);
15130   CHECK_EQ(0, promise_reject_frame_count);
15131   CHECK_EQ(-1, promise_reject_line_number);
15132   CHECK_EQ(-1, promise_reject_column_number);
15133
15134   ResetPromiseStates();
15135
15136   // Create promise t1, which rejects by throwing syntax error from eval.
15137   CompileRunWithOrigin(
15138       "var t1 = new Promise(   \n"
15139       "  function(res, rej) {  \n"
15140       "    var content = '\\n\\\n"
15141       "      }';               \n"
15142       "    eval(content);      \n"
15143       "  }                     \n"
15144       ");                      \n",
15145       "pro", 0, 0);
15146   CHECK(!GetPromise("t1")->HasHandler());
15147   CHECK_EQ(1, promise_reject_counter);
15148   CHECK_EQ(0, promise_revoke_counter);
15149   CHECK_EQ(2, promise_reject_frame_count);
15150   CHECK_EQ(5, promise_reject_line_number);
15151   CHECK_EQ(10, promise_reject_column_number);
15152   CHECK_EQ(2, promise_reject_msg_line_number);
15153   CHECK_EQ(7, promise_reject_msg_column_number);
15154 }
15155
15156
15157 void AnalyzeStackOfEvalWithSourceURL(
15158     const v8::FunctionCallbackInfo<v8::Value>& args) {
15159   v8::HandleScope scope(args.GetIsolate());
15160   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15161       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15162   CHECK_EQ(5, stackTrace->GetFrameCount());
15163   v8::Handle<v8::String> url = v8_str("eval_url");
15164   for (int i = 0; i < 3; i++) {
15165     v8::Handle<v8::String> name =
15166         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15167     CHECK(!name.IsEmpty());
15168     CHECK(url->Equals(name));
15169   }
15170 }
15171
15172
15173 TEST(SourceURLInStackTrace) {
15174   v8::Isolate* isolate = CcTest::isolate();
15175   v8::HandleScope scope(isolate);
15176   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15177   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
15178              v8::FunctionTemplate::New(isolate,
15179                                        AnalyzeStackOfEvalWithSourceURL));
15180   LocalContext context(0, templ);
15181
15182   const char *source =
15183     "function outer() {\n"
15184     "function bar() {\n"
15185     "  AnalyzeStackOfEvalWithSourceURL();\n"
15186     "}\n"
15187     "function foo() {\n"
15188     "\n"
15189     "  bar();\n"
15190     "}\n"
15191     "foo();\n"
15192     "}\n"
15193     "eval('(' + outer +')()%s');";
15194
15195   i::ScopedVector<char> code(1024);
15196   i::SNPrintF(code, source, "//# sourceURL=eval_url");
15197   CHECK(CompileRun(code.start())->IsUndefined());
15198   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
15199   CHECK(CompileRun(code.start())->IsUndefined());
15200 }
15201
15202
15203 static int scriptIdInStack[2];
15204
15205 void AnalyzeScriptIdInStack(
15206     const v8::FunctionCallbackInfo<v8::Value>& args) {
15207   v8::HandleScope scope(args.GetIsolate());
15208   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15209       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
15210   CHECK_EQ(2, stackTrace->GetFrameCount());
15211   for (int i = 0; i < 2; i++) {
15212     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
15213   }
15214 }
15215
15216
15217 TEST(ScriptIdInStackTrace) {
15218   v8::Isolate* isolate = CcTest::isolate();
15219   v8::HandleScope scope(isolate);
15220   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15221   templ->Set(v8_str("AnalyzeScriptIdInStack"),
15222              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
15223   LocalContext context(0, templ);
15224
15225   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
15226     isolate,
15227     "function foo() {\n"
15228     "  AnalyzeScriptIdInStack();"
15229     "}\n"
15230     "foo();\n");
15231   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
15232   script->Run();
15233   for (int i = 0; i < 2; i++) {
15234     CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
15235     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
15236   }
15237 }
15238
15239
15240 void AnalyzeStackOfInlineScriptWithSourceURL(
15241     const v8::FunctionCallbackInfo<v8::Value>& args) {
15242   v8::HandleScope scope(args.GetIsolate());
15243   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15244       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15245   CHECK_EQ(4, stackTrace->GetFrameCount());
15246   v8::Handle<v8::String> url = v8_str("source_url");
15247   for (int i = 0; i < 3; i++) {
15248     v8::Handle<v8::String> name =
15249         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15250     CHECK(!name.IsEmpty());
15251     CHECK(url->Equals(name));
15252   }
15253 }
15254
15255
15256 TEST(InlineScriptWithSourceURLInStackTrace) {
15257   v8::Isolate* isolate = CcTest::isolate();
15258   v8::HandleScope scope(isolate);
15259   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15260   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
15261              v8::FunctionTemplate::New(
15262                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
15263   LocalContext context(0, templ);
15264
15265   const char *source =
15266     "function outer() {\n"
15267     "function bar() {\n"
15268     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
15269     "}\n"
15270     "function foo() {\n"
15271     "\n"
15272     "  bar();\n"
15273     "}\n"
15274     "foo();\n"
15275     "}\n"
15276     "outer()\n%s";
15277
15278   i::ScopedVector<char> code(1024);
15279   i::SNPrintF(code, source, "//# sourceURL=source_url");
15280   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
15281   i::SNPrintF(code, source, "//@ sourceURL=source_url");
15282   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
15283 }
15284
15285
15286 void AnalyzeStackOfDynamicScriptWithSourceURL(
15287     const v8::FunctionCallbackInfo<v8::Value>& args) {
15288   v8::HandleScope scope(args.GetIsolate());
15289   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15290       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15291   CHECK_EQ(4, stackTrace->GetFrameCount());
15292   v8::Handle<v8::String> url = v8_str("source_url");
15293   for (int i = 0; i < 3; i++) {
15294     v8::Handle<v8::String> name =
15295         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15296     CHECK(!name.IsEmpty());
15297     CHECK(url->Equals(name));
15298   }
15299 }
15300
15301
15302 TEST(DynamicWithSourceURLInStackTrace) {
15303   v8::Isolate* isolate = CcTest::isolate();
15304   v8::HandleScope scope(isolate);
15305   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15306   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
15307              v8::FunctionTemplate::New(
15308                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
15309   LocalContext context(0, templ);
15310
15311   const char *source =
15312     "function outer() {\n"
15313     "function bar() {\n"
15314     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
15315     "}\n"
15316     "function foo() {\n"
15317     "\n"
15318     "  bar();\n"
15319     "}\n"
15320     "foo();\n"
15321     "}\n"
15322     "outer()\n%s";
15323
15324   i::ScopedVector<char> code(1024);
15325   i::SNPrintF(code, source, "//# sourceURL=source_url");
15326   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
15327   i::SNPrintF(code, source, "//@ sourceURL=source_url");
15328   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
15329 }
15330
15331
15332 TEST(DynamicWithSourceURLInStackTraceString) {
15333   LocalContext context;
15334   v8::HandleScope scope(context->GetIsolate());
15335
15336   const char *source =
15337     "function outer() {\n"
15338     "  function foo() {\n"
15339     "    FAIL.FAIL;\n"
15340     "  }\n"
15341     "  foo();\n"
15342     "}\n"
15343     "outer()\n%s";
15344
15345   i::ScopedVector<char> code(1024);
15346   i::SNPrintF(code, source, "//# sourceURL=source_url");
15347   v8::TryCatch try_catch(context->GetIsolate());
15348   CompileRunWithOrigin(code.start(), "", 0, 0);
15349   CHECK(try_catch.HasCaught());
15350   v8::String::Utf8Value stack(try_catch.StackTrace());
15351   CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
15352 }
15353
15354
15355 TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
15356   LocalContext context;
15357   v8::HandleScope scope(context->GetIsolate());
15358
15359   const char *source =
15360     "function outer() {\n"
15361     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
15362     "  //# sourceURL=source_url\";\n"
15363     "  eval(scriptContents);\n"
15364     "  foo(); }\n"
15365     "outer();\n"
15366     "//# sourceURL=outer_url";
15367
15368   v8::TryCatch try_catch(context->GetIsolate());
15369   CompileRun(source);
15370   CHECK(try_catch.HasCaught());
15371
15372   Local<v8::Message> message = try_catch.Message();
15373   Handle<Value> sourceURL =
15374     message->GetScriptOrigin().ResourceName();
15375   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
15376 }
15377
15378
15379 TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
15380   LocalContext context;
15381   v8::HandleScope scope(context->GetIsolate());
15382
15383   const char *source =
15384     "function outer() {\n"
15385     "  var scriptContents = \"function boo(){ boo(); }\\\n"
15386     "  //# sourceURL=source_url\";\n"
15387     "  eval(scriptContents);\n"
15388     "  boo(); }\n"
15389     "outer();\n"
15390     "//# sourceURL=outer_url";
15391
15392   v8::TryCatch try_catch(context->GetIsolate());
15393   CompileRun(source);
15394   CHECK(try_catch.HasCaught());
15395
15396   Local<v8::Message> message = try_catch.Message();
15397   Handle<Value> sourceURL =
15398     message->GetScriptOrigin().ResourceName();
15399   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
15400 }
15401
15402
15403 static void CreateGarbageInOldSpace() {
15404   i::Factory* factory = CcTest::i_isolate()->factory();
15405   v8::HandleScope scope(CcTest::isolate());
15406   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
15407   for (int i = 0; i < 1000; i++) {
15408     factory->NewFixedArray(1000, i::TENURED);
15409   }
15410 }
15411
15412
15413 // Test that idle notification can be handled and eventually collects garbage.
15414 TEST(TestIdleNotification) {
15415   if (!i::FLAG_incremental_marking) return;
15416   const intptr_t MB = 1024 * 1024;
15417   const double IdlePauseInSeconds = 1.0;
15418   LocalContext env;
15419   v8::HandleScope scope(env->GetIsolate());
15420   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
15421   CreateGarbageInOldSpace();
15422   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
15423   CHECK_GT(size_with_garbage, initial_size + MB);
15424   bool finished = false;
15425   for (int i = 0; i < 200 && !finished; i++) {
15426     if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
15427       CcTest::heap()->StartIdleIncrementalMarking();
15428     }
15429     finished = env->GetIsolate()->IdleNotificationDeadline(
15430         (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
15431          static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
15432         IdlePauseInSeconds);
15433     if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
15434       CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
15435     }
15436   }
15437   intptr_t final_size = CcTest::heap()->SizeOfObjects();
15438   CHECK(finished);
15439   CHECK_LT(final_size, initial_size + 1);
15440 }
15441
15442
15443 TEST(Regress2333) {
15444   LocalContext env;
15445   for (int i = 0; i < 3; i++) {
15446     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
15447   }
15448 }
15449
15450 static uint32_t* stack_limit;
15451
15452 static void GetStackLimitCallback(
15453     const v8::FunctionCallbackInfo<v8::Value>& args) {
15454   stack_limit = reinterpret_cast<uint32_t*>(
15455       CcTest::i_isolate()->stack_guard()->real_climit());
15456 }
15457
15458
15459 // Uses the address of a local variable to determine the stack top now.
15460 // Given a size, returns an address that is that far from the current
15461 // top of stack.
15462 static uint32_t* ComputeStackLimit(uint32_t size) {
15463   uint32_t* answer = &size - (size / sizeof(size));
15464   // If the size is very large and the stack is very near the bottom of
15465   // memory then the calculation above may wrap around and give an address
15466   // that is above the (downwards-growing) stack.  In that case we return
15467   // a very low address.
15468   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
15469   return answer;
15470 }
15471
15472
15473 // We need at least 165kB for an x64 debug build with clang and ASAN.
15474 static const int stack_breathing_room = 256 * i::KB;
15475
15476
15477 TEST(SetStackLimit) {
15478   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
15479
15480   // Set stack limit.
15481   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
15482
15483   // Execute a script.
15484   LocalContext env;
15485   v8::HandleScope scope(env->GetIsolate());
15486   Local<v8::FunctionTemplate> fun_templ =
15487       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
15488   Local<Function> fun = fun_templ->GetFunction();
15489   env->Global()->Set(v8_str("get_stack_limit"), fun);
15490   CompileRun("get_stack_limit();");
15491
15492   CHECK(stack_limit == set_limit);
15493 }
15494
15495
15496 TEST(SetStackLimitInThread) {
15497   uint32_t* set_limit;
15498   {
15499     v8::Locker locker(CcTest::isolate());
15500     set_limit = ComputeStackLimit(stack_breathing_room);
15501
15502     // Set stack limit.
15503     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
15504
15505     // Execute a script.
15506     v8::HandleScope scope(CcTest::isolate());
15507     LocalContext env;
15508     Local<v8::FunctionTemplate> fun_templ =
15509         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
15510     Local<Function> fun = fun_templ->GetFunction();
15511     env->Global()->Set(v8_str("get_stack_limit"), fun);
15512     CompileRun("get_stack_limit();");
15513
15514     CHECK(stack_limit == set_limit);
15515   }
15516   {
15517     v8::Locker locker(CcTest::isolate());
15518     CHECK(stack_limit == set_limit);
15519   }
15520 }
15521
15522
15523 THREADED_TEST(GetHeapStatistics) {
15524   LocalContext c1;
15525   v8::HandleScope scope(c1->GetIsolate());
15526   v8::HeapStatistics heap_statistics;
15527   CHECK_EQ(0u, heap_statistics.total_heap_size());
15528   CHECK_EQ(0u, heap_statistics.used_heap_size());
15529   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
15530   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
15531   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
15532 }
15533
15534
15535 class VisitorImpl : public v8::ExternalResourceVisitor {
15536  public:
15537   explicit VisitorImpl(TestResource** resource) {
15538     for (int i = 0; i < 4; i++) {
15539       resource_[i] = resource[i];
15540       found_resource_[i] = false;
15541     }
15542   }
15543   virtual ~VisitorImpl() {}
15544   virtual void VisitExternalString(v8::Handle<v8::String> string) {
15545     if (!string->IsExternal()) {
15546       CHECK(string->IsExternalOneByte());
15547       return;
15548     }
15549     v8::String::ExternalStringResource* resource =
15550         string->GetExternalStringResource();
15551     CHECK(resource);
15552     for (int i = 0; i < 4; i++) {
15553       if (resource_[i] == resource) {
15554         CHECK(!found_resource_[i]);
15555         found_resource_[i] = true;
15556       }
15557     }
15558   }
15559   void CheckVisitedResources() {
15560     for (int i = 0; i < 4; i++) {
15561       CHECK(found_resource_[i]);
15562     }
15563   }
15564
15565  private:
15566   v8::String::ExternalStringResource* resource_[4];
15567   bool found_resource_[4];
15568 };
15569
15570
15571 TEST(ExternalizeOldSpaceTwoByteCons) {
15572   v8::Isolate* isolate = CcTest::isolate();
15573   LocalContext env;
15574   v8::HandleScope scope(isolate);
15575   v8::Local<v8::String> cons =
15576       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
15577   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
15578   CcTest::heap()->CollectAllAvailableGarbage();
15579   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
15580
15581   TestResource* resource = new TestResource(
15582       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
15583   cons->MakeExternal(resource);
15584
15585   CHECK(cons->IsExternal());
15586   CHECK_EQ(resource, cons->GetExternalStringResource());
15587   String::Encoding encoding;
15588   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
15589   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
15590 }
15591
15592
15593 TEST(ExternalizeOldSpaceOneByteCons) {
15594   v8::Isolate* isolate = CcTest::isolate();
15595   LocalContext env;
15596   v8::HandleScope scope(isolate);
15597   v8::Local<v8::String> cons =
15598       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
15599   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
15600   CcTest::heap()->CollectAllAvailableGarbage();
15601   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
15602
15603   TestOneByteResource* resource =
15604       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
15605   cons->MakeExternal(resource);
15606
15607   CHECK(cons->IsExternalOneByte());
15608   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
15609   String::Encoding encoding;
15610   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
15611   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
15612 }
15613
15614
15615 TEST(VisitExternalStrings) {
15616   v8::Isolate* isolate = CcTest::isolate();
15617   LocalContext env;
15618   v8::HandleScope scope(isolate);
15619   const char* string = "Some string";
15620   uint16_t* two_byte_string = AsciiToTwoByteString(string);
15621   TestResource* resource[4];
15622   resource[0] = new TestResource(two_byte_string);
15623   v8::Local<v8::String> string0 =
15624       v8::String::NewExternal(env->GetIsolate(), resource[0]);
15625   resource[1] = new TestResource(two_byte_string, NULL, false);
15626   v8::Local<v8::String> string1 =
15627       v8::String::NewExternal(env->GetIsolate(), resource[1]);
15628
15629   // Externalized symbol.
15630   resource[2] = new TestResource(two_byte_string, NULL, false);
15631   v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
15632       env->GetIsolate(), string, v8::String::kInternalizedString);
15633   CHECK(string2->MakeExternal(resource[2]));
15634
15635   // Symbolized External.
15636   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
15637   v8::Local<v8::String> string3 =
15638       v8::String::NewExternal(env->GetIsolate(), resource[3]);
15639   CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
15640   // Turn into a symbol.
15641   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
15642   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
15643       string3_i).is_null());
15644   CHECK(string3_i->IsInternalizedString());
15645
15646   // We need to add usages for string* to avoid warnings in GCC 4.7
15647   CHECK(string0->IsExternal());
15648   CHECK(string1->IsExternal());
15649   CHECK(string2->IsExternal());
15650   CHECK(string3->IsExternal());
15651
15652   VisitorImpl visitor(resource);
15653   v8::V8::VisitExternalResources(&visitor);
15654   visitor.CheckVisitedResources();
15655 }
15656
15657
15658 TEST(ExternalStringCollectedAtTearDown) {
15659   int destroyed = 0;
15660   v8::Isolate::CreateParams create_params;
15661   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
15662   v8::Isolate* isolate = v8::Isolate::New(create_params);
15663   { v8::Isolate::Scope isolate_scope(isolate);
15664     v8::HandleScope handle_scope(isolate);
15665     const char* s = "One string to test them all, one string to find them.";
15666     TestOneByteResource* inscription =
15667         new TestOneByteResource(i::StrDup(s), &destroyed);
15668     v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
15669     // Ring is still alive.  Orcs are roaming freely across our lands.
15670     CHECK_EQ(0, destroyed);
15671     USE(ring);
15672   }
15673
15674   isolate->Dispose();
15675   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
15676   CHECK_EQ(1, destroyed);
15677 }
15678
15679
15680 TEST(ExternalInternalizedStringCollectedAtTearDown) {
15681   int destroyed = 0;
15682   v8::Isolate::CreateParams create_params;
15683   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
15684   v8::Isolate* isolate = v8::Isolate::New(create_params);
15685   { v8::Isolate::Scope isolate_scope(isolate);
15686     LocalContext env(isolate);
15687     v8::HandleScope handle_scope(isolate);
15688     CompileRun("var ring = 'One string to test them all';");
15689     const char* s = "One string to test them all";
15690     TestOneByteResource* inscription =
15691         new TestOneByteResource(i::StrDup(s), &destroyed);
15692     v8::Local<v8::String> ring = CompileRun("ring")->ToString(isolate);
15693     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
15694     ring->MakeExternal(inscription);
15695     // Ring is still alive.  Orcs are roaming freely across our lands.
15696     CHECK_EQ(0, destroyed);
15697     USE(ring);
15698   }
15699
15700   isolate->Dispose();
15701   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
15702   CHECK_EQ(1, destroyed);
15703 }
15704
15705
15706 TEST(ExternalInternalizedStringCollectedAtGC) {
15707   int destroyed = 0;
15708   { LocalContext env;
15709     v8::HandleScope handle_scope(env->GetIsolate());
15710     CompileRun("var ring = 'One string to test them all';");
15711     const char* s = "One string to test them all";
15712     TestOneByteResource* inscription =
15713         new TestOneByteResource(i::StrDup(s), &destroyed);
15714     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
15715     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
15716     ring->MakeExternal(inscription);
15717     // Ring is still alive.  Orcs are roaming freely across our lands.
15718     CHECK_EQ(0, destroyed);
15719     USE(ring);
15720   }
15721
15722   // Garbage collector deals swift blows to evil.
15723   CcTest::i_isolate()->compilation_cache()->Clear();
15724   CcTest::heap()->CollectAllAvailableGarbage();
15725
15726   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
15727   CHECK_EQ(1, destroyed);
15728 }
15729
15730
15731 static double DoubleFromBits(uint64_t value) {
15732   double target;
15733   i::MemCopy(&target, &value, sizeof(target));
15734   return target;
15735 }
15736
15737
15738 static uint64_t DoubleToBits(double value) {
15739   uint64_t target;
15740   i::MemCopy(&target, &value, sizeof(target));
15741   return target;
15742 }
15743
15744
15745 static double DoubleToDateTime(double input) {
15746   double date_limit = 864e13;
15747   if (std::isnan(input) || input < -date_limit || input > date_limit) {
15748     return std::numeric_limits<double>::quiet_NaN();
15749   }
15750   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
15751 }
15752
15753
15754 // We don't have a consistent way to write 64-bit constants syntactically, so we
15755 // split them into two 32-bit constants and combine them programmatically.
15756 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
15757   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
15758 }
15759
15760
15761 THREADED_TEST(QuietSignalingNaNs) {
15762   LocalContext context;
15763   v8::Isolate* isolate = context->GetIsolate();
15764   v8::HandleScope scope(isolate);
15765   v8::TryCatch try_catch(isolate);
15766
15767   // Special double values.
15768   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
15769   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
15770   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
15771   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
15772   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
15773   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
15774   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
15775
15776   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
15777   // on either side of the epoch.
15778   double date_limit = 864e13;
15779
15780   double test_values[] = {
15781       snan,
15782       qnan,
15783       infinity,
15784       max_normal,
15785       date_limit + 1,
15786       date_limit,
15787       min_normal,
15788       max_denormal,
15789       min_denormal,
15790       0,
15791       -0,
15792       -min_denormal,
15793       -max_denormal,
15794       -min_normal,
15795       -date_limit,
15796       -date_limit - 1,
15797       -max_normal,
15798       -infinity,
15799       -qnan,
15800       -snan
15801   };
15802   int num_test_values = 20;
15803
15804   for (int i = 0; i < num_test_values; i++) {
15805     double test_value = test_values[i];
15806
15807     // Check that Number::New preserves non-NaNs and quiets SNaNs.
15808     v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
15809     double stored_number = number->NumberValue();
15810     if (!std::isnan(test_value)) {
15811       CHECK_EQ(test_value, stored_number);
15812     } else {
15813       uint64_t stored_bits = DoubleToBits(stored_number);
15814       // Check if quiet nan (bits 51..62 all set).
15815 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
15816     !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
15817       // Most significant fraction bit for quiet nan is set to 0
15818       // on MIPS architecture. Allowed by IEEE-754.
15819       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
15820 #else
15821       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
15822 #endif
15823     }
15824
15825     // Check that Date::New preserves non-NaNs in the date range and
15826     // quiets SNaNs.
15827     v8::Handle<v8::Value> date =
15828         v8::Date::New(isolate, test_value);
15829     double expected_stored_date = DoubleToDateTime(test_value);
15830     double stored_date = date->NumberValue();
15831     if (!std::isnan(expected_stored_date)) {
15832       CHECK_EQ(expected_stored_date, stored_date);
15833     } else {
15834       uint64_t stored_bits = DoubleToBits(stored_date);
15835       // Check if quiet nan (bits 51..62 all set).
15836 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
15837     !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
15838       // Most significant fraction bit for quiet nan is set to 0
15839       // on MIPS architecture. Allowed by IEEE-754.
15840       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
15841 #else
15842       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
15843 #endif
15844     }
15845   }
15846 }
15847
15848
15849 static void SpaghettiIncident(
15850     const v8::FunctionCallbackInfo<v8::Value>& args) {
15851   v8::HandleScope scope(args.GetIsolate());
15852   v8::TryCatch tc(args.GetIsolate());
15853   v8::Handle<v8::String> str(args[0]->ToString(args.GetIsolate()));
15854   USE(str);
15855   if (tc.HasCaught())
15856     tc.ReThrow();
15857 }
15858
15859
15860 // Test that an exception can be propagated down through a spaghetti
15861 // stack using ReThrow.
15862 THREADED_TEST(SpaghettiStackReThrow) {
15863   v8::Isolate* isolate = CcTest::isolate();
15864   v8::HandleScope scope(isolate);
15865   LocalContext context;
15866   context->Global()->Set(
15867       v8::String::NewFromUtf8(isolate, "s"),
15868       v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
15869   v8::TryCatch try_catch(isolate);
15870   CompileRun(
15871       "var i = 0;"
15872       "var o = {"
15873       "  toString: function () {"
15874       "    if (i == 10) {"
15875       "      throw 'Hey!';"
15876       "    } else {"
15877       "      i++;"
15878       "      return s(o);"
15879       "    }"
15880       "  }"
15881       "};"
15882       "s(o);");
15883   CHECK(try_catch.HasCaught());
15884   v8::String::Utf8Value value(try_catch.Exception());
15885   CHECK_EQ(0, strcmp(*value, "Hey!"));
15886 }
15887
15888
15889 TEST(Regress528) {
15890   v8::V8::Initialize();
15891   v8::Isolate* isolate = CcTest::isolate();
15892   i::FLAG_retain_maps_for_n_gc = 0;
15893   v8::HandleScope scope(isolate);
15894   v8::Local<Context> other_context;
15895   int gc_count;
15896
15897   // Create a context used to keep the code from aging in the compilation
15898   // cache.
15899   other_context = Context::New(isolate);
15900
15901   // Context-dependent context data creates reference from the compilation
15902   // cache to the global object.
15903   const char* source_simple = "1";
15904   {
15905     v8::HandleScope scope(isolate);
15906     v8::Local<Context> context = Context::New(isolate);
15907
15908     context->Enter();
15909     Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
15910     context->SetEmbedderData(0, obj);
15911     CompileRun(source_simple);
15912     context->Exit();
15913   }
15914   isolate->ContextDisposedNotification();
15915   for (gc_count = 1; gc_count < 10; gc_count++) {
15916     other_context->Enter();
15917     CompileRun(source_simple);
15918     other_context->Exit();
15919     CcTest::heap()->CollectAllGarbage();
15920     if (GetGlobalObjectsCount() == 1) break;
15921   }
15922   CHECK_GE(2, gc_count);
15923   CHECK_EQ(1, GetGlobalObjectsCount());
15924
15925   // Eval in a function creates reference from the compilation cache to the
15926   // global object.
15927   const char* source_eval = "function f(){eval('1')}; f()";
15928   {
15929     v8::HandleScope scope(isolate);
15930     v8::Local<Context> context = Context::New(isolate);
15931
15932     context->Enter();
15933     CompileRun(source_eval);
15934     context->Exit();
15935   }
15936   isolate->ContextDisposedNotification();
15937   for (gc_count = 1; gc_count < 10; gc_count++) {
15938     other_context->Enter();
15939     CompileRun(source_eval);
15940     other_context->Exit();
15941     CcTest::heap()->CollectAllGarbage();
15942     if (GetGlobalObjectsCount() == 1) break;
15943   }
15944   CHECK_GE(2, gc_count);
15945   CHECK_EQ(1, GetGlobalObjectsCount());
15946
15947   // Looking up the line number for an exception creates reference from the
15948   // compilation cache to the global object.
15949   const char* source_exception = "function f(){throw 1;} f()";
15950   {
15951     v8::HandleScope scope(isolate);
15952     v8::Local<Context> context = Context::New(isolate);
15953
15954     context->Enter();
15955     v8::TryCatch try_catch(isolate);
15956     CompileRun(source_exception);
15957     CHECK(try_catch.HasCaught());
15958     v8::Handle<v8::Message> message = try_catch.Message();
15959     CHECK(!message.IsEmpty());
15960     CHECK_EQ(1, message->GetLineNumber());
15961     context->Exit();
15962   }
15963   isolate->ContextDisposedNotification();
15964   for (gc_count = 1; gc_count < 10; gc_count++) {
15965     other_context->Enter();
15966     CompileRun(source_exception);
15967     other_context->Exit();
15968     CcTest::heap()->CollectAllGarbage();
15969     if (GetGlobalObjectsCount() == 1) break;
15970   }
15971   CHECK_GE(2, gc_count);
15972   CHECK_EQ(1, GetGlobalObjectsCount());
15973
15974   isolate->ContextDisposedNotification();
15975 }
15976
15977
15978 THREADED_TEST(ScriptOrigin) {
15979   LocalContext env;
15980   v8::HandleScope scope(env->GetIsolate());
15981   v8::ScriptOrigin origin = v8::ScriptOrigin(
15982       v8::String::NewFromUtf8(env->GetIsolate(), "test"),
15983       v8::Integer::New(env->GetIsolate(), 1),
15984       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
15985       v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()),
15986       v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl"),
15987       v8::True(env->GetIsolate()));
15988   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
15989       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
15990   v8::Script::Compile(script, &origin)->Run();
15991   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15992       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
15993   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
15994       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
15995
15996   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
15997   CHECK_EQ(0, strcmp("test",
15998                      *v8::String::Utf8Value(script_origin_f.ResourceName())));
15999   CHECK_EQ(1, script_origin_f.ResourceLineOffset()->Int32Value());
16000   CHECK(script_origin_f.Options().IsSharedCrossOrigin());
16001   CHECK(script_origin_f.Options().IsEmbedderDebugScript());
16002   CHECK(script_origin_f.Options().IsOpaque());
16003   printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
16004
16005   CHECK_EQ(0, strcmp("http://sourceMapUrl",
16006                      *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
16007
16008   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
16009   CHECK_EQ(0, strcmp("test",
16010                      *v8::String::Utf8Value(script_origin_g.ResourceName())));
16011   CHECK_EQ(1, script_origin_g.ResourceLineOffset()->Int32Value());
16012   CHECK(script_origin_g.Options().IsSharedCrossOrigin());
16013   CHECK(script_origin_g.Options().IsEmbedderDebugScript());
16014   CHECK(script_origin_g.Options().IsOpaque());
16015   CHECK_EQ(0, strcmp("http://sourceMapUrl",
16016                      *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
16017 }
16018
16019
16020 THREADED_TEST(FunctionGetInferredName) {
16021   LocalContext env;
16022   v8::HandleScope scope(env->GetIsolate());
16023   v8::ScriptOrigin origin =
16024       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16025   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16026       env->GetIsolate(),
16027       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
16028   v8::Script::Compile(script, &origin)->Run();
16029   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16030       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16031   CHECK_EQ(0,
16032            strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
16033 }
16034
16035
16036 THREADED_TEST(FunctionGetDisplayName) {
16037   LocalContext env;
16038   v8::HandleScope scope(env->GetIsolate());
16039   const char* code = "var error = false;"
16040                      "function a() { this.x = 1; };"
16041                      "a.displayName = 'display_a';"
16042                      "var b = (function() {"
16043                      "  var f = function() { this.x = 2; };"
16044                      "  f.displayName = 'display_b';"
16045                      "  return f;"
16046                      "})();"
16047                      "var c = function() {};"
16048                      "c.__defineGetter__('displayName', function() {"
16049                      "  error = true;"
16050                      "  throw new Error();"
16051                      "});"
16052                      "function d() {};"
16053                      "d.__defineGetter__('displayName', function() {"
16054                      "  error = true;"
16055                      "  return 'wrong_display_name';"
16056                      "});"
16057                      "function e() {};"
16058                      "e.displayName = 'wrong_display_name';"
16059                      "e.__defineSetter__('displayName', function() {"
16060                      "  error = true;"
16061                      "  throw new Error();"
16062                      "});"
16063                      "function f() {};"
16064                      "f.displayName = { 'foo': 6, toString: function() {"
16065                      "  error = true;"
16066                      "  return 'wrong_display_name';"
16067                      "}};"
16068                      "var g = function() {"
16069                      "  arguments.callee.displayName = 'set_in_runtime';"
16070                      "}; g();"
16071                      ;
16072   v8::ScriptOrigin origin =
16073       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16074   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
16075       ->Run();
16076   v8::Local<v8::Value> error =
16077       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
16078   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
16079       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
16080   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
16081       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
16082   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
16083       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
16084   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
16085       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
16086   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
16087       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
16088   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16089       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16090   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16091       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16092   CHECK_EQ(false, error->BooleanValue());
16093   CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
16094   CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
16095   CHECK(c->GetDisplayName()->IsUndefined());
16096   CHECK(d->GetDisplayName()->IsUndefined());
16097   CHECK(e->GetDisplayName()->IsUndefined());
16098   CHECK(f->GetDisplayName()->IsUndefined());
16099   CHECK_EQ(
16100       0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
16101 }
16102
16103
16104 THREADED_TEST(ScriptLineNumber) {
16105   LocalContext env;
16106   v8::HandleScope scope(env->GetIsolate());
16107   v8::ScriptOrigin origin =
16108       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16109   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16110       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
16111   v8::Script::Compile(script, &origin)->Run();
16112   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16113       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16114   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16115       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16116   CHECK_EQ(0, f->GetScriptLineNumber());
16117   CHECK_EQ(2, g->GetScriptLineNumber());
16118 }
16119
16120
16121 THREADED_TEST(ScriptColumnNumber) {
16122   LocalContext env;
16123   v8::Isolate* isolate = env->GetIsolate();
16124   v8::HandleScope scope(isolate);
16125   v8::ScriptOrigin origin =
16126       v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
16127                        v8::Integer::New(isolate, 3),
16128                        v8::Integer::New(isolate, 2));
16129   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16130       isolate, "function foo() {}\n\n     function bar() {}");
16131   v8::Script::Compile(script, &origin)->Run();
16132   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
16133       env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
16134   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
16135       env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
16136   CHECK_EQ(14, foo->GetScriptColumnNumber());
16137   CHECK_EQ(17, bar->GetScriptColumnNumber());
16138 }
16139
16140
16141 THREADED_TEST(FunctionIsBuiltin) {
16142   LocalContext env;
16143   v8::Isolate* isolate = env->GetIsolate();
16144   v8::HandleScope scope(isolate);
16145   v8::Local<v8::Function> f;
16146   f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
16147   CHECK(f->IsBuiltin());
16148   f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
16149   CHECK(f->IsBuiltin());
16150   f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
16151   CHECK(f->IsBuiltin());
16152   f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
16153   CHECK(f->IsBuiltin());
16154   f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
16155   CHECK(!f->IsBuiltin());
16156 }
16157
16158
16159 THREADED_TEST(FunctionGetScriptId) {
16160   LocalContext env;
16161   v8::Isolate* isolate = env->GetIsolate();
16162   v8::HandleScope scope(isolate);
16163   v8::ScriptOrigin origin =
16164       v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
16165                        v8::Integer::New(isolate, 3),
16166                        v8::Integer::New(isolate, 2));
16167   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
16168       isolate, "function foo() {}\n\n     function bar() {}");
16169   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
16170   script->Run();
16171   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
16172       env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
16173   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
16174       env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
16175   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
16176   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
16177 }
16178
16179
16180 THREADED_TEST(FunctionGetBoundFunction) {
16181   LocalContext env;
16182   v8::HandleScope scope(env->GetIsolate());
16183   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
16184       env->GetIsolate(), "test"));
16185   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16186       env->GetIsolate(),
16187       "var a = new Object();\n"
16188       "a.x = 1;\n"
16189       "function f () { return this.x };\n"
16190       "var g = f.bind(a);\n"
16191       "var b = g();");
16192   v8::Script::Compile(script, &origin)->Run();
16193   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16194       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16195   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16196       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16197   CHECK(g->GetBoundFunction()->IsFunction());
16198   Local<v8::Function> original_function = Local<v8::Function>::Cast(
16199       g->GetBoundFunction());
16200   CHECK(f->GetName()->Equals(original_function->GetName()));
16201   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
16202   CHECK_EQ(f->GetScriptColumnNumber(),
16203            original_function->GetScriptColumnNumber());
16204 }
16205
16206
16207 static void GetterWhichReturns42(
16208     Local<String> name,
16209     const v8::PropertyCallbackInfo<v8::Value>& info) {
16210   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16211   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16212   info.GetReturnValue().Set(v8_num(42));
16213 }
16214
16215
16216 static void SetterWhichSetsYOnThisTo23(
16217     Local<String> name,
16218     Local<Value> value,
16219     const v8::PropertyCallbackInfo<void>& info) {
16220   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16221   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16222   Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16223 }
16224
16225
16226 void FooGetInterceptor(Local<Name> name,
16227                        const v8::PropertyCallbackInfo<v8::Value>& info) {
16228   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16229   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16230   if (!name->Equals(v8_str("foo"))) return;
16231   info.GetReturnValue().Set(v8_num(42));
16232 }
16233
16234
16235 void FooSetInterceptor(Local<Name> name, Local<Value> value,
16236                        const v8::PropertyCallbackInfo<v8::Value>& info) {
16237   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16238   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16239   if (!name->Equals(v8_str("foo"))) return;
16240   Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16241   info.GetReturnValue().Set(v8_num(23));
16242 }
16243
16244
16245 TEST(SetterOnConstructorPrototype) {
16246   v8::Isolate* isolate = CcTest::isolate();
16247   v8::HandleScope scope(isolate);
16248   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16249   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
16250                      SetterWhichSetsYOnThisTo23);
16251   LocalContext context;
16252   context->Global()->Set(v8_str("P"), templ->NewInstance());
16253   CompileRun("function C1() {"
16254              "  this.x = 23;"
16255              "};"
16256              "C1.prototype = P;"
16257              "function C2() {"
16258              "  this.x = 23"
16259              "};"
16260              "C2.prototype = { };"
16261              "C2.prototype.__proto__ = P;");
16262
16263   v8::Local<v8::Script> script;
16264   script = v8_compile("new C1();");
16265   for (int i = 0; i < 10; i++) {
16266     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16267     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
16268     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
16269   }
16270
16271 script = v8_compile("new C2();");
16272   for (int i = 0; i < 10; i++) {
16273     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
16274     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
16275     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
16276   }
16277 }
16278
16279
16280 static void NamedPropertyGetterWhichReturns42(
16281     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
16282   info.GetReturnValue().Set(v8_num(42));
16283 }
16284
16285
16286 static void NamedPropertySetterWhichSetsYOnThisTo23(
16287     Local<Name> name, Local<Value> value,
16288     const v8::PropertyCallbackInfo<v8::Value>& info) {
16289   if (name->Equals(v8_str("x"))) {
16290     Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16291   }
16292 }
16293
16294
16295 THREADED_TEST(InterceptorOnConstructorPrototype) {
16296   v8::Isolate* isolate = CcTest::isolate();
16297   v8::HandleScope scope(isolate);
16298   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16299   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
16300       NamedPropertyGetterWhichReturns42,
16301       NamedPropertySetterWhichSetsYOnThisTo23));
16302   LocalContext context;
16303   context->Global()->Set(v8_str("P"), templ->NewInstance());
16304   CompileRun("function C1() {"
16305              "  this.x = 23;"
16306              "};"
16307              "C1.prototype = P;"
16308              "function C2() {"
16309              "  this.x = 23"
16310              "};"
16311              "C2.prototype = { };"
16312              "C2.prototype.__proto__ = P;");
16313
16314   v8::Local<v8::Script> script;
16315   script = v8_compile("new C1();");
16316   for (int i = 0; i < 10; i++) {
16317     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16318     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
16319     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
16320   }
16321
16322   script = v8_compile("new C2();");
16323   for (int i = 0; i < 10; i++) {
16324     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
16325     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
16326     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
16327   }
16328 }
16329
16330
16331 TEST(Regress618) {
16332   const char* source = "function C1() {"
16333                        "  this.x = 23;"
16334                        "};"
16335                        "C1.prototype = P;";
16336
16337   LocalContext context;
16338   v8::Isolate* isolate = context->GetIsolate();
16339   v8::HandleScope scope(isolate);
16340   v8::Local<v8::Script> script;
16341
16342   // Use a simple object as prototype.
16343   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
16344   prototype->Set(v8_str("y"), v8_num(42));
16345   context->Global()->Set(v8_str("P"), prototype);
16346
16347   // This compile will add the code to the compilation cache.
16348   CompileRun(source);
16349
16350   script = v8_compile("new C1();");
16351   // Allow enough iterations for the inobject slack tracking logic
16352   // to finalize instance size and install the fast construct stub.
16353   for (int i = 0; i < 256; i++) {
16354     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16355     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
16356     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
16357   }
16358
16359   // Use an API object with accessors as prototype.
16360   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16361   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
16362                      SetterWhichSetsYOnThisTo23);
16363   context->Global()->Set(v8_str("P"), templ->NewInstance());
16364
16365   // This compile will get the code from the compilation cache.
16366   CompileRun(source);
16367
16368   script = v8_compile("new C1();");
16369   for (int i = 0; i < 10; i++) {
16370     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16371     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
16372     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
16373   }
16374 }
16375
16376 v8::Isolate* gc_callbacks_isolate = NULL;
16377 int prologue_call_count = 0;
16378 int epilogue_call_count = 0;
16379 int prologue_call_count_second = 0;
16380 int epilogue_call_count_second = 0;
16381 int prologue_call_count_alloc = 0;
16382 int epilogue_call_count_alloc = 0;
16383
16384 void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
16385   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16386   ++prologue_call_count;
16387 }
16388
16389
16390 void PrologueCallback(v8::Isolate* isolate,
16391                       v8::GCType,
16392                       v8::GCCallbackFlags flags) {
16393   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16394   CHECK_EQ(gc_callbacks_isolate, isolate);
16395   ++prologue_call_count;
16396 }
16397
16398
16399 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
16400   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16401   ++epilogue_call_count;
16402 }
16403
16404
16405 void EpilogueCallback(v8::Isolate* isolate,
16406                       v8::GCType,
16407                       v8::GCCallbackFlags flags) {
16408   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16409   CHECK_EQ(gc_callbacks_isolate, isolate);
16410   ++epilogue_call_count;
16411 }
16412
16413
16414 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
16415   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16416   ++prologue_call_count_second;
16417 }
16418
16419
16420 void PrologueCallbackSecond(v8::Isolate* isolate,
16421                             v8::GCType,
16422                             v8::GCCallbackFlags flags) {
16423   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16424   CHECK_EQ(gc_callbacks_isolate, isolate);
16425   ++prologue_call_count_second;
16426 }
16427
16428
16429 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
16430   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16431   ++epilogue_call_count_second;
16432 }
16433
16434
16435 void EpilogueCallbackSecond(v8::Isolate* isolate,
16436                             v8::GCType,
16437                             v8::GCCallbackFlags flags) {
16438   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16439   CHECK_EQ(gc_callbacks_isolate, isolate);
16440   ++epilogue_call_count_second;
16441 }
16442
16443
16444 void PrologueCallbackAlloc(v8::Isolate* isolate,
16445                            v8::GCType,
16446                            v8::GCCallbackFlags flags) {
16447   v8::HandleScope scope(isolate);
16448
16449   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16450   CHECK_EQ(gc_callbacks_isolate, isolate);
16451   ++prologue_call_count_alloc;
16452
16453   // Simulate full heap to see if we will reenter this callback
16454   SimulateFullSpace(CcTest::heap()->new_space());
16455
16456   Local<Object> obj = Object::New(isolate);
16457   CHECK(!obj.IsEmpty());
16458
16459   CcTest::heap()->CollectAllGarbage(
16460       i::Heap::kAbortIncrementalMarkingMask);
16461 }
16462
16463
16464 void EpilogueCallbackAlloc(v8::Isolate* isolate,
16465                            v8::GCType,
16466                            v8::GCCallbackFlags flags) {
16467   v8::HandleScope scope(isolate);
16468
16469   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16470   CHECK_EQ(gc_callbacks_isolate, isolate);
16471   ++epilogue_call_count_alloc;
16472
16473   // Simulate full heap to see if we will reenter this callback
16474   SimulateFullSpace(CcTest::heap()->new_space());
16475
16476   Local<Object> obj = Object::New(isolate);
16477   CHECK(!obj.IsEmpty());
16478
16479   CcTest::heap()->CollectAllGarbage(
16480       i::Heap::kAbortIncrementalMarkingMask);
16481 }
16482
16483
16484 TEST(GCCallbacksOld) {
16485   LocalContext context;
16486
16487   v8::V8::AddGCPrologueCallback(PrologueCallback);
16488   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
16489   CHECK_EQ(0, prologue_call_count);
16490   CHECK_EQ(0, epilogue_call_count);
16491   CcTest::heap()->CollectAllGarbage();
16492   CHECK_EQ(1, prologue_call_count);
16493   CHECK_EQ(1, epilogue_call_count);
16494   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
16495   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
16496   CcTest::heap()->CollectAllGarbage();
16497   CHECK_EQ(2, prologue_call_count);
16498   CHECK_EQ(2, epilogue_call_count);
16499   CHECK_EQ(1, prologue_call_count_second);
16500   CHECK_EQ(1, epilogue_call_count_second);
16501   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
16502   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
16503   CcTest::heap()->CollectAllGarbage();
16504   CHECK_EQ(2, prologue_call_count);
16505   CHECK_EQ(2, epilogue_call_count);
16506   CHECK_EQ(2, prologue_call_count_second);
16507   CHECK_EQ(2, epilogue_call_count_second);
16508   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
16509   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
16510   CcTest::heap()->CollectAllGarbage();
16511   CHECK_EQ(2, prologue_call_count);
16512   CHECK_EQ(2, epilogue_call_count);
16513   CHECK_EQ(2, prologue_call_count_second);
16514   CHECK_EQ(2, epilogue_call_count_second);
16515 }
16516
16517
16518 TEST(GCCallbacks) {
16519   LocalContext context;
16520   v8::Isolate* isolate = context->GetIsolate();
16521   gc_callbacks_isolate = isolate;
16522   isolate->AddGCPrologueCallback(PrologueCallback);
16523   isolate->AddGCEpilogueCallback(EpilogueCallback);
16524   CHECK_EQ(0, prologue_call_count);
16525   CHECK_EQ(0, epilogue_call_count);
16526   CcTest::heap()->CollectAllGarbage();
16527   CHECK_EQ(1, prologue_call_count);
16528   CHECK_EQ(1, epilogue_call_count);
16529   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
16530   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
16531   CcTest::heap()->CollectAllGarbage();
16532   CHECK_EQ(2, prologue_call_count);
16533   CHECK_EQ(2, epilogue_call_count);
16534   CHECK_EQ(1, prologue_call_count_second);
16535   CHECK_EQ(1, epilogue_call_count_second);
16536   isolate->RemoveGCPrologueCallback(PrologueCallback);
16537   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
16538   CcTest::heap()->CollectAllGarbage();
16539   CHECK_EQ(2, prologue_call_count);
16540   CHECK_EQ(2, epilogue_call_count);
16541   CHECK_EQ(2, prologue_call_count_second);
16542   CHECK_EQ(2, epilogue_call_count_second);
16543   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
16544   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
16545   CcTest::heap()->CollectAllGarbage();
16546   CHECK_EQ(2, prologue_call_count);
16547   CHECK_EQ(2, epilogue_call_count);
16548   CHECK_EQ(2, prologue_call_count_second);
16549   CHECK_EQ(2, epilogue_call_count_second);
16550
16551   CHECK_EQ(0, prologue_call_count_alloc);
16552   CHECK_EQ(0, epilogue_call_count_alloc);
16553   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
16554   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
16555   CcTest::heap()->CollectAllGarbage(
16556       i::Heap::kAbortIncrementalMarkingMask);
16557   CHECK_EQ(1, prologue_call_count_alloc);
16558   CHECK_EQ(1, epilogue_call_count_alloc);
16559   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
16560   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
16561 }
16562
16563
16564 THREADED_TEST(TwoByteStringInOneByteCons) {
16565   // See Chromium issue 47824.
16566   LocalContext context;
16567   v8::HandleScope scope(context->GetIsolate());
16568
16569   const char* init_code =
16570       "var str1 = 'abelspendabel';"
16571       "var str2 = str1 + str1 + str1;"
16572       "str2;";
16573   Local<Value> result = CompileRun(init_code);
16574
16575   Local<Value> indexof = CompileRun("str2.indexOf('els')");
16576   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
16577
16578   CHECK(result->IsString());
16579   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
16580   int length = string->length();
16581   CHECK(string->IsOneByteRepresentation());
16582
16583   i::Handle<i::String> flat_string = i::String::Flatten(string);
16584
16585   CHECK(string->IsOneByteRepresentation());
16586   CHECK(flat_string->IsOneByteRepresentation());
16587
16588   // Create external resource.
16589   uint16_t* uc16_buffer = new uint16_t[length + 1];
16590
16591   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
16592   uc16_buffer[length] = 0;
16593
16594   TestResource resource(uc16_buffer);
16595
16596   flat_string->MakeExternal(&resource);
16597
16598   CHECK(flat_string->IsTwoByteRepresentation());
16599
16600   // If the cons string has been short-circuited, skip the following checks.
16601   if (!string.is_identical_to(flat_string)) {
16602     // At this point, we should have a Cons string which is flat and one-byte,
16603     // with a first half that is a two-byte string (although it only contains
16604     // one-byte characters). This is a valid sequence of steps, and it can
16605     // happen in real pages.
16606     CHECK(string->IsOneByteRepresentation());
16607     i::ConsString* cons = i::ConsString::cast(*string);
16608     CHECK_EQ(0, cons->second()->length());
16609     CHECK(cons->first()->IsTwoByteRepresentation());
16610   }
16611
16612   // Check that some string operations work.
16613
16614   // Atom RegExp.
16615   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
16616   CHECK_EQ(6, reresult->Int32Value());
16617
16618   // Nonatom RegExp.
16619   reresult = CompileRun("str2.match(/abe./g).length;");
16620   CHECK_EQ(6, reresult->Int32Value());
16621
16622   reresult = CompileRun("str2.search(/bel/g);");
16623   CHECK_EQ(1, reresult->Int32Value());
16624
16625   reresult = CompileRun("str2.search(/be./g);");
16626   CHECK_EQ(1, reresult->Int32Value());
16627
16628   ExpectTrue("/bel/g.test(str2);");
16629
16630   ExpectTrue("/be./g.test(str2);");
16631
16632   reresult = CompileRun("/bel/g.exec(str2);");
16633   CHECK(!reresult->IsNull());
16634
16635   reresult = CompileRun("/be./g.exec(str2);");
16636   CHECK(!reresult->IsNull());
16637
16638   ExpectString("str2.substring(2, 10);", "elspenda");
16639
16640   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
16641
16642   ExpectString("str2.charAt(2);", "e");
16643
16644   ExpectObject("str2.indexOf('els');", indexof);
16645
16646   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
16647
16648   reresult = CompileRun("str2.charCodeAt(2);");
16649   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
16650 }
16651
16652
16653 TEST(ContainsOnlyOneByte) {
16654   v8::V8::Initialize();
16655   v8::Isolate* isolate = CcTest::isolate();
16656   v8::HandleScope scope(isolate);
16657   // Make a buffer long enough that it won't automatically be converted.
16658   const int length = 512;
16659   // Ensure word aligned assignment.
16660   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
16661   v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
16662       new uintptr_t[aligned_length]);
16663   uint16_t* string_contents =
16664       reinterpret_cast<uint16_t*>(aligned_contents.get());
16665   // Set to contain only one byte.
16666   for (int i = 0; i < length-1; i++) {
16667     string_contents[i] = 0x41;
16668   }
16669   string_contents[length-1] = 0;
16670   // Simple case.
16671   Handle<String> string =
16672       String::NewExternal(isolate,
16673                           new TestResource(string_contents, NULL, false));
16674   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16675   // Counter example.
16676   string = String::NewFromTwoByte(isolate, string_contents);
16677   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
16678   // Test left right and balanced cons strings.
16679   Handle<String> base = String::NewFromUtf8(isolate, "a");
16680   Handle<String> left = base;
16681   Handle<String> right = base;
16682   for (int i = 0; i < 1000; i++) {
16683     left = String::Concat(base, left);
16684     right = String::Concat(right, base);
16685   }
16686   Handle<String> balanced = String::Concat(left, base);
16687   balanced = String::Concat(balanced, right);
16688   Handle<String> cons_strings[] = {left, balanced, right};
16689   Handle<String> two_byte =
16690       String::NewExternal(isolate,
16691                           new TestResource(string_contents, NULL, false));
16692   USE(two_byte); USE(cons_strings);
16693   for (size_t i = 0; i < arraysize(cons_strings); i++) {
16694     // Base assumptions.
16695     string = cons_strings[i];
16696     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
16697     // Test left and right concatentation.
16698     string = String::Concat(two_byte, cons_strings[i]);
16699     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16700     string = String::Concat(cons_strings[i], two_byte);
16701     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16702   }
16703   // Set bits in different positions
16704   // for strings of different lengths and alignments.
16705   for (int alignment = 0; alignment < 7; alignment++) {
16706     for (int size = 2; alignment + size < length; size *= 2) {
16707       int zero_offset = size + alignment;
16708       string_contents[zero_offset] = 0;
16709       for (int i = 0; i < size; i++) {
16710         int shift = 8 + (i % 7);
16711         string_contents[alignment + i] = 1 << shift;
16712         string = String::NewExternal(
16713             isolate,
16714             new TestResource(string_contents + alignment, NULL, false));
16715         CHECK_EQ(size, string->Length());
16716         CHECK(!string->ContainsOnlyOneByte());
16717         string_contents[alignment + i] = 0x41;
16718       }
16719       string_contents[zero_offset] = 0x41;
16720     }
16721   }
16722 }
16723
16724
16725 // Failed access check callback that performs a GC on each invocation.
16726 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
16727                                  v8::AccessType type,
16728                                  Local<v8::Value> data) {
16729   CcTest::heap()->CollectAllGarbage();
16730   CcTest::isolate()->ThrowException(
16731       v8::Exception::Error(v8_str("cross context")));
16732 }
16733
16734
16735 TEST(GCInFailedAccessCheckCallback) {
16736   // Install a failed access check callback that performs a GC on each
16737   // invocation. Then force the callback to be called from va
16738
16739   v8::V8::Initialize();
16740   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
16741
16742   v8::Isolate* isolate = CcTest::isolate();
16743   v8::HandleScope scope(isolate);
16744
16745   // Create an ObjectTemplate for global objects and install access
16746   // check callbacks that will block access.
16747   v8::Handle<v8::ObjectTemplate> global_template =
16748       v8::ObjectTemplate::New(isolate);
16749   global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL,
16750                                            v8::Handle<v8::Value>());
16751
16752   // Create a context and set an x property on it's global object.
16753   LocalContext context0(NULL, global_template);
16754   context0->Global()->Set(v8_str("x"), v8_num(42));
16755   v8::Handle<v8::Object> global0 = context0->Global();
16756
16757   // Create a context with a different security token so that the
16758   // failed access check callback will be called on each access.
16759   LocalContext context1(NULL, global_template);
16760   context1->Global()->Set(v8_str("other"), global0);
16761
16762   v8::TryCatch try_catch(isolate);
16763
16764   // Get property with failed access check.
16765   CHECK(CompileRun("other.x").IsEmpty());
16766   CHECK(try_catch.HasCaught());
16767   try_catch.Reset();
16768
16769   // Get element with failed access check.
16770   CHECK(CompileRun("other[0]").IsEmpty());
16771   CHECK(try_catch.HasCaught());
16772   try_catch.Reset();
16773
16774   // Set property with failed access check.
16775   CHECK(CompileRun("other.x = new Object()").IsEmpty());
16776   CHECK(try_catch.HasCaught());
16777   try_catch.Reset();
16778
16779   // Set element with failed access check.
16780   CHECK(CompileRun("other[0] = new Object()").IsEmpty());
16781   CHECK(try_catch.HasCaught());
16782   try_catch.Reset();
16783
16784   // Get property attribute with failed access check.
16785   CHECK(CompileRun("\'x\' in other").IsEmpty());
16786   CHECK(try_catch.HasCaught());
16787   try_catch.Reset();
16788
16789   // Get property attribute for element with failed access check.
16790   CHECK(CompileRun("0 in other").IsEmpty());
16791   CHECK(try_catch.HasCaught());
16792   try_catch.Reset();
16793
16794   // Delete property.
16795   CHECK(CompileRun("delete other.x").IsEmpty());
16796   CHECK(try_catch.HasCaught());
16797   try_catch.Reset();
16798
16799   // Delete element.
16800   CHECK_EQ(false, global0->Delete(0));
16801
16802   // DefineAccessor.
16803   CHECK_EQ(false,
16804            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
16805
16806   // Define JavaScript accessor.
16807   CHECK(CompileRun(
16808             "Object.prototype.__defineGetter__.call("
16809             "    other, \'x\', function() { return 42; })").IsEmpty());
16810   CHECK(try_catch.HasCaught());
16811   try_catch.Reset();
16812
16813   // LookupAccessor.
16814   CHECK(CompileRun(
16815             "Object.prototype.__lookupGetter__.call("
16816             "    other, \'x\')").IsEmpty());
16817   CHECK(try_catch.HasCaught());
16818   try_catch.Reset();
16819
16820   // HasOwnElement.
16821   CHECK(CompileRun(
16822             "Object.prototype.hasOwnProperty.call("
16823             "other, \'0\')").IsEmpty());
16824   CHECK(try_catch.HasCaught());
16825   try_catch.Reset();
16826
16827   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
16828   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
16829   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
16830
16831   // Reset the failed access check callback so it does not influence
16832   // the other tests.
16833   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
16834 }
16835
16836
16837 TEST(IsolateNewDispose) {
16838   v8::Isolate* current_isolate = CcTest::isolate();
16839   v8::Isolate::CreateParams create_params;
16840   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16841   v8::Isolate* isolate = v8::Isolate::New(create_params);
16842   CHECK(isolate != NULL);
16843   CHECK(current_isolate != isolate);
16844   CHECK(current_isolate == CcTest::isolate());
16845
16846   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16847   last_location = last_message = NULL;
16848   isolate->Dispose();
16849   CHECK(!last_location);
16850   CHECK(!last_message);
16851 }
16852
16853
16854 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
16855   v8::Isolate::CreateParams create_params;
16856   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16857   v8::Isolate* isolate = v8::Isolate::New(create_params);
16858   {
16859     v8::Isolate::Scope i_scope(isolate);
16860     v8::HandleScope scope(isolate);
16861     LocalContext context(isolate);
16862     // Run something in this isolate.
16863     ExpectTrue("true");
16864     v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16865     last_location = last_message = NULL;
16866     // Still entered, should fail.
16867     isolate->Dispose();
16868     CHECK(last_location);
16869     CHECK(last_message);
16870   }
16871   isolate->Dispose();
16872 }
16873
16874
16875 static void BreakArrayGuarantees(const char* script) {
16876   v8::Isolate::CreateParams create_params;
16877   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16878   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
16879   isolate1->Enter();
16880   v8::Persistent<v8::Context> context1;
16881   {
16882     v8::HandleScope scope(isolate1);
16883     context1.Reset(isolate1, Context::New(isolate1));
16884   }
16885
16886   {
16887     v8::HandleScope scope(isolate1);
16888     v8::Local<v8::Context> context =
16889         v8::Local<v8::Context>::New(isolate1, context1);
16890     v8::Context::Scope context_scope(context);
16891     v8::internal::Isolate* i_isolate =
16892         reinterpret_cast<v8::internal::Isolate*>(isolate1);
16893     CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
16894     // Run something in new isolate.
16895     CompileRun(script);
16896     CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
16897   }
16898   isolate1->Exit();
16899   isolate1->Dispose();
16900 }
16901
16902
16903 TEST(VerifyArrayPrototypeGuarantees) {
16904   // Break fast array hole handling by element changes.
16905   BreakArrayGuarantees("[].__proto__[1] = 3;");
16906   BreakArrayGuarantees("Object.prototype[3] = 'three';");
16907   BreakArrayGuarantees("Array.prototype.push(1);");
16908   BreakArrayGuarantees("Array.prototype.unshift(1);");
16909   // Break fast array hole handling by changing length.
16910   BreakArrayGuarantees("Array.prototype.length = 30;");
16911   // Break fast array hole handling by prototype structure changes.
16912   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
16913   // By sending elements to dictionary mode.
16914   BreakArrayGuarantees(
16915       "Object.defineProperty(Array.prototype, 0, {"
16916       "  get: function() { return 3; }});");
16917   BreakArrayGuarantees(
16918       "Object.defineProperty(Object.prototype, 0, {"
16919       "  get: function() { return 3; }});");
16920 }
16921
16922
16923 TEST(RunTwoIsolatesOnSingleThread) {
16924   // Run isolate 1.
16925   v8::Isolate::CreateParams create_params;
16926   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16927   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
16928   isolate1->Enter();
16929   v8::Persistent<v8::Context> context1;
16930   {
16931     v8::HandleScope scope(isolate1);
16932     context1.Reset(isolate1, Context::New(isolate1));
16933   }
16934
16935   {
16936     v8::HandleScope scope(isolate1);
16937     v8::Local<v8::Context> context =
16938         v8::Local<v8::Context>::New(isolate1, context1);
16939     v8::Context::Scope context_scope(context);
16940     // Run something in new isolate.
16941     CompileRun("var foo = 'isolate 1';");
16942     ExpectString("function f() { return foo; }; f()", "isolate 1");
16943   }
16944
16945   // Run isolate 2.
16946   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
16947   v8::Persistent<v8::Context> context2;
16948
16949   {
16950     v8::Isolate::Scope iscope(isolate2);
16951     v8::HandleScope scope(isolate2);
16952     context2.Reset(isolate2, Context::New(isolate2));
16953     v8::Local<v8::Context> context =
16954         v8::Local<v8::Context>::New(isolate2, context2);
16955     v8::Context::Scope context_scope(context);
16956
16957     // Run something in new isolate.
16958     CompileRun("var foo = 'isolate 2';");
16959     ExpectString("function f() { return foo; }; f()", "isolate 2");
16960   }
16961
16962   {
16963     v8::HandleScope scope(isolate1);
16964     v8::Local<v8::Context> context =
16965         v8::Local<v8::Context>::New(isolate1, context1);
16966     v8::Context::Scope context_scope(context);
16967     // Now again in isolate 1
16968     ExpectString("function f() { return foo; }; f()", "isolate 1");
16969   }
16970
16971   isolate1->Exit();
16972
16973   // Run some stuff in default isolate.
16974   v8::Persistent<v8::Context> context_default;
16975   {
16976     v8::Isolate* isolate = CcTest::isolate();
16977     v8::Isolate::Scope iscope(isolate);
16978     v8::HandleScope scope(isolate);
16979     context_default.Reset(isolate, Context::New(isolate));
16980   }
16981
16982   {
16983     v8::HandleScope scope(CcTest::isolate());
16984     v8::Local<v8::Context> context =
16985         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
16986     v8::Context::Scope context_scope(context);
16987     // Variables in other isolates should be not available, verify there
16988     // is an exception.
16989     ExpectTrue("function f() {"
16990                "  try {"
16991                "    foo;"
16992                "    return false;"
16993                "  } catch(e) {"
16994                "    return true;"
16995                "  }"
16996                "};"
16997                "var isDefaultIsolate = true;"
16998                "f()");
16999   }
17000
17001   isolate1->Enter();
17002
17003   {
17004     v8::Isolate::Scope iscope(isolate2);
17005     v8::HandleScope scope(isolate2);
17006     v8::Local<v8::Context> context =
17007         v8::Local<v8::Context>::New(isolate2, context2);
17008     v8::Context::Scope context_scope(context);
17009     ExpectString("function f() { return foo; }; f()", "isolate 2");
17010   }
17011
17012   {
17013     v8::HandleScope scope(v8::Isolate::GetCurrent());
17014     v8::Local<v8::Context> context =
17015         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
17016     v8::Context::Scope context_scope(context);
17017     ExpectString("function f() { return foo; }; f()", "isolate 1");
17018   }
17019
17020   {
17021     v8::Isolate::Scope iscope(isolate2);
17022     context2.Reset();
17023   }
17024
17025   context1.Reset();
17026   isolate1->Exit();
17027
17028   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
17029   last_location = last_message = NULL;
17030
17031   isolate1->Dispose();
17032   CHECK(!last_location);
17033   CHECK(!last_message);
17034
17035   isolate2->Dispose();
17036   CHECK(!last_location);
17037   CHECK(!last_message);
17038
17039   // Check that default isolate still runs.
17040   {
17041     v8::HandleScope scope(CcTest::isolate());
17042     v8::Local<v8::Context> context =
17043         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
17044     v8::Context::Scope context_scope(context);
17045     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
17046   }
17047 }
17048
17049
17050 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
17051   v8::Isolate::Scope isolate_scope(isolate);
17052   v8::HandleScope scope(isolate);
17053   LocalContext context(isolate);
17054   i::ScopedVector<char> code(1024);
17055   i::SNPrintF(code, "function fib(n) {"
17056                     "  if (n <= 2) return 1;"
17057                     "  return fib(n-1) + fib(n-2);"
17058                     "}"
17059                     "fib(%d)", limit);
17060   Local<Value> value = CompileRun(code.start());
17061   CHECK(value->IsNumber());
17062   return static_cast<int>(value->NumberValue());
17063 }
17064
17065 class IsolateThread : public v8::base::Thread {
17066  public:
17067   explicit IsolateThread(int fib_limit)
17068       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
17069
17070   void Run() {
17071     v8::Isolate::CreateParams create_params;
17072     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17073     v8::Isolate* isolate = v8::Isolate::New(create_params);
17074     result_ = CalcFibonacci(isolate, fib_limit_);
17075     isolate->Dispose();
17076   }
17077
17078   int result() { return result_; }
17079
17080  private:
17081   int fib_limit_;
17082   int result_;
17083 };
17084
17085
17086 TEST(MultipleIsolatesOnIndividualThreads) {
17087   IsolateThread thread1(21);
17088   IsolateThread thread2(12);
17089
17090   // Compute some fibonacci numbers on 3 threads in 3 isolates.
17091   thread1.Start();
17092   thread2.Start();
17093
17094   int result1 = CalcFibonacci(CcTest::isolate(), 21);
17095   int result2 = CalcFibonacci(CcTest::isolate(), 12);
17096
17097   thread1.Join();
17098   thread2.Join();
17099
17100   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
17101   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
17102   CHECK_EQ(result1, 10946);
17103   CHECK_EQ(result2, 144);
17104   CHECK_EQ(result1, thread1.result());
17105   CHECK_EQ(result2, thread2.result());
17106 }
17107
17108
17109 TEST(IsolateDifferentContexts) {
17110   v8::Isolate::CreateParams create_params;
17111   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17112   v8::Isolate* isolate = v8::Isolate::New(create_params);
17113   Local<v8::Context> context;
17114   {
17115     v8::Isolate::Scope isolate_scope(isolate);
17116     v8::HandleScope handle_scope(isolate);
17117     context = v8::Context::New(isolate);
17118     v8::Context::Scope context_scope(context);
17119     Local<Value> v = CompileRun("2");
17120     CHECK(v->IsNumber());
17121     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
17122   }
17123   {
17124     v8::Isolate::Scope isolate_scope(isolate);
17125     v8::HandleScope handle_scope(isolate);
17126     context = v8::Context::New(isolate);
17127     v8::Context::Scope context_scope(context);
17128     Local<Value> v = CompileRun("22");
17129     CHECK(v->IsNumber());
17130     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
17131   }
17132   isolate->Dispose();
17133 }
17134
17135 class InitDefaultIsolateThread : public v8::base::Thread {
17136  public:
17137   enum TestCase {
17138     SetResourceConstraints,
17139     SetFatalHandler,
17140     SetCounterFunction,
17141     SetCreateHistogramFunction,
17142     SetAddHistogramSampleFunction
17143   };
17144
17145   explicit InitDefaultIsolateThread(TestCase testCase)
17146       : Thread(Options("InitDefaultIsolateThread")),
17147         testCase_(testCase),
17148         result_(false) {}
17149
17150   void Run() {
17151     v8::Isolate::CreateParams create_params;
17152     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17153     const intptr_t pageSizeMult =
17154         v8::internal::Page::kPageSize / v8::internal::MB;
17155     switch (testCase_) {
17156       case SetResourceConstraints: {
17157         create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
17158         create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
17159         break;
17160       }
17161       default:
17162         break;
17163     }
17164     v8::Isolate* isolate = v8::Isolate::New(create_params);
17165     isolate->Enter();
17166     switch (testCase_) {
17167       case SetResourceConstraints:
17168         // Already handled in pre-Isolate-creation block.
17169         break;
17170
17171       case SetFatalHandler:
17172         v8::V8::SetFatalErrorHandler(NULL);
17173         break;
17174
17175       case SetCounterFunction:
17176         CcTest::isolate()->SetCounterFunction(NULL);
17177         break;
17178
17179       case SetCreateHistogramFunction:
17180         CcTest::isolate()->SetCreateHistogramFunction(NULL);
17181         break;
17182
17183       case SetAddHistogramSampleFunction:
17184         CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
17185         break;
17186     }
17187     isolate->Exit();
17188     isolate->Dispose();
17189     result_ = true;
17190   }
17191
17192   bool result() { return result_; }
17193
17194  private:
17195   TestCase testCase_;
17196   bool result_;
17197 };
17198
17199
17200 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
17201   InitDefaultIsolateThread thread(testCase);
17202   thread.Start();
17203   thread.Join();
17204   CHECK_EQ(thread.result(), true);
17205 }
17206
17207
17208 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
17209   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
17210 }
17211
17212
17213 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
17214   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
17215 }
17216
17217
17218 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
17219   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
17220 }
17221
17222
17223 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
17224   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
17225 }
17226
17227
17228 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
17229   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
17230 }
17231
17232
17233 TEST(StringCheckMultipleContexts) {
17234   const char* code =
17235       "(function() { return \"a\".charAt(0); })()";
17236
17237   {
17238     // Run the code twice in the first context to initialize the call IC.
17239     LocalContext context1;
17240     v8::HandleScope scope(context1->GetIsolate());
17241     ExpectString(code, "a");
17242     ExpectString(code, "a");
17243   }
17244
17245   {
17246     // Change the String.prototype in the second context and check
17247     // that the right function gets called.
17248     LocalContext context2;
17249     v8::HandleScope scope(context2->GetIsolate());
17250     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
17251     ExpectString(code, "not a");
17252   }
17253 }
17254
17255
17256 TEST(NumberCheckMultipleContexts) {
17257   const char* code =
17258       "(function() { return (42).toString(); })()";
17259
17260   {
17261     // Run the code twice in the first context to initialize the call IC.
17262     LocalContext context1;
17263     v8::HandleScope scope(context1->GetIsolate());
17264     ExpectString(code, "42");
17265     ExpectString(code, "42");
17266   }
17267
17268   {
17269     // Change the Number.prototype in the second context and check
17270     // that the right function gets called.
17271     LocalContext context2;
17272     v8::HandleScope scope(context2->GetIsolate());
17273     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
17274     ExpectString(code, "not 42");
17275   }
17276 }
17277
17278
17279 TEST(BooleanCheckMultipleContexts) {
17280   const char* code =
17281       "(function() { return true.toString(); })()";
17282
17283   {
17284     // Run the code twice in the first context to initialize the call IC.
17285     LocalContext context1;
17286     v8::HandleScope scope(context1->GetIsolate());
17287     ExpectString(code, "true");
17288     ExpectString(code, "true");
17289   }
17290
17291   {
17292     // Change the Boolean.prototype in the second context and check
17293     // that the right function gets called.
17294     LocalContext context2;
17295     v8::HandleScope scope(context2->GetIsolate());
17296     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
17297     ExpectString(code, "");
17298   }
17299 }
17300
17301
17302 TEST(DontDeleteCellLoadIC) {
17303   const char* function_code =
17304       "function readCell() { while (true) { return cell; } }";
17305
17306   {
17307     // Run the code twice in the first context to initialize the load
17308     // IC for a don't delete cell.
17309     LocalContext context1;
17310     v8::HandleScope scope(context1->GetIsolate());
17311     CompileRun("var cell = \"first\";");
17312     ExpectBoolean("delete cell", false);
17313     CompileRun(function_code);
17314     ExpectString("readCell()", "first");
17315     ExpectString("readCell()", "first");
17316   }
17317
17318   {
17319     // Use a deletable cell in the second context.
17320     LocalContext context2;
17321     v8::HandleScope scope(context2->GetIsolate());
17322     CompileRun("cell = \"second\";");
17323     CompileRun(function_code);
17324     ExpectString("readCell()", "second");
17325     ExpectBoolean("delete cell", true);
17326     ExpectString("(function() {"
17327                  "  try {"
17328                  "    return readCell();"
17329                  "  } catch(e) {"
17330                  "    return e.toString();"
17331                  "  }"
17332                  "})()",
17333                  "ReferenceError: cell is not defined");
17334     CompileRun("cell = \"new_second\";");
17335     CcTest::heap()->CollectAllGarbage();
17336     ExpectString("readCell()", "new_second");
17337     ExpectString("readCell()", "new_second");
17338   }
17339 }
17340
17341
17342 class Visitor42 : public v8::PersistentHandleVisitor {
17343  public:
17344   explicit Visitor42(v8::Persistent<v8::Object>* object)
17345       : counter_(0), object_(object) { }
17346
17347   virtual void VisitPersistentHandle(Persistent<Value>* value,
17348                                      uint16_t class_id) {
17349     if (class_id != 42) return;
17350     CHECK_EQ(42, value->WrapperClassId());
17351     v8::Isolate* isolate = CcTest::isolate();
17352     v8::HandleScope handle_scope(isolate);
17353     v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
17354     v8::Handle<v8::Value> object =
17355         v8::Local<v8::Object>::New(isolate, *object_);
17356     CHECK(handle->IsObject());
17357     CHECK(Handle<Object>::Cast(handle)->Equals(object));
17358     ++counter_;
17359   }
17360
17361   int counter_;
17362   v8::Persistent<v8::Object>* object_;
17363 };
17364
17365
17366 TEST(PersistentHandleVisitor) {
17367   LocalContext context;
17368   v8::Isolate* isolate = context->GetIsolate();
17369   v8::HandleScope scope(isolate);
17370   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
17371   CHECK_EQ(0, object.WrapperClassId());
17372   object.SetWrapperClassId(42);
17373   CHECK_EQ(42, object.WrapperClassId());
17374
17375   Visitor42 visitor(&object);
17376   v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
17377   CHECK_EQ(1, visitor.counter_);
17378
17379   object.Reset();
17380 }
17381
17382
17383 TEST(WrapperClassId) {
17384   LocalContext context;
17385   v8::Isolate* isolate = context->GetIsolate();
17386   v8::HandleScope scope(isolate);
17387   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
17388   CHECK_EQ(0, object.WrapperClassId());
17389   object.SetWrapperClassId(65535);
17390   CHECK_EQ(65535, object.WrapperClassId());
17391   object.Reset();
17392 }
17393
17394
17395 TEST(PersistentHandleInNewSpaceVisitor) {
17396   LocalContext context;
17397   v8::Isolate* isolate = context->GetIsolate();
17398   v8::HandleScope scope(isolate);
17399   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
17400   CHECK_EQ(0, object1.WrapperClassId());
17401   object1.SetWrapperClassId(42);
17402   CHECK_EQ(42, object1.WrapperClassId());
17403
17404   CcTest::heap()->CollectAllGarbage();
17405   CcTest::heap()->CollectAllGarbage();
17406
17407   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
17408   CHECK_EQ(0, object2.WrapperClassId());
17409   object2.SetWrapperClassId(42);
17410   CHECK_EQ(42, object2.WrapperClassId());
17411
17412   Visitor42 visitor(&object2);
17413   v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
17414   CHECK_EQ(1, visitor.counter_);
17415
17416   object1.Reset();
17417   object2.Reset();
17418 }
17419
17420
17421 TEST(RegExp) {
17422   LocalContext context;
17423   v8::HandleScope scope(context->GetIsolate());
17424
17425   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
17426   CHECK(re->IsRegExp());
17427   CHECK(re->GetSource()->Equals(v8_str("foo")));
17428   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17429
17430   re = v8::RegExp::New(v8_str("bar"),
17431                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17432                                                       v8::RegExp::kGlobal));
17433   CHECK(re->IsRegExp());
17434   CHECK(re->GetSource()->Equals(v8_str("bar")));
17435   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
17436            static_cast<int>(re->GetFlags()));
17437
17438   re = v8::RegExp::New(v8_str("baz"),
17439                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17440                                                       v8::RegExp::kMultiline));
17441   CHECK(re->IsRegExp());
17442   CHECK(re->GetSource()->Equals(v8_str("baz")));
17443   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
17444            static_cast<int>(re->GetFlags()));
17445
17446   re = CompileRun("/quux/").As<v8::RegExp>();
17447   CHECK(re->IsRegExp());
17448   CHECK(re->GetSource()->Equals(v8_str("quux")));
17449   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17450
17451   re = CompileRun("/quux/gm").As<v8::RegExp>();
17452   CHECK(re->IsRegExp());
17453   CHECK(re->GetSource()->Equals(v8_str("quux")));
17454   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
17455            static_cast<int>(re->GetFlags()));
17456
17457   // Override the RegExp constructor and check the API constructor
17458   // still works.
17459   CompileRun("RegExp = function() {}");
17460
17461   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
17462   CHECK(re->IsRegExp());
17463   CHECK(re->GetSource()->Equals(v8_str("foobar")));
17464   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17465
17466   re = v8::RegExp::New(v8_str("foobarbaz"),
17467                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17468                                                       v8::RegExp::kMultiline));
17469   CHECK(re->IsRegExp());
17470   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
17471   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
17472            static_cast<int>(re->GetFlags()));
17473
17474   context->Global()->Set(v8_str("re"), re);
17475   ExpectTrue("re.test('FoobarbaZ')");
17476
17477   // RegExps are objects on which you can set properties.
17478   re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
17479   v8::Handle<v8::Value> value(CompileRun("re.property"));
17480   CHECK_EQ(32, value->Int32Value());
17481
17482   v8::TryCatch try_catch(context->GetIsolate());
17483   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
17484   CHECK(re.IsEmpty());
17485   CHECK(try_catch.HasCaught());
17486   context->Global()->Set(v8_str("ex"), try_catch.Exception());
17487   ExpectTrue("ex instanceof SyntaxError");
17488 }
17489
17490
17491 THREADED_TEST(Equals) {
17492   LocalContext localContext;
17493   v8::HandleScope handleScope(localContext->GetIsolate());
17494
17495   v8::Handle<v8::Object> globalProxy = localContext->Global();
17496   v8::Handle<Value> global = globalProxy->GetPrototype();
17497
17498   CHECK(global->StrictEquals(global));
17499   CHECK(!global->StrictEquals(globalProxy));
17500   CHECK(!globalProxy->StrictEquals(global));
17501   CHECK(globalProxy->StrictEquals(globalProxy));
17502
17503   CHECK(global->Equals(global));
17504   CHECK(!global->Equals(globalProxy));
17505   CHECK(!globalProxy->Equals(global));
17506   CHECK(globalProxy->Equals(globalProxy));
17507 }
17508
17509
17510 static void Getter(v8::Local<v8::Name> property,
17511                    const v8::PropertyCallbackInfo<v8::Value>& info) {
17512   info.GetReturnValue().Set(v8_str("42!"));
17513 }
17514
17515
17516 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
17517   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
17518   result->Set(0, v8_str("universalAnswer"));
17519   info.GetReturnValue().Set(result);
17520 }
17521
17522
17523 TEST(NamedEnumeratorAndForIn) {
17524   LocalContext context;
17525   v8::Isolate* isolate = context->GetIsolate();
17526   v8::HandleScope handle_scope(isolate);
17527   v8::Context::Scope context_scope(context.local());
17528
17529   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
17530   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
17531                                                          NULL, Enumerator));
17532   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
17533   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
17534         "var result = []; for (var k in o) result.push(k); result"));
17535   CHECK_EQ(1u, result->Length());
17536   CHECK(v8_str("universalAnswer")->Equals(result->Get(0)));
17537 }
17538
17539
17540 TEST(DefinePropertyPostDetach) {
17541   LocalContext context;
17542   v8::HandleScope scope(context->GetIsolate());
17543   v8::Handle<v8::Object> proxy = context->Global();
17544   v8::Handle<v8::Function> define_property =
17545       CompileRun("(function() {"
17546                  "  Object.defineProperty("
17547                  "    this,"
17548                  "    1,"
17549                  "    { configurable: true, enumerable: true, value: 3 });"
17550                  "})").As<Function>();
17551   context->DetachGlobal();
17552   define_property->Call(proxy, 0, NULL);
17553 }
17554
17555
17556 static void InstallContextId(v8::Handle<Context> context, int id) {
17557   Context::Scope scope(context);
17558   CompileRun("Object.prototype").As<Object>()->
17559       Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
17560 }
17561
17562
17563 static void CheckContextId(v8::Handle<Object> object, int expected) {
17564   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
17565 }
17566
17567
17568 THREADED_TEST(CreationContext) {
17569   v8::Isolate* isolate = CcTest::isolate();
17570   HandleScope handle_scope(isolate);
17571   Handle<Context> context1 = Context::New(isolate);
17572   InstallContextId(context1, 1);
17573   Handle<Context> context2 = Context::New(isolate);
17574   InstallContextId(context2, 2);
17575   Handle<Context> context3 = Context::New(isolate);
17576   InstallContextId(context3, 3);
17577
17578   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
17579
17580   Local<Object> object1;
17581   Local<Function> func1;
17582   {
17583     Context::Scope scope(context1);
17584     object1 = Object::New(isolate);
17585     func1 = tmpl->GetFunction();
17586   }
17587
17588   Local<Object> object2;
17589   Local<Function> func2;
17590   {
17591     Context::Scope scope(context2);
17592     object2 = Object::New(isolate);
17593     func2 = tmpl->GetFunction();
17594   }
17595
17596   Local<Object> instance1;
17597   Local<Object> instance2;
17598
17599   {
17600     Context::Scope scope(context3);
17601     instance1 = func1->NewInstance();
17602     instance2 = func2->NewInstance();
17603   }
17604
17605   {
17606     Handle<Context> other_context = Context::New(isolate);
17607     Context::Scope scope(other_context);
17608     CHECK(object1->CreationContext() == context1);
17609     CheckContextId(object1, 1);
17610     CHECK(func1->CreationContext() == context1);
17611     CheckContextId(func1, 1);
17612     CHECK(instance1->CreationContext() == context1);
17613     CheckContextId(instance1, 1);
17614     CHECK(object2->CreationContext() == context2);
17615     CheckContextId(object2, 2);
17616     CHECK(func2->CreationContext() == context2);
17617     CheckContextId(func2, 2);
17618     CHECK(instance2->CreationContext() == context2);
17619     CheckContextId(instance2, 2);
17620   }
17621
17622   {
17623     Context::Scope scope(context1);
17624     CHECK(object1->CreationContext() == context1);
17625     CheckContextId(object1, 1);
17626     CHECK(func1->CreationContext() == context1);
17627     CheckContextId(func1, 1);
17628     CHECK(instance1->CreationContext() == context1);
17629     CheckContextId(instance1, 1);
17630     CHECK(object2->CreationContext() == context2);
17631     CheckContextId(object2, 2);
17632     CHECK(func2->CreationContext() == context2);
17633     CheckContextId(func2, 2);
17634     CHECK(instance2->CreationContext() == context2);
17635     CheckContextId(instance2, 2);
17636   }
17637
17638   {
17639     Context::Scope scope(context2);
17640     CHECK(object1->CreationContext() == context1);
17641     CheckContextId(object1, 1);
17642     CHECK(func1->CreationContext() == context1);
17643     CheckContextId(func1, 1);
17644     CHECK(instance1->CreationContext() == context1);
17645     CheckContextId(instance1, 1);
17646     CHECK(object2->CreationContext() == context2);
17647     CheckContextId(object2, 2);
17648     CHECK(func2->CreationContext() == context2);
17649     CheckContextId(func2, 2);
17650     CHECK(instance2->CreationContext() == context2);
17651     CheckContextId(instance2, 2);
17652   }
17653 }
17654
17655
17656 THREADED_TEST(CreationContextOfJsFunction) {
17657   HandleScope handle_scope(CcTest::isolate());
17658   Handle<Context> context = Context::New(CcTest::isolate());
17659   InstallContextId(context, 1);
17660
17661   Local<Object> function;
17662   {
17663     Context::Scope scope(context);
17664     function = CompileRun("function foo() {}; foo").As<Object>();
17665   }
17666
17667   Handle<Context> other_context = Context::New(CcTest::isolate());
17668   Context::Scope scope(other_context);
17669   CHECK(function->CreationContext() == context);
17670   CheckContextId(function, 1);
17671 }
17672
17673
17674 void HasOwnPropertyIndexedPropertyGetter(
17675     uint32_t index,
17676     const v8::PropertyCallbackInfo<v8::Value>& info) {
17677   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
17678 }
17679
17680
17681 void HasOwnPropertyNamedPropertyGetter(
17682     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
17683   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
17684 }
17685
17686
17687 void HasOwnPropertyIndexedPropertyQuery(
17688     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17689   if (index == 42) info.GetReturnValue().Set(1);
17690 }
17691
17692
17693 void HasOwnPropertyNamedPropertyQuery(
17694     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17695   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
17696 }
17697
17698
17699 void HasOwnPropertyNamedPropertyQuery2(
17700     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17701   if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
17702 }
17703
17704
17705 void HasOwnPropertyAccessorGetter(
17706     Local<String> property,
17707     const v8::PropertyCallbackInfo<v8::Value>& info) {
17708   info.GetReturnValue().Set(v8_str("yes"));
17709 }
17710
17711
17712 TEST(HasOwnProperty) {
17713   LocalContext env;
17714   v8::Isolate* isolate = env->GetIsolate();
17715   v8::HandleScope scope(isolate);
17716   { // Check normal properties and defined getters.
17717     Handle<Value> value = CompileRun(
17718         "function Foo() {"
17719         "    this.foo = 11;"
17720         "    this.__defineGetter__('baz', function() { return 1; });"
17721         "};"
17722         "function Bar() { "
17723         "    this.bar = 13;"
17724         "    this.__defineGetter__('bla', function() { return 2; });"
17725         "};"
17726         "Bar.prototype = new Foo();"
17727         "new Bar();");
17728     CHECK(value->IsObject());
17729     Handle<Object> object = value->ToObject(isolate);
17730     CHECK(object->Has(v8_str("foo")));
17731     CHECK(!object->HasOwnProperty(v8_str("foo")));
17732     CHECK(object->HasOwnProperty(v8_str("bar")));
17733     CHECK(object->Has(v8_str("baz")));
17734     CHECK(!object->HasOwnProperty(v8_str("baz")));
17735     CHECK(object->HasOwnProperty(v8_str("bla")));
17736   }
17737   { // Check named getter interceptors.
17738     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17739     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17740         HasOwnPropertyNamedPropertyGetter));
17741     Handle<Object> instance = templ->NewInstance();
17742     CHECK(!instance->HasOwnProperty(v8_str("42")));
17743     CHECK(instance->HasOwnProperty(v8_str("foo")));
17744     CHECK(!instance->HasOwnProperty(v8_str("bar")));
17745   }
17746   { // Check indexed getter interceptors.
17747     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17748     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17749         HasOwnPropertyIndexedPropertyGetter));
17750     Handle<Object> instance = templ->NewInstance();
17751     CHECK(instance->HasOwnProperty(v8_str("42")));
17752     CHECK(!instance->HasOwnProperty(v8_str("43")));
17753     CHECK(!instance->HasOwnProperty(v8_str("foo")));
17754   }
17755   { // Check named query interceptors.
17756     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17757     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17758         0, 0, HasOwnPropertyNamedPropertyQuery));
17759     Handle<Object> instance = templ->NewInstance();
17760     CHECK(instance->HasOwnProperty(v8_str("foo")));
17761     CHECK(!instance->HasOwnProperty(v8_str("bar")));
17762   }
17763   { // Check indexed query interceptors.
17764     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17765     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17766         0, 0, HasOwnPropertyIndexedPropertyQuery));
17767     Handle<Object> instance = templ->NewInstance();
17768     CHECK(instance->HasOwnProperty(v8_str("42")));
17769     CHECK(!instance->HasOwnProperty(v8_str("41")));
17770   }
17771   { // Check callbacks.
17772     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17773     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
17774     Handle<Object> instance = templ->NewInstance();
17775     CHECK(instance->HasOwnProperty(v8_str("foo")));
17776     CHECK(!instance->HasOwnProperty(v8_str("bar")));
17777   }
17778   { // Check that query wins on disagreement.
17779     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17780     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17781         HasOwnPropertyNamedPropertyGetter, 0,
17782         HasOwnPropertyNamedPropertyQuery2));
17783     Handle<Object> instance = templ->NewInstance();
17784     CHECK(!instance->HasOwnProperty(v8_str("foo")));
17785     CHECK(instance->HasOwnProperty(v8_str("bar")));
17786   }
17787 }
17788
17789
17790 TEST(IndexedInterceptorWithStringProto) {
17791   v8::Isolate* isolate = CcTest::isolate();
17792   v8::HandleScope scope(isolate);
17793   Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17794   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17795       NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
17796   LocalContext context;
17797   context->Global()->Set(v8_str("obj"), templ->NewInstance());
17798   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
17799   // These should be intercepted.
17800   CHECK(CompileRun("42 in obj")->BooleanValue());
17801   CHECK(CompileRun("'42' in obj")->BooleanValue());
17802   // These should fall through to the String prototype.
17803   CHECK(CompileRun("0 in obj")->BooleanValue());
17804   CHECK(CompileRun("'0' in obj")->BooleanValue());
17805   // And these should both fail.
17806   CHECK(!CompileRun("32 in obj")->BooleanValue());
17807   CHECK(!CompileRun("'32' in obj")->BooleanValue());
17808 }
17809
17810
17811 void CheckCodeGenerationAllowed() {
17812   Handle<Value> result = CompileRun("eval('42')");
17813   CHECK_EQ(42, result->Int32Value());
17814   result = CompileRun("(function(e) { return e('42'); })(eval)");
17815   CHECK_EQ(42, result->Int32Value());
17816   result = CompileRun("var f = new Function('return 42'); f()");
17817   CHECK_EQ(42, result->Int32Value());
17818 }
17819
17820
17821 void CheckCodeGenerationDisallowed() {
17822   TryCatch try_catch(CcTest::isolate());
17823
17824   Handle<Value> result = CompileRun("eval('42')");
17825   CHECK(result.IsEmpty());
17826   CHECK(try_catch.HasCaught());
17827   try_catch.Reset();
17828
17829   result = CompileRun("(function(e) { return e('42'); })(eval)");
17830   CHECK(result.IsEmpty());
17831   CHECK(try_catch.HasCaught());
17832   try_catch.Reset();
17833
17834   result = CompileRun("var f = new Function('return 42'); f()");
17835   CHECK(result.IsEmpty());
17836   CHECK(try_catch.HasCaught());
17837 }
17838
17839
17840 bool CodeGenerationAllowed(Local<Context> context) {
17841   ApiTestFuzzer::Fuzz();
17842   return true;
17843 }
17844
17845
17846 bool CodeGenerationDisallowed(Local<Context> context) {
17847   ApiTestFuzzer::Fuzz();
17848   return false;
17849 }
17850
17851
17852 THREADED_TEST(AllowCodeGenFromStrings) {
17853   LocalContext context;
17854   v8::HandleScope scope(context->GetIsolate());
17855
17856   // eval and the Function constructor allowed by default.
17857   CHECK(context->IsCodeGenerationFromStringsAllowed());
17858   CheckCodeGenerationAllowed();
17859
17860   // Disallow eval and the Function constructor.
17861   context->AllowCodeGenerationFromStrings(false);
17862   CHECK(!context->IsCodeGenerationFromStringsAllowed());
17863   CheckCodeGenerationDisallowed();
17864
17865   // Allow again.
17866   context->AllowCodeGenerationFromStrings(true);
17867   CheckCodeGenerationAllowed();
17868
17869   // Disallow but setting a global callback that will allow the calls.
17870   context->AllowCodeGenerationFromStrings(false);
17871   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
17872   CHECK(!context->IsCodeGenerationFromStringsAllowed());
17873   CheckCodeGenerationAllowed();
17874
17875   // Set a callback that disallows the code generation.
17876   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
17877   CHECK(!context->IsCodeGenerationFromStringsAllowed());
17878   CheckCodeGenerationDisallowed();
17879 }
17880
17881
17882 TEST(SetErrorMessageForCodeGenFromStrings) {
17883   LocalContext context;
17884   v8::HandleScope scope(context->GetIsolate());
17885   TryCatch try_catch(context->GetIsolate());
17886
17887   Handle<String> message = v8_str("Message") ;
17888   Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
17889   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
17890   context->AllowCodeGenerationFromStrings(false);
17891   context->SetErrorMessageForCodeGenerationFromStrings(message);
17892   Handle<Value> result = CompileRun("eval('42')");
17893   CHECK(result.IsEmpty());
17894   CHECK(try_catch.HasCaught());
17895   Handle<String> actual_message = try_catch.Message()->Get();
17896   CHECK(expected_message->Equals(actual_message));
17897 }
17898
17899
17900 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
17901 }
17902
17903
17904 THREADED_TEST(CallAPIFunctionOnNonObject) {
17905   LocalContext context;
17906   v8::Isolate* isolate = context->GetIsolate();
17907   v8::HandleScope scope(isolate);
17908   Handle<FunctionTemplate> templ =
17909       v8::FunctionTemplate::New(isolate, NonObjectThis);
17910   Handle<Function> function = templ->GetFunction();
17911   context->Global()->Set(v8_str("f"), function);
17912   TryCatch try_catch(isolate);
17913   CompileRun("f.call(2)");
17914 }
17915
17916
17917 // Regression test for issue 1470.
17918 THREADED_TEST(ReadOnlyIndexedProperties) {
17919   v8::Isolate* isolate = CcTest::isolate();
17920   v8::HandleScope scope(isolate);
17921   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17922
17923   LocalContext context;
17924   Local<v8::Object> obj = templ->NewInstance();
17925   context->Global()->Set(v8_str("obj"), obj);
17926   obj->ForceSet(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
17927   obj->Set(v8_str("1"), v8_str("foobar"));
17928   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("1"))));
17929   obj->ForceSet(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
17930   obj->Set(v8_num(2), v8_str("foobar"));
17931   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_num(2))));
17932
17933   // Test non-smi case.
17934   obj->ForceSet(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
17935   obj->Set(v8_str("2000000000"), v8_str("foobar"));
17936   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("2000000000"))));
17937 }
17938
17939
17940 static int CountLiveMapsInMapCache(i::Context* context) {
17941   i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
17942   int length = map_cache->length();
17943   int count = 0;
17944   for (int i = 0; i < length; i++) {
17945     i::Object* value = map_cache->get(i);
17946     if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
17947   }
17948   return count;
17949 }
17950
17951
17952 THREADED_TEST(Regress1516) {
17953   LocalContext context;
17954   v8::HandleScope scope(context->GetIsolate());
17955
17956   // Object with 20 properties is not a common case, so it should be removed
17957   // from the cache after GC.
17958   { v8::HandleScope temp_scope(context->GetIsolate());
17959     CompileRun(
17960         "({"
17961         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
17962         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
17963         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
17964         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
17965         "})");
17966   }
17967
17968   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
17969   CHECK_LE(1, elements);
17970
17971   CcTest::heap()->CollectAllGarbage();
17972
17973   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
17974 }
17975
17976
17977 THREADED_TEST(Regress93759) {
17978   v8::Isolate* isolate = CcTest::isolate();
17979   HandleScope scope(isolate);
17980
17981   // Template for object with security check.
17982   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
17983   no_proto_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
17984
17985   // Templates for objects with hidden prototypes and possibly security check.
17986   Local<FunctionTemplate> hidden_proto_template =
17987       v8::FunctionTemplate::New(isolate);
17988   hidden_proto_template->SetHiddenPrototype(true);
17989
17990   Local<FunctionTemplate> protected_hidden_proto_template =
17991       v8::FunctionTemplate::New(isolate);
17992   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
17993       AccessAlwaysBlocked, NULL);
17994   protected_hidden_proto_template->SetHiddenPrototype(true);
17995
17996   // Context for "foreign" objects used in test.
17997   Local<Context> context = v8::Context::New(isolate);
17998   context->Enter();
17999
18000   // Plain object, no security check.
18001   Local<Object> simple_object = Object::New(isolate);
18002
18003   // Object with explicit security check.
18004   Local<Object> protected_object = no_proto_template->NewInstance();
18005
18006   // JSGlobalProxy object, always have security check.
18007   Local<Object> proxy_object = context->Global();
18008
18009   // Global object, the  prototype of proxy_object. No security checks.
18010   Local<Object> global_object = proxy_object->GetPrototype()->ToObject(isolate);
18011
18012   // Hidden prototype without security check.
18013   Local<Object> hidden_prototype =
18014       hidden_proto_template->GetFunction()->NewInstance();
18015   Local<Object> object_with_hidden =
18016     Object::New(isolate);
18017   object_with_hidden->SetPrototype(hidden_prototype);
18018
18019   // Hidden prototype with security check on the hidden prototype.
18020   Local<Object> protected_hidden_prototype =
18021       protected_hidden_proto_template->GetFunction()->NewInstance();
18022   Local<Object> object_with_protected_hidden =
18023     Object::New(isolate);
18024   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
18025
18026   context->Exit();
18027
18028   // Template for object for second context. Values to test are put on it as
18029   // properties.
18030   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
18031   global_template->Set(v8_str("simple"), simple_object);
18032   global_template->Set(v8_str("protected"), protected_object);
18033   global_template->Set(v8_str("global"), global_object);
18034   global_template->Set(v8_str("proxy"), proxy_object);
18035   global_template->Set(v8_str("hidden"), object_with_hidden);
18036   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
18037
18038   LocalContext context2(NULL, global_template);
18039
18040   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
18041   CHECK(result1->Equals(simple_object->GetPrototype()));
18042
18043   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
18044   CHECK(result2->IsNull());
18045
18046   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
18047   CHECK(result3->Equals(global_object->GetPrototype()));
18048
18049   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
18050   CHECK(result4->IsNull());
18051
18052   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
18053   CHECK(result5->Equals(
18054       object_with_hidden->GetPrototype()->ToObject(isolate)->GetPrototype()));
18055
18056   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
18057   CHECK(result6->IsNull());
18058 }
18059
18060
18061 static void TestReceiver(Local<Value> expected_result,
18062                          Local<Value> expected_receiver,
18063                          const char* code) {
18064   Local<Value> result = CompileRun(code);
18065   CHECK(result->IsObject());
18066   CHECK(expected_receiver->Equals(result.As<v8::Object>()->Get(1)));
18067   CHECK(expected_result->Equals(result.As<v8::Object>()->Get(0)));
18068 }
18069
18070
18071 THREADED_TEST(ForeignFunctionReceiver) {
18072   v8::Isolate* isolate = CcTest::isolate();
18073   HandleScope scope(isolate);
18074
18075   // Create two contexts with different "id" properties ('i' and 'o').
18076   // Call a function both from its own context and from a the foreign
18077   // context, and see what "this" is bound to (returning both "this"
18078   // and "this.id" for comparison).
18079
18080   Local<Context> foreign_context = v8::Context::New(isolate);
18081   foreign_context->Enter();
18082   Local<Value> foreign_function =
18083     CompileRun("function func() { return { 0: this.id, "
18084                "                           1: this, "
18085                "                           toString: function() { "
18086                "                               return this[0];"
18087                "                           }"
18088                "                         };"
18089                "}"
18090                "var id = 'i';"
18091                "func;");
18092   CHECK(foreign_function->IsFunction());
18093   foreign_context->Exit();
18094
18095   LocalContext context;
18096
18097   Local<String> password = v8_str("Password");
18098   // Don't get hit by security checks when accessing foreign_context's
18099   // global receiver (aka. global proxy).
18100   context->SetSecurityToken(password);
18101   foreign_context->SetSecurityToken(password);
18102
18103   Local<String> i = v8_str("i");
18104   Local<String> o = v8_str("o");
18105   Local<String> id = v8_str("id");
18106
18107   CompileRun("function ownfunc() { return { 0: this.id, "
18108              "                              1: this, "
18109              "                              toString: function() { "
18110              "                                  return this[0];"
18111              "                              }"
18112              "                             };"
18113              "}"
18114              "var id = 'o';"
18115              "ownfunc");
18116   context->Global()->Set(v8_str("func"), foreign_function);
18117
18118   // Sanity check the contexts.
18119   CHECK(i->Equals(foreign_context->Global()->Get(id)));
18120   CHECK(o->Equals(context->Global()->Get(id)));
18121
18122   // Checking local function's receiver.
18123   // Calling function using its call/apply methods.
18124   TestReceiver(o, context->Global(), "ownfunc.call()");
18125   TestReceiver(o, context->Global(), "ownfunc.apply()");
18126   // Making calls through built-in functions.
18127   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
18128   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
18129   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
18130   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
18131   // Calling with environment record as base.
18132   TestReceiver(o, context->Global(), "ownfunc()");
18133   // Calling with no base.
18134   TestReceiver(o, context->Global(), "(1,ownfunc)()");
18135
18136   // Checking foreign function return value.
18137   // Calling function using its call/apply methods.
18138   TestReceiver(i, foreign_context->Global(), "func.call()");
18139   TestReceiver(i, foreign_context->Global(), "func.apply()");
18140   // Calling function using another context's call/apply methods.
18141   TestReceiver(i, foreign_context->Global(),
18142                "Function.prototype.call.call(func)");
18143   TestReceiver(i, foreign_context->Global(),
18144                "Function.prototype.call.apply(func)");
18145   TestReceiver(i, foreign_context->Global(),
18146                "Function.prototype.apply.call(func)");
18147   TestReceiver(i, foreign_context->Global(),
18148                "Function.prototype.apply.apply(func)");
18149   // Making calls through built-in functions.
18150   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
18151   // ToString(func()) is func()[0], i.e., the returned this.id.
18152   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
18153   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
18154   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
18155
18156   // Calling with environment record as base.
18157   TestReceiver(i, foreign_context->Global(), "func()");
18158   // Calling with no base.
18159   TestReceiver(i, foreign_context->Global(), "(1,func)()");
18160 }
18161
18162
18163 uint8_t callback_fired = 0;
18164
18165
18166 void CallCompletedCallback1() {
18167   v8::base::OS::Print("Firing callback 1.\n");
18168   callback_fired ^= 1;  // Toggle first bit.
18169 }
18170
18171
18172 void CallCompletedCallback2() {
18173   v8::base::OS::Print("Firing callback 2.\n");
18174   callback_fired ^= 2;  // Toggle second bit.
18175 }
18176
18177
18178 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
18179   int32_t level = args[0]->Int32Value();
18180   if (level < 3) {
18181     level++;
18182     v8::base::OS::Print("Entering recursion level %d.\n", level);
18183     char script[64];
18184     i::Vector<char> script_vector(script, sizeof(script));
18185     i::SNPrintF(script_vector, "recursion(%d)", level);
18186     CompileRun(script_vector.start());
18187     v8::base::OS::Print("Leaving recursion level %d.\n", level);
18188     CHECK_EQ(0, callback_fired);
18189   } else {
18190     v8::base::OS::Print("Recursion ends.\n");
18191     CHECK_EQ(0, callback_fired);
18192   }
18193 }
18194
18195
18196 TEST(CallCompletedCallback) {
18197   LocalContext env;
18198   v8::HandleScope scope(env->GetIsolate());
18199   v8::Handle<v8::FunctionTemplate> recursive_runtime =
18200       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
18201   env->Global()->Set(v8_str("recursion"),
18202                      recursive_runtime->GetFunction());
18203   // Adding the same callback a second time has no effect.
18204   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
18205   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
18206   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
18207   v8::base::OS::Print("--- Script (1) ---\n");
18208   Local<Script> script = v8::Script::Compile(
18209       v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
18210   script->Run();
18211   CHECK_EQ(3, callback_fired);
18212
18213   v8::base::OS::Print("\n--- Script (2) ---\n");
18214   callback_fired = 0;
18215   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
18216   script->Run();
18217   CHECK_EQ(2, callback_fired);
18218
18219   v8::base::OS::Print("\n--- Function ---\n");
18220   callback_fired = 0;
18221   Local<Function> recursive_function =
18222       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
18223   v8::Handle<Value> args[] = { v8_num(0) };
18224   recursive_function->Call(env->Global(), 1, args);
18225   CHECK_EQ(2, callback_fired);
18226 }
18227
18228
18229 void CallCompletedCallbackNoException() {
18230   v8::HandleScope scope(CcTest::isolate());
18231   CompileRun("1+1;");
18232 }
18233
18234
18235 void CallCompletedCallbackException() {
18236   v8::HandleScope scope(CcTest::isolate());
18237   CompileRun("throw 'second exception';");
18238 }
18239
18240
18241 TEST(CallCompletedCallbackOneException) {
18242   LocalContext env;
18243   v8::HandleScope scope(env->GetIsolate());
18244   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
18245   CompileRun("throw 'exception';");
18246 }
18247
18248
18249 TEST(CallCompletedCallbackTwoExceptions) {
18250   LocalContext env;
18251   v8::HandleScope scope(env->GetIsolate());
18252   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
18253   CompileRun("throw 'first exception';");
18254 }
18255
18256
18257 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
18258   v8::HandleScope scope(info.GetIsolate());
18259   CompileRun("ext1Calls++;");
18260 }
18261
18262
18263 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
18264   v8::HandleScope scope(info.GetIsolate());
18265   CompileRun("ext2Calls++;");
18266 }
18267
18268
18269 void* g_passed_to_three = NULL;
18270
18271
18272 static void MicrotaskThree(void* data) {
18273   g_passed_to_three = data;
18274 }
18275
18276
18277 TEST(EnqueueMicrotask) {
18278   LocalContext env;
18279   v8::HandleScope scope(env->GetIsolate());
18280   CompileRun(
18281       "var ext1Calls = 0;"
18282       "var ext2Calls = 0;");
18283   CompileRun("1+1;");
18284   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
18285   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18286
18287   env->GetIsolate()->EnqueueMicrotask(
18288       Function::New(env->GetIsolate(), MicrotaskOne));
18289   CompileRun("1+1;");
18290   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18291   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18292
18293   env->GetIsolate()->EnqueueMicrotask(
18294       Function::New(env->GetIsolate(), MicrotaskOne));
18295   env->GetIsolate()->EnqueueMicrotask(
18296       Function::New(env->GetIsolate(), MicrotaskTwo));
18297   CompileRun("1+1;");
18298   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18299   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18300
18301   env->GetIsolate()->EnqueueMicrotask(
18302       Function::New(env->GetIsolate(), MicrotaskTwo));
18303   CompileRun("1+1;");
18304   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18305   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18306
18307   CompileRun("1+1;");
18308   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18309   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18310
18311   g_passed_to_three = NULL;
18312   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
18313   CompileRun("1+1;");
18314   CHECK(!g_passed_to_three);
18315   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18316   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18317
18318   int dummy;
18319   env->GetIsolate()->EnqueueMicrotask(
18320       Function::New(env->GetIsolate(), MicrotaskOne));
18321   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
18322   env->GetIsolate()->EnqueueMicrotask(
18323       Function::New(env->GetIsolate(), MicrotaskTwo));
18324   CompileRun("1+1;");
18325   CHECK_EQ(&dummy, g_passed_to_three);
18326   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
18327   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18328   g_passed_to_three = NULL;
18329 }
18330
18331
18332 static void MicrotaskExceptionOne(
18333     const v8::FunctionCallbackInfo<Value>& info) {
18334   v8::HandleScope scope(info.GetIsolate());
18335   CompileRun("exception1Calls++;");
18336   info.GetIsolate()->ThrowException(
18337       v8::Exception::Error(v8_str("first")));
18338 }
18339
18340
18341 static void MicrotaskExceptionTwo(
18342     const v8::FunctionCallbackInfo<Value>& info) {
18343   v8::HandleScope scope(info.GetIsolate());
18344   CompileRun("exception2Calls++;");
18345   info.GetIsolate()->ThrowException(
18346       v8::Exception::Error(v8_str("second")));
18347 }
18348
18349
18350 TEST(RunMicrotasksIgnoresThrownExceptions) {
18351   LocalContext env;
18352   v8::Isolate* isolate = env->GetIsolate();
18353   v8::HandleScope scope(isolate);
18354   CompileRun(
18355       "var exception1Calls = 0;"
18356       "var exception2Calls = 0;");
18357   isolate->EnqueueMicrotask(
18358       Function::New(isolate, MicrotaskExceptionOne));
18359   isolate->EnqueueMicrotask(
18360       Function::New(isolate, MicrotaskExceptionTwo));
18361   TryCatch try_catch(isolate);
18362   CompileRun("1+1;");
18363   CHECK(!try_catch.HasCaught());
18364   CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
18365   CHECK_EQ(1, CompileRun("exception2Calls")->Int32Value());
18366 }
18367
18368
18369 TEST(SetAutorunMicrotasks) {
18370   LocalContext env;
18371   v8::HandleScope scope(env->GetIsolate());
18372   CompileRun(
18373       "var ext1Calls = 0;"
18374       "var ext2Calls = 0;");
18375   CompileRun("1+1;");
18376   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
18377   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18378
18379   env->GetIsolate()->EnqueueMicrotask(
18380       Function::New(env->GetIsolate(), MicrotaskOne));
18381   CompileRun("1+1;");
18382   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18383   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18384
18385   env->GetIsolate()->SetAutorunMicrotasks(false);
18386   env->GetIsolate()->EnqueueMicrotask(
18387       Function::New(env->GetIsolate(), MicrotaskOne));
18388   env->GetIsolate()->EnqueueMicrotask(
18389       Function::New(env->GetIsolate(), MicrotaskTwo));
18390   CompileRun("1+1;");
18391   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18392   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18393
18394   env->GetIsolate()->RunMicrotasks();
18395   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18396   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18397
18398   env->GetIsolate()->EnqueueMicrotask(
18399       Function::New(env->GetIsolate(), MicrotaskTwo));
18400   CompileRun("1+1;");
18401   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18402   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18403
18404   env->GetIsolate()->RunMicrotasks();
18405   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18406   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18407
18408   env->GetIsolate()->SetAutorunMicrotasks(true);
18409   env->GetIsolate()->EnqueueMicrotask(
18410       Function::New(env->GetIsolate(), MicrotaskTwo));
18411   CompileRun("1+1;");
18412   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18413   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18414
18415   env->GetIsolate()->EnqueueMicrotask(
18416       Function::New(env->GetIsolate(), MicrotaskTwo));
18417   {
18418     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
18419     CompileRun("1+1;");
18420     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18421     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18422   }
18423
18424   CompileRun("1+1;");
18425   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18426   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value());
18427 }
18428
18429
18430 TEST(RunMicrotasksWithoutEnteringContext) {
18431   v8::Isolate* isolate = CcTest::isolate();
18432   HandleScope handle_scope(isolate);
18433   isolate->SetAutorunMicrotasks(false);
18434   Handle<Context> context = Context::New(isolate);
18435   {
18436     Context::Scope context_scope(context);
18437     CompileRun("var ext1Calls = 0;");
18438     isolate->EnqueueMicrotask(Function::New(isolate, MicrotaskOne));
18439   }
18440   isolate->RunMicrotasks();
18441   {
18442     Context::Scope context_scope(context);
18443     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18444   }
18445   isolate->SetAutorunMicrotasks(true);
18446 }
18447
18448
18449 static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
18450   v8::DebugEvent event = event_details.GetEvent();
18451   if (event != v8::Break) return;
18452   Handle<Object> exec_state = event_details.GetExecutionState();
18453   Handle<Value> break_id = exec_state->Get(v8_str("break_id"));
18454   CompileRun("function f(id) { new FrameDetails(id, 0); }");
18455   Handle<Function> fun =
18456       Handle<Function>::Cast(CcTest::global()->Get(v8_str("f")));
18457   fun->Call(CcTest::global(), 1, &break_id);
18458 }
18459
18460
18461 TEST(Regress385349) {
18462   i::FLAG_allow_natives_syntax = true;
18463   v8::Isolate* isolate = CcTest::isolate();
18464   HandleScope handle_scope(isolate);
18465   isolate->SetAutorunMicrotasks(false);
18466   Handle<Context> context = Context::New(isolate);
18467   v8::Debug::SetDebugEventListener(DebugEventInObserver);
18468   {
18469     Context::Scope context_scope(context);
18470     CompileRun("var obj = {};"
18471                "Object.observe(obj, function(changes) { debugger; });"
18472                "obj.a = 0;");
18473   }
18474   isolate->RunMicrotasks();
18475   isolate->SetAutorunMicrotasks(true);
18476   v8::Debug::SetDebugEventListener(NULL);
18477 }
18478
18479
18480 #ifdef ENABLE_DISASSEMBLER
18481 static int probes_counter = 0;
18482 static int misses_counter = 0;
18483 static int updates_counter = 0;
18484
18485
18486 static int* LookupCounter(const char* name) {
18487   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
18488     return &probes_counter;
18489   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
18490     return &misses_counter;
18491   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
18492     return &updates_counter;
18493   }
18494   return NULL;
18495 }
18496
18497
18498 static const char* kMegamorphicTestProgram =
18499     "function ClassA() { };"
18500     "function ClassB() { };"
18501     "ClassA.prototype.foo = function() { };"
18502     "ClassB.prototype.foo = function() { };"
18503     "function fooify(obj) { obj.foo(); };"
18504     "var a = new ClassA();"
18505     "var b = new ClassB();"
18506     "for (var i = 0; i < 10000; i++) {"
18507     "  fooify(a);"
18508     "  fooify(b);"
18509     "}";
18510 #endif
18511
18512
18513 static void StubCacheHelper(bool primary) {
18514 #ifdef ENABLE_DISASSEMBLER
18515   i::FLAG_native_code_counters = true;
18516   if (primary) {
18517     i::FLAG_test_primary_stub_cache = true;
18518   } else {
18519     i::FLAG_test_secondary_stub_cache = true;
18520   }
18521   i::FLAG_crankshaft = false;
18522   LocalContext env;
18523   env->GetIsolate()->SetCounterFunction(LookupCounter);
18524   v8::HandleScope scope(env->GetIsolate());
18525   int initial_probes = probes_counter;
18526   int initial_misses = misses_counter;
18527   int initial_updates = updates_counter;
18528   CompileRun(kMegamorphicTestProgram);
18529   int probes = probes_counter - initial_probes;
18530   int misses = misses_counter - initial_misses;
18531   int updates = updates_counter - initial_updates;
18532   CHECK_LT(updates, 10);
18533   CHECK_LT(misses, 10);
18534   // TODO(verwaest): Update this test to overflow the degree of polymorphism
18535   // before megamorphism. The number of probes will only work once we teach the
18536   // serializer to embed references to counters in the stubs, given that the
18537   // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
18538   CHECK_GE(probes, 0);
18539 #endif
18540 }
18541
18542
18543 TEST(SecondaryStubCache) {
18544   StubCacheHelper(true);
18545 }
18546
18547
18548 TEST(PrimaryStubCache) {
18549   StubCacheHelper(false);
18550 }
18551
18552
18553 #ifdef DEBUG
18554 static int cow_arrays_created_runtime = 0;
18555
18556
18557 static int* LookupCounterCOWArrays(const char* name) {
18558   if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
18559     return &cow_arrays_created_runtime;
18560   }
18561   return NULL;
18562 }
18563 #endif
18564
18565
18566 TEST(CheckCOWArraysCreatedRuntimeCounter) {
18567 #ifdef DEBUG
18568   i::FLAG_native_code_counters = true;
18569   LocalContext env;
18570   env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
18571   v8::HandleScope scope(env->GetIsolate());
18572   int initial_cow_arrays = cow_arrays_created_runtime;
18573   CompileRun("var o = [1, 2, 3];");
18574   CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
18575   CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
18576   CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
18577   CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
18578   CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
18579 #endif
18580 }
18581
18582
18583 TEST(StaticGetters) {
18584   LocalContext context;
18585   i::Factory* factory = CcTest::i_isolate()->factory();
18586   v8::Isolate* isolate = CcTest::isolate();
18587   v8::HandleScope scope(isolate);
18588   i::Handle<i::Object> undefined_value = factory->undefined_value();
18589   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
18590   i::Handle<i::Object> null_value = factory->null_value();
18591   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
18592   i::Handle<i::Object> true_value = factory->true_value();
18593   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
18594   i::Handle<i::Object> false_value = factory->false_value();
18595   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
18596 }
18597
18598
18599 UNINITIALIZED_TEST(IsolateEmbedderData) {
18600   CcTest::DisableAutomaticDispose();
18601   v8::Isolate::CreateParams create_params;
18602   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18603   v8::Isolate* isolate = v8::Isolate::New(create_params);
18604   isolate->Enter();
18605   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
18606   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18607     CHECK(!isolate->GetData(slot));
18608     CHECK(!i_isolate->GetData(slot));
18609   }
18610   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18611     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
18612     isolate->SetData(slot, data);
18613   }
18614   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18615     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
18616     CHECK_EQ(data, isolate->GetData(slot));
18617     CHECK_EQ(data, i_isolate->GetData(slot));
18618   }
18619   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18620     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
18621     isolate->SetData(slot, data);
18622   }
18623   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18624     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
18625     CHECK_EQ(data, isolate->GetData(slot));
18626     CHECK_EQ(data, i_isolate->GetData(slot));
18627   }
18628   isolate->Exit();
18629   isolate->Dispose();
18630 }
18631
18632
18633 TEST(StringEmpty) {
18634   LocalContext context;
18635   i::Factory* factory = CcTest::i_isolate()->factory();
18636   v8::Isolate* isolate = CcTest::isolate();
18637   v8::HandleScope scope(isolate);
18638   i::Handle<i::Object> empty_string = factory->empty_string();
18639   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
18640 }
18641
18642
18643 static int instance_checked_getter_count = 0;
18644 static void InstanceCheckedGetter(
18645     Local<String> name,
18646     const v8::PropertyCallbackInfo<v8::Value>& info) {
18647   CHECK(name->Equals(v8_str("foo")));
18648   instance_checked_getter_count++;
18649   info.GetReturnValue().Set(v8_num(11));
18650 }
18651
18652
18653 static int instance_checked_setter_count = 0;
18654 static void InstanceCheckedSetter(Local<String> name,
18655                       Local<Value> value,
18656                       const v8::PropertyCallbackInfo<void>& info) {
18657   CHECK(name->Equals(v8_str("foo")));
18658   CHECK(value->Equals(v8_num(23)));
18659   instance_checked_setter_count++;
18660 }
18661
18662
18663 static void CheckInstanceCheckedResult(int getters, int setters,
18664                                        bool expects_callbacks,
18665                                        TryCatch* try_catch) {
18666   if (expects_callbacks) {
18667     CHECK(!try_catch->HasCaught());
18668     CHECK_EQ(getters, instance_checked_getter_count);
18669     CHECK_EQ(setters, instance_checked_setter_count);
18670   } else {
18671     CHECK(try_catch->HasCaught());
18672     CHECK_EQ(0, instance_checked_getter_count);
18673     CHECK_EQ(0, instance_checked_setter_count);
18674   }
18675   try_catch->Reset();
18676 }
18677
18678
18679 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
18680   instance_checked_getter_count = 0;
18681   instance_checked_setter_count = 0;
18682   TryCatch try_catch(CcTest::isolate());
18683
18684   // Test path through generic runtime code.
18685   CompileRun("obj.foo");
18686   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
18687   CompileRun("obj.foo = 23");
18688   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
18689
18690   // Test path through generated LoadIC and StoredIC.
18691   CompileRun("function test_get(o) { o.foo; }"
18692              "test_get(obj);");
18693   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
18694   CompileRun("test_get(obj);");
18695   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
18696   CompileRun("test_get(obj);");
18697   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
18698   CompileRun("function test_set(o) { o.foo = 23; }"
18699              "test_set(obj);");
18700   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
18701   CompileRun("test_set(obj);");
18702   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
18703   CompileRun("test_set(obj);");
18704   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
18705
18706   // Test path through optimized code.
18707   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
18708              "test_get(obj);");
18709   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
18710   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
18711              "test_set(obj);");
18712   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
18713
18714   // Cleanup so that closures start out fresh in next check.
18715   CompileRun("%DeoptimizeFunction(test_get);"
18716              "%ClearFunctionTypeFeedback(test_get);"
18717              "%DeoptimizeFunction(test_set);"
18718              "%ClearFunctionTypeFeedback(test_set);");
18719 }
18720
18721
18722 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
18723   v8::internal::FLAG_allow_natives_syntax = true;
18724   LocalContext context;
18725   v8::HandleScope scope(context->GetIsolate());
18726
18727   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18728   Local<ObjectTemplate> inst = templ->InstanceTemplate();
18729   inst->SetAccessor(v8_str("foo"),
18730                     InstanceCheckedGetter, InstanceCheckedSetter,
18731                     Handle<Value>(),
18732                     v8::DEFAULT,
18733                     v8::None,
18734                     v8::AccessorSignature::New(context->GetIsolate(), templ));
18735   context->Global()->Set(v8_str("f"), templ->GetFunction());
18736
18737   printf("Testing positive ...\n");
18738   CompileRun("var obj = new f();");
18739   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18740   CheckInstanceCheckedAccessors(true);
18741
18742   printf("Testing negative ...\n");
18743   CompileRun("var obj = {};"
18744              "obj.__proto__ = new f();");
18745   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18746   CheckInstanceCheckedAccessors(false);
18747 }
18748
18749
18750 static void EmptyInterceptorGetter(
18751     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
18752
18753
18754 static void EmptyInterceptorSetter(
18755     Local<String> name, Local<Value> value,
18756     const v8::PropertyCallbackInfo<v8::Value>& info) {}
18757
18758
18759 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
18760   v8::internal::FLAG_allow_natives_syntax = true;
18761   LocalContext context;
18762   v8::HandleScope scope(context->GetIsolate());
18763
18764   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18765   Local<ObjectTemplate> inst = templ->InstanceTemplate();
18766   templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
18767                                                      EmptyInterceptorSetter);
18768   inst->SetAccessor(v8_str("foo"),
18769                     InstanceCheckedGetter, InstanceCheckedSetter,
18770                     Handle<Value>(),
18771                     v8::DEFAULT,
18772                     v8::None,
18773                     v8::AccessorSignature::New(context->GetIsolate(), templ));
18774   context->Global()->Set(v8_str("f"), templ->GetFunction());
18775
18776   printf("Testing positive ...\n");
18777   CompileRun("var obj = new f();");
18778   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18779   CheckInstanceCheckedAccessors(true);
18780
18781   printf("Testing negative ...\n");
18782   CompileRun("var obj = {};"
18783              "obj.__proto__ = new f();");
18784   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18785   CheckInstanceCheckedAccessors(false);
18786 }
18787
18788
18789 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
18790   v8::internal::FLAG_allow_natives_syntax = true;
18791   LocalContext context;
18792   v8::HandleScope scope(context->GetIsolate());
18793
18794   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18795   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
18796   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
18797                      InstanceCheckedSetter, Handle<Value>(), v8::DEFAULT,
18798                      v8::None,
18799                      v8::AccessorSignature::New(context->GetIsolate(), templ));
18800   context->Global()->Set(v8_str("f"), templ->GetFunction());
18801
18802   printf("Testing positive ...\n");
18803   CompileRun("var obj = new f();");
18804   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18805   CheckInstanceCheckedAccessors(true);
18806
18807   printf("Testing negative ...\n");
18808   CompileRun("var obj = {};"
18809              "obj.__proto__ = new f();");
18810   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18811   CheckInstanceCheckedAccessors(false);
18812
18813   printf("Testing positive with modified prototype chain ...\n");
18814   CompileRun("var obj = new f();"
18815              "var pro = {};"
18816              "pro.__proto__ = obj.__proto__;"
18817              "obj.__proto__ = pro;");
18818   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18819   CheckInstanceCheckedAccessors(true);
18820 }
18821
18822
18823 TEST(TryFinallyMessage) {
18824   LocalContext context;
18825   v8::HandleScope scope(context->GetIsolate());
18826   {
18827     // Test that the original error message is not lost if there is a
18828     // recursive call into Javascript is done in the finally block, e.g. to
18829     // initialize an IC. (crbug.com/129171)
18830     TryCatch try_catch(context->GetIsolate());
18831     const char* trigger_ic =
18832         "try {                      \n"
18833         "  throw new Error('test'); \n"
18834         "} finally {                \n"
18835         "  var x = 0;               \n"
18836         "  x++;                     \n"  // Trigger an IC initialization here.
18837         "}                          \n";
18838     CompileRun(trigger_ic);
18839     CHECK(try_catch.HasCaught());
18840     Local<Message> message = try_catch.Message();
18841     CHECK(!message.IsEmpty());
18842     CHECK_EQ(2, message->GetLineNumber());
18843   }
18844
18845   {
18846     // Test that the original exception message is indeed overwritten if
18847     // a new error is thrown in the finally block.
18848     TryCatch try_catch(context->GetIsolate());
18849     const char* throw_again =
18850         "try {                       \n"
18851         "  throw new Error('test');  \n"
18852         "} finally {                 \n"
18853         "  var x = 0;                \n"
18854         "  x++;                      \n"
18855         "  throw new Error('again'); \n"  // This is the new uncaught error.
18856         "}                           \n";
18857     CompileRun(throw_again);
18858     CHECK(try_catch.HasCaught());
18859     Local<Message> message = try_catch.Message();
18860     CHECK(!message.IsEmpty());
18861     CHECK_EQ(6, message->GetLineNumber());
18862   }
18863 }
18864
18865
18866 static void Helper137002(bool do_store,
18867                          bool polymorphic,
18868                          bool remove_accessor,
18869                          bool interceptor) {
18870   LocalContext context;
18871   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
18872   if (interceptor) {
18873     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
18874                                                             FooSetInterceptor));
18875   } else {
18876     templ->SetAccessor(v8_str("foo"),
18877                        GetterWhichReturns42,
18878                        SetterWhichSetsYOnThisTo23);
18879   }
18880   context->Global()->Set(v8_str("obj"), templ->NewInstance());
18881
18882   // Turn monomorphic on slow object with native accessor, then turn
18883   // polymorphic, finally optimize to create negative lookup and fail.
18884   CompileRun(do_store ?
18885              "function f(x) { x.foo = void 0; }" :
18886              "function f(x) { return x.foo; }");
18887   CompileRun("obj.y = void 0;");
18888   if (!interceptor) {
18889     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
18890   }
18891   CompileRun("obj.__proto__ = null;"
18892              "f(obj); f(obj); f(obj);");
18893   if (polymorphic) {
18894     CompileRun("f({});");
18895   }
18896   CompileRun("obj.y = void 0;"
18897              "%OptimizeFunctionOnNextCall(f);");
18898   if (remove_accessor) {
18899     CompileRun("delete obj.foo;");
18900   }
18901   CompileRun("var result = f(obj);");
18902   if (do_store) {
18903     CompileRun("result = obj.y;");
18904   }
18905   if (remove_accessor && !interceptor) {
18906     CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
18907   } else {
18908     CHECK_EQ(do_store ? 23 : 42,
18909              context->Global()->Get(v8_str("result"))->Int32Value());
18910   }
18911 }
18912
18913
18914 THREADED_TEST(Regress137002a) {
18915   i::FLAG_allow_natives_syntax = true;
18916   i::FLAG_compilation_cache = false;
18917   v8::HandleScope scope(CcTest::isolate());
18918   for (int i = 0; i < 16; i++) {
18919     Helper137002(i & 8, i & 4, i & 2, i & 1);
18920   }
18921 }
18922
18923
18924 THREADED_TEST(Regress137002b) {
18925   i::FLAG_allow_natives_syntax = true;
18926   LocalContext context;
18927   v8::Isolate* isolate = context->GetIsolate();
18928   v8::HandleScope scope(isolate);
18929   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18930   templ->SetAccessor(v8_str("foo"),
18931                      GetterWhichReturns42,
18932                      SetterWhichSetsYOnThisTo23);
18933   context->Global()->Set(v8_str("obj"), templ->NewInstance());
18934
18935   // Turn monomorphic on slow object with native accessor, then just
18936   // delete the property and fail.
18937   CompileRun("function load(x) { return x.foo; }"
18938              "function store(x) { x.foo = void 0; }"
18939              "function keyed_load(x, key) { return x[key]; }"
18940              // Second version of function has a different source (add void 0)
18941              // so that it does not share code with the first version.  This
18942              // ensures that the ICs are monomorphic.
18943              "function load2(x) { void 0; return x.foo; }"
18944              "function store2(x) { void 0; x.foo = void 0; }"
18945              "function keyed_load2(x, key) { void 0; return x[key]; }"
18946
18947              "obj.y = void 0;"
18948              "obj.__proto__ = null;"
18949              "var subobj = {};"
18950              "subobj.y = void 0;"
18951              "subobj.__proto__ = obj;"
18952              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
18953
18954              // Make the ICs monomorphic.
18955              "load(obj); load(obj);"
18956              "load2(subobj); load2(subobj);"
18957              "store(obj); store(obj);"
18958              "store2(subobj); store2(subobj);"
18959              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
18960              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
18961
18962              // Actually test the shiny new ICs and better not crash. This
18963              // serves as a regression test for issue 142088 as well.
18964              "load(obj);"
18965              "load2(subobj);"
18966              "store(obj);"
18967              "store2(subobj);"
18968              "keyed_load(obj, 'foo');"
18969              "keyed_load2(subobj, 'foo');"
18970
18971              // Delete the accessor.  It better not be called any more now.
18972              "delete obj.foo;"
18973              "obj.y = void 0;"
18974              "subobj.y = void 0;"
18975
18976              "var load_result = load(obj);"
18977              "var load_result2 = load2(subobj);"
18978              "var keyed_load_result = keyed_load(obj, 'foo');"
18979              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
18980              "store(obj);"
18981              "store2(subobj);"
18982              "var y_from_obj = obj.y;"
18983              "var y_from_subobj = subobj.y;");
18984   CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
18985   CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
18986   CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
18987   CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
18988   CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
18989   CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
18990 }
18991
18992
18993 THREADED_TEST(Regress142088) {
18994   i::FLAG_allow_natives_syntax = true;
18995   LocalContext context;
18996   v8::Isolate* isolate = context->GetIsolate();
18997   v8::HandleScope scope(isolate);
18998   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18999   templ->SetAccessor(v8_str("foo"),
19000                      GetterWhichReturns42,
19001                      SetterWhichSetsYOnThisTo23);
19002   context->Global()->Set(v8_str("obj"), templ->NewInstance());
19003
19004   CompileRun("function load(x) { return x.foo; }"
19005              "var o = Object.create(obj);"
19006              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
19007              "load(o); load(o); load(o); load(o);");
19008 }
19009
19010
19011 THREADED_TEST(Regress137496) {
19012   i::FLAG_expose_gc = true;
19013   LocalContext context;
19014   v8::HandleScope scope(context->GetIsolate());
19015
19016   // Compile a try-finally clause where the finally block causes a GC
19017   // while there still is a message pending for external reporting.
19018   TryCatch try_catch(context->GetIsolate());
19019   try_catch.SetVerbose(true);
19020   CompileRun("try { throw new Error(); } finally { gc(); }");
19021   CHECK(try_catch.HasCaught());
19022 }
19023
19024
19025 THREADED_TEST(Regress157124) {
19026   LocalContext context;
19027   v8::Isolate* isolate = context->GetIsolate();
19028   v8::HandleScope scope(isolate);
19029   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19030   Local<Object> obj = templ->NewInstance();
19031   obj->GetIdentityHash();
19032   obj->DeleteHiddenValue(v8_str("Bug"));
19033 }
19034
19035
19036 THREADED_TEST(Regress2535) {
19037   LocalContext context;
19038   v8::HandleScope scope(context->GetIsolate());
19039   Local<Value> set_value = CompileRun("new Set();");
19040   Local<Object> set_object(Local<Object>::Cast(set_value));
19041   CHECK_EQ(0, set_object->InternalFieldCount());
19042   Local<Value> map_value = CompileRun("new Map();");
19043   Local<Object> map_object(Local<Object>::Cast(map_value));
19044   CHECK_EQ(0, map_object->InternalFieldCount());
19045 }
19046
19047
19048 THREADED_TEST(Regress2746) {
19049   LocalContext context;
19050   v8::Isolate* isolate = context->GetIsolate();
19051   v8::HandleScope scope(isolate);
19052   Local<Object> obj = Object::New(isolate);
19053   Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
19054   obj->SetHiddenValue(key, v8::Undefined(isolate));
19055   Local<Value> value = obj->GetHiddenValue(key);
19056   CHECK(!value.IsEmpty());
19057   CHECK(value->IsUndefined());
19058 }
19059
19060
19061 THREADED_TEST(Regress260106) {
19062   LocalContext context;
19063   v8::Isolate* isolate = context->GetIsolate();
19064   v8::HandleScope scope(isolate);
19065   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
19066                                                         DummyCallHandler);
19067   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
19068   Local<Function> function = templ->GetFunction();
19069   CHECK(!function.IsEmpty());
19070   CHECK(function->IsFunction());
19071 }
19072
19073
19074 THREADED_TEST(JSONParseObject) {
19075   LocalContext context;
19076   HandleScope scope(context->GetIsolate());
19077   Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
19078   Handle<Object> global = context->Global();
19079   global->Set(v8_str("obj"), obj);
19080   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
19081 }
19082
19083
19084 THREADED_TEST(JSONParseNumber) {
19085   LocalContext context;
19086   HandleScope scope(context->GetIsolate());
19087   Local<Value> obj = v8::JSON::Parse(v8_str("42"));
19088   Handle<Object> global = context->Global();
19089   global->Set(v8_str("obj"), obj);
19090   ExpectString("JSON.stringify(obj)", "42");
19091 }
19092
19093
19094 #if V8_OS_POSIX && !V8_OS_NACL
19095 class ThreadInterruptTest {
19096  public:
19097   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
19098   ~ThreadInterruptTest() {}
19099
19100   void RunTest() {
19101     InterruptThread i_thread(this);
19102     i_thread.Start();
19103
19104     sem_.Wait();
19105     CHECK_EQ(kExpectedValue, sem_value_);
19106   }
19107
19108  private:
19109   static const int kExpectedValue = 1;
19110
19111   class InterruptThread : public v8::base::Thread {
19112    public:
19113     explicit InterruptThread(ThreadInterruptTest* test)
19114         : Thread(Options("InterruptThread")), test_(test) {}
19115
19116     virtual void Run() {
19117       struct sigaction action;
19118
19119       // Ensure that we'll enter waiting condition
19120       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
19121
19122       // Setup signal handler
19123       memset(&action, 0, sizeof(action));
19124       action.sa_handler = SignalHandler;
19125       sigaction(SIGCHLD, &action, NULL);
19126
19127       // Send signal
19128       kill(getpid(), SIGCHLD);
19129
19130       // Ensure that if wait has returned because of error
19131       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
19132
19133       // Set value and signal semaphore
19134       test_->sem_value_ = 1;
19135       test_->sem_.Signal();
19136     }
19137
19138     static void SignalHandler(int signal) {
19139     }
19140
19141    private:
19142      ThreadInterruptTest* test_;
19143   };
19144
19145   v8::base::Semaphore sem_;
19146   volatile int sem_value_;
19147 };
19148
19149
19150 THREADED_TEST(SemaphoreInterruption) {
19151   ThreadInterruptTest().RunTest();
19152 }
19153
19154
19155 #endif  // V8_OS_POSIX
19156
19157
19158 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19159   CHECK(false);
19160 }
19161
19162
19163 TEST(JSONStringifyAccessCheck) {
19164   v8::V8::Initialize();
19165   v8::Isolate* isolate = CcTest::isolate();
19166   v8::HandleScope scope(isolate);
19167
19168   // Create an ObjectTemplate for global objects and install access
19169   // check callbacks that will block access.
19170   v8::Handle<v8::ObjectTemplate> global_template =
19171       v8::ObjectTemplate::New(isolate);
19172   global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
19173
19174   // Create a context and set an x property on it's global object.
19175   LocalContext context0(NULL, global_template);
19176   v8::Handle<v8::Object> global0 = context0->Global();
19177   global0->Set(v8_str("x"), v8_num(42));
19178   ExpectString("JSON.stringify(this)", "{\"x\":42}");
19179
19180   for (int i = 0; i < 2; i++) {
19181     if (i == 1) {
19182       // Install a toJSON function on the second run.
19183       v8::Handle<v8::FunctionTemplate> toJSON =
19184           v8::FunctionTemplate::New(isolate, UnreachableCallback);
19185
19186       global0->Set(v8_str("toJSON"), toJSON->GetFunction());
19187     }
19188     // Create a context with a different security token so that the
19189     // failed access check callback will be called on each access.
19190     LocalContext context1(NULL, global_template);
19191     context1->Global()->Set(v8_str("other"), global0);
19192
19193     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
19194     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
19195     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
19196   }
19197 }
19198
19199
19200 bool access_check_fail_thrown = false;
19201 bool catch_callback_called = false;
19202
19203
19204 // Failed access check callback that performs a GC on each invocation.
19205 void FailedAccessCheckThrows(Local<v8::Object> target,
19206                              v8::AccessType type,
19207                              Local<v8::Value> data) {
19208   access_check_fail_thrown = true;
19209   i::PrintF("Access check failed. Error thrown.\n");
19210   CcTest::isolate()->ThrowException(
19211       v8::Exception::Error(v8_str("cross context")));
19212 }
19213
19214
19215 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19216   for (int i = 0; i < args.Length(); i++) {
19217     i::PrintF("%s\n", *String::Utf8Value(args[i]));
19218   }
19219   catch_callback_called = true;
19220 }
19221
19222
19223 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19224   args[0]->ToObject(args.GetIsolate())->HasOwnProperty(
19225       args[1]->ToString(args.GetIsolate()));
19226 }
19227
19228
19229 void CheckCorrectThrow(const char* script) {
19230   // Test that the script, when wrapped into a try-catch, triggers the catch
19231   // clause due to failed access check throwing an exception.
19232   // The subsequent try-catch should run without any exception.
19233   access_check_fail_thrown = false;
19234   catch_callback_called = false;
19235   i::ScopedVector<char> source(1024);
19236   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
19237   CompileRun(source.start());
19238   CHECK(access_check_fail_thrown);
19239   CHECK(catch_callback_called);
19240
19241   access_check_fail_thrown = false;
19242   catch_callback_called = false;
19243   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
19244   CHECK(!access_check_fail_thrown);
19245   CHECK(!catch_callback_called);
19246 }
19247
19248
19249 TEST(AccessCheckThrows) {
19250   i::FLAG_allow_natives_syntax = true;
19251   i::FLAG_turbo_try_catch = true;
19252   v8::V8::Initialize();
19253   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
19254   v8::Isolate* isolate = CcTest::isolate();
19255   v8::HandleScope scope(isolate);
19256
19257   // Create an ObjectTemplate for global objects and install access
19258   // check callbacks that will block access.
19259   v8::Handle<v8::ObjectTemplate> global_template =
19260       v8::ObjectTemplate::New(isolate);
19261   global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
19262
19263   // Create a context and set an x property on it's global object.
19264   LocalContext context0(NULL, global_template);
19265   v8::Handle<v8::Object> global0 = context0->Global();
19266
19267   // Create a context with a different security token so that the
19268   // failed access check callback will be called on each access.
19269   LocalContext context1(NULL, global_template);
19270   context1->Global()->Set(v8_str("other"), global0);
19271
19272   v8::Handle<v8::FunctionTemplate> catcher_fun =
19273       v8::FunctionTemplate::New(isolate, CatcherCallback);
19274   context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
19275
19276   v8::Handle<v8::FunctionTemplate> has_own_property_fun =
19277       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
19278   context1->Global()->Set(v8_str("has_own_property"),
19279                           has_own_property_fun->GetFunction());
19280
19281   {
19282     v8::TryCatch try_catch(isolate);
19283     access_check_fail_thrown = false;
19284     CompileRun("other.x;");
19285     CHECK(access_check_fail_thrown);
19286     CHECK(try_catch.HasCaught());
19287   }
19288
19289   CheckCorrectThrow("other.x");
19290   CheckCorrectThrow("other[1]");
19291   CheckCorrectThrow("JSON.stringify(other)");
19292   CheckCorrectThrow("has_own_property(other, 'x')");
19293   CheckCorrectThrow("%GetProperty(other, 'x')");
19294   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
19295   CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
19296   CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
19297   CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
19298   CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
19299   CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
19300   CheckCorrectThrow("%HasOwnProperty(other, 'x')");
19301   CheckCorrectThrow("%HasProperty('x', other)");
19302   CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
19303   // PROPERTY_ATTRIBUTES_NONE = 0
19304   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
19305                         "other, 'x', null, null, 1)");
19306
19307   // Reset the failed access check callback so it does not influence
19308   // the other tests.
19309   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19310 }
19311
19312
19313 class RequestInterruptTestBase {
19314  public:
19315   RequestInterruptTestBase()
19316       : env_(),
19317         isolate_(env_->GetIsolate()),
19318         sem_(0),
19319         warmup_(20000),
19320         should_continue_(true) {
19321   }
19322
19323   virtual ~RequestInterruptTestBase() { }
19324
19325   virtual void StartInterruptThread() = 0;
19326
19327   virtual void TestBody() = 0;
19328
19329   void RunTest() {
19330     StartInterruptThread();
19331
19332     v8::HandleScope handle_scope(isolate_);
19333
19334     TestBody();
19335
19336     // Verify we arrived here because interruptor was called
19337     // not due to a bug causing us to exit the loop too early.
19338     CHECK(!should_continue());
19339   }
19340
19341   void WakeUpInterruptor() {
19342     sem_.Signal();
19343   }
19344
19345   bool should_continue() const { return should_continue_; }
19346
19347   bool ShouldContinue() {
19348     if (warmup_ > 0) {
19349       if (--warmup_ == 0) {
19350         WakeUpInterruptor();
19351       }
19352     }
19353
19354     return should_continue_;
19355   }
19356
19357   static void ShouldContinueCallback(
19358       const v8::FunctionCallbackInfo<Value>& info) {
19359     RequestInterruptTestBase* test =
19360         reinterpret_cast<RequestInterruptTestBase*>(
19361             info.Data().As<v8::External>()->Value());
19362     info.GetReturnValue().Set(test->ShouldContinue());
19363   }
19364
19365   LocalContext env_;
19366   v8::Isolate* isolate_;
19367   v8::base::Semaphore sem_;
19368   int warmup_;
19369   bool should_continue_;
19370 };
19371
19372
19373 class RequestInterruptTestBaseWithSimpleInterrupt
19374     : public RequestInterruptTestBase {
19375  public:
19376   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
19377
19378   virtual void StartInterruptThread() {
19379     i_thread.Start();
19380   }
19381
19382  private:
19383   class InterruptThread : public v8::base::Thread {
19384    public:
19385     explicit InterruptThread(RequestInterruptTestBase* test)
19386         : Thread(Options("RequestInterruptTest")), test_(test) {}
19387
19388     virtual void Run() {
19389       test_->sem_.Wait();
19390       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
19391     }
19392
19393     static void OnInterrupt(v8::Isolate* isolate, void* data) {
19394       reinterpret_cast<RequestInterruptTestBase*>(data)->
19395           should_continue_ = false;
19396     }
19397
19398    private:
19399      RequestInterruptTestBase* test_;
19400   };
19401
19402   InterruptThread i_thread;
19403 };
19404
19405
19406 class RequestInterruptTestWithFunctionCall
19407     : public RequestInterruptTestBaseWithSimpleInterrupt {
19408  public:
19409   virtual void TestBody() {
19410     Local<Function> func = Function::New(
19411         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
19412     env_->Global()->Set(v8_str("ShouldContinue"), func);
19413
19414     CompileRun("while (ShouldContinue()) { }");
19415   }
19416 };
19417
19418
19419 class RequestInterruptTestWithMethodCall
19420     : public RequestInterruptTestBaseWithSimpleInterrupt {
19421  public:
19422   virtual void TestBody() {
19423     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19424     v8::Local<v8::Template> proto = t->PrototypeTemplate();
19425     proto->Set(v8_str("shouldContinue"), Function::New(
19426         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19427     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19428
19429     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
19430   }
19431 };
19432
19433
19434 class RequestInterruptTestWithAccessor
19435     : public RequestInterruptTestBaseWithSimpleInterrupt {
19436  public:
19437   virtual void TestBody() {
19438     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19439     v8::Local<v8::Template> proto = t->PrototypeTemplate();
19440     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
19441         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19442     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19443
19444     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
19445   }
19446 };
19447
19448
19449 class RequestInterruptTestWithNativeAccessor
19450     : public RequestInterruptTestBaseWithSimpleInterrupt {
19451  public:
19452   virtual void TestBody() {
19453     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19454     t->InstanceTemplate()->SetNativeDataProperty(
19455         v8_str("shouldContinue"),
19456         &ShouldContinueNativeGetter,
19457         NULL,
19458         v8::External::New(isolate_, this));
19459     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19460
19461     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
19462   }
19463
19464  private:
19465   static void ShouldContinueNativeGetter(
19466       Local<String> property,
19467       const v8::PropertyCallbackInfo<v8::Value>& info) {
19468     RequestInterruptTestBase* test =
19469         reinterpret_cast<RequestInterruptTestBase*>(
19470             info.Data().As<v8::External>()->Value());
19471     info.GetReturnValue().Set(test->ShouldContinue());
19472   }
19473 };
19474
19475
19476 class RequestInterruptTestWithMethodCallAndInterceptor
19477     : public RequestInterruptTestBaseWithSimpleInterrupt {
19478  public:
19479   virtual void TestBody() {
19480     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19481     v8::Local<v8::Template> proto = t->PrototypeTemplate();
19482     proto->Set(v8_str("shouldContinue"), Function::New(
19483         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19484     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
19485     instance_template->SetHandler(
19486         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
19487
19488     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19489
19490     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
19491   }
19492
19493  private:
19494   static void EmptyInterceptor(
19495       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
19496 };
19497
19498
19499 class RequestInterruptTestWithMathAbs
19500     : public RequestInterruptTestBaseWithSimpleInterrupt {
19501  public:
19502   virtual void TestBody() {
19503     env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
19504         isolate_,
19505         WakeUpInterruptorCallback,
19506         v8::External::New(isolate_, this)));
19507
19508     env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
19509         isolate_,
19510         ShouldContinueCallback,
19511         v8::External::New(isolate_, this)));
19512
19513     i::FLAG_allow_natives_syntax = true;
19514     CompileRun("function loopish(o) {"
19515                "  var pre = 10;"
19516                "  while (o.abs(1) > 0) {"
19517                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
19518                "    if (pre > 0) {"
19519                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
19520                "    }"
19521                "  }"
19522                "}"
19523                "var i = 50;"
19524                "var obj = {abs: function () { return i-- }, x: null};"
19525                "delete obj.x;"
19526                "loopish(obj);"
19527                "%OptimizeFunctionOnNextCall(loopish);"
19528                "loopish(Math);");
19529
19530     i::FLAG_allow_natives_syntax = false;
19531   }
19532
19533  private:
19534   static void WakeUpInterruptorCallback(
19535       const v8::FunctionCallbackInfo<Value>& info) {
19536     if (!info[0]->BooleanValue()) return;
19537
19538     RequestInterruptTestBase* test =
19539         reinterpret_cast<RequestInterruptTestBase*>(
19540             info.Data().As<v8::External>()->Value());
19541     test->WakeUpInterruptor();
19542   }
19543
19544   static void ShouldContinueCallback(
19545       const v8::FunctionCallbackInfo<Value>& info) {
19546     RequestInterruptTestBase* test =
19547         reinterpret_cast<RequestInterruptTestBase*>(
19548             info.Data().As<v8::External>()->Value());
19549     info.GetReturnValue().Set(test->should_continue());
19550   }
19551 };
19552
19553
19554 TEST(RequestInterruptTestWithFunctionCall) {
19555   RequestInterruptTestWithFunctionCall().RunTest();
19556 }
19557
19558
19559 TEST(RequestInterruptTestWithMethodCall) {
19560   RequestInterruptTestWithMethodCall().RunTest();
19561 }
19562
19563
19564 TEST(RequestInterruptTestWithAccessor) {
19565   RequestInterruptTestWithAccessor().RunTest();
19566 }
19567
19568
19569 TEST(RequestInterruptTestWithNativeAccessor) {
19570   RequestInterruptTestWithNativeAccessor().RunTest();
19571 }
19572
19573
19574 TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
19575   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
19576 }
19577
19578
19579 TEST(RequestInterruptTestWithMathAbs) {
19580   RequestInterruptTestWithMathAbs().RunTest();
19581 }
19582
19583
19584 class RequestMultipleInterrupts : public RequestInterruptTestBase {
19585  public:
19586   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
19587
19588   virtual void StartInterruptThread() {
19589     i_thread.Start();
19590   }
19591
19592   virtual void TestBody() {
19593     Local<Function> func = Function::New(
19594         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
19595     env_->Global()->Set(v8_str("ShouldContinue"), func);
19596
19597     CompileRun("while (ShouldContinue()) { }");
19598   }
19599
19600  private:
19601   class InterruptThread : public v8::base::Thread {
19602    public:
19603     enum { NUM_INTERRUPTS = 10 };
19604     explicit InterruptThread(RequestMultipleInterrupts* test)
19605         : Thread(Options("RequestInterruptTest")), test_(test) {}
19606
19607     virtual void Run() {
19608       test_->sem_.Wait();
19609       for (int i = 0; i < NUM_INTERRUPTS; i++) {
19610         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
19611       }
19612     }
19613
19614     static void OnInterrupt(v8::Isolate* isolate, void* data) {
19615       RequestMultipleInterrupts* test =
19616           reinterpret_cast<RequestMultipleInterrupts*>(data);
19617       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
19618     }
19619
19620    private:
19621     RequestMultipleInterrupts* test_;
19622   };
19623
19624   InterruptThread i_thread;
19625   int counter_;
19626 };
19627
19628
19629 TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
19630
19631
19632 static bool interrupt_was_called = false;
19633
19634
19635 void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
19636   interrupt_was_called = true;
19637 }
19638
19639
19640 TEST(RequestInterruptSmallScripts) {
19641   LocalContext env;
19642   v8::Isolate* isolate = CcTest::isolate();
19643   v8::HandleScope scope(isolate);
19644
19645   interrupt_was_called = false;
19646   isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
19647   CompileRun("(function(x){return x;})(1);");
19648   CHECK(interrupt_was_called);
19649 }
19650
19651
19652 static Local<Value> function_new_expected_env;
19653 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
19654   CHECK(function_new_expected_env->Equals(info.Data()));
19655   info.GetReturnValue().Set(17);
19656 }
19657
19658
19659 THREADED_TEST(FunctionNew) {
19660   LocalContext env;
19661   v8::Isolate* isolate = env->GetIsolate();
19662   v8::HandleScope scope(isolate);
19663   Local<Object> data = v8::Object::New(isolate);
19664   function_new_expected_env = data;
19665   Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
19666   env->Global()->Set(v8_str("func"), func);
19667   Local<Value> result = CompileRun("func();");
19668   CHECK(v8::Integer::New(isolate, 17)->Equals(result));
19669   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
19670   // Verify function not cached
19671   auto serial_number = handle(i::Smi::cast(v8::Utils::OpenHandle(*func)
19672                                                ->shared()
19673                                                ->get_api_func_data()
19674                                                ->serial_number()),
19675                               i_isolate);
19676   auto cache = i_isolate->function_cache();
19677   CHECK(cache->Lookup(serial_number)->IsTheHole());
19678   // Verify that each Function::New creates a new function instance
19679   Local<Object> data2 = v8::Object::New(isolate);
19680   function_new_expected_env = data2;
19681   Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
19682   CHECK(!func2->IsNull());
19683   CHECK(!func->Equals(func2));
19684   env->Global()->Set(v8_str("func2"), func2);
19685   Local<Value> result2 = CompileRun("func2();");
19686   CHECK(v8::Integer::New(isolate, 17)->Equals(result2));
19687 }
19688
19689
19690 TEST(EscapeableHandleScope) {
19691   HandleScope outer_scope(CcTest::isolate());
19692   LocalContext context;
19693   const int runs = 10;
19694   Local<String> values[runs];
19695   for (int i = 0; i < runs; i++) {
19696     v8::EscapableHandleScope inner_scope(CcTest::isolate());
19697     Local<String> value;
19698     if (i != 0) value = v8_str("escape value");
19699     values[i] = inner_scope.Escape(value);
19700   }
19701   for (int i = 0; i < runs; i++) {
19702     Local<String> expected;
19703     if (i != 0) {
19704       CHECK(v8_str("escape value")->Equals(values[i]));
19705     } else {
19706       CHECK(values[i].IsEmpty());
19707     }
19708   }
19709 }
19710
19711
19712 static void SetterWhichExpectsThisAndHolderToDiffer(
19713     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
19714   CHECK(info.Holder() != info.This());
19715 }
19716
19717
19718 TEST(Regress239669) {
19719   LocalContext context;
19720   v8::Isolate* isolate = context->GetIsolate();
19721   v8::HandleScope scope(isolate);
19722   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19723   templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
19724   context->Global()->Set(v8_str("P"), templ->NewInstance());
19725   CompileRun(
19726       "function C1() {"
19727       "  this.x = 23;"
19728       "};"
19729       "C1.prototype = P;"
19730       "for (var i = 0; i < 4; i++ ) {"
19731       "  new C1();"
19732       "}");
19733 }
19734
19735
19736 class ApiCallOptimizationChecker {
19737  private:
19738   static Local<Object> data;
19739   static Local<Object> receiver;
19740   static Local<Object> holder;
19741   static Local<Object> callee;
19742   static int count;
19743
19744   static void OptimizationCallback(
19745       const v8::FunctionCallbackInfo<v8::Value>& info) {
19746     CHECK(callee == info.Callee());
19747     CHECK(data == info.Data());
19748     CHECK(receiver == info.This());
19749     if (info.Length() == 1) {
19750       CHECK(v8_num(1)->Equals(info[0]));
19751     }
19752     CHECK(holder == info.Holder());
19753     count++;
19754     info.GetReturnValue().Set(v8_str("returned"));
19755   }
19756
19757  public:
19758   enum SignatureType {
19759     kNoSignature,
19760     kSignatureOnReceiver,
19761     kSignatureOnPrototype
19762   };
19763
19764   void RunAll() {
19765     SignatureType signature_types[] =
19766       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
19767     for (unsigned i = 0; i < arraysize(signature_types); i++) {
19768       SignatureType signature_type = signature_types[i];
19769       for (int j = 0; j < 2; j++) {
19770         bool global = j == 0;
19771         int key = signature_type +
19772             arraysize(signature_types) * (global ? 1 : 0);
19773         Run(signature_type, global, key);
19774       }
19775     }
19776   }
19777
19778   void Run(SignatureType signature_type, bool global, int key) {
19779     v8::Isolate* isolate = CcTest::isolate();
19780     v8::HandleScope scope(isolate);
19781     // Build a template for signature checks.
19782     Local<v8::ObjectTemplate> signature_template;
19783     Local<v8::Signature> signature;
19784     {
19785       Local<v8::FunctionTemplate> parent_template =
19786         FunctionTemplate::New(isolate);
19787       parent_template->SetHiddenPrototype(true);
19788       Local<v8::FunctionTemplate> function_template
19789           = FunctionTemplate::New(isolate);
19790       function_template->Inherit(parent_template);
19791       switch (signature_type) {
19792         case kNoSignature:
19793           break;
19794         case kSignatureOnReceiver:
19795           signature = v8::Signature::New(isolate, function_template);
19796           break;
19797         case kSignatureOnPrototype:
19798           signature = v8::Signature::New(isolate, parent_template);
19799           break;
19800       }
19801       signature_template = function_template->InstanceTemplate();
19802     }
19803     // Global object must pass checks.
19804     Local<v8::Context> context =
19805         v8::Context::New(isolate, NULL, signature_template);
19806     v8::Context::Scope context_scope(context);
19807     // Install regular object that can pass signature checks.
19808     Local<Object> function_receiver = signature_template->NewInstance();
19809     context->Global()->Set(v8_str("function_receiver"), function_receiver);
19810     // Get the holder objects.
19811     Local<Object> inner_global =
19812         Local<Object>::Cast(context->Global()->GetPrototype());
19813     // Install functions on hidden prototype object if there is one.
19814     data = Object::New(isolate);
19815     Local<FunctionTemplate> function_template = FunctionTemplate::New(
19816         isolate, OptimizationCallback, data, signature);
19817     Local<Function> function = function_template->GetFunction();
19818     Local<Object> global_holder = inner_global;
19819     Local<Object> function_holder = function_receiver;
19820     if (signature_type == kSignatureOnPrototype) {
19821       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
19822       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
19823     }
19824     global_holder->Set(v8_str("g_f"), function);
19825     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
19826     function_holder->Set(v8_str("f"), function);
19827     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
19828     // Initialize expected values.
19829     callee = function;
19830     count = 0;
19831     if (global) {
19832       receiver = context->Global();
19833       holder = inner_global;
19834     } else {
19835       holder = function_receiver;
19836       // If not using a signature, add something else to the prototype chain
19837       // to test the case that holder != receiver
19838       if (signature_type == kNoSignature) {
19839         receiver = Local<Object>::Cast(CompileRun(
19840             "var receiver_subclass = {};\n"
19841             "receiver_subclass.__proto__ = function_receiver;\n"
19842             "receiver_subclass"));
19843       } else {
19844         receiver = Local<Object>::Cast(CompileRun(
19845           "var receiver_subclass = function_receiver;\n"
19846           "receiver_subclass"));
19847       }
19848     }
19849     // With no signature, the holder is not set.
19850     if (signature_type == kNoSignature) holder = receiver;
19851     // build wrap_function
19852     i::ScopedVector<char> wrap_function(200);
19853     if (global) {
19854       i::SNPrintF(
19855           wrap_function,
19856           "function wrap_f_%d() { var f = g_f; return f(); }\n"
19857           "function wrap_get_%d() { return this.g_acc; }\n"
19858           "function wrap_set_%d() { return this.g_acc = 1; }\n",
19859           key, key, key);
19860     } else {
19861       i::SNPrintF(
19862           wrap_function,
19863           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
19864           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
19865           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
19866           key, key, key);
19867     }
19868     // build source string
19869     i::ScopedVector<char> source(1000);
19870     i::SNPrintF(
19871         source,
19872         "%s\n"  // wrap functions
19873         "function wrap_f() { return wrap_f_%d(); }\n"
19874         "function wrap_get() { return wrap_get_%d(); }\n"
19875         "function wrap_set() { return wrap_set_%d(); }\n"
19876         "check = function(returned) {\n"
19877         "  if (returned !== 'returned') { throw returned; }\n"
19878         "}\n"
19879         "\n"
19880         "check(wrap_f());\n"
19881         "check(wrap_f());\n"
19882         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
19883         "check(wrap_f());\n"
19884         "\n"
19885         "check(wrap_get());\n"
19886         "check(wrap_get());\n"
19887         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
19888         "check(wrap_get());\n"
19889         "\n"
19890         "check = function(returned) {\n"
19891         "  if (returned !== 1) { throw returned; }\n"
19892         "}\n"
19893         "check(wrap_set());\n"
19894         "check(wrap_set());\n"
19895         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
19896         "check(wrap_set());\n",
19897         wrap_function.start(), key, key, key, key, key, key);
19898     v8::TryCatch try_catch(isolate);
19899     CompileRun(source.start());
19900     DCHECK(!try_catch.HasCaught());
19901     CHECK_EQ(9, count);
19902   }
19903 };
19904
19905
19906 Local<Object> ApiCallOptimizationChecker::data;
19907 Local<Object> ApiCallOptimizationChecker::receiver;
19908 Local<Object> ApiCallOptimizationChecker::holder;
19909 Local<Object> ApiCallOptimizationChecker::callee;
19910 int ApiCallOptimizationChecker::count = 0;
19911
19912
19913 TEST(FunctionCallOptimization) {
19914   i::FLAG_allow_natives_syntax = true;
19915   ApiCallOptimizationChecker checker;
19916   checker.RunAll();
19917 }
19918
19919
19920 TEST(FunctionCallOptimizationMultipleArgs) {
19921   i::FLAG_allow_natives_syntax = true;
19922   LocalContext context;
19923   v8::Isolate* isolate = context->GetIsolate();
19924   v8::HandleScope scope(isolate);
19925   Handle<Object> global = context->Global();
19926   Local<v8::Function> function = Function::New(isolate, Returns42);
19927   global->Set(v8_str("x"), function);
19928   CompileRun(
19929       "function x_wrap() {\n"
19930       "  for (var i = 0; i < 5; i++) {\n"
19931       "    x(1,2,3);\n"
19932       "  }\n"
19933       "}\n"
19934       "x_wrap();\n"
19935       "%OptimizeFunctionOnNextCall(x_wrap);"
19936       "x_wrap();\n");
19937 }
19938
19939
19940 static void ReturnsSymbolCallback(
19941     const v8::FunctionCallbackInfo<v8::Value>& info) {
19942   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
19943 }
19944
19945
19946 TEST(ApiCallbackCanReturnSymbols) {
19947   i::FLAG_allow_natives_syntax = true;
19948   LocalContext context;
19949   v8::Isolate* isolate = context->GetIsolate();
19950   v8::HandleScope scope(isolate);
19951   Handle<Object> global = context->Global();
19952   Local<v8::Function> function = Function::New(isolate, ReturnsSymbolCallback);
19953   global->Set(v8_str("x"), function);
19954   CompileRun(
19955       "function x_wrap() {\n"
19956       "  for (var i = 0; i < 5; i++) {\n"
19957       "    x();\n"
19958       "  }\n"
19959       "}\n"
19960       "x_wrap();\n"
19961       "%OptimizeFunctionOnNextCall(x_wrap);"
19962       "x_wrap();\n");
19963 }
19964
19965
19966 TEST(EmptyApiCallback) {
19967   LocalContext context;
19968   auto isolate = context->GetIsolate();
19969   v8::HandleScope scope(isolate);
19970   auto global = context->Global();
19971   auto function = FunctionTemplate::New(isolate)->GetFunction();
19972   global->Set(v8_str("x"), function);
19973
19974   auto result = CompileRun("x()");
19975   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
19976
19977   result = CompileRun("x(1,2,3)");
19978   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
19979
19980   result = CompileRun("7 + x.call(3) + 11");
19981   CHECK(result->IsInt32());
19982   CHECK_EQ(21, result->Int32Value());
19983
19984   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
19985   CHECK(result->IsInt32());
19986   CHECK_EQ(21, result->Int32Value());
19987
19988   result = CompileRun("var y = []; x.call(y)");
19989   CHECK(result->IsArray());
19990
19991   result = CompileRun("x.call(y, 1, 2, 3, 4)");
19992   CHECK(result->IsArray());
19993 }
19994
19995
19996 TEST(SimpleSignatureCheck) {
19997   LocalContext context;
19998   auto isolate = context->GetIsolate();
19999   v8::HandleScope scope(isolate);
20000   auto global = context->Global();
20001   auto sig_obj = FunctionTemplate::New(isolate);
20002   auto sig = v8::Signature::New(isolate, sig_obj);
20003   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20004   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20005   global->Set(v8_str("x"), x->GetFunction());
20006   CompileRun("var s = new sig_obj();");
20007   {
20008     TryCatch try_catch(isolate);
20009     CompileRun("x()");
20010     CHECK(try_catch.HasCaught());
20011   }
20012   {
20013     TryCatch try_catch(isolate);
20014     CompileRun("x.call(1)");
20015     CHECK(try_catch.HasCaught());
20016   }
20017   {
20018     TryCatch try_catch(isolate);
20019     auto result = CompileRun("s.x = x; s.x()");
20020     CHECK(!try_catch.HasCaught());
20021     CHECK_EQ(42, result->Int32Value());
20022   }
20023   {
20024     TryCatch try_catch(isolate);
20025     auto result = CompileRun("x.call(s)");
20026     CHECK(!try_catch.HasCaught());
20027     CHECK_EQ(42, result->Int32Value());
20028   }
20029 }
20030
20031
20032 TEST(ChainSignatureCheck) {
20033   LocalContext context;
20034   auto isolate = context->GetIsolate();
20035   v8::HandleScope scope(isolate);
20036   auto global = context->Global();
20037   auto sig_obj = FunctionTemplate::New(isolate);
20038   auto sig = v8::Signature::New(isolate, sig_obj);
20039   for (int i = 0; i < 4; ++i) {
20040     auto temp = FunctionTemplate::New(isolate);
20041     temp->Inherit(sig_obj);
20042     sig_obj = temp;
20043   }
20044   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20045   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20046   global->Set(v8_str("x"), x->GetFunction());
20047   CompileRun("var s = new sig_obj();");
20048   {
20049     TryCatch try_catch(isolate);
20050     CompileRun("x()");
20051     CHECK(try_catch.HasCaught());
20052   }
20053   {
20054     TryCatch try_catch(isolate);
20055     CompileRun("x.call(1)");
20056     CHECK(try_catch.HasCaught());
20057   }
20058   {
20059     TryCatch try_catch(isolate);
20060     auto result = CompileRun("s.x = x; s.x()");
20061     CHECK(!try_catch.HasCaught());
20062     CHECK_EQ(42, result->Int32Value());
20063   }
20064   {
20065     TryCatch try_catch(isolate);
20066     auto result = CompileRun("x.call(s)");
20067     CHECK(!try_catch.HasCaught());
20068     CHECK_EQ(42, result->Int32Value());
20069   }
20070 }
20071
20072
20073 TEST(PrototypeSignatureCheck) {
20074   LocalContext context;
20075   auto isolate = context->GetIsolate();
20076   v8::HandleScope scope(isolate);
20077   auto global = context->Global();
20078   auto sig_obj = FunctionTemplate::New(isolate);
20079   sig_obj->SetHiddenPrototype(true);
20080   auto sig = v8::Signature::New(isolate, sig_obj);
20081   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20082   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20083   global->Set(v8_str("x"), x->GetFunction());
20084   CompileRun("s = {}; s.__proto__ = new sig_obj();");
20085   {
20086     TryCatch try_catch(isolate);
20087     CompileRun("x()");
20088     CHECK(try_catch.HasCaught());
20089   }
20090   {
20091     TryCatch try_catch(isolate);
20092     CompileRun("x.call(1)");
20093     CHECK(try_catch.HasCaught());
20094   }
20095   {
20096     TryCatch try_catch(isolate);
20097     auto result = CompileRun("s.x = x; s.x()");
20098     CHECK(!try_catch.HasCaught());
20099     CHECK_EQ(42, result->Int32Value());
20100   }
20101   {
20102     TryCatch try_catch(isolate);
20103     auto result = CompileRun("x.call(s)");
20104     CHECK(!try_catch.HasCaught());
20105     CHECK_EQ(42, result->Int32Value());
20106   }
20107 }
20108
20109
20110 static const char* last_event_message;
20111 static int last_event_status;
20112 void StoringEventLoggerCallback(const char* message, int status) {
20113     last_event_message = message;
20114     last_event_status = status;
20115 }
20116
20117
20118 TEST(EventLogging) {
20119   v8::Isolate* isolate = CcTest::isolate();
20120   isolate->SetEventLogger(StoringEventLoggerCallback);
20121   v8::internal::HistogramTimer histogramTimer(
20122       "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
20123       reinterpret_cast<v8::internal::Isolate*>(isolate));
20124   histogramTimer.Start();
20125   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
20126   CHECK_EQ(0, last_event_status);
20127   histogramTimer.Stop();
20128   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
20129   CHECK_EQ(1, last_event_status);
20130 }
20131
20132
20133 TEST(Promises) {
20134   LocalContext context;
20135   v8::Isolate* isolate = context->GetIsolate();
20136   v8::HandleScope scope(isolate);
20137   Handle<Object> global = context->Global();
20138
20139   // Creation.
20140   Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
20141   Handle<v8::Promise::Resolver> rr = v8::Promise::Resolver::New(isolate);
20142   Handle<v8::Promise> p = pr->GetPromise();
20143   Handle<v8::Promise> r = rr->GetPromise();
20144   CHECK_EQ(isolate, p->GetIsolate());
20145
20146   // IsPromise predicate.
20147   CHECK(p->IsPromise());
20148   CHECK(r->IsPromise());
20149   Handle<Value> o = v8::Object::New(isolate);
20150   CHECK(!o->IsPromise());
20151
20152   // Resolution and rejection.
20153   pr->Resolve(v8::Integer::New(isolate, 1));
20154   CHECK(p->IsPromise());
20155   rr->Reject(v8::Integer::New(isolate, 2));
20156   CHECK(r->IsPromise());
20157
20158   // Chaining non-pending promises.
20159   CompileRun(
20160       "var x1 = 0;\n"
20161       "var x2 = 0;\n"
20162       "function f1(x) { x1 = x; return x+1 };\n"
20163       "function f2(x) { x2 = x; return x+1 };\n");
20164   Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
20165   Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
20166
20167   p->Chain(f1);
20168   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20169   isolate->RunMicrotasks();
20170   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20171
20172   p->Catch(f2);
20173   isolate->RunMicrotasks();
20174   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20175
20176   r->Catch(f2);
20177   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20178   isolate->RunMicrotasks();
20179   CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
20180
20181   r->Chain(f1);
20182   isolate->RunMicrotasks();
20183   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20184
20185   // Chaining pending promises.
20186   CompileRun("x1 = x2 = 0;");
20187   pr = v8::Promise::Resolver::New(isolate);
20188   rr = v8::Promise::Resolver::New(isolate);
20189
20190   pr->GetPromise()->Chain(f1);
20191   rr->GetPromise()->Catch(f2);
20192   isolate->RunMicrotasks();
20193   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20194   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20195
20196   pr->Resolve(v8::Integer::New(isolate, 1));
20197   rr->Reject(v8::Integer::New(isolate, 2));
20198   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20199   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20200
20201   isolate->RunMicrotasks();
20202   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20203   CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
20204
20205   // Multi-chaining.
20206   CompileRun("x1 = x2 = 0;");
20207   pr = v8::Promise::Resolver::New(isolate);
20208   pr->GetPromise()->Chain(f1)->Chain(f2);
20209   pr->Resolve(v8::Integer::New(isolate, 3));
20210   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20211   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20212   isolate->RunMicrotasks();
20213   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20214   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20215
20216   CompileRun("x1 = x2 = 0;");
20217   rr = v8::Promise::Resolver::New(isolate);
20218   rr->GetPromise()->Catch(f1)->Chain(f2);
20219   rr->Reject(v8::Integer::New(isolate, 3));
20220   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20221   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20222   isolate->RunMicrotasks();
20223   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20224   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20225 }
20226
20227
20228 TEST(PromiseThen) {
20229   LocalContext context;
20230   v8::Isolate* isolate = context->GetIsolate();
20231   v8::HandleScope scope(isolate);
20232   Handle<Object> global = context->Global();
20233
20234   // Creation.
20235   Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
20236   Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
20237   Handle<v8::Promise> p = pr->GetPromise();
20238   Handle<v8::Promise> q = qr->GetPromise();
20239
20240   CHECK(p->IsPromise());
20241   CHECK(q->IsPromise());
20242
20243   pr->Resolve(v8::Integer::New(isolate, 1));
20244   qr->Resolve(p);
20245
20246   // Chaining non-pending promises.
20247   CompileRun(
20248       "var x1 = 0;\n"
20249       "var x2 = 0;\n"
20250       "function f1(x) { x1 = x; return x+1 };\n"
20251       "function f2(x) { x2 = x; return x+1 };\n");
20252   Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
20253   Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
20254
20255   // Chain
20256   q->Chain(f1);
20257   CHECK(global->Get(v8_str("x1"))->IsNumber());
20258   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20259   isolate->RunMicrotasks();
20260   CHECK(!global->Get(v8_str("x1"))->IsNumber());
20261   CHECK(p->Equals(global->Get(v8_str("x1"))));
20262
20263   // Then
20264   CompileRun("x1 = x2 = 0;");
20265   q->Then(f1);
20266   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20267   isolate->RunMicrotasks();
20268   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20269
20270   // Then
20271   CompileRun("x1 = x2 = 0;");
20272   pr = v8::Promise::Resolver::New(isolate);
20273   qr = v8::Promise::Resolver::New(isolate);
20274
20275   qr->Resolve(pr);
20276   qr->GetPromise()->Then(f1)->Then(f2);
20277
20278   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20279   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20280   isolate->RunMicrotasks();
20281   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20282   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20283
20284   pr->Resolve(v8::Integer::New(isolate, 3));
20285
20286   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20287   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20288   isolate->RunMicrotasks();
20289   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20290   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20291 }
20292
20293
20294 TEST(DisallowJavascriptExecutionScope) {
20295   LocalContext context;
20296   v8::Isolate* isolate = context->GetIsolate();
20297   v8::HandleScope scope(isolate);
20298   v8::Isolate::DisallowJavascriptExecutionScope no_js(
20299       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
20300   CompileRun("2+2");
20301 }
20302
20303
20304 TEST(AllowJavascriptExecutionScope) {
20305   LocalContext context;
20306   v8::Isolate* isolate = context->GetIsolate();
20307   v8::HandleScope scope(isolate);
20308   v8::Isolate::DisallowJavascriptExecutionScope no_js(
20309       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
20310   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
20311       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
20312   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
20313     CompileRun("1+1");
20314   }
20315 }
20316
20317
20318 TEST(ThrowOnJavascriptExecution) {
20319   LocalContext context;
20320   v8::Isolate* isolate = context->GetIsolate();
20321   v8::HandleScope scope(isolate);
20322   v8::TryCatch try_catch(isolate);
20323   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
20324       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
20325   CompileRun("1+1");
20326   CHECK(try_catch.HasCaught());
20327 }
20328
20329
20330 TEST(Regress354123) {
20331   LocalContext current;
20332   v8::Isolate* isolate = current->GetIsolate();
20333   v8::HandleScope scope(isolate);
20334
20335   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
20336   templ->SetAccessCheckCallbacks(AccessCounter, NULL);
20337   current->Global()->Set(v8_str("friend"), templ->NewInstance());
20338
20339   // Test access using __proto__ from the prototype chain.
20340   access_count = 0;
20341   CompileRun("friend.__proto__ = {};");
20342   CHECK_EQ(2, access_count);
20343   CompileRun("friend.__proto__;");
20344   CHECK_EQ(4, access_count);
20345
20346   // Test access using __proto__ as a hijacked function (A).
20347   access_count = 0;
20348   CompileRun("var p = Object.prototype;"
20349              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
20350              "f.call(friend, {});");
20351   CHECK_EQ(1, access_count);
20352   CompileRun("var p = Object.prototype;"
20353              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
20354              "f.call(friend);");
20355   CHECK_EQ(2, access_count);
20356
20357   // Test access using __proto__ as a hijacked function (B).
20358   access_count = 0;
20359   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
20360              "f.call(friend, {});");
20361   CHECK_EQ(1, access_count);
20362   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
20363              "f.call(friend);");
20364   CHECK_EQ(2, access_count);
20365
20366   // Test access using Object.setPrototypeOf reflective method.
20367   access_count = 0;
20368   CompileRun("Object.setPrototypeOf(friend, {});");
20369   CHECK_EQ(1, access_count);
20370   CompileRun("Object.getPrototypeOf(friend);");
20371   CHECK_EQ(2, access_count);
20372 }
20373
20374
20375 TEST(CaptureStackTraceForStackOverflow) {
20376   v8::internal::FLAG_stack_size = 150;
20377   LocalContext current;
20378   v8::Isolate* isolate = current->GetIsolate();
20379   v8::HandleScope scope(isolate);
20380   V8::SetCaptureStackTraceForUncaughtExceptions(
20381       true, 10, v8::StackTrace::kDetailed);
20382   v8::TryCatch try_catch(isolate);
20383   CompileRun("(function f(x) { f(x+1); })(0)");
20384   CHECK(try_catch.HasCaught());
20385 }
20386
20387
20388 TEST(ScriptNameAndLineNumber) {
20389   LocalContext env;
20390   v8::Isolate* isolate = env->GetIsolate();
20391   v8::HandleScope scope(isolate);
20392   const char* url = "http://www.foo.com/foo.js";
20393   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
20394   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
20395   Local<Script> script = v8::ScriptCompiler::Compile(
20396       isolate, &script_source);
20397   Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
20398   CHECK(!script_name.IsEmpty());
20399   CHECK(script_name->IsString());
20400   String::Utf8Value utf8_name(script_name);
20401   CHECK_EQ(0, strcmp(url, *utf8_name));
20402   int line_number = script->GetUnboundScript()->GetLineNumber(0);
20403   CHECK_EQ(13, line_number);
20404 }
20405
20406 void CheckMagicComments(Handle<Script> script, const char* expected_source_url,
20407                         const char* expected_source_mapping_url) {
20408   if (expected_source_url != NULL) {
20409     v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
20410     CHECK_EQ(0, strcmp(expected_source_url, *url));
20411   } else {
20412     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
20413   }
20414   if (expected_source_mapping_url != NULL) {
20415     v8::String::Utf8Value url(
20416         script->GetUnboundScript()->GetSourceMappingURL());
20417     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
20418   } else {
20419     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
20420   }
20421 }
20422
20423 void SourceURLHelper(const char* source, const char* expected_source_url,
20424                      const char* expected_source_mapping_url) {
20425   Local<Script> script = v8_compile(source);
20426   CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
20427 }
20428
20429
20430 TEST(ScriptSourceURLAndSourceMappingURL) {
20431   LocalContext env;
20432   v8::Isolate* isolate = env->GetIsolate();
20433   v8::HandleScope scope(isolate);
20434   SourceURLHelper("function foo() {}\n"
20435                   "//# sourceURL=bar1.js\n", "bar1.js", NULL);
20436   SourceURLHelper("function foo() {}\n"
20437                   "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
20438
20439   // Both sourceURL and sourceMappingURL.
20440   SourceURLHelper("function foo() {}\n"
20441                   "//# sourceURL=bar3.js\n"
20442                   "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
20443
20444   // Two source URLs; the first one is ignored.
20445   SourceURLHelper("function foo() {}\n"
20446                   "//# sourceURL=ignoreme.js\n"
20447                   "//# sourceURL=bar5.js\n", "bar5.js", NULL);
20448   SourceURLHelper("function foo() {}\n"
20449                   "//# sourceMappingURL=ignoreme.js\n"
20450                   "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
20451
20452   // SourceURL or sourceMappingURL in the middle of the script.
20453   SourceURLHelper("function foo() {}\n"
20454                   "//# sourceURL=bar7.js\n"
20455                   "function baz() {}\n", "bar7.js", NULL);
20456   SourceURLHelper("function foo() {}\n"
20457                   "//# sourceMappingURL=bar8.js\n"
20458                   "function baz() {}\n", NULL, "bar8.js");
20459
20460   // Too much whitespace.
20461   SourceURLHelper("function foo() {}\n"
20462                   "//#  sourceURL=bar9.js\n"
20463                   "//#  sourceMappingURL=bar10.js\n", NULL, NULL);
20464   SourceURLHelper("function foo() {}\n"
20465                   "//# sourceURL =bar11.js\n"
20466                   "//# sourceMappingURL =bar12.js\n", NULL, NULL);
20467
20468   // Disallowed characters in value.
20469   SourceURLHelper("function foo() {}\n"
20470                   "//# sourceURL=bar13 .js   \n"
20471                   "//# sourceMappingURL=bar14 .js \n",
20472                   NULL, NULL);
20473   SourceURLHelper("function foo() {}\n"
20474                   "//# sourceURL=bar15\t.js   \n"
20475                   "//# sourceMappingURL=bar16\t.js \n",
20476                   NULL, NULL);
20477   SourceURLHelper("function foo() {}\n"
20478                   "//# sourceURL=bar17'.js   \n"
20479                   "//# sourceMappingURL=bar18'.js \n",
20480                   NULL, NULL);
20481   SourceURLHelper("function foo() {}\n"
20482                   "//# sourceURL=bar19\".js   \n"
20483                   "//# sourceMappingURL=bar20\".js \n",
20484                   NULL, NULL);
20485
20486   // Not too much whitespace.
20487   SourceURLHelper("function foo() {}\n"
20488                   "//# sourceURL=  bar21.js   \n"
20489                   "//# sourceMappingURL=  bar22.js \n", "bar21.js", "bar22.js");
20490 }
20491
20492
20493 TEST(GetOwnPropertyDescriptor) {
20494   LocalContext env;
20495   v8::Isolate* isolate = env->GetIsolate();
20496   v8::HandleScope scope(isolate);
20497   CompileRun(
20498     "var x = { value : 13};"
20499     "Object.defineProperty(x, 'p0', {value : 12});"
20500     "Object.defineProperty(x, 'p1', {"
20501     "  set : function(value) { this.value = value; },"
20502     "  get : function() { return this.value; },"
20503     "});");
20504   Local<Object> x = Local<Object>::Cast(env->Global()->Get(v8_str("x")));
20505   Local<Value> desc = x->GetOwnPropertyDescriptor(v8_str("no_prop"));
20506   CHECK(desc->IsUndefined());
20507   desc = x->GetOwnPropertyDescriptor(v8_str("p0"));
20508   CHECK(v8_num(12)->Equals(Local<Object>::Cast(desc)->Get(v8_str("value"))));
20509   desc = x->GetOwnPropertyDescriptor(v8_str("p1"));
20510   Local<Function> set =
20511     Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("set")));
20512   Local<Function> get =
20513     Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("get")));
20514   CHECK(v8_num(13)->Equals(get->Call(x, 0, NULL)));
20515   Handle<Value> args[] = { v8_num(14) };
20516   set->Call(x, 1, args);
20517   CHECK(v8_num(14)->Equals(get->Call(x, 0, NULL)));
20518 }
20519
20520
20521 TEST(Regress411877) {
20522   v8::Isolate* isolate = CcTest::isolate();
20523   v8::HandleScope handle_scope(isolate);
20524   v8::Handle<v8::ObjectTemplate> object_template =
20525       v8::ObjectTemplate::New(isolate);
20526   object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20527
20528   v8::Handle<Context> context = Context::New(isolate);
20529   v8::Context::Scope context_scope(context);
20530
20531   context->Global()->Set(v8_str("o"), object_template->NewInstance());
20532   CompileRun("Object.getOwnPropertyNames(o)");
20533 }
20534
20535
20536 TEST(GetHiddenPropertyTableAfterAccessCheck) {
20537   v8::Isolate* isolate = CcTest::isolate();
20538   v8::HandleScope handle_scope(isolate);
20539   v8::Handle<v8::ObjectTemplate> object_template =
20540       v8::ObjectTemplate::New(isolate);
20541   object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20542
20543   v8::Handle<Context> context = Context::New(isolate);
20544   v8::Context::Scope context_scope(context);
20545
20546   v8::Handle<v8::Object> obj = object_template->NewInstance();
20547   obj->Set(v8_str("key"), v8_str("value"));
20548   obj->Delete(v8_str("key"));
20549
20550   obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
20551 }
20552
20553
20554 TEST(Regress411793) {
20555   v8::Isolate* isolate = CcTest::isolate();
20556   v8::HandleScope handle_scope(isolate);
20557   v8::Handle<v8::ObjectTemplate> object_template =
20558       v8::ObjectTemplate::New(isolate);
20559   object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20560
20561   v8::Handle<Context> context = Context::New(isolate);
20562   v8::Context::Scope context_scope(context);
20563
20564   context->Global()->Set(v8_str("o"), object_template->NewInstance());
20565   CompileRun(
20566       "Object.defineProperty(o, 'key', "
20567       "    { get: function() {}, set: function() {} });");
20568 }
20569
20570 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
20571  public:
20572   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
20573
20574   virtual size_t GetMoreData(const uint8_t** src) {
20575     // Unlike in real use cases, this function will never block.
20576     if (chunks_[index_] == NULL) {
20577       return 0;
20578     }
20579     // Copy the data, since the caller takes ownership of it.
20580     size_t len = strlen(chunks_[index_]);
20581     // We don't need to zero-terminate since we return the length.
20582     uint8_t* copy = new uint8_t[len];
20583     memcpy(copy, chunks_[index_], len);
20584     *src = copy;
20585     ++index_;
20586     return len;
20587   }
20588
20589   // Helper for constructing a string from chunks (the compilation needs it
20590   // too).
20591   static char* FullSourceString(const char** chunks) {
20592     size_t total_len = 0;
20593     for (size_t i = 0; chunks[i] != NULL; ++i) {
20594       total_len += strlen(chunks[i]);
20595     }
20596     char* full_string = new char[total_len + 1];
20597     size_t offset = 0;
20598     for (size_t i = 0; chunks[i] != NULL; ++i) {
20599       size_t len = strlen(chunks[i]);
20600       memcpy(full_string + offset, chunks[i], len);
20601       offset += len;
20602     }
20603     full_string[total_len] = 0;
20604     return full_string;
20605   }
20606
20607  private:
20608   const char** chunks_;
20609   unsigned index_;
20610 };
20611
20612
20613 // Helper function for running streaming tests.
20614 void RunStreamingTest(const char** chunks,
20615                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
20616                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
20617                       bool expected_success = true,
20618                       const char* expected_source_url = NULL,
20619                       const char* expected_source_mapping_url = NULL) {
20620   LocalContext env;
20621   v8::Isolate* isolate = env->GetIsolate();
20622   v8::HandleScope scope(isolate);
20623   v8::TryCatch try_catch(isolate);
20624
20625   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
20626                                             encoding);
20627   v8::ScriptCompiler::ScriptStreamingTask* task =
20628       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
20629
20630   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
20631   // task here in the main thread.
20632   task->Run();
20633   delete task;
20634
20635   // Possible errors are only produced while compiling.
20636   CHECK_EQ(false, try_catch.HasCaught());
20637
20638   v8::ScriptOrigin origin(v8_str("http://foo.com"));
20639   char* full_source = TestSourceStream::FullSourceString(chunks);
20640   v8::Handle<Script> script = v8::ScriptCompiler::Compile(
20641       isolate, &source, v8_str(full_source), origin);
20642   if (expected_success) {
20643     CHECK(!script.IsEmpty());
20644     v8::Handle<Value> result(script->Run());
20645     // All scripts are supposed to return the fixed value 13 when ran.
20646     CHECK_EQ(13, result->Int32Value());
20647     CheckMagicComments(script, expected_source_url,
20648                        expected_source_mapping_url);
20649   } else {
20650     CHECK(script.IsEmpty());
20651     CHECK(try_catch.HasCaught());
20652   }
20653   delete[] full_source;
20654 }
20655
20656
20657 TEST(StreamingSimpleScript) {
20658   // This script is unrealistically small, since no one chunk is enough to fill
20659   // the backing buffer of Scanner, let alone overflow it.
20660   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
20661                           NULL};
20662   RunStreamingTest(chunks);
20663 }
20664
20665
20666 TEST(StreamingBiggerScript) {
20667   const char* chunk1 =
20668       "function foo() {\n"
20669       "  // Make this chunk sufficiently long so that it will overflow the\n"
20670       "  // backing buffer of the Scanner.\n"
20671       "  var i = 0;\n"
20672       "  var result = 0;\n"
20673       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20674       "  result = 0;\n"
20675       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20676       "  result = 0;\n"
20677       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20678       "  result = 0;\n"
20679       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20680       "  return result;\n"
20681       "}\n";
20682   const char* chunks[] = {chunk1, "foo(); ", NULL};
20683   RunStreamingTest(chunks);
20684 }
20685
20686
20687 TEST(StreamingScriptWithParseError) {
20688   // Test that parse errors from streamed scripts are propagated correctly.
20689   {
20690     char chunk1[] =
20691         "  // This will result in a parse error.\n"
20692         "  var if else then foo";
20693     char chunk2[] = "  13\n";
20694     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20695
20696     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
20697                      false);
20698   }
20699   // Test that the next script succeeds normally.
20700   {
20701     char chunk1[] =
20702         "  // This will be parsed successfully.\n"
20703         "  function foo() { return ";
20704     char chunk2[] = "  13; }\n";
20705     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20706
20707     RunStreamingTest(chunks);
20708   }
20709 }
20710
20711
20712 TEST(StreamingUtf8Script) {
20713   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
20714   // don't like it.
20715   const char* chunk1 =
20716       "function foo() {\n"
20717       "  // This function will contain an UTF-8 character which is not in\n"
20718       "  // ASCII.\n"
20719       "  var foob\xec\x92\x81r = 13;\n"
20720       "  return foob\xec\x92\x81r;\n"
20721       "}\n";
20722   const char* chunks[] = {chunk1, "foo(); ", NULL};
20723   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20724 }
20725
20726
20727 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
20728   // A sanity check to prove that the approach of splitting UTF-8
20729   // characters is correct. Here is an UTF-8 character which will take three
20730   // bytes.
20731   const char* reference = "\xec\x92\x81";
20732   CHECK(3u == strlen(reference));  // NOLINT - no CHECK_EQ for unsigned.
20733
20734   char chunk1[] =
20735       "function foo() {\n"
20736       "  // This function will contain an UTF-8 character which is not in\n"
20737       "  // ASCII.\n"
20738       "  var foob";
20739   char chunk2[] =
20740       "XXXr = 13;\n"
20741       "  return foob\xec\x92\x81r;\n"
20742       "}\n";
20743   for (int i = 0; i < 3; ++i) {
20744     chunk2[i] = reference[i];
20745   }
20746   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20747   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20748 }
20749
20750
20751 TEST(StreamingUtf8ScriptWithSplitCharacters) {
20752   // Stream data where a multi-byte UTF-8 character is split between two data
20753   // chunks.
20754   const char* reference = "\xec\x92\x81";
20755   char chunk1[] =
20756       "function foo() {\n"
20757       "  // This function will contain an UTF-8 character which is not in\n"
20758       "  // ASCII.\n"
20759       "  var foobX";
20760   char chunk2[] =
20761       "XXr = 13;\n"
20762       "  return foob\xec\x92\x81r;\n"
20763       "}\n";
20764   chunk1[strlen(chunk1) - 1] = reference[0];
20765   chunk2[0] = reference[1];
20766   chunk2[1] = reference[2];
20767   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20768   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20769 }
20770
20771
20772 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
20773   // Tests edge cases which should still be decoded correctly.
20774
20775   // Case 1: a chunk contains only bytes for a split character (and no other
20776   // data). This kind of a chunk would be exceptionally small, but we should
20777   // still decode it correctly.
20778   const char* reference = "\xec\x92\x81";
20779   // The small chunk is at the beginning of the split character
20780   {
20781     char chunk1[] =
20782         "function foo() {\n"
20783         "  // This function will contain an UTF-8 character which is not in\n"
20784         "  // ASCII.\n"
20785         "  var foob";
20786     char chunk2[] = "XX";
20787     char chunk3[] =
20788         "Xr = 13;\n"
20789         "  return foob\xec\x92\x81r;\n"
20790         "}\n";
20791     chunk2[0] = reference[0];
20792     chunk2[1] = reference[1];
20793     chunk3[0] = reference[2];
20794     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20795     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20796   }
20797   // The small chunk is at the end of a character
20798   {
20799     char chunk1[] =
20800         "function foo() {\n"
20801         "  // This function will contain an UTF-8 character which is not in\n"
20802         "  // ASCII.\n"
20803         "  var foobX";
20804     char chunk2[] = "XX";
20805     char chunk3[] =
20806         "r = 13;\n"
20807         "  return foob\xec\x92\x81r;\n"
20808         "}\n";
20809     chunk1[strlen(chunk1) - 1] = reference[0];
20810     chunk2[0] = reference[1];
20811     chunk2[1] = reference[2];
20812     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20813     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20814   }
20815   // Case 2: the script ends with a multi-byte character. Make sure that it's
20816   // decoded correctly and not just ignored.
20817   {
20818     char chunk1[] =
20819         "var foob\xec\x92\x81 = 13;\n"
20820         "foob\xec\x92\x81";
20821     const char* chunks[] = {chunk1, NULL};
20822     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20823   }
20824 }
20825
20826
20827 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
20828   // Test cases where a UTF-8 character is split over several chunks. Those
20829   // cases are not supported (the embedder should give the data in big enough
20830   // chunks), but we shouldn't crash, just produce a parse error.
20831   const char* reference = "\xec\x92\x81";
20832   char chunk1[] =
20833       "function foo() {\n"
20834       "  // This function will contain an UTF-8 character which is not in\n"
20835       "  // ASCII.\n"
20836       "  var foobX";
20837   char chunk2[] = "X";
20838   char chunk3[] =
20839       "Xr = 13;\n"
20840       "  return foob\xec\x92\x81r;\n"
20841       "}\n";
20842   chunk1[strlen(chunk1) - 1] = reference[0];
20843   chunk2[0] = reference[1];
20844   chunk3[0] = reference[2];
20845   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20846
20847   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
20848 }
20849
20850
20851 TEST(StreamingProducesParserCache) {
20852   i::FLAG_min_preparse_length = 0;
20853   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
20854                           NULL};
20855
20856   LocalContext env;
20857   v8::Isolate* isolate = env->GetIsolate();
20858   v8::HandleScope scope(isolate);
20859
20860   v8::ScriptCompiler::StreamedSource source(
20861       new TestSourceStream(chunks),
20862       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
20863   v8::ScriptCompiler::ScriptStreamingTask* task =
20864       v8::ScriptCompiler::StartStreamingScript(
20865           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
20866
20867   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
20868   // task here in the main thread.
20869   task->Run();
20870   delete task;
20871
20872   const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
20873   CHECK(cached_data != NULL);
20874   CHECK(cached_data->data != NULL);
20875   CHECK(!cached_data->rejected);
20876   CHECK_GT(cached_data->length, 0);
20877 }
20878
20879
20880 TEST(StreamingWithDebuggingEnabledLate) {
20881   // The streaming parser can only parse lazily, i.e. inner functions are not
20882   // fully parsed. However, we may compile inner functions eagerly when
20883   // debugging. Make sure that we can deal with this when turning on debugging
20884   // after streaming parser has already finished parsing.
20885   i::FLAG_min_preparse_length = 0;
20886   const char* chunks[] = {"with({x:1}) {",
20887                           "  var foo = function foo(y) {",
20888                           "    return x + y;",
20889                           "  };",
20890                           "  foo(2);",
20891                           "}",
20892                           NULL};
20893
20894   LocalContext env;
20895   v8::Isolate* isolate = env->GetIsolate();
20896   v8::HandleScope scope(isolate);
20897   v8::TryCatch try_catch(isolate);
20898
20899   v8::ScriptCompiler::StreamedSource source(
20900       new TestSourceStream(chunks),
20901       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
20902   v8::ScriptCompiler::ScriptStreamingTask* task =
20903       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
20904
20905   task->Run();
20906   delete task;
20907
20908   CHECK(!try_catch.HasCaught());
20909
20910   v8::ScriptOrigin origin(v8_str("http://foo.com"));
20911   char* full_source = TestSourceStream::FullSourceString(chunks);
20912
20913   EnableDebugger();
20914
20915   v8::Handle<Script> script = v8::ScriptCompiler::Compile(
20916       isolate, &source, v8_str(full_source), origin);
20917
20918   Maybe<uint32_t> result =
20919       script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
20920   CHECK_EQ(3U, result.FromMaybe(0));
20921
20922   delete[] full_source;
20923
20924   DisableDebugger();
20925 }
20926
20927
20928 TEST(StreamingScriptWithInvalidUtf8) {
20929   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
20930   // chunk don't produce a crash.
20931   const char* reference = "\xec\x92\x81\x80\x80";
20932   char chunk1[] =
20933       "function foo() {\n"
20934       "  // This function will contain an UTF-8 character which is not in\n"
20935       "  // ASCII.\n"
20936       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
20937   char chunk2[] =
20938       "r = 13;\n"
20939       "  return foob\xec\x92\x81\x80\x80r;\n"
20940       "}\n";
20941   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
20942
20943   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20944   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
20945 }
20946
20947
20948 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
20949   // Regression test: Stream data where there are several multi-byte UTF-8
20950   // characters in a sequence and one of them is split between two data chunks.
20951   const char* reference = "\xec\x92\x81";
20952   char chunk1[] =
20953       "function foo() {\n"
20954       "  // This function will contain an UTF-8 character which is not in\n"
20955       "  // ASCII.\n"
20956       "  var foob\xec\x92\x81X";
20957   char chunk2[] =
20958       "XXr = 13;\n"
20959       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
20960       "}\n";
20961   chunk1[strlen(chunk1) - 1] = reference[0];
20962   chunk2[0] = reference[1];
20963   chunk2[1] = reference[2];
20964   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20965   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20966 }
20967
20968
20969 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
20970   // Another regression test, similar to the previous one. The difference is
20971   // that the split character is not the last one in the sequence.
20972   const char* reference = "\xec\x92\x81";
20973   char chunk1[] =
20974       "function foo() {\n"
20975       "  // This function will contain an UTF-8 character which is not in\n"
20976       "  // ASCII.\n"
20977       "  var foobX";
20978   char chunk2[] =
20979       "XX\xec\x92\x81r = 13;\n"
20980       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
20981       "}\n";
20982   chunk1[strlen(chunk1) - 1] = reference[0];
20983   chunk2[0] = reference[1];
20984   chunk2[1] = reference[2];
20985   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20986   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20987 }
20988
20989
20990 TEST(StreamingWithHarmonyScopes) {
20991   // Don't use RunStreamingTest here so that both scripts get to use the same
20992   // LocalContext and HandleScope.
20993   LocalContext env;
20994   v8::Isolate* isolate = env->GetIsolate();
20995   v8::HandleScope scope(isolate);
20996
20997   // First, run a script with a let variable.
20998   CompileRun("\"use strict\"; let x = 1;");
20999
21000   // Then stream a script which (erroneously) tries to introduce the same
21001   // variable again.
21002   const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
21003
21004   v8::TryCatch try_catch(isolate);
21005   v8::ScriptCompiler::StreamedSource source(
21006       new TestSourceStream(chunks),
21007       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
21008   v8::ScriptCompiler::ScriptStreamingTask* task =
21009       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
21010   task->Run();
21011   delete task;
21012
21013   // Parsing should succeed (the script will be parsed and compiled in a context
21014   // independent way, so the error is not detected).
21015   CHECK_EQ(false, try_catch.HasCaught());
21016
21017   v8::ScriptOrigin origin(v8_str("http://foo.com"));
21018   char* full_source = TestSourceStream::FullSourceString(chunks);
21019   v8::Handle<Script> script = v8::ScriptCompiler::Compile(
21020       isolate, &source, v8_str(full_source), origin);
21021   CHECK(!script.IsEmpty());
21022   CHECK_EQ(false, try_catch.HasCaught());
21023
21024   // Running the script exposes the error.
21025   v8::Handle<Value> result(script->Run());
21026   CHECK(result.IsEmpty());
21027   CHECK(try_catch.HasCaught());
21028   delete[] full_source;
21029 }
21030
21031
21032 TEST(CodeCache) {
21033   v8::Isolate::CreateParams create_params;
21034   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
21035
21036   const char* source = "Math.sqrt(4)";
21037   const char* origin = "code cache test";
21038   v8::ScriptCompiler::CachedData* cache;
21039
21040   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
21041   {
21042     v8::Isolate::Scope iscope(isolate1);
21043     v8::HandleScope scope(isolate1);
21044     v8::Local<v8::Context> context = v8::Context::New(isolate1);
21045     v8::Context::Scope cscope(context);
21046     v8::Local<v8::String> source_string = v8_str(source);
21047     v8::ScriptOrigin script_origin(v8_str(origin));
21048     v8::ScriptCompiler::Source source(source_string, script_origin);
21049     v8::ScriptCompiler::CompileOptions option =
21050         v8::ScriptCompiler::kProduceCodeCache;
21051     v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
21052     int length = source.GetCachedData()->length;
21053     uint8_t* cache_data = new uint8_t[length];
21054     memcpy(cache_data, source.GetCachedData()->data, length);
21055     cache = new v8::ScriptCompiler::CachedData(
21056         cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
21057   }
21058   isolate1->Dispose();
21059
21060   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
21061   {
21062     v8::Isolate::Scope iscope(isolate2);
21063     v8::HandleScope scope(isolate2);
21064     v8::Local<v8::Context> context = v8::Context::New(isolate2);
21065     v8::Context::Scope cscope(context);
21066     v8::Local<v8::String> source_string = v8_str(source);
21067     v8::ScriptOrigin script_origin(v8_str(origin));
21068     v8::ScriptCompiler::Source source(source_string, script_origin, cache);
21069     v8::ScriptCompiler::CompileOptions option =
21070         v8::ScriptCompiler::kConsumeCodeCache;
21071     v8::Local<v8::Script> script;
21072     {
21073       i::DisallowCompilation no_compile(
21074           reinterpret_cast<i::Isolate*>(isolate2));
21075       script = v8::ScriptCompiler::Compile(context, &source, option)
21076                    .ToLocalChecked();
21077     }
21078     CHECK_EQ(2, script->Run()->ToInt32(isolate2)->Int32Value());
21079   }
21080   isolate2->Dispose();
21081 }
21082
21083
21084 void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
21085   const char* garbage = "garbage garbage garbage garbage garbage garbage";
21086   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
21087   int length = 16;
21088   v8::ScriptCompiler::CachedData* cached_data =
21089       new v8::ScriptCompiler::CachedData(data, length);
21090   DCHECK(!cached_data->rejected);
21091   v8::ScriptOrigin origin(v8_str("origin"));
21092   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
21093   v8::Handle<v8::Script> script =
21094       v8::ScriptCompiler::Compile(CcTest::isolate(), &source, option);
21095   CHECK(cached_data->rejected);
21096   CHECK_EQ(42, script->Run()->Int32Value());
21097 }
21098
21099
21100 TEST(InvalidCacheData) {
21101   v8::V8::Initialize();
21102   v8::HandleScope scope(CcTest::isolate());
21103   LocalContext context;
21104   TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
21105   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
21106 }
21107
21108
21109 TEST(ParserCacheRejectedGracefully) {
21110   i::FLAG_min_preparse_length = 0;
21111   v8::V8::Initialize();
21112   v8::HandleScope scope(CcTest::isolate());
21113   LocalContext context;
21114   // Produce valid cached data.
21115   v8::ScriptOrigin origin(v8_str("origin"));
21116   v8::Local<v8::String> source_str = v8_str("function foo() {}");
21117   v8::ScriptCompiler::Source source(source_str, origin);
21118   v8::Handle<v8::Script> script = v8::ScriptCompiler::Compile(
21119       CcTest::isolate(), &source, v8::ScriptCompiler::kProduceParserCache);
21120   CHECK(!script.IsEmpty());
21121   const v8::ScriptCompiler::CachedData* original_cached_data =
21122       source.GetCachedData();
21123   CHECK(original_cached_data != NULL);
21124   CHECK(original_cached_data->data != NULL);
21125   CHECK(!original_cached_data->rejected);
21126   CHECK_GT(original_cached_data->length, 0);
21127   // Recompiling the same script with it won't reject the data.
21128   {
21129     v8::ScriptCompiler::Source source_with_cached_data(
21130         source_str, origin,
21131         new v8::ScriptCompiler::CachedData(original_cached_data->data,
21132                                            original_cached_data->length));
21133     v8::Handle<v8::Script> script =
21134         v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
21135                                     v8::ScriptCompiler::kConsumeParserCache);
21136     CHECK(!script.IsEmpty());
21137     const v8::ScriptCompiler::CachedData* new_cached_data =
21138         source_with_cached_data.GetCachedData();
21139     CHECK(new_cached_data != NULL);
21140     CHECK(!new_cached_data->rejected);
21141   }
21142   // Compile an incompatible script with the cached data. The new script doesn't
21143   // have the same starting position for the function as the old one, so the old
21144   // cached data will be incompatible with it and will be rejected.
21145   {
21146     v8::Local<v8::String> incompatible_source_str =
21147         v8_str("   function foo() {}");
21148     v8::ScriptCompiler::Source source_with_cached_data(
21149         incompatible_source_str, origin,
21150         new v8::ScriptCompiler::CachedData(original_cached_data->data,
21151                                            original_cached_data->length));
21152     v8::Handle<v8::Script> script =
21153         v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
21154                                     v8::ScriptCompiler::kConsumeParserCache);
21155     CHECK(!script.IsEmpty());
21156     const v8::ScriptCompiler::CachedData* new_cached_data =
21157         source_with_cached_data.GetCachedData();
21158     CHECK(new_cached_data != NULL);
21159     CHECK(new_cached_data->rejected);
21160   }
21161 }
21162
21163
21164 TEST(StringConcatOverflow) {
21165   v8::V8::Initialize();
21166   v8::HandleScope scope(CcTest::isolate());
21167   RandomLengthOneByteResource* r =
21168       new RandomLengthOneByteResource(i::String::kMaxLength);
21169   v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), r);
21170   CHECK(!str.IsEmpty());
21171   v8::TryCatch try_catch(CcTest::isolate());
21172   v8::Local<v8::String> result = v8::String::Concat(str, str);
21173   CHECK(result.IsEmpty());
21174   CHECK(!try_catch.HasCaught());
21175 }
21176
21177
21178 TEST(TurboAsmDisablesNeuter) {
21179   v8::V8::Initialize();
21180   v8::HandleScope scope(CcTest::isolate());
21181   LocalContext context;
21182   bool should_be_neuterable = !i::FLAG_turbo_asm;
21183   const char* load =
21184       "function Module(stdlib, foreign, heap) {"
21185       "  'use asm';"
21186       "  var MEM32 = new stdlib.Int32Array(heap);"
21187       "  function load() { return MEM32[0]; }"
21188       "  return { load: load };"
21189       "}"
21190       "var buffer = new ArrayBuffer(4);"
21191       "Module(this, {}, buffer).load();"
21192       "buffer";
21193
21194   i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
21195   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
21196   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
21197
21198   const char* store =
21199       "function Module(stdlib, foreign, heap) {"
21200       "  'use asm';"
21201       "  var MEM32 = new stdlib.Int32Array(heap);"
21202       "  function store() { MEM32[0] = 0; }"
21203       "  return { store: store };"
21204       "}"
21205       "var buffer = new ArrayBuffer(4);"
21206       "Module(this, {}, buffer).store();"
21207       "buffer";
21208
21209   i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
21210   result = CompileRun(store).As<v8::ArrayBuffer>();
21211   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
21212 }
21213
21214
21215 TEST(GetPrototypeAccessControl) {
21216   i::FLAG_allow_natives_syntax = true;
21217   v8::Isolate* isolate = CcTest::isolate();
21218   v8::HandleScope handle_scope(isolate);
21219   LocalContext env;
21220
21221   v8::Handle<v8::ObjectTemplate> obj_template =
21222       v8::ObjectTemplate::New(isolate);
21223   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
21224
21225   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
21226
21227   CHECK(CompileRun(
21228             "function f() { return %_GetPrototype(prohibited); }"
21229             "%OptimizeFunctionOnNextCall(f);"
21230             "f();")->IsNull());
21231 }
21232
21233
21234 TEST(GetPrototypeHidden) {
21235   i::FLAG_allow_natives_syntax = true;
21236   v8::Isolate* isolate = CcTest::isolate();
21237   v8::HandleScope handle_scope(isolate);
21238   LocalContext env;
21239
21240   Handle<FunctionTemplate> t = FunctionTemplate::New(isolate);
21241   t->SetHiddenPrototype(true);
21242   Handle<Object> proto = t->GetFunction()->NewInstance();
21243   Handle<Object> object = Object::New(isolate);
21244   Handle<Object> proto2 = Object::New(isolate);
21245   object->SetPrototype(proto);
21246   proto->SetPrototype(proto2);
21247
21248   env->Global()->Set(v8_str("object"), object);
21249   env->Global()->Set(v8_str("proto"), proto);
21250   env->Global()->Set(v8_str("proto2"), proto2);
21251
21252   v8::Handle<v8::Value> result = CompileRun("%_GetPrototype(object)");
21253   CHECK(result->Equals(proto2));
21254
21255   result = CompileRun(
21256       "function f() { return %_GetPrototype(object); }"
21257       "%OptimizeFunctionOnNextCall(f);"
21258       "f()");
21259   CHECK(result->Equals(proto2));
21260 }
21261
21262
21263 TEST(ClassPrototypeCreationContext) {
21264   v8::Isolate* isolate = CcTest::isolate();
21265   v8::HandleScope handle_scope(isolate);
21266   LocalContext env;
21267
21268   Handle<Object> result = Handle<Object>::Cast(
21269       CompileRun("'use strict'; class Example { }; Example.prototype"));
21270   CHECK(env.local() == result->CreationContext());
21271 }
21272
21273
21274 TEST(SimpleStreamingScriptWithSourceURL) {
21275   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
21276                           "//# sourceURL=bar2.js\n", NULL};
21277   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
21278                    "bar2.js");
21279 }
21280
21281
21282 TEST(StreamingScriptWithSplitSourceURL) {
21283   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
21284                           "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
21285   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
21286                    "bar2.js");
21287 }
21288
21289
21290 TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
21291   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
21292                           " sourceMappingURL=bar2.js\n", "foo();", NULL};
21293   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
21294                    "bar2.js");
21295 }
21296
21297
21298 TEST(NewStringRangeError) {
21299   v8::Isolate* isolate = CcTest::isolate();
21300   v8::HandleScope handle_scope(isolate);
21301   const int length = i::String::kMaxLength + 1;
21302   const int buffer_size = length * sizeof(uint16_t);
21303   void* buffer = malloc(buffer_size);
21304   if (buffer == NULL) return;
21305   memset(buffer, 'A', buffer_size);
21306   {
21307     v8::TryCatch try_catch(isolate);
21308     char* data = reinterpret_cast<char*>(buffer);
21309     CHECK(v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString,
21310                                   length).IsEmpty());
21311     CHECK(!try_catch.HasCaught());
21312   }
21313   {
21314     v8::TryCatch try_catch(isolate);
21315     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
21316     CHECK(v8::String::NewFromOneByte(isolate, data, v8::String::kNormalString,
21317                                      length).IsEmpty());
21318     CHECK(!try_catch.HasCaught());
21319   }
21320   {
21321     v8::TryCatch try_catch(isolate);
21322     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
21323     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString,
21324                                      length).IsEmpty());
21325     CHECK(!try_catch.HasCaught());
21326   }
21327   free(buffer);
21328 }
21329
21330
21331 TEST(SealHandleScope) {
21332   v8::Isolate* isolate = CcTest::isolate();
21333   v8::HandleScope handle_scope(isolate);
21334   LocalContext env;
21335
21336   v8::SealHandleScope seal(isolate);
21337
21338   // Should fail
21339   v8::Local<v8::Object> obj = v8::Object::New(isolate);
21340
21341   USE(obj);
21342 }
21343
21344
21345 TEST(SealHandleScopeNested) {
21346   v8::Isolate* isolate = CcTest::isolate();
21347   v8::HandleScope handle_scope(isolate);
21348   LocalContext env;
21349
21350   v8::SealHandleScope seal(isolate);
21351
21352   {
21353     v8::HandleScope handle_scope(isolate);
21354
21355     // Should work
21356     v8::Local<v8::Object> obj = v8::Object::New(isolate);
21357
21358     USE(obj);
21359   }
21360 }
21361
21362
21363 static bool access_was_called = false;
21364
21365
21366 static bool AccessAlwaysAllowedWithFlag(Local<v8::Object> global,
21367                                         Local<Value> name, v8::AccessType type,
21368                                         Local<Value> data) {
21369   access_was_called = true;
21370   return true;
21371 }
21372
21373
21374 static bool AccessAlwaysBlockedWithFlag(Local<v8::Object> global,
21375                                         Local<Value> name, v8::AccessType type,
21376                                         Local<Value> data) {
21377   access_was_called = true;
21378   return false;
21379 }
21380
21381
21382 TEST(StrongModeAccessCheckAllowed) {
21383   i::FLAG_strong_mode = true;
21384   v8::Isolate* isolate = CcTest::isolate();
21385   v8::HandleScope handle_scope(isolate);
21386   v8::Handle<Value> value;
21387   access_was_called = false;
21388
21389   v8::Handle<v8::ObjectTemplate> obj_template =
21390       v8::ObjectTemplate::New(isolate);
21391
21392   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
21393   obj_template->SetAccessCheckCallbacks(AccessAlwaysAllowedWithFlag, NULL);
21394
21395   // Create an environment
21396   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
21397   context0->Enter();
21398   v8::Handle<v8::Object> global0 = context0->Global();
21399   global0->Set(v8_str("object"), obj_template->NewInstance());
21400   {
21401     v8::TryCatch try_catch(isolate);
21402     value = CompileRun("'use strong'; object.x");
21403     CHECK(!try_catch.HasCaught());
21404     CHECK(!access_was_called);
21405     CHECK_EQ(42, value->Int32Value());
21406   }
21407   {
21408     v8::TryCatch try_catch(isolate);
21409     value = CompileRun("'use strong'; object.foo");
21410     CHECK(try_catch.HasCaught());
21411     CHECK(!access_was_called);
21412   }
21413   {
21414     v8::TryCatch try_catch(isolate);
21415     value = CompileRun("'use strong'; object[10]");
21416     CHECK(try_catch.HasCaught());
21417     CHECK(!access_was_called);
21418   }
21419
21420   // Create an environment
21421   v8::Local<Context> context1 = Context::New(isolate);
21422   context1->Enter();
21423   v8::Handle<v8::Object> global1 = context1->Global();
21424   global1->Set(v8_str("object"), obj_template->NewInstance());
21425   {
21426     v8::TryCatch try_catch(isolate);
21427     value = CompileRun("'use strong'; object.x");
21428     CHECK(!try_catch.HasCaught());
21429     CHECK(access_was_called);
21430     CHECK_EQ(42, value->Int32Value());
21431   }
21432   access_was_called = false;
21433   {
21434     v8::TryCatch try_catch(isolate);
21435     value = CompileRun("'use strong'; object.foo");
21436     CHECK(try_catch.HasCaught());
21437     CHECK(access_was_called);
21438   }
21439   access_was_called = false;
21440   {
21441     v8::TryCatch try_catch(isolate);
21442     value = CompileRun("'use strong'; object[10]");
21443     CHECK(try_catch.HasCaught());
21444     CHECK(access_was_called);
21445   }
21446
21447   context1->Exit();
21448   context0->Exit();
21449 }
21450
21451
21452 TEST(StrongModeAccessCheckBlocked) {
21453   i::FLAG_strong_mode = true;
21454   v8::Isolate* isolate = CcTest::isolate();
21455   v8::HandleScope handle_scope(isolate);
21456   v8::Handle<Value> value;
21457   access_was_called = false;
21458
21459   v8::Handle<v8::ObjectTemplate> obj_template =
21460       v8::ObjectTemplate::New(isolate);
21461
21462   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
21463   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlockedWithFlag, NULL);
21464
21465   // Create an environment
21466   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
21467   context0->Enter();
21468   v8::Handle<v8::Object> global0 = context0->Global();
21469   global0->Set(v8_str("object"), obj_template->NewInstance());
21470   {
21471     v8::TryCatch try_catch(isolate);
21472     value = CompileRun("'use strong'; object.x");
21473     CHECK(!try_catch.HasCaught());
21474     CHECK(!access_was_called);
21475     CHECK_EQ(42, value->Int32Value());
21476   }
21477   {
21478     v8::TryCatch try_catch(isolate);
21479     value = CompileRun("'use strong'; object.foo");
21480     CHECK(try_catch.HasCaught());
21481     CHECK(!access_was_called);
21482   }
21483   {
21484     v8::TryCatch try_catch(isolate);
21485     value = CompileRun("'use strong'; object[10]");
21486     CHECK(try_catch.HasCaught());
21487     CHECK(!access_was_called);
21488   }
21489
21490   // Create an environment
21491   v8::Local<Context> context1 = Context::New(isolate);
21492   context1->Enter();
21493   v8::Handle<v8::Object> global1 = context1->Global();
21494   global1->Set(v8_str("object"), obj_template->NewInstance());
21495   {
21496     v8::TryCatch try_catch(isolate);
21497     value = CompileRun("'use strong'; object.x");
21498     CHECK(try_catch.HasCaught());
21499     CHECK(access_was_called);
21500   }
21501   access_was_called = false;
21502   {
21503     v8::TryCatch try_catch(isolate);
21504     value = CompileRun("'use strong'; object.foo");
21505     CHECK(try_catch.HasCaught());
21506     CHECK(access_was_called);
21507   }
21508   access_was_called = false;
21509   {
21510     v8::TryCatch try_catch(isolate);
21511     value = CompileRun("'use strong'; object[10]");
21512     CHECK(try_catch.HasCaught());
21513     CHECK(access_was_called);
21514   }
21515
21516   context1->Exit();
21517   context0->Exit();
21518 }
21519
21520
21521 TEST(StrongModeArityCallFromApi) {
21522   i::FLAG_strong_mode = true;
21523   LocalContext env;
21524   v8::Isolate* isolate = env->GetIsolate();
21525   v8::HandleScope scope(isolate);
21526   Local<Function> fun;
21527   {
21528     v8::TryCatch try_catch(isolate);
21529     fun = Local<Function>::Cast(CompileRun(
21530         "function f(x) { 'use strong'; }"
21531         "f"));
21532
21533     CHECK(!try_catch.HasCaught());
21534   }
21535
21536   {
21537     v8::TryCatch try_catch(isolate);
21538     fun->Call(v8::Undefined(isolate), 0, nullptr);
21539     CHECK(try_catch.HasCaught());
21540   }
21541
21542   {
21543     v8::TryCatch try_catch(isolate);
21544     v8::Handle<Value> args[] = {v8_num(42)};
21545     fun->Call(v8::Undefined(isolate), arraysize(args), args);
21546     CHECK(!try_catch.HasCaught());
21547   }
21548
21549   {
21550     v8::TryCatch try_catch(isolate);
21551     v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
21552     fun->Call(v8::Undefined(isolate), arraysize(args), args);
21553     CHECK(!try_catch.HasCaught());
21554   }
21555 }
21556
21557
21558 TEST(StrongModeArityCallFromApi2) {
21559   i::FLAG_strong_mode = true;
21560   LocalContext env;
21561   v8::Isolate* isolate = env->GetIsolate();
21562   v8::HandleScope scope(isolate);
21563   Local<Function> fun;
21564   {
21565     v8::TryCatch try_catch(isolate);
21566     fun = Local<Function>::Cast(CompileRun(
21567         "'use strong';"
21568         "function f(x) {}"
21569         "f"));
21570
21571     CHECK(!try_catch.HasCaught());
21572   }
21573
21574   {
21575     v8::TryCatch try_catch(isolate);
21576     fun->Call(v8::Undefined(isolate), 0, nullptr);
21577     CHECK(try_catch.HasCaught());
21578   }
21579
21580   {
21581     v8::TryCatch try_catch(isolate);
21582     v8::Handle<Value> args[] = {v8_num(42)};
21583     fun->Call(v8::Undefined(isolate), arraysize(args), args);
21584     CHECK(!try_catch.HasCaught());
21585   }
21586
21587   {
21588     v8::TryCatch try_catch(isolate);
21589     v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
21590     fun->Call(v8::Undefined(isolate), arraysize(args), args);
21591     CHECK(!try_catch.HasCaught());
21592   }
21593 }
21594
21595
21596 TEST(StrongObjectDelete) {
21597   i::FLAG_strong_mode = true;
21598   LocalContext env;
21599   v8::Isolate* isolate = env->GetIsolate();
21600   v8::HandleScope scope(isolate);
21601   Local<Object> obj;
21602   {
21603     v8::TryCatch try_catch;
21604     obj = Local<Object>::Cast(CompileRun(
21605         "'use strong';"
21606         "({});"));
21607     CHECK(!try_catch.HasCaught());
21608   }
21609   obj->ForceSet(v8_str("foo"), v8_num(1), v8::None);
21610   obj->ForceSet(v8_str("2"), v8_num(1), v8::None);
21611   CHECK(obj->HasOwnProperty(v8_str("foo")));
21612   CHECK(obj->HasOwnProperty(v8_str("2")));
21613   CHECK(!obj->Delete(v8_str("foo")));
21614   CHECK(!obj->Delete(2));
21615 }
21616
21617
21618 static void ExtrasExportsTestRuntimeFunction(
21619     const v8::FunctionCallbackInfo<v8::Value>& args) {
21620   CHECK_EQ(3, args[0]->Int32Value());
21621   args.GetReturnValue().Set(v8_num(7));
21622 }
21623
21624
21625 TEST(ExtrasExportsObject) {
21626   v8::Isolate* isolate = CcTest::isolate();
21627   v8::HandleScope handle_scope(isolate);
21628   LocalContext env;
21629
21630   // standalone.gypi ensures we include the test-extra.js file, which should
21631   // export the tested functions.
21632   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
21633
21634   auto func =
21635       binding->Get(v8_str("testExtraShouldReturnFive")).As<v8::Function>();
21636   auto undefined = v8::Undefined(isolate);
21637   auto result = func->Call(undefined, 0, {}).As<v8::Number>();
21638   CHECK_EQ(5, result->Int32Value());
21639
21640   v8::Handle<v8::FunctionTemplate> runtimeFunction =
21641       v8::FunctionTemplate::New(isolate, ExtrasExportsTestRuntimeFunction);
21642   binding->Set(v8_str("runtime"), runtimeFunction->GetFunction());
21643   func =
21644       binding->Get(v8_str("testExtraShouldCallToRuntime")).As<v8::Function>();
21645   result = func->Call(undefined, 0, {}).As<v8::Number>();
21646   CHECK_EQ(7, result->Int32Value());
21647 }
21648
21649
21650 TEST(Map) {
21651   v8::Isolate* isolate = CcTest::isolate();
21652   v8::HandleScope handle_scope(isolate);
21653   LocalContext env;
21654
21655   v8::Local<v8::Map> map = v8::Map::New(isolate);
21656   CHECK(map->IsObject());
21657   CHECK(map->IsMap());
21658   CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
21659   CHECK_EQ(0U, map->Size());
21660
21661   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
21662   CHECK(val->IsMap());
21663   map = v8::Local<v8::Map>::Cast(val);
21664   CHECK_EQ(2U, map->Size());
21665
21666   v8::Local<v8::Array> contents = map->AsArray();
21667   CHECK_EQ(4U, contents->Length());
21668   CHECK_EQ(1, contents->Get(0).As<v8::Int32>()->Value());
21669   CHECK_EQ(2, contents->Get(1).As<v8::Int32>()->Value());
21670   CHECK_EQ(3, contents->Get(2).As<v8::Int32>()->Value());
21671   CHECK_EQ(4, contents->Get(3).As<v8::Int32>()->Value());
21672
21673   CHECK_EQ(2U, map->Size());
21674
21675   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
21676   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
21677
21678   CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
21679   CHECK(!map->Has(env.local(), map).FromJust());
21680
21681   CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
21682                   .ToLocalChecked()
21683                   ->Int32Value());
21684   CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
21685                   .ToLocalChecked()
21686                   ->Int32Value());
21687
21688   CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
21689             .ToLocalChecked()
21690             ->IsUndefined());
21691
21692   CHECK(!map->Set(env.local(), map, map).IsEmpty());
21693   CHECK_EQ(3U, map->Size());
21694   CHECK(map->Has(env.local(), map).FromJust());
21695
21696   CHECK(map->Delete(env.local(), map).FromJust());
21697   CHECK_EQ(2U, map->Size());
21698   CHECK(!map->Has(env.local(), map).FromJust());
21699   CHECK(!map->Delete(env.local(), map).FromJust());
21700
21701   map->Clear();
21702   CHECK_EQ(0U, map->Size());
21703 }
21704
21705
21706 TEST(Set) {
21707   v8::Isolate* isolate = CcTest::isolate();
21708   v8::HandleScope handle_scope(isolate);
21709   LocalContext env;
21710
21711   v8::Local<v8::Set> set = v8::Set::New(isolate);
21712   CHECK(set->IsObject());
21713   CHECK(set->IsSet());
21714   CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
21715   CHECK_EQ(0U, set->Size());
21716
21717   v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
21718   CHECK(val->IsSet());
21719   set = v8::Local<v8::Set>::Cast(val);
21720   CHECK_EQ(2U, set->Size());
21721
21722   v8::Local<v8::Array> keys = set->AsArray();
21723   CHECK_EQ(2U, keys->Length());
21724   CHECK_EQ(1, keys->Get(0).As<v8::Int32>()->Value());
21725   CHECK_EQ(2, keys->Get(1).As<v8::Int32>()->Value());
21726
21727   CHECK_EQ(2U, set->Size());
21728
21729   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
21730   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
21731
21732   CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
21733   CHECK(!set->Has(env.local(), set).FromJust());
21734
21735   CHECK(!set->Add(env.local(), set).IsEmpty());
21736   CHECK_EQ(3U, set->Size());
21737   CHECK(set->Has(env.local(), set).FromJust());
21738
21739   CHECK(set->Delete(env.local(), set).FromJust());
21740   CHECK_EQ(2U, set->Size());
21741   CHECK(!set->Has(env.local(), set).FromJust());
21742   CHECK(!set->Delete(env.local(), set).FromJust());
21743
21744   set->Clear();
21745   CHECK_EQ(0U, set->Size());
21746 }
21747
21748
21749 TEST(CompatibleReceiverCheckOnCachedICHandler) {
21750   v8::Isolate* isolate = CcTest::isolate();
21751   v8::HandleScope scope(isolate);
21752   v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
21753   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
21754   auto returns_42 =
21755       v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
21756   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
21757   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
21758   child->Inherit(parent);
21759   LocalContext env;
21760   env->Global()->Set(v8_str("Child"), child->GetFunction());
21761
21762   // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
21763   CompileRun(
21764       "var real = new Child();\n"
21765       "for (var i = 0; i < 3; ++i) {\n"
21766       "  real.age;\n"
21767       "}\n");
21768
21769   // Check that the cached stub is never used.
21770   ExpectInt32(
21771       "var fake = Object.create(Child.prototype);\n"
21772       "var result = 0;\n"
21773       "function test(d) {\n"
21774       "  if (d == 3) return;\n"
21775       "  try {\n"
21776       "    fake.age;\n"
21777       "    result = 1;\n"
21778       "  } catch (e) {\n"
21779       "  }\n"
21780       "  test(d+1);\n"
21781       "}\n"
21782       "test(0);\n"
21783       "result;\n",
21784       0);
21785 }
21786
21787 class FutexInterruptionThread : public v8::base::Thread {
21788  public:
21789   explicit FutexInterruptionThread(v8::Isolate* isolate)
21790       : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
21791
21792   virtual void Run() {
21793     // Wait a bit before terminating.
21794     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
21795     v8::V8::TerminateExecution(isolate_);
21796   }
21797
21798  private:
21799   v8::Isolate* isolate_;
21800 };
21801
21802
21803 TEST(FutexInterruption) {
21804   i::FLAG_harmony_sharedarraybuffer = true;
21805   i::FLAG_harmony_atomics = true;
21806   v8::Isolate* isolate = CcTest::isolate();
21807   v8::HandleScope scope(isolate);
21808   LocalContext env;
21809
21810   FutexInterruptionThread timeout_thread(isolate);
21811
21812   v8::TryCatch try_catch(CcTest::isolate());
21813   timeout_thread.Start();
21814
21815   CompileRun(
21816       "var ab = new SharedArrayBuffer(4);"
21817       "var i32a = new Int32Array(ab);"
21818       "Atomics.futexWait(i32a, 0, 0);");
21819   CHECK(try_catch.HasTerminated());
21820 }
21821
21822
21823 TEST(EstimatedContextSize) {
21824   v8::Isolate* isolate = CcTest::isolate();
21825   v8::HandleScope scope(isolate);
21826   LocalContext env;
21827   CHECK(50000 < env->EstimatedSize());
21828 }