revise installing a license file
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-api.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include <climits>
29 #include <csignal>
30 #include <map>
31 #include <string>
32
33 #include "test/cctest/test-api.h"
34
35 #if V8_OS_POSIX
36 #include <unistd.h>  // NOLINT
37 #endif
38
39 #include "include/v8-util.h"
40 #include "src/api.h"
41 #include "src/arguments.h"
42 #include "src/base/platform/platform.h"
43 #include "src/compilation-cache.h"
44 #include "src/debug.h"
45 #include "src/execution.h"
46 #include "src/objects.h"
47 #include "src/parser.h"
48 #include "src/smart-pointers.h"
49 #include "src/unicode-inl.h"
50 #include "src/utils.h"
51 #include "src/vm-state.h"
52
53 static const bool kLogThreading = false;
54
55 using ::v8::Boolean;
56 using ::v8::BooleanObject;
57 using ::v8::Context;
58 using ::v8::Extension;
59 using ::v8::Function;
60 using ::v8::FunctionTemplate;
61 using ::v8::Handle;
62 using ::v8::HandleScope;
63 using ::v8::Local;
64 using ::v8::Maybe;
65 using ::v8::Message;
66 using ::v8::MessageCallback;
67 using ::v8::Name;
68 using ::v8::None;
69 using ::v8::Object;
70 using ::v8::ObjectTemplate;
71 using ::v8::Persistent;
72 using ::v8::PropertyAttribute;
73 using ::v8::Script;
74 using ::v8::StackTrace;
75 using ::v8::String;
76 using ::v8::Symbol;
77 using ::v8::TryCatch;
78 using ::v8::Undefined;
79 using ::v8::UniqueId;
80 using ::v8::V8;
81 using ::v8::Value;
82
83
84 #define THREADED_PROFILED_TEST(Name)                                 \
85   static void Test##Name();                                          \
86   TEST(Name##WithProfiler) {                                         \
87     RunWithProfiler(&Test##Name);                                    \
88   }                                                                  \
89   THREADED_TEST(Name)
90
91
92 void RunWithProfiler(void (*test)()) {
93   LocalContext env;
94   v8::HandleScope scope(env->GetIsolate());
95   v8::Local<v8::String> profile_name =
96       v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
97   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
98
99   cpu_profiler->StartProfiling(profile_name);
100   (*test)();
101   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
102 }
103
104
105 static int signature_callback_count;
106 static Local<Value> signature_expected_receiver;
107 static void IncrementingSignatureCallback(
108     const v8::FunctionCallbackInfo<v8::Value>& args) {
109   ApiTestFuzzer::Fuzz();
110   signature_callback_count++;
111   CHECK(signature_expected_receiver->Equals(args.Holder()));
112   CHECK(signature_expected_receiver->Equals(args.This()));
113   v8::Handle<v8::Array> result =
114       v8::Array::New(args.GetIsolate(), args.Length());
115   for (int i = 0; i < args.Length(); i++)
116     result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
117   args.GetReturnValue().Set(result);
118 }
119
120
121 static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
122   info.GetReturnValue().Set(42);
123 }
124
125
126 // Tests that call v8::V8::Dispose() cannot be threaded.
127 UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
128   CHECK(v8::V8::Initialize());
129   CHECK(v8::V8::Dispose());
130 }
131
132
133 // Tests that call v8::V8::Dispose() cannot be threaded.
134 UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
135   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
136   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
137   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
138   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
139   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
140 }
141
142
143 THREADED_TEST(Handles) {
144   v8::HandleScope scope(CcTest::isolate());
145   Local<Context> local_env;
146   {
147     LocalContext env;
148     local_env = env.local();
149   }
150
151   // Local context should still be live.
152   CHECK(!local_env.IsEmpty());
153   local_env->Enter();
154
155   v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
156   CHECK(!undef.IsEmpty());
157   CHECK(undef->IsUndefined());
158
159   const char* source = "1 + 2 + 3";
160   Local<Script> script = v8_compile(source);
161   CHECK_EQ(6, script->Run()->Int32Value());
162
163   local_env->Exit();
164 }
165
166
167 THREADED_TEST(IsolateOfContext) {
168   v8::HandleScope scope(CcTest::isolate());
169   v8::Handle<Context> env = Context::New(CcTest::isolate());
170
171   CHECK(!env->GetIsolate()->InContext());
172   CHECK(env->GetIsolate() == CcTest::isolate());
173   env->Enter();
174   CHECK(env->GetIsolate()->InContext());
175   CHECK(env->GetIsolate() == CcTest::isolate());
176   env->Exit();
177   CHECK(!env->GetIsolate()->InContext());
178   CHECK(env->GetIsolate() == CcTest::isolate());
179 }
180
181
182 static void TestSignature(const char* loop_js, Local<Value> receiver,
183                           v8::Isolate* isolate) {
184   i::ScopedVector<char> source(200);
185   i::SNPrintF(source,
186               "for (var i = 0; i < 10; i++) {"
187               "  %s"
188               "}",
189               loop_js);
190   signature_callback_count = 0;
191   signature_expected_receiver = receiver;
192   bool expected_to_throw = receiver.IsEmpty();
193   v8::TryCatch try_catch(isolate);
194   CompileRun(source.start());
195   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
196   if (!expected_to_throw) {
197     CHECK_EQ(10, signature_callback_count);
198   } else {
199     CHECK(v8_str("TypeError: Illegal invocation")
200               ->Equals(try_catch.Exception()->ToString(isolate)));
201   }
202 }
203
204
205 THREADED_TEST(ReceiverSignature) {
206   LocalContext env;
207   v8::Isolate* isolate = env->GetIsolate();
208   v8::HandleScope scope(isolate);
209   // Setup templates.
210   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
211   v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
212   v8::Handle<v8::FunctionTemplate> callback_sig =
213       v8::FunctionTemplate::New(
214           isolate, IncrementingSignatureCallback, Local<Value>(), sig);
215   v8::Handle<v8::FunctionTemplate> callback =
216       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
217   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
218   sub_fun->Inherit(fun);
219   v8::Handle<v8::FunctionTemplate> unrel_fun =
220       v8::FunctionTemplate::New(isolate);
221   // Install properties.
222   v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
223   fun_proto->Set(v8_str("prop_sig"), callback_sig);
224   fun_proto->Set(v8_str("prop"), callback);
225   fun_proto->SetAccessorProperty(
226       v8_str("accessor_sig"), callback_sig, callback_sig);
227   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
228   // Instantiate templates.
229   Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
230   Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
231   // Setup global variables.
232   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
233   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
234   env->Global()->Set(v8_str("fun_instance"), fun_instance);
235   env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
236   CompileRun(
237       "var accessor_sig_key = 'accessor_sig';"
238       "var accessor_key = 'accessor';"
239       "var prop_sig_key = 'prop_sig';"
240       "var prop_key = 'prop';"
241       ""
242       "function copy_props(obj) {"
243       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
244       "  var source = Fun.prototype;"
245       "  for (var i in keys) {"
246       "    var key = keys[i];"
247       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
248       "    Object.defineProperty(obj, key, desc);"
249       "  }"
250       "}"
251       ""
252       "var obj = {};"
253       "copy_props(obj);"
254       "var unrel = new UnrelFun();"
255       "copy_props(unrel);");
256   // Test with and without ICs
257   const char* test_objects[] = {
258       "fun_instance", "sub_fun_instance", "obj", "unrel" };
259   unsigned bad_signature_start_offset = 2;
260   for (unsigned i = 0; i < arraysize(test_objects); i++) {
261     i::ScopedVector<char> source(200);
262     i::SNPrintF(
263         source, "var test_object = %s; test_object", test_objects[i]);
264     Local<Value> test_object = CompileRun(source.start());
265     TestSignature("test_object.prop();", test_object, isolate);
266     TestSignature("test_object.accessor;", test_object, isolate);
267     TestSignature("test_object[accessor_key];", test_object, isolate);
268     TestSignature("test_object.accessor = 1;", test_object, isolate);
269     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
270     if (i >= bad_signature_start_offset) test_object = Local<Value>();
271     TestSignature("test_object.prop_sig();", test_object, isolate);
272     TestSignature("test_object.accessor_sig;", test_object, isolate);
273     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
274     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
275     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
276   }
277 }
278
279
280 THREADED_TEST(HulIgennem) {
281   LocalContext env;
282   v8::Isolate* isolate = env->GetIsolate();
283   v8::HandleScope scope(isolate);
284   v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
285   Local<String> undef_str = undef->ToString(isolate);
286   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
287   undef_str->WriteUtf8(value);
288   CHECK_EQ(0, strcmp(value, "undefined"));
289   i::DeleteArray(value);
290 }
291
292
293 THREADED_TEST(Access) {
294   LocalContext env;
295   v8::Isolate* isolate = env->GetIsolate();
296   v8::HandleScope scope(isolate);
297   Local<v8::Object> obj = v8::Object::New(isolate);
298   Local<Value> foo_before = obj->Get(v8_str("foo"));
299   CHECK(foo_before->IsUndefined());
300   Local<String> bar_str = v8_str("bar");
301   obj->Set(v8_str("foo"), bar_str);
302   Local<Value> foo_after = obj->Get(v8_str("foo"));
303   CHECK(!foo_after->IsUndefined());
304   CHECK(foo_after->IsString());
305   CHECK(bar_str->Equals(foo_after));
306 }
307
308
309 THREADED_TEST(AccessElement) {
310   LocalContext env;
311   v8::HandleScope scope(env->GetIsolate());
312   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
313   Local<Value> before = obj->Get(1);
314   CHECK(before->IsUndefined());
315   Local<String> bar_str = v8_str("bar");
316   obj->Set(1, bar_str);
317   Local<Value> after = obj->Get(1);
318   CHECK(!after->IsUndefined());
319   CHECK(after->IsString());
320   CHECK(bar_str->Equals(after));
321
322   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
323   CHECK(v8_str("a")->Equals(value->Get(0)));
324   CHECK(v8_str("b")->Equals(value->Get(1)));
325 }
326
327
328 THREADED_TEST(Script) {
329   LocalContext env;
330   v8::HandleScope scope(env->GetIsolate());
331   const char* source = "1 + 2 + 3";
332   Local<Script> script = v8_compile(source);
333   CHECK_EQ(6, script->Run()->Int32Value());
334 }
335
336
337 class TestResource: public String::ExternalStringResource {
338  public:
339   explicit TestResource(uint16_t* data, int* counter = NULL,
340                         bool owning_data = true)
341       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
342     while (data[length_]) ++length_;
343   }
344
345   ~TestResource() {
346     if (owning_data_) i::DeleteArray(data_);
347     if (counter_ != NULL) ++*counter_;
348   }
349
350   const uint16_t* data() const {
351     return data_;
352   }
353
354   size_t length() const {
355     return length_;
356   }
357
358  private:
359   uint16_t* data_;
360   size_t length_;
361   int* counter_;
362   bool owning_data_;
363 };
364
365
366 class TestOneByteResource : public String::ExternalOneByteStringResource {
367  public:
368   explicit TestOneByteResource(const char* data, int* counter = NULL,
369                                size_t offset = 0)
370       : orig_data_(data),
371         data_(data + offset),
372         length_(strlen(data) - offset),
373         counter_(counter) {}
374
375   ~TestOneByteResource() {
376     i::DeleteArray(orig_data_);
377     if (counter_ != NULL) ++*counter_;
378   }
379
380   const char* data() const {
381     return data_;
382   }
383
384   size_t length() const {
385     return length_;
386   }
387
388  private:
389   const char* orig_data_;
390   const char* data_;
391   size_t length_;
392   int* counter_;
393 };
394
395
396 THREADED_TEST(ScriptUsingStringResource) {
397   int dispose_count = 0;
398   const char* c_source = "1 + 2 * 3";
399   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
400   {
401     LocalContext env;
402     v8::HandleScope scope(env->GetIsolate());
403     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
404     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
405     Local<Script> script = v8_compile(source);
406     Local<Value> value = script->Run();
407     CHECK(value->IsNumber());
408     CHECK_EQ(7, value->Int32Value());
409     CHECK(source->IsExternal());
410     CHECK_EQ(resource,
411              static_cast<TestResource*>(source->GetExternalStringResource()));
412     String::Encoding encoding = String::UNKNOWN_ENCODING;
413     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
414              source->GetExternalStringResourceBase(&encoding));
415     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
416     CcTest::heap()->CollectAllGarbage();
417     CHECK_EQ(0, dispose_count);
418   }
419   CcTest::i_isolate()->compilation_cache()->Clear();
420   CcTest::heap()->CollectAllAvailableGarbage();
421   CHECK_EQ(1, dispose_count);
422 }
423
424
425 THREADED_TEST(ScriptUsingOneByteStringResource) {
426   int dispose_count = 0;
427   const char* c_source = "1 + 2 * 3";
428   {
429     LocalContext env;
430     v8::HandleScope scope(env->GetIsolate());
431     TestOneByteResource* resource =
432         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
433     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
434     CHECK(source->IsExternalOneByte());
435     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
436              source->GetExternalOneByteStringResource());
437     String::Encoding encoding = String::UNKNOWN_ENCODING;
438     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
439              source->GetExternalStringResourceBase(&encoding));
440     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
441     Local<Script> script = v8_compile(source);
442     Local<Value> value = script->Run();
443     CHECK(value->IsNumber());
444     CHECK_EQ(7, value->Int32Value());
445     CcTest::heap()->CollectAllGarbage();
446     CHECK_EQ(0, dispose_count);
447   }
448   CcTest::i_isolate()->compilation_cache()->Clear();
449   CcTest::heap()->CollectAllAvailableGarbage();
450   CHECK_EQ(1, dispose_count);
451 }
452
453
454 THREADED_TEST(ScriptMakingExternalString) {
455   int dispose_count = 0;
456   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
457   {
458     LocalContext env;
459     v8::HandleScope scope(env->GetIsolate());
460     Local<String> source =
461         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
462     // Trigger GCs so that the newly allocated string moves to old gen.
463     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
464     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
465     CHECK_EQ(source->IsExternal(), false);
466     CHECK_EQ(source->IsExternalOneByte(), false);
467     String::Encoding encoding = String::UNKNOWN_ENCODING;
468     CHECK(!source->GetExternalStringResourceBase(&encoding));
469     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
470     bool success = source->MakeExternal(new TestResource(two_byte_source,
471                                                          &dispose_count));
472     CHECK(success);
473     Local<Script> script = v8_compile(source);
474     Local<Value> value = script->Run();
475     CHECK(value->IsNumber());
476     CHECK_EQ(7, value->Int32Value());
477     CcTest::heap()->CollectAllGarbage();
478     CHECK_EQ(0, dispose_count);
479   }
480   CcTest::i_isolate()->compilation_cache()->Clear();
481   CcTest::heap()->CollectAllGarbage();
482   CHECK_EQ(1, dispose_count);
483 }
484
485
486 THREADED_TEST(ScriptMakingExternalOneByteString) {
487   int dispose_count = 0;
488   const char* c_source = "1 + 2 * 3";
489   {
490     LocalContext env;
491     v8::HandleScope scope(env->GetIsolate());
492     Local<String> source = v8_str(c_source);
493     // Trigger GCs so that the newly allocated string moves to old gen.
494     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
495     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
496     bool success = source->MakeExternal(
497         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
498     CHECK(success);
499     Local<Script> script = v8_compile(source);
500     Local<Value> value = script->Run();
501     CHECK(value->IsNumber());
502     CHECK_EQ(7, value->Int32Value());
503     CcTest::heap()->CollectAllGarbage();
504     CHECK_EQ(0, dispose_count);
505   }
506   CcTest::i_isolate()->compilation_cache()->Clear();
507   CcTest::heap()->CollectAllGarbage();
508   CHECK_EQ(1, dispose_count);
509 }
510
511
512 TEST(MakingExternalStringConditions) {
513   LocalContext env;
514   v8::HandleScope scope(env->GetIsolate());
515
516   // Free some space in the new space so that we can check freshness.
517   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
518   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
519
520   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
521   Local<String> small_string =
522       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
523   i::DeleteArray(two_byte_string);
524
525   // We should refuse to externalize newly created small string.
526   CHECK(!small_string->CanMakeExternal());
527   // Trigger GCs so that the newly allocated string moves to old gen.
528   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
529   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
530   // Old space strings should be accepted.
531   CHECK(small_string->CanMakeExternal());
532
533   two_byte_string = AsciiToTwoByteString("small string 2");
534   small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
535   i::DeleteArray(two_byte_string);
536
537   // We should refuse externalizing newly created small string.
538   CHECK(!small_string->CanMakeExternal());
539   for (int i = 0; i < 100; i++) {
540     String::Value value(small_string);
541   }
542   // Frequently used strings should be accepted.
543   CHECK(small_string->CanMakeExternal());
544
545   const int buf_size = 10 * 1024;
546   char* buf = i::NewArray<char>(buf_size);
547   memset(buf, 'a', buf_size);
548   buf[buf_size - 1] = '\0';
549
550   two_byte_string = AsciiToTwoByteString(buf);
551   Local<String> large_string =
552       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
553   i::DeleteArray(buf);
554   i::DeleteArray(two_byte_string);
555   // Large strings should be immediately accepted.
556   CHECK(large_string->CanMakeExternal());
557 }
558
559
560 TEST(MakingExternalOneByteStringConditions) {
561   LocalContext env;
562   v8::HandleScope scope(env->GetIsolate());
563
564   // Free some space in the new space so that we can check freshness.
565   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
566   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
567
568   Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
569   // We should refuse to externalize newly created small string.
570   CHECK(!small_string->CanMakeExternal());
571   // Trigger GCs so that the newly allocated string moves to old gen.
572   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
573   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
574   // Old space strings should be accepted.
575   CHECK(small_string->CanMakeExternal());
576
577   small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
578   // We should refuse externalizing newly created small string.
579   CHECK(!small_string->CanMakeExternal());
580   for (int i = 0; i < 100; i++) {
581     String::Value value(small_string);
582   }
583   // Frequently used strings should be accepted.
584   CHECK(small_string->CanMakeExternal());
585
586   const int buf_size = 10 * 1024;
587   char* buf = i::NewArray<char>(buf_size);
588   memset(buf, 'a', buf_size);
589   buf[buf_size - 1] = '\0';
590   Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
591   i::DeleteArray(buf);
592   // Large strings should be immediately accepted.
593   CHECK(large_string->CanMakeExternal());
594 }
595
596
597 TEST(MakingExternalUnalignedOneByteString) {
598   LocalContext env;
599   v8::HandleScope scope(env->GetIsolate());
600
601   CompileRun("function cons(a, b) { return a + b; }"
602              "function slice(a) { return a.substring(1); }");
603   // Create a cons string that will land in old pointer space.
604   Local<String> cons = Local<String>::Cast(CompileRun(
605       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
606   // Create a sliced string that will land in old pointer space.
607   Local<String> slice = Local<String>::Cast(CompileRun(
608       "slice('abcdefghijklmnopqrstuvwxyz');"));
609
610   // Trigger GCs so that the newly allocated string moves to old gen.
611   SimulateFullSpace(CcTest::heap()->old_space());
612   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
613   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
614
615   // Turn into external string with unaligned resource data.
616   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
617   bool success =
618       cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
619   CHECK(success);
620   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
621   success =
622       slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
623   CHECK(success);
624
625   // Trigger GCs and force evacuation.
626   CcTest::heap()->CollectAllGarbage();
627   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
628 }
629
630
631 THREADED_TEST(UsingExternalString) {
632   i::Factory* factory = CcTest::i_isolate()->factory();
633   {
634     v8::HandleScope scope(CcTest::isolate());
635     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
636     Local<String> string = String::NewExternal(
637         CcTest::isolate(), new TestResource(two_byte_string));
638     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
639     // Trigger GCs so that the newly allocated string moves to old gen.
640     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
641     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
642     i::Handle<i::String> isymbol =
643         factory->InternalizeString(istring);
644     CHECK(isymbol->IsInternalizedString());
645   }
646   CcTest::heap()->CollectAllGarbage();
647   CcTest::heap()->CollectAllGarbage();
648 }
649
650
651 THREADED_TEST(UsingExternalOneByteString) {
652   i::Factory* factory = CcTest::i_isolate()->factory();
653   {
654     v8::HandleScope scope(CcTest::isolate());
655     const char* one_byte_string = "test string";
656     Local<String> string = String::NewExternal(
657         CcTest::isolate(), new TestOneByteResource(i::StrDup(one_byte_string)));
658     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
659     // Trigger GCs so that the newly allocated string moves to old gen.
660     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
661     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
662     i::Handle<i::String> isymbol =
663         factory->InternalizeString(istring);
664     CHECK(isymbol->IsInternalizedString());
665   }
666   CcTest::heap()->CollectAllGarbage();
667   CcTest::heap()->CollectAllGarbage();
668 }
669
670
671 class RandomLengthResource : public v8::String::ExternalStringResource {
672  public:
673   explicit RandomLengthResource(int length) : length_(length) {}
674   virtual const uint16_t* data() const { return string_; }
675   virtual size_t length() const { return length_; }
676
677  private:
678   uint16_t string_[10];
679   int length_;
680 };
681
682
683 class RandomLengthOneByteResource
684     : public v8::String::ExternalOneByteStringResource {
685  public:
686   explicit RandomLengthOneByteResource(int length) : length_(length) {}
687   virtual const char* data() const { return string_; }
688   virtual size_t length() const { return length_; }
689
690  private:
691   char string_[10];
692   int length_;
693 };
694
695
696 THREADED_TEST(NewExternalForVeryLongString) {
697   auto isolate = CcTest::isolate();
698   {
699     v8::HandleScope scope(isolate);
700     v8::TryCatch try_catch(isolate);
701     RandomLengthOneByteResource r(1 << 30);
702     v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
703     CHECK(str.IsEmpty());
704     CHECK(!try_catch.HasCaught());
705   }
706
707   {
708     v8::HandleScope scope(isolate);
709     v8::TryCatch try_catch(isolate);
710     RandomLengthResource r(1 << 30);
711     v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
712     CHECK(str.IsEmpty());
713     CHECK(!try_catch.HasCaught());
714   }
715 }
716
717
718 THREADED_TEST(ScavengeExternalString) {
719   i::FLAG_stress_compaction = false;
720   i::FLAG_gc_global = false;
721   int dispose_count = 0;
722   bool in_new_space = false;
723   {
724     v8::HandleScope scope(CcTest::isolate());
725     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
726     Local<String> string = String::NewExternal(
727         CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
728     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
729     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
730     in_new_space = CcTest::heap()->InNewSpace(*istring);
731     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
732     CHECK_EQ(0, dispose_count);
733   }
734   CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
735   CHECK_EQ(1, dispose_count);
736 }
737
738
739 THREADED_TEST(ScavengeExternalOneByteString) {
740   i::FLAG_stress_compaction = false;
741   i::FLAG_gc_global = false;
742   int dispose_count = 0;
743   bool in_new_space = false;
744   {
745     v8::HandleScope scope(CcTest::isolate());
746     const char* one_byte_string = "test string";
747     Local<String> string = String::NewExternal(
748         CcTest::isolate(),
749         new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count));
750     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
751     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
752     in_new_space = CcTest::heap()->InNewSpace(*istring);
753     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
754     CHECK_EQ(0, dispose_count);
755   }
756   CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
757   CHECK_EQ(1, dispose_count);
758 }
759
760
761 class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
762  public:
763   // Only used by non-threaded tests, so it can use static fields.
764   static int dispose_calls;
765   static int dispose_count;
766
767   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
768       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
769
770   void Dispose() {
771     ++dispose_calls;
772     if (dispose_) delete this;
773   }
774  private:
775   bool dispose_;
776 };
777
778
779 int TestOneByteResourceWithDisposeControl::dispose_count = 0;
780 int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
781
782
783 TEST(ExternalStringWithDisposeHandling) {
784   const char* c_source = "1 + 2 * 3";
785
786   // Use a stack allocated external string resource allocated object.
787   TestOneByteResourceWithDisposeControl::dispose_count = 0;
788   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
789   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
790   {
791     LocalContext env;
792     v8::HandleScope scope(env->GetIsolate());
793     Local<String> source =  String::NewExternal(env->GetIsolate(), &res_stack);
794     Local<Script> script = v8_compile(source);
795     Local<Value> value = script->Run();
796     CHECK(value->IsNumber());
797     CHECK_EQ(7, value->Int32Value());
798     CcTest::heap()->CollectAllAvailableGarbage();
799     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
800   }
801   CcTest::i_isolate()->compilation_cache()->Clear();
802   CcTest::heap()->CollectAllAvailableGarbage();
803   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
804   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
805
806   // Use a heap allocated external string resource allocated object.
807   TestOneByteResourceWithDisposeControl::dispose_count = 0;
808   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
809   TestOneByteResource* res_heap =
810       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
811   {
812     LocalContext env;
813     v8::HandleScope scope(env->GetIsolate());
814     Local<String> source =  String::NewExternal(env->GetIsolate(), res_heap);
815     Local<Script> script = v8_compile(source);
816     Local<Value> value = script->Run();
817     CHECK(value->IsNumber());
818     CHECK_EQ(7, value->Int32Value());
819     CcTest::heap()->CollectAllAvailableGarbage();
820     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
821   }
822   CcTest::i_isolate()->compilation_cache()->Clear();
823   CcTest::heap()->CollectAllAvailableGarbage();
824   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
825   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
826 }
827
828
829 THREADED_TEST(StringConcat) {
830   {
831     LocalContext env;
832     v8::HandleScope scope(env->GetIsolate());
833     const char* one_byte_string_1 = "function a_times_t";
834     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
835     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
836     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
837     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
838     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
839     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
840     Local<String> left = v8_str(one_byte_string_1);
841
842     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
843     Local<String> right =
844         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
845     i::DeleteArray(two_byte_source);
846
847     Local<String> source = String::Concat(left, right);
848     right = String::NewExternal(
849         env->GetIsolate(),
850         new TestOneByteResource(i::StrDup(one_byte_extern_1)));
851     source = String::Concat(source, right);
852     right = String::NewExternal(
853         env->GetIsolate(),
854         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
855     source = String::Concat(source, right);
856     right = v8_str(one_byte_string_2);
857     source = String::Concat(source, right);
858
859     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
860     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
861     i::DeleteArray(two_byte_source);
862
863     source = String::Concat(source, right);
864     right = String::NewExternal(
865         env->GetIsolate(),
866         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
867     source = String::Concat(source, right);
868     Local<Script> script = v8_compile(source);
869     Local<Value> value = script->Run();
870     CHECK(value->IsNumber());
871     CHECK_EQ(68, value->Int32Value());
872   }
873   CcTest::i_isolate()->compilation_cache()->Clear();
874   CcTest::heap()->CollectAllGarbage();
875   CcTest::heap()->CollectAllGarbage();
876 }
877
878
879 THREADED_TEST(GlobalProperties) {
880   LocalContext env;
881   v8::HandleScope scope(env->GetIsolate());
882   v8::Handle<v8::Object> global = env->Global();
883   global->Set(v8_str("pi"), v8_num(3.1415926));
884   Local<Value> pi = global->Get(v8_str("pi"));
885   CHECK_EQ(3.1415926, pi->NumberValue());
886 }
887
888
889 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
890                                  i::Address callback) {
891   ApiTestFuzzer::Fuzz();
892   CheckReturnValue(info, callback);
893   info.GetReturnValue().Set(v8_str("bad value"));
894   info.GetReturnValue().Set(v8_num(102));
895 }
896
897
898 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
899   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
900 }
901
902
903 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
904   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
905 }
906
907 static void construct_callback(
908     const v8::FunctionCallbackInfo<Value>& info) {
909   ApiTestFuzzer::Fuzz();
910   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
911   info.This()->Set(v8_str("x"), v8_num(1));
912   info.This()->Set(v8_str("y"), v8_num(2));
913   info.GetReturnValue().Set(v8_str("bad value"));
914   info.GetReturnValue().Set(info.This());
915 }
916
917
918 static void Return239Callback(
919     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
920   ApiTestFuzzer::Fuzz();
921   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
922   info.GetReturnValue().Set(v8_str("bad value"));
923   info.GetReturnValue().Set(v8_num(239));
924 }
925
926
927 template<typename Handler>
928 static void TestFunctionTemplateInitializer(Handler handler,
929                                             Handler handler_2) {
930   // Test constructor calls.
931   {
932     LocalContext env;
933     v8::Isolate* isolate = env->GetIsolate();
934     v8::HandleScope scope(isolate);
935
936     Local<v8::FunctionTemplate> fun_templ =
937         v8::FunctionTemplate::New(isolate, handler);
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   // Use SetCallHandler to initialize a function template, should work like
946   // the previous one.
947   {
948     LocalContext env;
949     v8::Isolate* isolate = env->GetIsolate();
950     v8::HandleScope scope(isolate);
951
952     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
953     fun_templ->SetCallHandler(handler_2);
954     Local<Function> fun = fun_templ->GetFunction();
955     env->Global()->Set(v8_str("obj"), fun);
956     Local<Script> script = v8_compile("obj()");
957     for (int i = 0; i < 30; i++) {
958       CHECK_EQ(102, script->Run()->Int32Value());
959     }
960   }
961 }
962
963
964 template<typename Constructor, typename Accessor>
965 static void TestFunctionTemplateAccessor(Constructor constructor,
966                                          Accessor accessor) {
967   LocalContext env;
968   v8::HandleScope scope(env->GetIsolate());
969
970   Local<v8::FunctionTemplate> fun_templ =
971       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
972   fun_templ->SetClassName(v8_str("funky"));
973   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
974   Local<Function> fun = fun_templ->GetFunction();
975   env->Global()->Set(v8_str("obj"), fun);
976   Local<Value> result = v8_compile("(new obj()).toString()")->Run();
977   CHECK(v8_str("[object funky]")->Equals(result));
978   CompileRun("var obj_instance = new obj();");
979   Local<Script> script;
980   script = v8_compile("obj_instance.x");
981   for (int i = 0; i < 30; i++) {
982     CHECK_EQ(1, script->Run()->Int32Value());
983   }
984   script = v8_compile("obj_instance.m");
985   for (int i = 0; i < 30; i++) {
986     CHECK_EQ(239, script->Run()->Int32Value());
987   }
988 }
989
990
991 THREADED_PROFILED_TEST(FunctionTemplate) {
992   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
993   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
994 }
995
996
997 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
998   ApiTestFuzzer::Fuzz();
999   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
1000   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1001 }
1002
1003
1004 template<typename Callback>
1005 static void TestSimpleCallback(Callback callback) {
1006   LocalContext env;
1007   v8::Isolate* isolate = env->GetIsolate();
1008   v8::HandleScope scope(isolate);
1009
1010   v8::Handle<v8::ObjectTemplate> object_template =
1011       v8::ObjectTemplate::New(isolate);
1012   object_template->Set(isolate, "callback",
1013                        v8::FunctionTemplate::New(isolate, callback));
1014   v8::Local<v8::Object> object = object_template->NewInstance();
1015   (*env)->Global()->Set(v8_str("callback_object"), object);
1016   v8::Handle<v8::Script> script;
1017   script = v8_compile("callback_object.callback(17)");
1018   for (int i = 0; i < 30; i++) {
1019     CHECK_EQ(51424, script->Run()->Int32Value());
1020   }
1021   script = v8_compile("callback_object.callback(17, 24)");
1022   for (int i = 0; i < 30; i++) {
1023     CHECK_EQ(51425, script->Run()->Int32Value());
1024   }
1025 }
1026
1027
1028 THREADED_PROFILED_TEST(SimpleCallback) {
1029   TestSimpleCallback(SimpleCallback);
1030 }
1031
1032
1033 template<typename T>
1034 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1035
1036 // constant return values
1037 static int32_t fast_return_value_int32 = 471;
1038 static uint32_t fast_return_value_uint32 = 571;
1039 static const double kFastReturnValueDouble = 2.7;
1040 // variable return values
1041 static bool fast_return_value_bool = false;
1042 enum ReturnValueOddball {
1043   kNullReturnValue,
1044   kUndefinedReturnValue,
1045   kEmptyStringReturnValue
1046 };
1047 static ReturnValueOddball fast_return_value_void;
1048 static bool fast_return_value_object_is_empty = false;
1049
1050 // Helper function to avoid compiler error: insufficient contextual information
1051 // to determine type when applying FUNCTION_ADDR to a template function.
1052 static i::Address address_of(v8::FunctionCallback callback) {
1053   return FUNCTION_ADDR(callback);
1054 }
1055
1056 template<>
1057 void FastReturnValueCallback<int32_t>(
1058     const v8::FunctionCallbackInfo<v8::Value>& info) {
1059   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1060   info.GetReturnValue().Set(fast_return_value_int32);
1061 }
1062
1063 template<>
1064 void FastReturnValueCallback<uint32_t>(
1065     const v8::FunctionCallbackInfo<v8::Value>& info) {
1066   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1067   info.GetReturnValue().Set(fast_return_value_uint32);
1068 }
1069
1070 template<>
1071 void FastReturnValueCallback<double>(
1072     const v8::FunctionCallbackInfo<v8::Value>& info) {
1073   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1074   info.GetReturnValue().Set(kFastReturnValueDouble);
1075 }
1076
1077 template<>
1078 void FastReturnValueCallback<bool>(
1079     const v8::FunctionCallbackInfo<v8::Value>& info) {
1080   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1081   info.GetReturnValue().Set(fast_return_value_bool);
1082 }
1083
1084 template<>
1085 void FastReturnValueCallback<void>(
1086     const v8::FunctionCallbackInfo<v8::Value>& info) {
1087   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1088   switch (fast_return_value_void) {
1089     case kNullReturnValue:
1090       info.GetReturnValue().SetNull();
1091       break;
1092     case kUndefinedReturnValue:
1093       info.GetReturnValue().SetUndefined();
1094       break;
1095     case kEmptyStringReturnValue:
1096       info.GetReturnValue().SetEmptyString();
1097       break;
1098   }
1099 }
1100
1101 template<>
1102 void FastReturnValueCallback<Object>(
1103     const v8::FunctionCallbackInfo<v8::Value>& info) {
1104   v8::Handle<v8::Object> object;
1105   if (!fast_return_value_object_is_empty) {
1106     object = Object::New(info.GetIsolate());
1107   }
1108   info.GetReturnValue().Set(object);
1109 }
1110
1111 template<typename T>
1112 Handle<Value> TestFastReturnValues() {
1113   LocalContext env;
1114   v8::Isolate* isolate = env->GetIsolate();
1115   v8::EscapableHandleScope scope(isolate);
1116   v8::Handle<v8::ObjectTemplate> object_template =
1117       v8::ObjectTemplate::New(isolate);
1118   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1119   object_template->Set(isolate, "callback",
1120                        v8::FunctionTemplate::New(isolate, callback));
1121   v8::Local<v8::Object> object = object_template->NewInstance();
1122   (*env)->Global()->Set(v8_str("callback_object"), object);
1123   return scope.Escape(CompileRun("callback_object.callback()"));
1124 }
1125
1126
1127 THREADED_PROFILED_TEST(FastReturnValues) {
1128   LocalContext env;
1129   v8::Isolate* isolate = env->GetIsolate();
1130   v8::HandleScope scope(isolate);
1131   v8::Handle<v8::Value> value;
1132   // check int32_t and uint32_t
1133   int32_t int_values[] = {
1134       0, 234, -723,
1135       i::Smi::kMinValue, i::Smi::kMaxValue
1136   };
1137   for (size_t i = 0; i < arraysize(int_values); i++) {
1138     for (int modifier = -1; modifier <= 1; modifier++) {
1139       int int_value = int_values[i] + modifier;
1140       // check int32_t
1141       fast_return_value_int32 = int_value;
1142       value = TestFastReturnValues<int32_t>();
1143       CHECK(value->IsInt32());
1144       CHECK(fast_return_value_int32 == value->Int32Value());
1145       // check uint32_t
1146       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1147       value = TestFastReturnValues<uint32_t>();
1148       CHECK(value->IsUint32());
1149       CHECK(fast_return_value_uint32 == value->Uint32Value());
1150     }
1151   }
1152   // check double
1153   value = TestFastReturnValues<double>();
1154   CHECK(value->IsNumber());
1155   CHECK_EQ(kFastReturnValueDouble, value->ToNumber(isolate)->Value());
1156   // check bool values
1157   for (int i = 0; i < 2; i++) {
1158     fast_return_value_bool = i == 0;
1159     value = TestFastReturnValues<bool>();
1160     CHECK(value->IsBoolean());
1161     CHECK_EQ(fast_return_value_bool, value->ToBoolean(isolate)->Value());
1162   }
1163   // check oddballs
1164   ReturnValueOddball oddballs[] = {
1165       kNullReturnValue,
1166       kUndefinedReturnValue,
1167       kEmptyStringReturnValue
1168   };
1169   for (size_t i = 0; i < arraysize(oddballs); i++) {
1170     fast_return_value_void = oddballs[i];
1171     value = TestFastReturnValues<void>();
1172     switch (fast_return_value_void) {
1173       case kNullReturnValue:
1174         CHECK(value->IsNull());
1175         break;
1176       case kUndefinedReturnValue:
1177         CHECK(value->IsUndefined());
1178         break;
1179       case kEmptyStringReturnValue:
1180         CHECK(value->IsString());
1181         CHECK_EQ(0, v8::String::Cast(*value)->Length());
1182         break;
1183     }
1184   }
1185   // check handles
1186   fast_return_value_object_is_empty = false;
1187   value = TestFastReturnValues<Object>();
1188   CHECK(value->IsObject());
1189   fast_return_value_object_is_empty = true;
1190   value = TestFastReturnValues<Object>();
1191   CHECK(value->IsUndefined());
1192 }
1193
1194
1195 THREADED_TEST(FunctionTemplateSetLength) {
1196   LocalContext env;
1197   v8::Isolate* isolate = env->GetIsolate();
1198   v8::HandleScope scope(isolate);
1199   {
1200     Local<v8::FunctionTemplate> fun_templ =
1201         v8::FunctionTemplate::New(isolate,
1202                                   handle_callback,
1203                                   Handle<v8::Value>(),
1204                                   Handle<v8::Signature>(),
1205                                   23);
1206     Local<Function> fun = fun_templ->GetFunction();
1207     env->Global()->Set(v8_str("obj"), fun);
1208     Local<Script> script = v8_compile("obj.length");
1209     CHECK_EQ(23, script->Run()->Int32Value());
1210   }
1211   {
1212     Local<v8::FunctionTemplate> fun_templ =
1213         v8::FunctionTemplate::New(isolate, handle_callback);
1214     fun_templ->SetLength(22);
1215     Local<Function> fun = fun_templ->GetFunction();
1216     env->Global()->Set(v8_str("obj"), fun);
1217     Local<Script> script = v8_compile("obj.length");
1218     CHECK_EQ(22, script->Run()->Int32Value());
1219   }
1220   {
1221     // Without setting length it defaults to 0.
1222     Local<v8::FunctionTemplate> fun_templ =
1223         v8::FunctionTemplate::New(isolate, handle_callback);
1224     Local<Function> fun = fun_templ->GetFunction();
1225     env->Global()->Set(v8_str("obj"), fun);
1226     Local<Script> script = v8_compile("obj.length");
1227     CHECK_EQ(0, script->Run()->Int32Value());
1228   }
1229 }
1230
1231
1232 static void* expected_ptr;
1233 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1234   void* ptr = v8::External::Cast(*args.Data())->Value();
1235   CHECK_EQ(expected_ptr, ptr);
1236   args.GetReturnValue().Set(true);
1237 }
1238
1239
1240 static void TestExternalPointerWrapping() {
1241   LocalContext env;
1242   v8::Isolate* isolate = env->GetIsolate();
1243   v8::HandleScope scope(isolate);
1244
1245   v8::Handle<v8::Value> data =
1246       v8::External::New(isolate, expected_ptr);
1247
1248   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
1249   obj->Set(v8_str("func"),
1250            v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
1251   env->Global()->Set(v8_str("obj"), obj);
1252
1253   CHECK(CompileRun(
1254         "function foo() {\n"
1255         "  for (var i = 0; i < 13; i++) obj.func();\n"
1256         "}\n"
1257         "foo(), true")->BooleanValue());
1258 }
1259
1260
1261 THREADED_TEST(ExternalWrap) {
1262   // Check heap allocated object.
1263   int* ptr = new int;
1264   expected_ptr = ptr;
1265   TestExternalPointerWrapping();
1266   delete ptr;
1267
1268   // Check stack allocated object.
1269   int foo;
1270   expected_ptr = &foo;
1271   TestExternalPointerWrapping();
1272
1273   // Check not aligned addresses.
1274   const int n = 100;
1275   char* s = new char[n];
1276   for (int i = 0; i < n; i++) {
1277     expected_ptr = s + i;
1278     TestExternalPointerWrapping();
1279   }
1280
1281   delete[] s;
1282
1283   // Check several invalid addresses.
1284   expected_ptr = reinterpret_cast<void*>(1);
1285   TestExternalPointerWrapping();
1286
1287   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1288   TestExternalPointerWrapping();
1289
1290   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1291   TestExternalPointerWrapping();
1292
1293 #if defined(V8_HOST_ARCH_X64)
1294   // Check a value with a leading 1 bit in x64 Smi encoding.
1295   expected_ptr = reinterpret_cast<void*>(0x400000000);
1296   TestExternalPointerWrapping();
1297
1298   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1299   TestExternalPointerWrapping();
1300
1301   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1302   TestExternalPointerWrapping();
1303 #endif
1304 }
1305
1306
1307 THREADED_TEST(FindInstanceInPrototypeChain) {
1308   LocalContext env;
1309   v8::Isolate* isolate = env->GetIsolate();
1310   v8::HandleScope scope(isolate);
1311
1312   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1313   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1314   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
1315   derived->Inherit(base);
1316
1317   Local<v8::Function> base_function = base->GetFunction();
1318   Local<v8::Function> derived_function = derived->GetFunction();
1319   Local<v8::Function> other_function = other->GetFunction();
1320
1321   Local<v8::Object> base_instance = base_function->NewInstance();
1322   Local<v8::Object> derived_instance = derived_function->NewInstance();
1323   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1324   Local<v8::Object> other_instance = other_function->NewInstance();
1325   derived_instance2->Set(v8_str("__proto__"), derived_instance);
1326   other_instance->Set(v8_str("__proto__"), derived_instance2);
1327
1328   // base_instance is only an instance of base.
1329   CHECK(
1330       base_instance->Equals(base_instance->FindInstanceInPrototypeChain(base)));
1331   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1332   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1333
1334   // derived_instance is an instance of base and derived.
1335   CHECK(derived_instance->Equals(
1336       derived_instance->FindInstanceInPrototypeChain(base)));
1337   CHECK(derived_instance->Equals(
1338       derived_instance->FindInstanceInPrototypeChain(derived)));
1339   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1340
1341   // other_instance is an instance of other and its immediate
1342   // prototype derived_instance2 is an instance of base and derived.
1343   // Note, derived_instance is an instance of base and derived too,
1344   // but it comes after derived_instance2 in the prototype chain of
1345   // other_instance.
1346   CHECK(derived_instance2->Equals(
1347       other_instance->FindInstanceInPrototypeChain(base)));
1348   CHECK(derived_instance2->Equals(
1349       other_instance->FindInstanceInPrototypeChain(derived)));
1350   CHECK(other_instance->Equals(
1351       other_instance->FindInstanceInPrototypeChain(other)));
1352 }
1353
1354
1355 THREADED_TEST(TinyInteger) {
1356   LocalContext env;
1357   v8::Isolate* isolate = env->GetIsolate();
1358   v8::HandleScope scope(isolate);
1359
1360   int32_t value = 239;
1361   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1362   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1363
1364   value_obj = v8::Integer::New(isolate, value);
1365   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1366 }
1367
1368
1369 THREADED_TEST(BigSmiInteger) {
1370   LocalContext env;
1371   v8::HandleScope scope(env->GetIsolate());
1372   v8::Isolate* isolate = CcTest::isolate();
1373
1374   int32_t value = i::Smi::kMaxValue;
1375   // We cannot add one to a Smi::kMaxValue without wrapping.
1376   if (i::SmiValuesAre31Bits()) {
1377     CHECK(i::Smi::IsValid(value));
1378     CHECK(!i::Smi::IsValid(value + 1));
1379
1380     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1381     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1382
1383     value_obj = v8::Integer::New(isolate, value);
1384     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1385   }
1386 }
1387
1388
1389 THREADED_TEST(BigInteger) {
1390   LocalContext env;
1391   v8::HandleScope scope(env->GetIsolate());
1392   v8::Isolate* isolate = CcTest::isolate();
1393
1394   // We cannot add one to a Smi::kMaxValue without wrapping.
1395   if (i::SmiValuesAre31Bits()) {
1396     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1397     // The code will not be run in that case, due to the "if" guard.
1398     int32_t value =
1399         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1400     CHECK(value > i::Smi::kMaxValue);
1401     CHECK(!i::Smi::IsValid(value));
1402
1403     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1404     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1405
1406     value_obj = v8::Integer::New(isolate, value);
1407     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1408   }
1409 }
1410
1411
1412 THREADED_TEST(TinyUnsignedInteger) {
1413   LocalContext env;
1414   v8::HandleScope scope(env->GetIsolate());
1415   v8::Isolate* isolate = CcTest::isolate();
1416
1417   uint32_t value = 239;
1418
1419   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1420   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1421
1422   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1423   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1424 }
1425
1426
1427 THREADED_TEST(BigUnsignedSmiInteger) {
1428   LocalContext env;
1429   v8::HandleScope scope(env->GetIsolate());
1430   v8::Isolate* isolate = CcTest::isolate();
1431
1432   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1433   CHECK(i::Smi::IsValid(value));
1434   CHECK(!i::Smi::IsValid(value + 1));
1435
1436   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1437   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1438
1439   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1440   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1441 }
1442
1443
1444 THREADED_TEST(BigUnsignedInteger) {
1445   LocalContext env;
1446   v8::HandleScope scope(env->GetIsolate());
1447   v8::Isolate* isolate = CcTest::isolate();
1448
1449   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1450   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1451   CHECK(!i::Smi::IsValid(value));
1452
1453   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1454   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1455
1456   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1457   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1458 }
1459
1460
1461 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
1462   LocalContext env;
1463   v8::HandleScope scope(env->GetIsolate());
1464   v8::Isolate* isolate = CcTest::isolate();
1465
1466   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1467   uint32_t value = INT32_MAX_AS_UINT + 1;
1468   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
1469
1470   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1471   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1472
1473   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1474   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1475 }
1476
1477
1478 THREADED_TEST(IsNativeError) {
1479   LocalContext env;
1480   v8::HandleScope scope(env->GetIsolate());
1481   v8::Handle<Value> syntax_error = CompileRun(
1482       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1483   CHECK(syntax_error->IsNativeError());
1484   v8::Handle<Value> not_error = CompileRun("{a:42}");
1485   CHECK(!not_error->IsNativeError());
1486   v8::Handle<Value> not_object = CompileRun("42");
1487   CHECK(!not_object->IsNativeError());
1488 }
1489
1490
1491 THREADED_TEST(IsGeneratorFunctionOrObject) {
1492   LocalContext env;
1493   v8::HandleScope scope(env->GetIsolate());
1494
1495   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
1496   v8::Handle<Value> gen = CompileRun("gen");
1497   v8::Handle<Value> genObj = CompileRun("gen()");
1498   v8::Handle<Value> object = CompileRun("{a:42}");
1499   v8::Handle<Value> func = CompileRun("func");
1500
1501   CHECK(gen->IsGeneratorFunction());
1502   CHECK(gen->IsFunction());
1503   CHECK(!gen->IsGeneratorObject());
1504
1505   CHECK(!genObj->IsGeneratorFunction());
1506   CHECK(!genObj->IsFunction());
1507   CHECK(genObj->IsGeneratorObject());
1508
1509   CHECK(!object->IsGeneratorFunction());
1510   CHECK(!object->IsFunction());
1511   CHECK(!object->IsGeneratorObject());
1512
1513   CHECK(!func->IsGeneratorFunction());
1514   CHECK(func->IsFunction());
1515   CHECK(!func->IsGeneratorObject());
1516 }
1517
1518
1519 THREADED_TEST(ArgumentsObject) {
1520   LocalContext env;
1521   v8::HandleScope scope(env->GetIsolate());
1522   v8::Handle<Value> arguments_object =
1523       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
1524   CHECK(arguments_object->IsArgumentsObject());
1525   v8::Handle<Value> array = CompileRun("[1,2,3]");
1526   CHECK(!array->IsArgumentsObject());
1527   v8::Handle<Value> object = CompileRun("{a:42}");
1528   CHECK(!object->IsArgumentsObject());
1529 }
1530
1531
1532 THREADED_TEST(IsMapOrSet) {
1533   LocalContext env;
1534   v8::HandleScope scope(env->GetIsolate());
1535   v8::Handle<Value> map = CompileRun("new Map()");
1536   v8::Handle<Value> set = CompileRun("new Set()");
1537   v8::Handle<Value> weak_map = CompileRun("new WeakMap()");
1538   v8::Handle<Value> weak_set = CompileRun("new WeakSet()");
1539   CHECK(map->IsMap());
1540   CHECK(set->IsSet());
1541   CHECK(weak_map->IsWeakMap());
1542   CHECK(weak_set->IsWeakSet());
1543
1544   CHECK(!map->IsSet());
1545   CHECK(!map->IsWeakMap());
1546   CHECK(!map->IsWeakSet());
1547
1548   CHECK(!set->IsMap());
1549   CHECK(!set->IsWeakMap());
1550   CHECK(!set->IsWeakSet());
1551
1552   CHECK(!weak_map->IsMap());
1553   CHECK(!weak_map->IsSet());
1554   CHECK(!weak_map->IsWeakSet());
1555
1556   CHECK(!weak_set->IsMap());
1557   CHECK(!weak_set->IsSet());
1558   CHECK(!weak_set->IsWeakMap());
1559
1560   v8::Handle<Value> object = CompileRun("{a:42}");
1561   CHECK(!object->IsMap());
1562   CHECK(!object->IsSet());
1563   CHECK(!object->IsWeakMap());
1564   CHECK(!object->IsWeakSet());
1565 }
1566
1567
1568 THREADED_TEST(StringObject) {
1569   LocalContext env;
1570   v8::HandleScope scope(env->GetIsolate());
1571   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1572   CHECK(boxed_string->IsStringObject());
1573   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1574   CHECK(!unboxed_string->IsStringObject());
1575   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1576   CHECK(!boxed_not_string->IsStringObject());
1577   v8::Handle<Value> not_object = CompileRun("0");
1578   CHECK(!not_object->IsStringObject());
1579   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1580   CHECK(!as_boxed.IsEmpty());
1581   Local<v8::String> the_string = as_boxed->ValueOf();
1582   CHECK(!the_string.IsEmpty());
1583   ExpectObject("\"test\"", the_string);
1584   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1585   CHECK(new_boxed_string->IsStringObject());
1586   as_boxed = new_boxed_string.As<v8::StringObject>();
1587   the_string = as_boxed->ValueOf();
1588   CHECK(!the_string.IsEmpty());
1589   ExpectObject("\"test\"", the_string);
1590 }
1591
1592
1593 TEST(StringObjectDelete) {
1594   LocalContext context;
1595   v8::HandleScope scope(context->GetIsolate());
1596   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1597   CHECK(boxed_string->IsStringObject());
1598   v8::Handle<v8::Object> str_obj = boxed_string.As<v8::Object>();
1599   CHECK(!str_obj->Delete(2));
1600   CHECK(!str_obj->Delete(v8_num(2)));
1601 }
1602
1603
1604 THREADED_TEST(NumberObject) {
1605   LocalContext env;
1606   v8::HandleScope scope(env->GetIsolate());
1607   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1608   CHECK(boxed_number->IsNumberObject());
1609   v8::Handle<Value> unboxed_number = CompileRun("42");
1610   CHECK(!unboxed_number->IsNumberObject());
1611   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1612   CHECK(!boxed_not_number->IsNumberObject());
1613   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1614   CHECK(!as_boxed.IsEmpty());
1615   double the_number = as_boxed->ValueOf();
1616   CHECK_EQ(42.0, the_number);
1617   v8::Handle<v8::Value> new_boxed_number =
1618       v8::NumberObject::New(env->GetIsolate(), 43);
1619   CHECK(new_boxed_number->IsNumberObject());
1620   as_boxed = new_boxed_number.As<v8::NumberObject>();
1621   the_number = as_boxed->ValueOf();
1622   CHECK_EQ(43.0, the_number);
1623 }
1624
1625
1626 THREADED_TEST(BooleanObject) {
1627   LocalContext env;
1628   v8::HandleScope scope(env->GetIsolate());
1629   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1630   CHECK(boxed_boolean->IsBooleanObject());
1631   v8::Handle<Value> unboxed_boolean = CompileRun("true");
1632   CHECK(!unboxed_boolean->IsBooleanObject());
1633   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1634   CHECK(!boxed_not_boolean->IsBooleanObject());
1635   v8::Handle<v8::BooleanObject> as_boxed =
1636       boxed_boolean.As<v8::BooleanObject>();
1637   CHECK(!as_boxed.IsEmpty());
1638   bool the_boolean = as_boxed->ValueOf();
1639   CHECK_EQ(true, the_boolean);
1640   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1641   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1642   CHECK(boxed_true->IsBooleanObject());
1643   CHECK(boxed_false->IsBooleanObject());
1644   as_boxed = boxed_true.As<v8::BooleanObject>();
1645   CHECK_EQ(true, as_boxed->ValueOf());
1646   as_boxed = boxed_false.As<v8::BooleanObject>();
1647   CHECK_EQ(false, as_boxed->ValueOf());
1648 }
1649
1650
1651 THREADED_TEST(PrimitiveAndWrappedBooleans) {
1652   LocalContext env;
1653   v8::HandleScope scope(env->GetIsolate());
1654
1655   Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1656   CHECK(primitive_false->IsBoolean());
1657   CHECK(!primitive_false->IsBooleanObject());
1658   CHECK(!primitive_false->BooleanValue());
1659   CHECK(!primitive_false->IsTrue());
1660   CHECK(primitive_false->IsFalse());
1661
1662   Local<Value> false_value = BooleanObject::New(false);
1663   CHECK(!false_value->IsBoolean());
1664   CHECK(false_value->IsBooleanObject());
1665   CHECK(false_value->BooleanValue());
1666   CHECK(!false_value->IsTrue());
1667   CHECK(!false_value->IsFalse());
1668
1669   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1670   CHECK(!false_boolean_object->IsBoolean());
1671   CHECK(false_boolean_object->IsBooleanObject());
1672   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1673   // CHECK(false_boolean_object->BooleanValue());
1674   CHECK(!false_boolean_object->ValueOf());
1675   CHECK(!false_boolean_object->IsTrue());
1676   CHECK(!false_boolean_object->IsFalse());
1677
1678   Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1679   CHECK(primitive_true->IsBoolean());
1680   CHECK(!primitive_true->IsBooleanObject());
1681   CHECK(primitive_true->BooleanValue());
1682   CHECK(primitive_true->IsTrue());
1683   CHECK(!primitive_true->IsFalse());
1684
1685   Local<Value> true_value = BooleanObject::New(true);
1686   CHECK(!true_value->IsBoolean());
1687   CHECK(true_value->IsBooleanObject());
1688   CHECK(true_value->BooleanValue());
1689   CHECK(!true_value->IsTrue());
1690   CHECK(!true_value->IsFalse());
1691
1692   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1693   CHECK(!true_boolean_object->IsBoolean());
1694   CHECK(true_boolean_object->IsBooleanObject());
1695   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1696   // CHECK(true_boolean_object->BooleanValue());
1697   CHECK(true_boolean_object->ValueOf());
1698   CHECK(!true_boolean_object->IsTrue());
1699   CHECK(!true_boolean_object->IsFalse());
1700 }
1701
1702
1703 THREADED_TEST(Number) {
1704   LocalContext env;
1705   v8::HandleScope scope(env->GetIsolate());
1706   double PI = 3.1415926;
1707   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
1708   CHECK_EQ(PI, pi_obj->NumberValue());
1709 }
1710
1711
1712 THREADED_TEST(ToNumber) {
1713   LocalContext env;
1714   v8::Isolate* isolate = CcTest::isolate();
1715   v8::HandleScope scope(isolate);
1716   Local<String> str = v8_str("3.1415926");
1717   CHECK_EQ(3.1415926, str->NumberValue());
1718   v8::Handle<v8::Boolean> t = v8::True(isolate);
1719   CHECK_EQ(1.0, t->NumberValue());
1720   v8::Handle<v8::Boolean> f = v8::False(isolate);
1721   CHECK_EQ(0.0, f->NumberValue());
1722 }
1723
1724
1725 THREADED_TEST(Date) {
1726   LocalContext env;
1727   v8::HandleScope scope(env->GetIsolate());
1728   double PI = 3.1415926;
1729   Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
1730   CHECK_EQ(3.0, date->NumberValue());
1731   date.As<v8::Date>()->Set(v8_str("property"),
1732                            v8::Integer::New(env->GetIsolate(), 42));
1733   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
1734 }
1735
1736
1737 THREADED_TEST(Boolean) {
1738   LocalContext env;
1739   v8::Isolate* isolate = env->GetIsolate();
1740   v8::HandleScope scope(isolate);
1741   v8::Handle<v8::Boolean> t = v8::True(isolate);
1742   CHECK(t->Value());
1743   v8::Handle<v8::Boolean> f = v8::False(isolate);
1744   CHECK(!f->Value());
1745   v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
1746   CHECK(!u->BooleanValue());
1747   v8::Handle<v8::Primitive> n = v8::Null(isolate);
1748   CHECK(!n->BooleanValue());
1749   v8::Handle<String> str1 = v8_str("");
1750   CHECK(!str1->BooleanValue());
1751   v8::Handle<String> str2 = v8_str("x");
1752   CHECK(str2->BooleanValue());
1753   CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1754   CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1755   CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1756   CHECK(v8::Number::New(isolate, 42)->BooleanValue());
1757   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1758 }
1759
1760
1761 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
1762   ApiTestFuzzer::Fuzz();
1763   args.GetReturnValue().Set(v8_num(13.4));
1764 }
1765
1766
1767 static void GetM(Local<String> name,
1768                  const v8::PropertyCallbackInfo<v8::Value>& info) {
1769   ApiTestFuzzer::Fuzz();
1770   info.GetReturnValue().Set(v8_num(876));
1771 }
1772
1773
1774 THREADED_TEST(GlobalPrototype) {
1775   v8::Isolate* isolate = CcTest::isolate();
1776   v8::HandleScope scope(isolate);
1777   v8::Handle<v8::FunctionTemplate> func_templ =
1778       v8::FunctionTemplate::New(isolate);
1779   func_templ->PrototypeTemplate()->Set(
1780       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
1781   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1782   templ->Set(isolate, "x", v8_num(200));
1783   templ->SetAccessor(v8_str("m"), GetM);
1784   LocalContext env(0, templ);
1785   v8::Handle<Script> script(v8_compile("dummy()"));
1786   v8::Handle<Value> result(script->Run());
1787   CHECK_EQ(13.4, result->NumberValue());
1788   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1789   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1790 }
1791
1792
1793 THREADED_TEST(ObjectTemplate) {
1794   v8::Isolate* isolate = CcTest::isolate();
1795   v8::HandleScope scope(isolate);
1796   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1797   v8::Local<v8::String> class_name =
1798       v8::String::NewFromUtf8(isolate, "the_class_name");
1799   fun->SetClassName(class_name);
1800   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
1801   templ1->Set(isolate, "x", v8_num(10));
1802   templ1->Set(isolate, "y", v8_num(13));
1803   LocalContext env;
1804   Local<v8::Object> instance1 = templ1->NewInstance();
1805   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
1806   env->Global()->Set(v8_str("p"), instance1);
1807   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1808   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1809   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
1810   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1811   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
1812   templ2->Set(isolate, "a", v8_num(12));
1813   templ2->Set(isolate, "b", templ1);
1814   Local<v8::Object> instance2 = templ2->NewInstance();
1815   env->Global()->Set(v8_str("q"), instance2);
1816   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1817   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1818   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1819   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1820 }
1821
1822
1823 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
1824   ApiTestFuzzer::Fuzz();
1825   args.GetReturnValue().Set(v8_num(17.2));
1826 }
1827
1828
1829 static void GetKnurd(Local<String> property,
1830                      const v8::PropertyCallbackInfo<v8::Value>& info) {
1831   ApiTestFuzzer::Fuzz();
1832   info.GetReturnValue().Set(v8_num(15.2));
1833 }
1834
1835
1836 THREADED_TEST(DescriptorInheritance) {
1837   v8::Isolate* isolate = CcTest::isolate();
1838   v8::HandleScope scope(isolate);
1839   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1840   super->PrototypeTemplate()->Set(isolate, "flabby",
1841                                   v8::FunctionTemplate::New(isolate,
1842                                                             GetFlabby));
1843   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
1844
1845   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1846
1847   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
1848   base1->Inherit(super);
1849   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
1850
1851   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
1852   base2->Inherit(super);
1853   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
1854
1855   LocalContext env;
1856
1857   env->Global()->Set(v8_str("s"), super->GetFunction());
1858   env->Global()->Set(v8_str("base1"), base1->GetFunction());
1859   env->Global()->Set(v8_str("base2"), base2->GetFunction());
1860
1861   // Checks right __proto__ chain.
1862   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1863   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1864
1865   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1866
1867   // Instance accessor should not be visible on function object or its prototype
1868   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1869   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1870   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1871
1872   env->Global()->Set(v8_str("obj"),
1873                      base1->GetFunction()->NewInstance());
1874   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1875   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1876   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1877   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1878   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1879
1880   env->Global()->Set(v8_str("obj2"),
1881                      base2->GetFunction()->NewInstance());
1882   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1883   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1884   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1885   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1886   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1887
1888   // base1 and base2 cannot cross reference to each's prototype
1889   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1890   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1891 }
1892
1893
1894 // Helper functions for Interceptor/Accessor interaction tests
1895
1896 void SimpleAccessorGetter(Local<String> name,
1897                           const v8::PropertyCallbackInfo<v8::Value>& info) {
1898   Handle<Object> self = Handle<Object>::Cast(info.This());
1899   info.GetReturnValue().Set(
1900       self->Get(String::Concat(v8_str("accessor_"), name)));
1901 }
1902
1903 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1904                           const v8::PropertyCallbackInfo<void>& info) {
1905   Handle<Object> self = Handle<Object>::Cast(info.This());
1906   self->Set(String::Concat(v8_str("accessor_"), name), value);
1907 }
1908
1909 void SymbolAccessorGetter(Local<Name> name,
1910                           const v8::PropertyCallbackInfo<v8::Value>& info) {
1911   CHECK(name->IsSymbol());
1912   Local<Symbol> sym = Local<Symbol>::Cast(name);
1913   if (sym->Name()->IsUndefined())
1914     return;
1915   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
1916 }
1917
1918 void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
1919                           const v8::PropertyCallbackInfo<void>& info) {
1920   CHECK(name->IsSymbol());
1921   Local<Symbol> sym = Local<Symbol>::Cast(name);
1922   if (sym->Name()->IsUndefined())
1923     return;
1924   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
1925 }
1926
1927 void SymbolAccessorGetterReturnsDefault(
1928     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1929   CHECK(name->IsSymbol());
1930   Local<Symbol> sym = Local<Symbol>::Cast(name);
1931   if (sym->Name()->IsUndefined()) return;
1932   info.GetReturnValue().Set(info.Data());
1933 }
1934
1935 static void ThrowingSymbolAccessorGetter(
1936     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1937   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
1938 }
1939
1940
1941 THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
1942   v8::Isolate* isolate = CcTest::isolate();
1943   v8::HandleScope scope(isolate);
1944   LocalContext env;
1945   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
1946   i::Handle<i::JSObject> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
1947   CHECK(a->map()->instance_descriptors()->IsFixedArray());
1948   CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
1949   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
1950   CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
1951   // But we should still have an ExecutableAccessorInfo.
1952   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
1953   i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
1954   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
1955   CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
1956 }
1957
1958
1959 THREADED_TEST(UndefinedIsNotEnumerable) {
1960   LocalContext env;
1961   v8::HandleScope scope(env->GetIsolate());
1962   v8::Handle<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
1963   CHECK(result->IsFalse());
1964 }
1965
1966
1967 v8::Handle<Script> call_recursively_script;
1968 static const int kTargetRecursionDepth = 200;  // near maximum
1969
1970
1971 static void CallScriptRecursivelyCall(
1972     const v8::FunctionCallbackInfo<v8::Value>& args) {
1973   ApiTestFuzzer::Fuzz();
1974   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1975   if (depth == kTargetRecursionDepth) return;
1976   args.This()->Set(v8_str("depth"),
1977                    v8::Integer::New(args.GetIsolate(), depth + 1));
1978   args.GetReturnValue().Set(call_recursively_script->Run());
1979 }
1980
1981
1982 static void CallFunctionRecursivelyCall(
1983     const v8::FunctionCallbackInfo<v8::Value>& args) {
1984   ApiTestFuzzer::Fuzz();
1985   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1986   if (depth == kTargetRecursionDepth) {
1987     printf("[depth = %d]\n", depth);
1988     return;
1989   }
1990   args.This()->Set(v8_str("depth"),
1991                    v8::Integer::New(args.GetIsolate(), depth + 1));
1992   v8::Handle<Value> function =
1993       args.This()->Get(v8_str("callFunctionRecursively"));
1994   args.GetReturnValue().Set(
1995       function.As<Function>()->Call(args.This(), 0, NULL));
1996 }
1997
1998
1999 THREADED_TEST(DeepCrossLanguageRecursion) {
2000   v8::Isolate* isolate = CcTest::isolate();
2001   v8::HandleScope scope(isolate);
2002   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
2003   global->Set(v8_str("callScriptRecursively"),
2004               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
2005   global->Set(v8_str("callFunctionRecursively"),
2006               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
2007   LocalContext env(NULL, global);
2008
2009   env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
2010   call_recursively_script = v8_compile("callScriptRecursively()");
2011   call_recursively_script->Run();
2012   call_recursively_script = v8::Handle<Script>();
2013
2014   env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
2015   CompileRun("callFunctionRecursively()");
2016 }
2017
2018
2019 static void ThrowingPropertyHandlerGet(
2020     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
2021   // Since this interceptor is used on "with" objects, the runtime will look up
2022   // @@unscopables.  Punt.
2023   if (key->IsSymbol()) return;
2024   ApiTestFuzzer::Fuzz();
2025   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
2026 }
2027
2028
2029 static void ThrowingPropertyHandlerSet(
2030     Local<Name> key, Local<Value>,
2031     const v8::PropertyCallbackInfo<v8::Value>& info) {
2032   info.GetIsolate()->ThrowException(key);
2033   info.GetReturnValue().SetUndefined();  // not the same as empty handle
2034 }
2035
2036
2037 THREADED_TEST(CallbackExceptionRegression) {
2038   v8::Isolate* isolate = CcTest::isolate();
2039   v8::HandleScope scope(isolate);
2040   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
2041   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
2042       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
2043   LocalContext env;
2044   env->Global()->Set(v8_str("obj"), obj->NewInstance());
2045   v8::Handle<Value> otto =
2046       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
2047   CHECK(v8_str("otto")->Equals(otto));
2048   v8::Handle<Value> netto =
2049       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
2050   CHECK(v8_str("netto")->Equals(netto));
2051 }
2052
2053
2054 THREADED_TEST(FunctionPrototype) {
2055   v8::Isolate* isolate = CcTest::isolate();
2056   v8::HandleScope scope(isolate);
2057   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
2058   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2059   LocalContext env;
2060   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2061   Local<Script> script = v8_compile("Foo.prototype.plak");
2062   CHECK_EQ(script->Run()->Int32Value(), 321);
2063 }
2064
2065
2066 THREADED_TEST(InternalFields) {
2067   LocalContext env;
2068   v8::Isolate* isolate = env->GetIsolate();
2069   v8::HandleScope scope(isolate);
2070
2071   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2072   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2073   instance_templ->SetInternalFieldCount(1);
2074   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2075   CHECK_EQ(1, obj->InternalFieldCount());
2076   CHECK(obj->GetInternalField(0)->IsUndefined());
2077   obj->SetInternalField(0, v8_num(17));
2078   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2079 }
2080
2081
2082 THREADED_TEST(GlobalObjectInternalFields) {
2083   v8::Isolate* isolate = CcTest::isolate();
2084   v8::HandleScope scope(isolate);
2085   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
2086   global_template->SetInternalFieldCount(1);
2087   LocalContext env(NULL, global_template);
2088   v8::Handle<v8::Object> global_proxy = env->Global();
2089   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2090   CHECK_EQ(1, global->InternalFieldCount());
2091   CHECK(global->GetInternalField(0)->IsUndefined());
2092   global->SetInternalField(0, v8_num(17));
2093   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2094 }
2095
2096
2097 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2098   LocalContext env;
2099   v8::HandleScope scope(CcTest::isolate());
2100
2101   v8::Local<v8::Object> global = env->Global();
2102   global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
2103   CHECK(global->HasRealIndexedProperty(0));
2104 }
2105
2106
2107 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2108                                                void* value) {
2109   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2110   obj->SetAlignedPointerInInternalField(0, value);
2111   CcTest::heap()->CollectAllGarbage();
2112   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2113 }
2114
2115
2116 THREADED_TEST(InternalFieldsAlignedPointers) {
2117   LocalContext env;
2118   v8::Isolate* isolate = env->GetIsolate();
2119   v8::HandleScope scope(isolate);
2120
2121   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2122   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2123   instance_templ->SetInternalFieldCount(1);
2124   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2125   CHECK_EQ(1, obj->InternalFieldCount());
2126
2127   CheckAlignedPointerInInternalField(obj, NULL);
2128
2129   int* heap_allocated = new int[100];
2130   CheckAlignedPointerInInternalField(obj, heap_allocated);
2131   delete[] heap_allocated;
2132
2133   int stack_allocated[100];
2134   CheckAlignedPointerInInternalField(obj, stack_allocated);
2135
2136   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2137   CheckAlignedPointerInInternalField(obj, huge);
2138
2139   v8::Global<v8::Object> persistent(isolate, obj);
2140   CHECK_EQ(1, Object::InternalFieldCount(persistent));
2141   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2142 }
2143
2144
2145 static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
2146                                               void* value) {
2147   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2148   (*env)->SetAlignedPointerInEmbedderData(index, value);
2149   CcTest::heap()->CollectAllGarbage();
2150   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2151 }
2152
2153
2154 static void* AlignedTestPointer(int i) {
2155   return reinterpret_cast<void*>(i * 1234);
2156 }
2157
2158
2159 THREADED_TEST(EmbedderDataAlignedPointers) {
2160   LocalContext env;
2161   v8::HandleScope scope(env->GetIsolate());
2162
2163   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2164
2165   int* heap_allocated = new int[100];
2166   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2167   delete[] heap_allocated;
2168
2169   int stack_allocated[100];
2170   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2171
2172   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2173   CheckAlignedPointerInEmbedderData(&env, 3, huge);
2174
2175   // Test growing of the embedder data's backing store.
2176   for (int i = 0; i < 100; i++) {
2177     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2178   }
2179   CcTest::heap()->CollectAllGarbage();
2180   for (int i = 0; i < 100; i++) {
2181     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2182   }
2183 }
2184
2185
2186 static void CheckEmbedderData(LocalContext* env, int index,
2187                               v8::Handle<Value> data) {
2188   (*env)->SetEmbedderData(index, data);
2189   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2190 }
2191
2192
2193 THREADED_TEST(EmbedderData) {
2194   LocalContext env;
2195   v8::Isolate* isolate = env->GetIsolate();
2196   v8::HandleScope scope(isolate);
2197
2198   CheckEmbedderData(
2199       &env, 3, v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2200   CheckEmbedderData(&env, 2,
2201                     v8::String::NewFromUtf8(isolate, "over the lazy dog."));
2202   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2203   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
2204 }
2205
2206
2207 THREADED_TEST(GetIsolate) {
2208   LocalContext env;
2209   v8::Isolate* isolate = env->GetIsolate();
2210   v8::HandleScope scope(isolate);
2211   Local<v8::Object> obj = v8::Object::New(isolate);
2212   CHECK_EQ(isolate, obj->GetIsolate());
2213   CHECK_EQ(isolate, CcTest::global()->GetIsolate());
2214 }
2215
2216
2217 THREADED_TEST(IdentityHash) {
2218   LocalContext env;
2219   v8::Isolate* isolate = env->GetIsolate();
2220   v8::HandleScope scope(isolate);
2221
2222   // Ensure that the test starts with an fresh heap to test whether the hash
2223   // code is based on the address.
2224   CcTest::heap()->CollectAllGarbage();
2225   Local<v8::Object> obj = v8::Object::New(isolate);
2226   int hash = obj->GetIdentityHash();
2227   int hash1 = obj->GetIdentityHash();
2228   CHECK_EQ(hash, hash1);
2229   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
2230   // Since the identity hash is essentially a random number two consecutive
2231   // objects should not be assigned the same hash code. If the test below fails
2232   // the random number generator should be evaluated.
2233   CHECK_NE(hash, hash2);
2234   CcTest::heap()->CollectAllGarbage();
2235   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
2236   // Make sure that the identity hash is not based on the initial address of
2237   // the object alone. If the test below fails the random number generator
2238   // should be evaluated.
2239   CHECK_NE(hash, hash3);
2240   int hash4 = obj->GetIdentityHash();
2241   CHECK_EQ(hash, hash4);
2242
2243   // Check identity hashes behaviour in the presence of JS accessors.
2244   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2245   {
2246     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2247     Local<v8::Object> o1 = v8::Object::New(isolate);
2248     Local<v8::Object> o2 = v8::Object::New(isolate);
2249     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2250   }
2251   {
2252     CompileRun(
2253         "function cnst() { return 42; };\n"
2254         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2255     Local<v8::Object> o1 = v8::Object::New(isolate);
2256     Local<v8::Object> o2 = v8::Object::New(isolate);
2257     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2258   }
2259 }
2260
2261
2262 void GlobalProxyIdentityHash(bool set_in_js) {
2263   LocalContext env;
2264   v8::Isolate* isolate = env->GetIsolate();
2265   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2266   v8::HandleScope scope(isolate);
2267   Handle<Object> global_proxy = env->Global();
2268   i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
2269   env->Global()->Set(v8_str("global"), global_proxy);
2270   i::Handle<i::Object> original_hash;
2271   if (set_in_js) {
2272     CompileRun("var m = new Set(); m.add(global);");
2273     original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
2274   } else {
2275     original_hash = i::Handle<i::Object>(
2276         i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
2277   }
2278   CHECK(original_hash->IsSmi());
2279   int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
2280   // Hash should be retained after being detached.
2281   env->DetachGlobal();
2282   int hash2 = global_proxy->GetIdentityHash();
2283   CHECK_EQ(hash1, hash2);
2284   {
2285     // Re-attach global proxy to a new context, hash should stay the same.
2286     LocalContext env2(NULL, Handle<ObjectTemplate>(), global_proxy);
2287     int hash3 = global_proxy->GetIdentityHash();
2288     CHECK_EQ(hash1, hash3);
2289   }
2290 }
2291
2292
2293 THREADED_TEST(GlobalProxyIdentityHash) {
2294   GlobalProxyIdentityHash(true);
2295   GlobalProxyIdentityHash(false);
2296 }
2297
2298
2299 TEST(SymbolIdentityHash) {
2300   LocalContext env;
2301   v8::Isolate* isolate = env->GetIsolate();
2302   v8::HandleScope scope(isolate);
2303
2304   {
2305     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
2306     int hash = symbol->GetIdentityHash();
2307     int hash1 = symbol->GetIdentityHash();
2308     CHECK_EQ(hash, hash1);
2309     CcTest::heap()->CollectAllGarbage();
2310     int hash3 = symbol->GetIdentityHash();
2311     CHECK_EQ(hash, hash3);
2312   }
2313
2314   {
2315     v8::Handle<v8::Symbol> js_symbol =
2316         CompileRun("Symbol('foo')").As<v8::Symbol>();
2317     int hash = js_symbol->GetIdentityHash();
2318     int hash1 = js_symbol->GetIdentityHash();
2319     CHECK_EQ(hash, hash1);
2320     CcTest::heap()->CollectAllGarbage();
2321     int hash3 = js_symbol->GetIdentityHash();
2322     CHECK_EQ(hash, hash3);
2323   }
2324 }
2325
2326
2327 TEST(StringIdentityHash) {
2328   LocalContext env;
2329   v8::Isolate* isolate = env->GetIsolate();
2330   v8::HandleScope scope(isolate);
2331
2332   Local<v8::String> str = v8::String::NewFromUtf8(isolate, "str1");
2333   int hash = str->GetIdentityHash();
2334   int hash1 = str->GetIdentityHash();
2335   CHECK_EQ(hash, hash1);
2336   CcTest::heap()->CollectAllGarbage();
2337   int hash3 = str->GetIdentityHash();
2338   CHECK_EQ(hash, hash3);
2339
2340   Local<v8::String> str2 = v8::String::NewFromUtf8(isolate, "str1");
2341   int hash4 = str2->GetIdentityHash();
2342   CHECK_EQ(hash, hash4);
2343 }
2344
2345
2346 THREADED_TEST(SymbolProperties) {
2347   LocalContext env;
2348   v8::Isolate* isolate = env->GetIsolate();
2349   v8::HandleScope scope(isolate);
2350
2351   v8::Local<v8::Object> obj = v8::Object::New(isolate);
2352   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2353   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
2354   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
2355
2356   CcTest::heap()->CollectAllGarbage();
2357
2358   // Check basic symbol functionality.
2359   CHECK(sym1->IsSymbol());
2360   CHECK(sym2->IsSymbol());
2361   CHECK(!obj->IsSymbol());
2362
2363   CHECK(sym1->Equals(sym1));
2364   CHECK(sym2->Equals(sym2));
2365   CHECK(!sym1->Equals(sym2));
2366   CHECK(!sym2->Equals(sym1));
2367   CHECK(sym1->StrictEquals(sym1));
2368   CHECK(sym2->StrictEquals(sym2));
2369   CHECK(!sym1->StrictEquals(sym2));
2370   CHECK(!sym2->StrictEquals(sym1));
2371
2372   CHECK(sym2->Name()->Equals(v8_str("my-symbol")));
2373
2374   v8::Local<v8::Value> sym_val = sym2;
2375   CHECK(sym_val->IsSymbol());
2376   CHECK(sym_val->Equals(sym2));
2377   CHECK(sym_val->StrictEquals(sym2));
2378   CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2379
2380   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2381   CHECK(sym_obj->IsSymbolObject());
2382   CHECK(!sym2->IsSymbolObject());
2383   CHECK(!obj->IsSymbolObject());
2384   CHECK(!sym_obj->Equals(sym2));
2385   CHECK(!sym_obj->StrictEquals(sym2));
2386   CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
2387   CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
2388
2389   // Make sure delete of a non-existent symbol property works.
2390   CHECK(obj->Delete(sym1));
2391   CHECK(!obj->Has(sym1));
2392
2393   CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
2394   CHECK(obj->Has(sym1));
2395   CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2396   CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
2397   CHECK(obj->Has(sym1));
2398   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2399   CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2400
2401   CHECK_EQ(0u, obj->GetOwnPropertyNames()->Length());
2402   unsigned num_props = obj->GetPropertyNames()->Length();
2403   CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2404                  v8::Integer::New(isolate, 20)));
2405   CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
2406   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2407
2408   CcTest::heap()->CollectAllGarbage();
2409
2410   CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
2411   CHECK(obj->Get(sym3)->IsUndefined());
2412   CHECK(obj->Set(sym3, v8::Integer::New(isolate, 42)));
2413   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2414   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2415             ->Equals(v8::Integer::New(isolate, 42)));
2416
2417   // Add another property and delete it afterwards to force the object in
2418   // slow case.
2419   CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
2420   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2421   CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2422   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2423   CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
2424
2425   CHECK(obj->Has(sym1));
2426   CHECK(obj->Has(sym2));
2427   CHECK(obj->Has(sym3));
2428   CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2429   CHECK(obj->Delete(sym2));
2430   CHECK(obj->Has(sym1));
2431   CHECK(!obj->Has(sym2));
2432   CHECK(obj->Has(sym3));
2433   CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2434   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2435   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2436   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2437             ->Equals(v8::Integer::New(isolate, 42)));
2438   CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
2439
2440   // Symbol properties are inherited.
2441   v8::Local<v8::Object> child = v8::Object::New(isolate);
2442   child->SetPrototype(obj);
2443   CHECK(child->Has(sym1));
2444   CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2445   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2446   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2447             ->Equals(v8::Integer::New(isolate, 42)));
2448   CHECK_EQ(0u, child->GetOwnPropertyNames()->Length());
2449 }
2450
2451
2452 THREADED_TEST(SymbolTemplateProperties) {
2453   LocalContext env;
2454   v8::Isolate* isolate = env->GetIsolate();
2455   v8::HandleScope scope(isolate);
2456   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
2457   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
2458   CHECK(!name.IsEmpty());
2459   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
2460   v8::Local<v8::Object> new_instance = foo->InstanceTemplate()->NewInstance();
2461   CHECK(!new_instance.IsEmpty());
2462   CHECK(new_instance->Has(name));
2463 }
2464
2465
2466 THREADED_TEST(GlobalSymbols) {
2467   LocalContext env;
2468   v8::Isolate* isolate = env->GetIsolate();
2469   v8::HandleScope scope(isolate);
2470
2471   v8::Local<String> name = v8_str("my-symbol");
2472   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
2473   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
2474   CHECK(glob2->SameValue(glob));
2475
2476   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
2477   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
2478   CHECK(glob_api2->SameValue(glob_api));
2479   CHECK(!glob_api->SameValue(glob));
2480
2481   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
2482   CHECK(!sym->SameValue(glob));
2483
2484   CompileRun("var sym2 = Symbol.for('my-symbol')");
2485   v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
2486   CHECK(sym2->SameValue(glob));
2487   CHECK(!sym2->SameValue(glob_api));
2488 }
2489
2490
2491 static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
2492                                  const char* name) {
2493   LocalContext env;
2494   v8::Isolate* isolate = env->GetIsolate();
2495   v8::HandleScope scope(isolate);
2496
2497   v8::Local<v8::Symbol> symbol = getter(isolate);
2498   std::string script = std::string("var sym = ") + name;
2499   CompileRun(script.c_str());
2500   v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
2501
2502   CHECK(!value.IsEmpty());
2503   CHECK(!symbol.IsEmpty());
2504   CHECK(value->SameValue(symbol));
2505 }
2506
2507
2508 THREADED_TEST(WellKnownSymbols) {
2509   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
2510   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
2511 }
2512
2513
2514 class ScopedArrayBufferContents {
2515  public:
2516   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
2517       : contents_(contents) {}
2518   ~ScopedArrayBufferContents() { free(contents_.Data()); }
2519   void* Data() const { return contents_.Data(); }
2520   size_t ByteLength() const { return contents_.ByteLength(); }
2521
2522  private:
2523   const v8::ArrayBuffer::Contents contents_;
2524 };
2525
2526 template <typename T>
2527 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2528   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2529   for (int i = 0; i < value->InternalFieldCount(); i++) {
2530     CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2531   }
2532 }
2533
2534
2535 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
2536   LocalContext env;
2537   v8::Isolate* isolate = env->GetIsolate();
2538   v8::HandleScope handle_scope(isolate);
2539
2540   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
2541   CheckInternalFieldsAreZero(ab);
2542   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2543   CHECK(!ab->IsExternal());
2544   CcTest::heap()->CollectAllGarbage();
2545
2546   ScopedArrayBufferContents ab_contents(ab->Externalize());
2547   CHECK(ab->IsExternal());
2548
2549   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2550   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2551   DCHECK(data != NULL);
2552   env->Global()->Set(v8_str("ab"), ab);
2553
2554   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2555   CHECK_EQ(1024, result->Int32Value());
2556
2557   result = CompileRun(
2558       "var u8 = new Uint8Array(ab);"
2559       "u8[0] = 0xFF;"
2560       "u8[1] = 0xAA;"
2561       "u8.length");
2562   CHECK_EQ(1024, result->Int32Value());
2563   CHECK_EQ(0xFF, data[0]);
2564   CHECK_EQ(0xAA, data[1]);
2565   data[0] = 0xCC;
2566   data[1] = 0x11;
2567   result = CompileRun("u8[0] + u8[1]");
2568   CHECK_EQ(0xDD, result->Int32Value());
2569 }
2570
2571
2572 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
2573   LocalContext env;
2574   v8::Isolate* isolate = env->GetIsolate();
2575   v8::HandleScope handle_scope(isolate);
2576
2577
2578   v8::Local<v8::Value> result = CompileRun(
2579       "var ab1 = new ArrayBuffer(2);"
2580       "var u8_a = new Uint8Array(ab1);"
2581       "u8_a[0] = 0xAA;"
2582       "u8_a[1] = 0xFF; u8_a.buffer");
2583   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
2584   CheckInternalFieldsAreZero(ab1);
2585   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
2586   CHECK(!ab1->IsExternal());
2587   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
2588   CHECK(ab1->IsExternal());
2589
2590   result = CompileRun("ab1.byteLength");
2591   CHECK_EQ(2, result->Int32Value());
2592   result = CompileRun("u8_a[0]");
2593   CHECK_EQ(0xAA, result->Int32Value());
2594   result = CompileRun("u8_a[1]");
2595   CHECK_EQ(0xFF, result->Int32Value());
2596   result = CompileRun(
2597       "var u8_b = new Uint8Array(ab1);"
2598       "u8_b[0] = 0xBB;"
2599       "u8_a[0]");
2600   CHECK_EQ(0xBB, result->Int32Value());
2601   result = CompileRun("u8_b[1]");
2602   CHECK_EQ(0xFF, result->Int32Value());
2603
2604   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2605   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2606   CHECK_EQ(0xBB, ab1_data[0]);
2607   CHECK_EQ(0xFF, ab1_data[1]);
2608   ab1_data[0] = 0xCC;
2609   ab1_data[1] = 0x11;
2610   result = CompileRun("u8_a[0] + u8_a[1]");
2611   CHECK_EQ(0xDD, result->Int32Value());
2612 }
2613
2614
2615 THREADED_TEST(ArrayBuffer_External) {
2616   LocalContext env;
2617   v8::Isolate* isolate = env->GetIsolate();
2618   v8::HandleScope handle_scope(isolate);
2619
2620   i::ScopedVector<uint8_t> my_data(100);
2621   memset(my_data.start(), 0, 100);
2622   Local<v8::ArrayBuffer> ab3 =
2623       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
2624   CheckInternalFieldsAreZero(ab3);
2625   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
2626   CHECK(ab3->IsExternal());
2627
2628   env->Global()->Set(v8_str("ab3"), ab3);
2629
2630   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2631   CHECK_EQ(100, result->Int32Value());
2632
2633   result = CompileRun(
2634       "var u8_b = new Uint8Array(ab3);"
2635       "u8_b[0] = 0xBB;"
2636       "u8_b[1] = 0xCC;"
2637       "u8_b.length");
2638   CHECK_EQ(100, result->Int32Value());
2639   CHECK_EQ(0xBB, my_data[0]);
2640   CHECK_EQ(0xCC, my_data[1]);
2641   my_data[0] = 0xCC;
2642   my_data[1] = 0x11;
2643   result = CompileRun("u8_b[0] + u8_b[1]");
2644   CHECK_EQ(0xDD, result->Int32Value());
2645 }
2646
2647
2648 THREADED_TEST(ArrayBuffer_DisableNeuter) {
2649   LocalContext env;
2650   v8::Isolate* isolate = env->GetIsolate();
2651   v8::HandleScope handle_scope(isolate);
2652
2653   i::ScopedVector<uint8_t> my_data(100);
2654   memset(my_data.start(), 0, 100);
2655   Local<v8::ArrayBuffer> ab =
2656       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
2657   CHECK(ab->IsNeuterable());
2658
2659   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
2660   buf->set_is_neuterable(false);
2661
2662   CHECK(!ab->IsNeuterable());
2663 }
2664
2665
2666 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
2667   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
2668   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
2669 }
2670
2671
2672 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
2673   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
2674   CHECK_EQ(0, static_cast<int>(ta->Length()));
2675   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
2676 }
2677
2678
2679 static void CheckIsTypedArrayVarNeutered(const char* name) {
2680   i::ScopedVector<char> source(1024);
2681   i::SNPrintF(source,
2682               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
2683               name, name, name);
2684   CHECK(CompileRun(source.start())->IsTrue());
2685   v8::Handle<v8::TypedArray> ta =
2686       v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
2687   CheckIsNeutered(ta);
2688 }
2689
2690
2691 template <typename TypedArray, int kElementSize>
2692 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
2693                                          int byteOffset, int length) {
2694   v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
2695   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
2696   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
2697   CHECK_EQ(length, static_cast<int>(ta->Length()));
2698   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
2699   return ta;
2700 }
2701
2702
2703 THREADED_TEST(ArrayBuffer_NeuteringApi) {
2704   LocalContext env;
2705   v8::Isolate* isolate = env->GetIsolate();
2706   v8::HandleScope handle_scope(isolate);
2707
2708   v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
2709
2710   v8::Handle<v8::Uint8Array> u8a =
2711       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
2712   v8::Handle<v8::Uint8ClampedArray> u8c =
2713       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
2714   v8::Handle<v8::Int8Array> i8a =
2715       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
2716
2717   v8::Handle<v8::Uint16Array> u16a =
2718       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
2719   v8::Handle<v8::Int16Array> i16a =
2720       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
2721
2722   v8::Handle<v8::Uint32Array> u32a =
2723       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
2724   v8::Handle<v8::Int32Array> i32a =
2725       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
2726
2727   v8::Handle<v8::Float32Array> f32a =
2728       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
2729   v8::Handle<v8::Float64Array> f64a =
2730       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
2731
2732   v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
2733   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
2734   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
2735   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
2736
2737   ScopedArrayBufferContents contents(buffer->Externalize());
2738   buffer->Neuter();
2739   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
2740   CheckIsNeutered(u8a);
2741   CheckIsNeutered(u8c);
2742   CheckIsNeutered(i8a);
2743   CheckIsNeutered(u16a);
2744   CheckIsNeutered(i16a);
2745   CheckIsNeutered(u32a);
2746   CheckIsNeutered(i32a);
2747   CheckIsNeutered(f32a);
2748   CheckIsNeutered(f64a);
2749   CheckDataViewIsNeutered(dv);
2750 }
2751
2752
2753 THREADED_TEST(ArrayBuffer_NeuteringScript) {
2754   LocalContext env;
2755   v8::Isolate* isolate = env->GetIsolate();
2756   v8::HandleScope handle_scope(isolate);
2757
2758   CompileRun(
2759       "var ab = new ArrayBuffer(1024);"
2760       "var u8a = new Uint8Array(ab, 1, 1023);"
2761       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
2762       "var i8a = new Int8Array(ab, 1, 1023);"
2763       "var u16a = new Uint16Array(ab, 2, 511);"
2764       "var i16a = new Int16Array(ab, 2, 511);"
2765       "var u32a = new Uint32Array(ab, 4, 255);"
2766       "var i32a = new Int32Array(ab, 4, 255);"
2767       "var f32a = new Float32Array(ab, 4, 255);"
2768       "var f64a = new Float64Array(ab, 8, 127);"
2769       "var dv = new DataView(ab, 1, 1023);");
2770
2771   v8::Handle<v8::ArrayBuffer> ab =
2772       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
2773
2774   v8::Handle<v8::DataView> dv =
2775       v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
2776
2777   ScopedArrayBufferContents contents(ab->Externalize());
2778   ab->Neuter();
2779   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
2780   CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
2781
2782   CheckIsTypedArrayVarNeutered("u8a");
2783   CheckIsTypedArrayVarNeutered("u8c");
2784   CheckIsTypedArrayVarNeutered("i8a");
2785   CheckIsTypedArrayVarNeutered("u16a");
2786   CheckIsTypedArrayVarNeutered("i16a");
2787   CheckIsTypedArrayVarNeutered("u32a");
2788   CheckIsTypedArrayVarNeutered("i32a");
2789   CheckIsTypedArrayVarNeutered("f32a");
2790   CheckIsTypedArrayVarNeutered("f64a");
2791
2792   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
2793   CheckDataViewIsNeutered(dv);
2794 }
2795
2796
2797 class ScopedSharedArrayBufferContents {
2798  public:
2799   explicit ScopedSharedArrayBufferContents(
2800       const v8::SharedArrayBuffer::Contents& contents)
2801       : contents_(contents) {}
2802   ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
2803   void* Data() const { return contents_.Data(); }
2804   size_t ByteLength() const { return contents_.ByteLength(); }
2805
2806  private:
2807   const v8::SharedArrayBuffer::Contents contents_;
2808 };
2809
2810
2811 THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
2812   i::FLAG_harmony_sharedarraybuffer = true;
2813   LocalContext env;
2814   v8::Isolate* isolate = env->GetIsolate();
2815   v8::HandleScope handle_scope(isolate);
2816
2817   Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
2818   CheckInternalFieldsAreZero(ab);
2819   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2820   CHECK(!ab->IsExternal());
2821   CcTest::heap()->CollectAllGarbage();
2822
2823   ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
2824   CHECK(ab->IsExternal());
2825
2826   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2827   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2828   DCHECK(data != NULL);
2829   env->Global()->Set(v8_str("ab"), ab);
2830
2831   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2832   CHECK_EQ(1024, result->Int32Value());
2833
2834   result = CompileRun(
2835       "var u8 = new Uint8Array(ab);"
2836       "u8[0] = 0xFF;"
2837       "u8[1] = 0xAA;"
2838       "u8.length");
2839   CHECK_EQ(1024, result->Int32Value());
2840   CHECK_EQ(0xFF, data[0]);
2841   CHECK_EQ(0xAA, data[1]);
2842   data[0] = 0xCC;
2843   data[1] = 0x11;
2844   result = CompileRun("u8[0] + u8[1]");
2845   CHECK_EQ(0xDD, result->Int32Value());
2846 }
2847
2848
2849 THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
2850   i::FLAG_harmony_sharedarraybuffer = true;
2851   LocalContext env;
2852   v8::Isolate* isolate = env->GetIsolate();
2853   v8::HandleScope handle_scope(isolate);
2854
2855
2856   v8::Local<v8::Value> result = CompileRun(
2857       "var ab1 = new SharedArrayBuffer(2);"
2858       "var u8_a = new Uint8Array(ab1);"
2859       "u8_a[0] = 0xAA;"
2860       "u8_a[1] = 0xFF; u8_a.buffer");
2861   Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
2862   CheckInternalFieldsAreZero(ab1);
2863   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
2864   CHECK(!ab1->IsExternal());
2865   ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
2866   CHECK(ab1->IsExternal());
2867
2868   result = CompileRun("ab1.byteLength");
2869   CHECK_EQ(2, result->Int32Value());
2870   result = CompileRun("u8_a[0]");
2871   CHECK_EQ(0xAA, result->Int32Value());
2872   result = CompileRun("u8_a[1]");
2873   CHECK_EQ(0xFF, result->Int32Value());
2874   result = CompileRun(
2875       "var u8_b = new Uint8Array(ab1);"
2876       "u8_b[0] = 0xBB;"
2877       "u8_a[0]");
2878   CHECK_EQ(0xBB, result->Int32Value());
2879   result = CompileRun("u8_b[1]");
2880   CHECK_EQ(0xFF, result->Int32Value());
2881
2882   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2883   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2884   CHECK_EQ(0xBB, ab1_data[0]);
2885   CHECK_EQ(0xFF, ab1_data[1]);
2886   ab1_data[0] = 0xCC;
2887   ab1_data[1] = 0x11;
2888   result = CompileRun("u8_a[0] + u8_a[1]");
2889   CHECK_EQ(0xDD, result->Int32Value());
2890 }
2891
2892
2893 THREADED_TEST(SharedArrayBuffer_External) {
2894   i::FLAG_harmony_sharedarraybuffer = true;
2895   LocalContext env;
2896   v8::Isolate* isolate = env->GetIsolate();
2897   v8::HandleScope handle_scope(isolate);
2898
2899   i::ScopedVector<uint8_t> my_data(100);
2900   memset(my_data.start(), 0, 100);
2901   Local<v8::SharedArrayBuffer> ab3 =
2902       v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
2903   CheckInternalFieldsAreZero(ab3);
2904   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
2905   CHECK(ab3->IsExternal());
2906
2907   env->Global()->Set(v8_str("ab3"), ab3);
2908
2909   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2910   CHECK_EQ(100, result->Int32Value());
2911
2912   result = CompileRun(
2913       "var u8_b = new Uint8Array(ab3);"
2914       "u8_b[0] = 0xBB;"
2915       "u8_b[1] = 0xCC;"
2916       "u8_b.length");
2917   CHECK_EQ(100, result->Int32Value());
2918   CHECK_EQ(0xBB, my_data[0]);
2919   CHECK_EQ(0xCC, my_data[1]);
2920   my_data[0] = 0xCC;
2921   my_data[1] = 0x11;
2922   result = CompileRun("u8_b[0] + u8_b[1]");
2923   CHECK_EQ(0xDD, result->Int32Value());
2924 }
2925
2926
2927 THREADED_TEST(HiddenProperties) {
2928   LocalContext env;
2929   v8::Isolate* isolate = env->GetIsolate();
2930   v8::HandleScope scope(isolate);
2931
2932   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
2933   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
2934   v8::Local<v8::String> empty = v8_str("");
2935   v8::Local<v8::String> prop_name = v8_str("prop_name");
2936
2937   CcTest::heap()->CollectAllGarbage();
2938
2939   // Make sure delete of a non-existent hidden value works
2940   CHECK(obj->DeleteHiddenValue(key));
2941
2942   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
2943   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
2944   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
2945   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2946
2947   CcTest::heap()->CollectAllGarbage();
2948
2949   // Make sure we do not find the hidden property.
2950   CHECK(!obj->Has(empty));
2951   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2952   CHECK(obj->Get(empty)->IsUndefined());
2953   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2954   CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
2955   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2956   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
2957
2958   CcTest::heap()->CollectAllGarbage();
2959
2960   // Add another property and delete it afterwards to force the object in
2961   // slow case.
2962   CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
2963   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2964   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
2965   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2966   CHECK(obj->Delete(prop_name));
2967   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2968
2969   CcTest::heap()->CollectAllGarbage();
2970
2971   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
2972   CHECK(obj->GetHiddenValue(key).IsEmpty());
2973
2974   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
2975   CHECK(obj->DeleteHiddenValue(key));
2976   CHECK(obj->GetHiddenValue(key).IsEmpty());
2977 }
2978
2979
2980 THREADED_TEST(Regress97784) {
2981   // Regression test for crbug.com/97784
2982   // Messing with the Object.prototype should not have effect on
2983   // hidden properties.
2984   LocalContext env;
2985   v8::HandleScope scope(env->GetIsolate());
2986
2987   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
2988   v8::Local<v8::String> key = v8_str("hidden");
2989
2990   CompileRun(
2991       "set_called = false;"
2992       "Object.defineProperty("
2993       "    Object.prototype,"
2994       "    'hidden',"
2995       "    {get: function() { return 45; },"
2996       "     set: function() { set_called = true; }})");
2997
2998   CHECK(obj->GetHiddenValue(key).IsEmpty());
2999   // Make sure that the getter and setter from Object.prototype is not invoked.
3000   // If it did we would have full access to the hidden properties in
3001   // the accessor.
3002   CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
3003   ExpectFalse("set_called");
3004   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
3005 }
3006
3007
3008 THREADED_TEST(External) {
3009   v8::HandleScope scope(CcTest::isolate());
3010   int x = 3;
3011   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
3012   LocalContext env;
3013   env->Global()->Set(v8_str("ext"), ext);
3014   Local<Value> reext_obj = CompileRun("this.ext");
3015   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
3016   int* ptr = static_cast<int*>(reext->Value());
3017   CHECK_EQ(x, 3);
3018   *ptr = 10;
3019   CHECK_EQ(x, 10);
3020
3021   // Make sure unaligned pointers are wrapped properly.
3022   char* data = i::StrDup("0123456789");
3023   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3024   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3025   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3026   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
3027
3028   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
3029   CHECK_EQ('0', *char_ptr);
3030   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
3031   CHECK_EQ('1', *char_ptr);
3032   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
3033   CHECK_EQ('2', *char_ptr);
3034   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
3035   CHECK_EQ('3', *char_ptr);
3036   i::DeleteArray(data);
3037 }
3038
3039
3040 THREADED_TEST(GlobalHandle) {
3041   v8::Isolate* isolate = CcTest::isolate();
3042   v8::Persistent<String> global;
3043   {
3044     v8::HandleScope scope(isolate);
3045     global.Reset(isolate, v8_str("str"));
3046   }
3047   {
3048     v8::HandleScope scope(isolate);
3049     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3050   }
3051   global.Reset();
3052   {
3053     v8::HandleScope scope(isolate);
3054     global.Reset(isolate, v8_str("str"));
3055   }
3056   {
3057     v8::HandleScope scope(isolate);
3058     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3059   }
3060   global.Reset();
3061 }
3062
3063
3064 THREADED_TEST(ResettingGlobalHandle) {
3065   v8::Isolate* isolate = CcTest::isolate();
3066   v8::Persistent<String> global;
3067   {
3068     v8::HandleScope scope(isolate);
3069     global.Reset(isolate, v8_str("str"));
3070   }
3071   v8::internal::GlobalHandles* global_handles =
3072       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3073   int initial_handle_count = global_handles->global_handles_count();
3074   {
3075     v8::HandleScope scope(isolate);
3076     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3077   }
3078   {
3079     v8::HandleScope scope(isolate);
3080     global.Reset(isolate, v8_str("longer"));
3081   }
3082   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3083   {
3084     v8::HandleScope scope(isolate);
3085     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3086   }
3087   global.Reset();
3088   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3089 }
3090
3091
3092 THREADED_TEST(ResettingGlobalHandleToEmpty) {
3093   v8::Isolate* isolate = CcTest::isolate();
3094   v8::Persistent<String> global;
3095   {
3096     v8::HandleScope scope(isolate);
3097     global.Reset(isolate, v8_str("str"));
3098   }
3099   v8::internal::GlobalHandles* global_handles =
3100       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3101   int initial_handle_count = global_handles->global_handles_count();
3102   {
3103     v8::HandleScope scope(isolate);
3104     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3105   }
3106   {
3107     v8::HandleScope scope(isolate);
3108     Local<String> empty;
3109     global.Reset(isolate, empty);
3110   }
3111   CHECK(global.IsEmpty());
3112   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3113 }
3114
3115
3116 template <class T>
3117 static v8::Global<T> PassUnique(v8::Global<T> unique) {
3118   return unique.Pass();
3119 }
3120
3121
3122 template <class T>
3123 static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
3124                                   const v8::Persistent<T>& global) {
3125   v8::Global<String> unique(isolate, global);
3126   return unique.Pass();
3127 }
3128
3129
3130 THREADED_TEST(Global) {
3131   v8::Isolate* isolate = CcTest::isolate();
3132   v8::Persistent<String> global;
3133   {
3134     v8::HandleScope scope(isolate);
3135     global.Reset(isolate, v8_str("str"));
3136   }
3137   v8::internal::GlobalHandles* global_handles =
3138       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3139   int initial_handle_count = global_handles->global_handles_count();
3140   {
3141     v8::Global<String> unique(isolate, global);
3142     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3143     // Test assignment via Pass
3144     {
3145       v8::Global<String> copy = unique.Pass();
3146       CHECK(unique.IsEmpty());
3147       CHECK(copy == global);
3148       CHECK_EQ(initial_handle_count + 1,
3149                global_handles->global_handles_count());
3150       unique = copy.Pass();
3151     }
3152     // Test ctor via Pass
3153     {
3154       v8::Global<String> copy(unique.Pass());
3155       CHECK(unique.IsEmpty());
3156       CHECK(copy == global);
3157       CHECK_EQ(initial_handle_count + 1,
3158                global_handles->global_handles_count());
3159       unique = copy.Pass();
3160     }
3161     // Test pass through function call
3162     {
3163       v8::Global<String> copy = PassUnique(unique.Pass());
3164       CHECK(unique.IsEmpty());
3165       CHECK(copy == global);
3166       CHECK_EQ(initial_handle_count + 1,
3167                global_handles->global_handles_count());
3168       unique = copy.Pass();
3169     }
3170     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3171   }
3172   // Test pass from function call
3173   {
3174     v8::Global<String> unique = ReturnUnique(isolate, global);
3175     CHECK(unique == global);
3176     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3177   }
3178   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3179   global.Reset();
3180 }
3181
3182
3183 namespace {
3184
3185 class TwoPassCallbackData;
3186 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3187 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3188
3189
3190 class TwoPassCallbackData {
3191  public:
3192   TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
3193       : first_pass_called_(false),
3194         second_pass_called_(false),
3195         trigger_gc_(false),
3196         instance_counter_(instance_counter) {
3197     HandleScope scope(isolate);
3198     i::ScopedVector<char> buffer(40);
3199     i::SNPrintF(buffer, "%p", static_cast<void*>(this));
3200     auto string =
3201         v8::String::NewFromUtf8(isolate, buffer.start(),
3202                                 v8::NewStringType::kNormal).ToLocalChecked();
3203     cell_.Reset(isolate, string);
3204     (*instance_counter_)++;
3205   }
3206
3207   ~TwoPassCallbackData() {
3208     CHECK(first_pass_called_);
3209     CHECK(second_pass_called_);
3210     CHECK(cell_.IsEmpty());
3211     (*instance_counter_)--;
3212   }
3213
3214   void FirstPass() {
3215     CHECK(!first_pass_called_);
3216     CHECK(!second_pass_called_);
3217     CHECK(!cell_.IsEmpty());
3218     cell_.Reset();
3219     first_pass_called_ = true;
3220   }
3221
3222   void SecondPass() {
3223     CHECK(first_pass_called_);
3224     CHECK(!second_pass_called_);
3225     CHECK(cell_.IsEmpty());
3226     second_pass_called_ = true;
3227     delete this;
3228   }
3229
3230   void SetWeak() {
3231     cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
3232   }
3233
3234   void MarkTriggerGc() { trigger_gc_ = true; }
3235   bool trigger_gc() { return trigger_gc_; }
3236
3237   int* instance_counter() { return instance_counter_; }
3238
3239  private:
3240   bool first_pass_called_;
3241   bool second_pass_called_;
3242   bool trigger_gc_;
3243   v8::Global<v8::String> cell_;
3244   int* instance_counter_;
3245 };
3246
3247
3248 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
3249   ApiTestFuzzer::Fuzz();
3250   bool trigger_gc = data.GetParameter()->trigger_gc();
3251   int* instance_counter = data.GetParameter()->instance_counter();
3252   data.GetParameter()->SecondPass();
3253   if (!trigger_gc) return;
3254   auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
3255   data_2->SetWeak();
3256   CcTest::heap()->CollectAllGarbage();
3257 }
3258
3259
3260 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
3261   data.GetParameter()->FirstPass();
3262   data.SetSecondPassCallback(SecondPassCallback);
3263 }
3264
3265 }  // namespace
3266
3267
3268 TEST(TwoPassPhantomCallbacks) {
3269   auto isolate = CcTest::isolate();
3270   const size_t kLength = 20;
3271   int instance_counter = 0;
3272   for (size_t i = 0; i < kLength; ++i) {
3273     auto data = new TwoPassCallbackData(isolate, &instance_counter);
3274     data->SetWeak();
3275   }
3276   CHECK_EQ(static_cast<int>(kLength), instance_counter);
3277   CcTest::heap()->CollectAllGarbage();
3278   CHECK_EQ(0, instance_counter);
3279 }
3280
3281
3282 TEST(TwoPassPhantomCallbacksNestedGc) {
3283   auto isolate = CcTest::isolate();
3284   const size_t kLength = 20;
3285   TwoPassCallbackData* array[kLength];
3286   int instance_counter = 0;
3287   for (size_t i = 0; i < kLength; ++i) {
3288     array[i] = new TwoPassCallbackData(isolate, &instance_counter);
3289     array[i]->SetWeak();
3290   }
3291   array[5]->MarkTriggerGc();
3292   array[10]->MarkTriggerGc();
3293   array[15]->MarkTriggerGc();
3294   CHECK_EQ(static_cast<int>(kLength), instance_counter);
3295   CcTest::heap()->CollectAllGarbage();
3296   CHECK_EQ(0, instance_counter);
3297 }
3298
3299
3300 namespace {
3301
3302 void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
3303
3304
3305 Local<v8::Object> NewObjectForIntKey(
3306     v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
3307     int key) {
3308   auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
3309   auto obj = local->NewInstance();
3310   obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
3311   return obj;
3312 }
3313
3314
3315 template <typename K, typename V>
3316 class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
3317  public:
3318   typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
3319   static const v8::PersistentContainerCallbackType kCallbackType =
3320       v8::kWeakWithInternalFields;
3321   struct WeakCallbackDataType {
3322     MapType* map;
3323     K key;
3324   };
3325   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
3326                                                      Local<V> value) {
3327     WeakCallbackDataType* data = new WeakCallbackDataType;
3328     data->map = map;
3329     data->key = key;
3330     return data;
3331   }
3332   static MapType* MapFromWeakCallbackInfo(
3333       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
3334     return data.GetParameter()->map;
3335   }
3336   static K KeyFromWeakCallbackInfo(
3337       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
3338     return data.GetParameter()->key;
3339   }
3340   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
3341   static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
3342     CHECK_EQ(IntKeyToVoidPointer(key),
3343              v8::Object::GetAlignedPointerFromInternalField(value, 0));
3344   }
3345   static void DisposeWeak(
3346       const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
3347     K key = KeyFromWeakCallbackInfo(info);
3348     CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
3349     DisposeCallbackData(info.GetParameter());
3350   }
3351 };
3352
3353
3354 template <typename Map>
3355 void TestGlobalValueMap() {
3356   LocalContext env;
3357   v8::Isolate* isolate = env->GetIsolate();
3358   v8::Global<ObjectTemplate> templ;
3359   {
3360     HandleScope scope(isolate);
3361     auto t = ObjectTemplate::New(isolate);
3362     t->SetInternalFieldCount(1);
3363     templ.Reset(isolate, t);
3364   }
3365   Map map(isolate);
3366   v8::internal::GlobalHandles* global_handles =
3367       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3368   int initial_handle_count = global_handles->global_handles_count();
3369   CHECK_EQ(0, static_cast<int>(map.Size()));
3370   {
3371     HandleScope scope(isolate);
3372     Local<v8::Object> obj = map.Get(7);
3373     CHECK(obj.IsEmpty());
3374     Local<v8::Object> expected = v8::Object::New(isolate);
3375     map.Set(7, expected);
3376     CHECK_EQ(1, static_cast<int>(map.Size()));
3377     obj = map.Get(7);
3378     CHECK(expected->Equals(obj));
3379     {
3380       typename Map::PersistentValueReference ref = map.GetReference(7);
3381       CHECK(expected->Equals(ref.NewLocal(isolate)));
3382     }
3383     v8::Global<v8::Object> removed = map.Remove(7);
3384     CHECK_EQ(0, static_cast<int>(map.Size()));
3385     CHECK(expected == removed);
3386     removed = map.Remove(7);
3387     CHECK(removed.IsEmpty());
3388     map.Set(8, expected);
3389     CHECK_EQ(1, static_cast<int>(map.Size()));
3390     map.Set(8, expected);
3391     CHECK_EQ(1, static_cast<int>(map.Size()));
3392     {
3393       typename Map::PersistentValueReference ref;
3394       Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
3395       removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
3396       CHECK_EQ(1, static_cast<int>(map.Size()));
3397       CHECK(expected == removed);
3398       CHECK(expected2->Equals(ref.NewLocal(isolate)));
3399     }
3400   }
3401   CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3402   if (map.IsWeak()) {
3403     CcTest::i_isolate()->heap()->CollectAllGarbage(
3404         i::Heap::kAbortIncrementalMarkingMask);
3405   } else {
3406     map.Clear();
3407   }
3408   CHECK_EQ(0, static_cast<int>(map.Size()));
3409   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3410   {
3411     HandleScope scope(isolate);
3412     Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
3413     map.Set(9, value);
3414     map.Clear();
3415   }
3416   CHECK_EQ(0, static_cast<int>(map.Size()));
3417   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3418 }
3419
3420 }  // namespace
3421
3422
3423 TEST(GlobalValueMap) {
3424   // Default case, w/o weak callbacks:
3425   TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
3426
3427   // Custom traits with weak callbacks:
3428   typedef v8::GlobalValueMap<int, v8::Object,
3429                              PhantomStdMapTraits<int, v8::Object>> WeakMap;
3430   TestGlobalValueMap<WeakMap>();
3431 }
3432
3433
3434 TEST(PersistentValueVector) {
3435   LocalContext env;
3436   v8::Isolate* isolate = env->GetIsolate();
3437   v8::internal::GlobalHandles* global_handles =
3438       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3439   int handle_count = global_handles->global_handles_count();
3440   HandleScope scope(isolate);
3441
3442   v8::PersistentValueVector<v8::Object> vector(isolate);
3443
3444   Local<v8::Object> obj1 = v8::Object::New(isolate);
3445   Local<v8::Object> obj2 = v8::Object::New(isolate);
3446   v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
3447
3448   CHECK(vector.IsEmpty());
3449   CHECK_EQ(0, static_cast<int>(vector.Size()));
3450
3451   vector.ReserveCapacity(3);
3452   CHECK(vector.IsEmpty());
3453
3454   vector.Append(obj1);
3455   vector.Append(obj2);
3456   vector.Append(obj1);
3457   vector.Append(obj3.Pass());
3458   vector.Append(obj1);
3459
3460   CHECK(!vector.IsEmpty());
3461   CHECK_EQ(5, static_cast<int>(vector.Size()));
3462   CHECK(obj3.IsEmpty());
3463   CHECK(obj1->Equals(vector.Get(0)));
3464   CHECK(obj1->Equals(vector.Get(2)));
3465   CHECK(obj1->Equals(vector.Get(4)));
3466   CHECK(obj2->Equals(vector.Get(1)));
3467
3468   CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
3469
3470   vector.Clear();
3471   CHECK(vector.IsEmpty());
3472   CHECK_EQ(0, static_cast<int>(vector.Size()));
3473   CHECK_EQ(handle_count, global_handles->global_handles_count());
3474 }
3475
3476
3477 THREADED_TEST(GlobalHandleUpcast) {
3478   v8::Isolate* isolate = CcTest::isolate();
3479   v8::HandleScope scope(isolate);
3480   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
3481   v8::Persistent<String> global_string(isolate, local);
3482   v8::Persistent<Value>& global_value =
3483       v8::Persistent<Value>::Cast(global_string);
3484   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3485   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
3486   global_string.Reset();
3487 }
3488
3489
3490 THREADED_TEST(HandleEquality) {
3491   v8::Isolate* isolate = CcTest::isolate();
3492   v8::Persistent<String> global1;
3493   v8::Persistent<String> global2;
3494   {
3495     v8::HandleScope scope(isolate);
3496     global1.Reset(isolate, v8_str("str"));
3497     global2.Reset(isolate, v8_str("str2"));
3498   }
3499   CHECK_EQ(global1 == global1, true);
3500   CHECK_EQ(global1 != global1, false);
3501   {
3502     v8::HandleScope scope(isolate);
3503     Local<String> local1 = Local<String>::New(isolate, global1);
3504     Local<String> local2 = Local<String>::New(isolate, global2);
3505
3506     CHECK_EQ(global1 == local1, true);
3507     CHECK_EQ(global1 != local1, false);
3508     CHECK_EQ(local1 == global1, true);
3509     CHECK_EQ(local1 != global1, false);
3510
3511     CHECK_EQ(global1 == local2, false);
3512     CHECK_EQ(global1 != local2, true);
3513     CHECK_EQ(local2 == global1, false);
3514     CHECK_EQ(local2 != global1, true);
3515
3516     CHECK_EQ(local1 == local2, false);
3517     CHECK_EQ(local1 != local2, true);
3518
3519     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3520     CHECK_EQ(local1 == anotherLocal1, true);
3521     CHECK_EQ(local1 != anotherLocal1, false);
3522   }
3523   global1.Reset();
3524   global2.Reset();
3525 }
3526
3527
3528 THREADED_TEST(LocalHandle) {
3529   v8::HandleScope scope(CcTest::isolate());
3530   v8::Local<String> local =
3531       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
3532   CHECK_EQ(local->Length(), 3);
3533 }
3534
3535
3536 class WeakCallCounter {
3537  public:
3538   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
3539   int id() { return id_; }
3540   void increment() { number_of_weak_calls_++; }
3541   int NumberOfWeakCalls() { return number_of_weak_calls_; }
3542
3543  private:
3544   int id_;
3545   int number_of_weak_calls_;
3546 };
3547
3548
3549 template <typename T>
3550 struct WeakCallCounterAndPersistent {
3551   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3552       : counter(counter) {}
3553   WeakCallCounter* counter;
3554   v8::Persistent<T> handle;
3555 };
3556
3557
3558 template <typename T>
3559 static void WeakPointerCallback(
3560     const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
3561   CHECK_EQ(1234, data.GetParameter()->counter->id());
3562   data.GetParameter()->counter->increment();
3563   data.GetParameter()->handle.Reset();
3564 }
3565
3566
3567 template <typename T>
3568 static UniqueId MakeUniqueId(const Persistent<T>& p) {
3569   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3570 }
3571
3572
3573 THREADED_TEST(ApiObjectGroups) {
3574   LocalContext env;
3575   v8::Isolate* iso = env->GetIsolate();
3576   HandleScope scope(iso);
3577
3578   WeakCallCounter counter(1234);
3579
3580   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3581   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3582   WeakCallCounterAndPersistent<Value> g1c1(&counter);
3583   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3584   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3585   WeakCallCounterAndPersistent<Value> g2c1(&counter);
3586
3587   {
3588     HandleScope scope(iso);
3589     g1s1.handle.Reset(iso, Object::New(iso));
3590     g1s2.handle.Reset(iso, Object::New(iso));
3591     g1c1.handle.Reset(iso, Object::New(iso));
3592     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3593                         v8::WeakCallbackType::kParameter);
3594     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3595                         v8::WeakCallbackType::kParameter);
3596     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3597                         v8::WeakCallbackType::kParameter);
3598
3599     g2s1.handle.Reset(iso, Object::New(iso));
3600     g2s2.handle.Reset(iso, Object::New(iso));
3601     g2c1.handle.Reset(iso, Object::New(iso));
3602     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3603                         v8::WeakCallbackType::kParameter);
3604     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3605                         v8::WeakCallbackType::kParameter);
3606     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3607                         v8::WeakCallbackType::kParameter);
3608   }
3609
3610   WeakCallCounterAndPersistent<Value> root(&counter);
3611   root.handle.Reset(iso, g1s1.handle);  // make a root.
3612
3613   // Connect group 1 and 2, make a cycle.
3614   {
3615     HandleScope scope(iso);
3616     CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
3617               ->Set(0, Local<Value>::New(iso, g2s2.handle)));
3618     CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
3619               ->Set(0, Local<Value>::New(iso, g1s1.handle)));
3620   }
3621
3622   {
3623     UniqueId id1 = MakeUniqueId(g1s1.handle);
3624     UniqueId id2 = MakeUniqueId(g2s2.handle);
3625     iso->SetObjectGroupId(g1s1.handle, id1);
3626     iso->SetObjectGroupId(g1s2.handle, id1);
3627     iso->SetReferenceFromGroup(id1, g1c1.handle);
3628     iso->SetObjectGroupId(g2s1.handle, id2);
3629     iso->SetObjectGroupId(g2s2.handle, id2);
3630     iso->SetReferenceFromGroup(id2, g2c1.handle);
3631   }
3632   // Do a single full GC, ensure incremental marking is stopped.
3633   v8::internal::Heap* heap =
3634       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3635   heap->CollectAllGarbage();
3636
3637   // All object should be alive.
3638   CHECK_EQ(0, counter.NumberOfWeakCalls());
3639
3640   // Weaken the root.
3641   root.handle.SetWeak(&root, &WeakPointerCallback,
3642                       v8::WeakCallbackType::kParameter);
3643   // But make children strong roots---all the objects (except for children)
3644   // should be collectable now.
3645   g1c1.handle.ClearWeak();
3646   g2c1.handle.ClearWeak();
3647
3648   // Groups are deleted, rebuild groups.
3649   {
3650     UniqueId id1 = MakeUniqueId(g1s1.handle);
3651     UniqueId id2 = MakeUniqueId(g2s2.handle);
3652     iso->SetObjectGroupId(g1s1.handle, id1);
3653     iso->SetObjectGroupId(g1s2.handle, id1);
3654     iso->SetReferenceFromGroup(id1, g1c1.handle);
3655     iso->SetObjectGroupId(g2s1.handle, id2);
3656     iso->SetObjectGroupId(g2s2.handle, id2);
3657     iso->SetReferenceFromGroup(id2, g2c1.handle);
3658   }
3659
3660   heap->CollectAllGarbage();
3661
3662   // All objects should be gone. 5 global handles in total.
3663   CHECK_EQ(5, counter.NumberOfWeakCalls());
3664
3665   // And now make children weak again and collect them.
3666   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3667                       v8::WeakCallbackType::kParameter);
3668   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3669                       v8::WeakCallbackType::kParameter);
3670
3671   heap->CollectAllGarbage();
3672   CHECK_EQ(7, counter.NumberOfWeakCalls());
3673 }
3674
3675
3676 THREADED_TEST(ApiObjectGroupsForSubtypes) {
3677   LocalContext env;
3678   v8::Isolate* iso = env->GetIsolate();
3679   HandleScope scope(iso);
3680
3681   WeakCallCounter counter(1234);
3682
3683   WeakCallCounterAndPersistent<Object> g1s1(&counter);
3684   WeakCallCounterAndPersistent<String> g1s2(&counter);
3685   WeakCallCounterAndPersistent<String> g1c1(&counter);
3686   WeakCallCounterAndPersistent<Object> g2s1(&counter);
3687   WeakCallCounterAndPersistent<String> g2s2(&counter);
3688   WeakCallCounterAndPersistent<String> g2c1(&counter);
3689
3690   {
3691     HandleScope scope(iso);
3692     g1s1.handle.Reset(iso, Object::New(iso));
3693     g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3694     g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3695     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3696                         v8::WeakCallbackType::kParameter);
3697     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3698                         v8::WeakCallbackType::kParameter);
3699     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3700                         v8::WeakCallbackType::kParameter);
3701
3702     g2s1.handle.Reset(iso, Object::New(iso));
3703     g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3704     g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3705     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3706                         v8::WeakCallbackType::kParameter);
3707     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3708                         v8::WeakCallbackType::kParameter);
3709     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3710                         v8::WeakCallbackType::kParameter);
3711   }
3712
3713   WeakCallCounterAndPersistent<Value> root(&counter);
3714   root.handle.Reset(iso, g1s1.handle);  // make a root.
3715
3716   // Connect group 1 and 2, make a cycle.
3717   {
3718     HandleScope scope(iso);
3719     CHECK(Local<Object>::New(iso, g1s1.handle)
3720               ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3721     CHECK(Local<Object>::New(iso, g2s1.handle)
3722               ->Set(0, Local<Object>::New(iso, g1s1.handle)));
3723   }
3724
3725   {
3726     UniqueId id1 = MakeUniqueId(g1s1.handle);
3727     UniqueId id2 = MakeUniqueId(g2s2.handle);
3728     iso->SetObjectGroupId(g1s1.handle, id1);
3729     iso->SetObjectGroupId(g1s2.handle, id1);
3730     iso->SetReference(g1s1.handle, g1c1.handle);
3731     iso->SetObjectGroupId(g2s1.handle, id2);
3732     iso->SetObjectGroupId(g2s2.handle, id2);
3733     iso->SetReferenceFromGroup(id2, g2c1.handle);
3734   }
3735   // Do a single full GC, ensure incremental marking is stopped.
3736   v8::internal::Heap* heap =
3737       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3738   heap->CollectAllGarbage();
3739
3740   // All object should be alive.
3741   CHECK_EQ(0, counter.NumberOfWeakCalls());
3742
3743   // Weaken the root.
3744   root.handle.SetWeak(&root, &WeakPointerCallback,
3745                       v8::WeakCallbackType::kParameter);
3746   // But make children strong roots---all the objects (except for children)
3747   // should be collectable now.
3748   g1c1.handle.ClearWeak();
3749   g2c1.handle.ClearWeak();
3750
3751   // Groups are deleted, rebuild groups.
3752   {
3753     UniqueId id1 = MakeUniqueId(g1s1.handle);
3754     UniqueId id2 = MakeUniqueId(g2s2.handle);
3755     iso->SetObjectGroupId(g1s1.handle, id1);
3756     iso->SetObjectGroupId(g1s2.handle, id1);
3757     iso->SetReference(g1s1.handle, g1c1.handle);
3758     iso->SetObjectGroupId(g2s1.handle, id2);
3759     iso->SetObjectGroupId(g2s2.handle, id2);
3760     iso->SetReferenceFromGroup(id2, g2c1.handle);
3761   }
3762
3763   heap->CollectAllGarbage();
3764
3765   // All objects should be gone. 5 global handles in total.
3766   CHECK_EQ(5, counter.NumberOfWeakCalls());
3767
3768   // And now make children weak again and collect them.
3769   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3770                       v8::WeakCallbackType::kParameter);
3771   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3772                       v8::WeakCallbackType::kParameter);
3773
3774   heap->CollectAllGarbage();
3775   CHECK_EQ(7, counter.NumberOfWeakCalls());
3776 }
3777
3778
3779 THREADED_TEST(ApiObjectGroupsCycle) {
3780   LocalContext env;
3781   v8::Isolate* iso = env->GetIsolate();
3782   HandleScope scope(iso);
3783
3784   WeakCallCounter counter(1234);
3785
3786   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3787   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3788   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3789   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3790   WeakCallCounterAndPersistent<Value> g3s1(&counter);
3791   WeakCallCounterAndPersistent<Value> g3s2(&counter);
3792   WeakCallCounterAndPersistent<Value> g4s1(&counter);
3793   WeakCallCounterAndPersistent<Value> g4s2(&counter);
3794
3795   {
3796     HandleScope scope(iso);
3797     g1s1.handle.Reset(iso, Object::New(iso));
3798     g1s2.handle.Reset(iso, Object::New(iso));
3799     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3800                         v8::WeakCallbackType::kParameter);
3801     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3802                         v8::WeakCallbackType::kParameter);
3803     CHECK(g1s1.handle.IsWeak());
3804     CHECK(g1s2.handle.IsWeak());
3805
3806     g2s1.handle.Reset(iso, Object::New(iso));
3807     g2s2.handle.Reset(iso, Object::New(iso));
3808     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3809                         v8::WeakCallbackType::kParameter);
3810     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3811                         v8::WeakCallbackType::kParameter);
3812     CHECK(g2s1.handle.IsWeak());
3813     CHECK(g2s2.handle.IsWeak());
3814
3815     g3s1.handle.Reset(iso, Object::New(iso));
3816     g3s2.handle.Reset(iso, Object::New(iso));
3817     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
3818                         v8::WeakCallbackType::kParameter);
3819     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
3820                         v8::WeakCallbackType::kParameter);
3821     CHECK(g3s1.handle.IsWeak());
3822     CHECK(g3s2.handle.IsWeak());
3823
3824     g4s1.handle.Reset(iso, Object::New(iso));
3825     g4s2.handle.Reset(iso, Object::New(iso));
3826     g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
3827                         v8::WeakCallbackType::kParameter);
3828     g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
3829                         v8::WeakCallbackType::kParameter);
3830     CHECK(g4s1.handle.IsWeak());
3831     CHECK(g4s2.handle.IsWeak());
3832   }
3833
3834   WeakCallCounterAndPersistent<Value> root(&counter);
3835   root.handle.Reset(iso, g1s1.handle);  // make a root.
3836
3837   // Connect groups.  We're building the following cycle:
3838   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3839   // groups.
3840   {
3841     UniqueId id1 = MakeUniqueId(g1s1.handle);
3842     UniqueId id2 = MakeUniqueId(g2s1.handle);
3843     UniqueId id3 = MakeUniqueId(g3s1.handle);
3844     UniqueId id4 = MakeUniqueId(g4s1.handle);
3845     iso->SetObjectGroupId(g1s1.handle, id1);
3846     iso->SetObjectGroupId(g1s2.handle, id1);
3847     iso->SetReferenceFromGroup(id1, g2s1.handle);
3848     iso->SetObjectGroupId(g2s1.handle, id2);
3849     iso->SetObjectGroupId(g2s2.handle, id2);
3850     iso->SetReferenceFromGroup(id2, g3s1.handle);
3851     iso->SetObjectGroupId(g3s1.handle, id3);
3852     iso->SetObjectGroupId(g3s2.handle, id3);
3853     iso->SetReferenceFromGroup(id3, g4s1.handle);
3854     iso->SetObjectGroupId(g4s1.handle, id4);
3855     iso->SetObjectGroupId(g4s2.handle, id4);
3856     iso->SetReferenceFromGroup(id4, g1s1.handle);
3857   }
3858   // Do a single full GC
3859   v8::internal::Heap* heap =
3860       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3861   heap->CollectAllGarbage();
3862
3863   // All object should be alive.
3864   CHECK_EQ(0, counter.NumberOfWeakCalls());
3865
3866   // Weaken the root.
3867   root.handle.SetWeak(&root, &WeakPointerCallback,
3868                       v8::WeakCallbackType::kParameter);
3869
3870   // Groups are deleted, rebuild groups.
3871   {
3872     UniqueId id1 = MakeUniqueId(g1s1.handle);
3873     UniqueId id2 = MakeUniqueId(g2s1.handle);
3874     UniqueId id3 = MakeUniqueId(g3s1.handle);
3875     UniqueId id4 = MakeUniqueId(g4s1.handle);
3876     iso->SetObjectGroupId(g1s1.handle, id1);
3877     iso->SetObjectGroupId(g1s2.handle, id1);
3878     iso->SetReferenceFromGroup(id1, g2s1.handle);
3879     iso->SetObjectGroupId(g2s1.handle, id2);
3880     iso->SetObjectGroupId(g2s2.handle, id2);
3881     iso->SetReferenceFromGroup(id2, g3s1.handle);
3882     iso->SetObjectGroupId(g3s1.handle, id3);
3883     iso->SetObjectGroupId(g3s2.handle, id3);
3884     iso->SetReferenceFromGroup(id3, g4s1.handle);
3885     iso->SetObjectGroupId(g4s1.handle, id4);
3886     iso->SetObjectGroupId(g4s2.handle, id4);
3887     iso->SetReferenceFromGroup(id4, g1s1.handle);
3888   }
3889
3890   heap->CollectAllGarbage();
3891
3892   // All objects should be gone. 9 global handles in total.
3893   CHECK_EQ(9, counter.NumberOfWeakCalls());
3894 }
3895
3896
3897 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3898 // on the buildbots, so was made non-threaded for the time being.
3899 TEST(ApiObjectGroupsCycleForScavenger) {
3900   i::FLAG_stress_compaction = false;
3901   i::FLAG_gc_global = false;
3902   LocalContext env;
3903   v8::Isolate* iso = env->GetIsolate();
3904   HandleScope scope(iso);
3905
3906   WeakCallCounter counter(1234);
3907
3908   WeakCallCounterAndPersistent<Value> g1s1(&counter);
3909   WeakCallCounterAndPersistent<Value> g1s2(&counter);
3910   WeakCallCounterAndPersistent<Value> g2s1(&counter);
3911   WeakCallCounterAndPersistent<Value> g2s2(&counter);
3912   WeakCallCounterAndPersistent<Value> g3s1(&counter);
3913   WeakCallCounterAndPersistent<Value> g3s2(&counter);
3914
3915   {
3916     HandleScope scope(iso);
3917     g1s1.handle.Reset(iso, Object::New(iso));
3918     g1s2.handle.Reset(iso, Object::New(iso));
3919     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3920                         v8::WeakCallbackType::kParameter);
3921     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3922                         v8::WeakCallbackType::kParameter);
3923
3924     g2s1.handle.Reset(iso, Object::New(iso));
3925     g2s2.handle.Reset(iso, Object::New(iso));
3926     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3927                         v8::WeakCallbackType::kParameter);
3928     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3929                         v8::WeakCallbackType::kParameter);
3930
3931     g3s1.handle.Reset(iso, Object::New(iso));
3932     g3s2.handle.Reset(iso, Object::New(iso));
3933     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
3934                         v8::WeakCallbackType::kParameter);
3935     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
3936                         v8::WeakCallbackType::kParameter);
3937   }
3938
3939   // Make a root.
3940   WeakCallCounterAndPersistent<Value> root(&counter);
3941   root.handle.Reset(iso, g1s1.handle);
3942   root.handle.MarkPartiallyDependent();
3943
3944   // Connect groups.  We're building the following cycle:
3945   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3946   // groups.
3947   {
3948     HandleScope handle_scope(iso);
3949     g1s1.handle.MarkPartiallyDependent();
3950     g1s2.handle.MarkPartiallyDependent();
3951     g2s1.handle.MarkPartiallyDependent();
3952     g2s2.handle.MarkPartiallyDependent();
3953     g3s1.handle.MarkPartiallyDependent();
3954     g3s2.handle.MarkPartiallyDependent();
3955     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3956     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3957     Local<Object>::New(iso, g1s1.handle.As<Object>())
3958         ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3959     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3960     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3961     Local<Object>::New(iso, g2s1.handle.As<Object>())
3962         ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3963     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3964     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3965     Local<Object>::New(iso, g3s1.handle.As<Object>())
3966         ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
3967   }
3968
3969   v8::internal::Heap* heap =
3970       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3971   heap->CollectAllGarbage();
3972
3973   // All objects should be alive.
3974   CHECK_EQ(0, counter.NumberOfWeakCalls());
3975
3976   // Weaken the root.
3977   root.handle.SetWeak(&root, &WeakPointerCallback,
3978                       v8::WeakCallbackType::kParameter);
3979   root.handle.MarkPartiallyDependent();
3980
3981   // Groups are deleted, rebuild groups.
3982   {
3983     HandleScope handle_scope(iso);
3984     g1s1.handle.MarkPartiallyDependent();
3985     g1s2.handle.MarkPartiallyDependent();
3986     g2s1.handle.MarkPartiallyDependent();
3987     g2s2.handle.MarkPartiallyDependent();
3988     g3s1.handle.MarkPartiallyDependent();
3989     g3s2.handle.MarkPartiallyDependent();
3990     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3991     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3992     Local<Object>::New(iso, g1s1.handle.As<Object>())
3993         ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3994     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3995     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3996     Local<Object>::New(iso, g2s1.handle.As<Object>())
3997         ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3998     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3999     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
4000     Local<Object>::New(iso, g3s1.handle.As<Object>())
4001         ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
4002   }
4003
4004   heap->CollectAllGarbage();
4005
4006   // All objects should be gone. 7 global handles in total.
4007   CHECK_EQ(7, counter.NumberOfWeakCalls());
4008 }
4009
4010
4011 THREADED_TEST(ScriptException) {
4012   LocalContext env;
4013   v8::HandleScope scope(env->GetIsolate());
4014   Local<Script> script = v8_compile("throw 'panama!';");
4015   v8::TryCatch try_catch(env->GetIsolate());
4016   Local<Value> result = script->Run();
4017   CHECK(result.IsEmpty());
4018   CHECK(try_catch.HasCaught());
4019   String::Utf8Value exception_value(try_catch.Exception());
4020   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
4021 }
4022
4023
4024 TEST(TryCatchCustomException) {
4025   LocalContext env;
4026   v8::Isolate* isolate = env->GetIsolate();
4027   v8::HandleScope scope(isolate);
4028   v8::TryCatch try_catch(isolate);
4029   CompileRun(
4030       "function CustomError() { this.a = 'b'; }"
4031       "(function f() { throw new CustomError(); })();");
4032   CHECK(try_catch.HasCaught());
4033   CHECK(try_catch.Exception()
4034             ->ToObject(isolate)
4035             ->Get(v8_str("a"))
4036             ->Equals(v8_str("b")));
4037 }
4038
4039
4040 bool message_received;
4041
4042
4043 static void check_message_0(v8::Handle<v8::Message> message,
4044                             v8::Handle<Value> data) {
4045   CHECK_EQ(5.76, data->NumberValue());
4046   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4047   CHECK(!message->IsSharedCrossOrigin());
4048   message_received = true;
4049 }
4050
4051
4052 THREADED_TEST(MessageHandler0) {
4053   message_received = false;
4054   v8::HandleScope scope(CcTest::isolate());
4055   CHECK(!message_received);
4056   LocalContext context;
4057   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
4058   v8::Handle<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4059   script->Run();
4060   CHECK(message_received);
4061   // clear out the message listener
4062   v8::V8::RemoveMessageListeners(check_message_0);
4063 }
4064
4065
4066 static void check_message_1(v8::Handle<v8::Message> message,
4067                             v8::Handle<Value> data) {
4068   CHECK(data->IsNumber());
4069   CHECK_EQ(1337, data->Int32Value());
4070   CHECK(!message->IsSharedCrossOrigin());
4071   message_received = true;
4072 }
4073
4074
4075 TEST(MessageHandler1) {
4076   message_received = false;
4077   v8::HandleScope scope(CcTest::isolate());
4078   CHECK(!message_received);
4079   v8::V8::AddMessageListener(check_message_1);
4080   LocalContext context;
4081   CompileRun("throw 1337;");
4082   CHECK(message_received);
4083   // clear out the message listener
4084   v8::V8::RemoveMessageListeners(check_message_1);
4085 }
4086
4087
4088 static void check_message_2(v8::Handle<v8::Message> message,
4089                             v8::Handle<Value> data) {
4090   LocalContext context;
4091   CHECK(data->IsObject());
4092   v8::Local<v8::Value> hidden_property =
4093       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4094   CHECK(v8_str("hidden value")->Equals(hidden_property));
4095   CHECK(!message->IsSharedCrossOrigin());
4096   message_received = true;
4097 }
4098
4099
4100 TEST(MessageHandler2) {
4101   message_received = false;
4102   v8::HandleScope scope(CcTest::isolate());
4103   CHECK(!message_received);
4104   v8::V8::AddMessageListener(check_message_2);
4105   LocalContext context;
4106   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4107   v8::Object::Cast(*error)
4108       ->SetHiddenValue(v8_str("hidden key"), v8_str("hidden value"));
4109   context->Global()->Set(v8_str("error"), error);
4110   CompileRun("throw error;");
4111   CHECK(message_received);
4112   // clear out the message listener
4113   v8::V8::RemoveMessageListeners(check_message_2);
4114 }
4115
4116
4117 static void check_message_3(v8::Handle<v8::Message> message,
4118                             v8::Handle<Value> data) {
4119   CHECK(message->IsSharedCrossOrigin());
4120   CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
4121   CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
4122   CHECK(message->GetScriptOrigin().Options().IsOpaque());
4123   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4124   CHECK_EQ(7.40, message->GetScriptOrigin().SourceMapUrl()->NumberValue());
4125   message_received = true;
4126 }
4127
4128
4129 TEST(MessageHandler3) {
4130   message_received = false;
4131   v8::Isolate* isolate = CcTest::isolate();
4132   v8::HandleScope scope(isolate);
4133   CHECK(!message_received);
4134   v8::V8::AddMessageListener(check_message_3);
4135   LocalContext context;
4136   v8::ScriptOrigin origin = v8::ScriptOrigin(
4137       v8_str("6.75"), v8::Integer::New(isolate, 1),
4138       v8::Integer::New(isolate, 2), v8::True(isolate), Handle<v8::Integer>(),
4139       v8::True(isolate), v8_str("7.40"), v8::True(isolate));
4140   v8::Handle<v8::Script> script =
4141       Script::Compile(v8_str("throw 'error'"), &origin);
4142   script->Run();
4143   CHECK(message_received);
4144   // clear out the message listener
4145   v8::V8::RemoveMessageListeners(check_message_3);
4146 }
4147
4148
4149 static void check_message_4(v8::Handle<v8::Message> message,
4150                             v8::Handle<Value> data) {
4151   CHECK(!message->IsSharedCrossOrigin());
4152   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4153   message_received = true;
4154 }
4155
4156
4157 TEST(MessageHandler4) {
4158   message_received = false;
4159   v8::Isolate* isolate = CcTest::isolate();
4160   v8::HandleScope scope(isolate);
4161   CHECK(!message_received);
4162   v8::V8::AddMessageListener(check_message_4);
4163   LocalContext context;
4164   v8::ScriptOrigin origin =
4165       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4166                        v8::Integer::New(isolate, 2), v8::False(isolate));
4167   v8::Handle<v8::Script> script =
4168       Script::Compile(v8_str("throw 'error'"), &origin);
4169   script->Run();
4170   CHECK(message_received);
4171   // clear out the message listener
4172   v8::V8::RemoveMessageListeners(check_message_4);
4173 }
4174
4175
4176 static void check_message_5a(v8::Handle<v8::Message> message,
4177                              v8::Handle<Value> data) {
4178   CHECK(message->IsSharedCrossOrigin());
4179   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4180   message_received = true;
4181 }
4182
4183
4184 static void check_message_5b(v8::Handle<v8::Message> message,
4185                              v8::Handle<Value> data) {
4186   CHECK(!message->IsSharedCrossOrigin());
4187   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4188   message_received = true;
4189 }
4190
4191
4192 TEST(MessageHandler5) {
4193   message_received = false;
4194   v8::Isolate* isolate = CcTest::isolate();
4195   v8::HandleScope scope(isolate);
4196   CHECK(!message_received);
4197   v8::V8::AddMessageListener(check_message_5a);
4198   LocalContext context;
4199   v8::ScriptOrigin origin1 =
4200       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4201                        v8::Integer::New(isolate, 2), v8::True(isolate));
4202   v8::Handle<v8::Script> script =
4203       Script::Compile(v8_str("throw 'error'"), &origin1);
4204   script->Run();
4205   CHECK(message_received);
4206   // clear out the message listener
4207   v8::V8::RemoveMessageListeners(check_message_5a);
4208
4209   message_received = false;
4210   v8::V8::AddMessageListener(check_message_5b);
4211   v8::ScriptOrigin origin2 =
4212       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4213                        v8::Integer::New(isolate, 2), v8::False(isolate));
4214   script = Script::Compile(v8_str("throw 'error'"), &origin2);
4215   script->Run();
4216   CHECK(message_received);
4217   // clear out the message listener
4218   v8::V8::RemoveMessageListeners(check_message_5b);
4219 }
4220
4221
4222 TEST(NativeWeakMap) {
4223   v8::Isolate* isolate = CcTest::isolate();
4224   HandleScope scope(isolate);
4225   Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
4226   CHECK(!weak_map.IsEmpty());
4227
4228   LocalContext env;
4229   Local<Object> value = v8::Object::New(isolate);
4230
4231   Local<Object> local1 = v8::Object::New(isolate);
4232   CHECK(!weak_map->Has(local1));
4233   CHECK(weak_map->Get(local1)->IsUndefined());
4234   weak_map->Set(local1, value);
4235   CHECK(weak_map->Has(local1));
4236   CHECK(value->Equals(weak_map->Get(local1)));
4237
4238   WeakCallCounter counter(1234);
4239   WeakCallCounterAndPersistent<Value> o1(&counter);
4240   WeakCallCounterAndPersistent<Value> o2(&counter);
4241   WeakCallCounterAndPersistent<Value> s1(&counter);
4242   {
4243     HandleScope scope(isolate);
4244     Local<v8::Object> obj1 = v8::Object::New(isolate);
4245     Local<v8::Object> obj2 = v8::Object::New(isolate);
4246     Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
4247
4248     weak_map->Set(obj1, value);
4249     weak_map->Set(obj2, value);
4250     weak_map->Set(sym1, value);
4251
4252     o1.handle.Reset(isolate, obj1);
4253     o2.handle.Reset(isolate, obj2);
4254     s1.handle.Reset(isolate, sym1);
4255
4256     CHECK(weak_map->Has(local1));
4257     CHECK(weak_map->Has(obj1));
4258     CHECK(weak_map->Has(obj2));
4259     CHECK(weak_map->Has(sym1));
4260
4261     CHECK(value->Equals(weak_map->Get(local1)));
4262     CHECK(value->Equals(weak_map->Get(obj1)));
4263     CHECK(value->Equals(weak_map->Get(obj2)));
4264     CHECK(value->Equals(weak_map->Get(sym1)));
4265   }
4266   CcTest::heap()->CollectAllGarbage();
4267   {
4268     HandleScope scope(isolate);
4269     CHECK(value->Equals(weak_map->Get(local1)));
4270     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o1.handle))));
4271     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o2.handle))));
4272     CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, s1.handle))));
4273   }
4274
4275   o1.handle.SetWeak(&o1, &WeakPointerCallback,
4276                     v8::WeakCallbackType::kParameter);
4277   o2.handle.SetWeak(&o2, &WeakPointerCallback,
4278                     v8::WeakCallbackType::kParameter);
4279   s1.handle.SetWeak(&s1, &WeakPointerCallback,
4280                     v8::WeakCallbackType::kParameter);
4281
4282   CcTest::heap()->CollectAllGarbage();
4283   CHECK_EQ(3, counter.NumberOfWeakCalls());
4284
4285   CHECK(o1.handle.IsEmpty());
4286   CHECK(o2.handle.IsEmpty());
4287   CHECK(s1.handle.IsEmpty());
4288
4289   CHECK(value->Equals(weak_map->Get(local1)));
4290   CHECK(weak_map->Delete(local1));
4291   CHECK(!weak_map->Has(local1));
4292   CHECK(weak_map->Get(local1)->IsUndefined());
4293 }
4294
4295
4296 THREADED_TEST(GetSetProperty) {
4297   LocalContext context;
4298   v8::Isolate* isolate = context->GetIsolate();
4299   v8::HandleScope scope(isolate);
4300   context->Global()->Set(v8_str("foo"), v8_num(14));
4301   context->Global()->Set(v8_str("12"), v8_num(92));
4302   context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
4303   context->Global()->Set(v8_num(13), v8_num(56));
4304   Local<Value> foo = CompileRun("this.foo");
4305   CHECK_EQ(14, foo->Int32Value());
4306   Local<Value> twelve = CompileRun("this[12]");
4307   CHECK_EQ(92, twelve->Int32Value());
4308   Local<Value> sixteen = CompileRun("this[16]");
4309   CHECK_EQ(32, sixteen->Int32Value());
4310   Local<Value> thirteen = CompileRun("this[13]");
4311   CHECK_EQ(56, thirteen->Int32Value());
4312   CHECK_EQ(92,
4313            context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
4314   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4315   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
4316   CHECK_EQ(32,
4317            context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
4318   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4319   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
4320   CHECK_EQ(56,
4321            context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
4322   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4323   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4324 }
4325
4326
4327 THREADED_TEST(PropertyAttributes) {
4328   LocalContext context;
4329   v8::HandleScope scope(context->GetIsolate());
4330   // none
4331   Local<String> prop = v8_str("none");
4332   context->Global()->Set(prop, v8_num(7));
4333   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4334   // read-only
4335   prop = v8_str("read_only");
4336   context->Global()->ForceSet(prop, v8_num(7), v8::ReadOnly);
4337   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4338   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
4339   CompileRun("read_only = 9");
4340   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4341   context->Global()->Set(prop, v8_num(10));
4342   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4343   // dont-delete
4344   prop = v8_str("dont_delete");
4345   context->Global()->ForceSet(prop, v8_num(13), v8::DontDelete);
4346   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4347   CompileRun("delete dont_delete");
4348   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4349   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4350   // dont-enum
4351   prop = v8_str("dont_enum");
4352   context->Global()->ForceSet(prop, v8_num(28), v8::DontEnum);
4353   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4354   // absent
4355   prop = v8_str("absent");
4356   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4357   Local<Value> fake_prop = v8_num(1);
4358   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4359   // exception
4360   TryCatch try_catch(context->GetIsolate());
4361   Local<Value> exception =
4362       CompileRun("({ toString: function() { throw 'exception';} })");
4363   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4364   CHECK(try_catch.HasCaught());
4365   String::Utf8Value exception_value(try_catch.Exception());
4366   CHECK_EQ(0, strcmp("exception", *exception_value));
4367   try_catch.Reset();
4368 }
4369
4370
4371 THREADED_TEST(Array) {
4372   LocalContext context;
4373   v8::HandleScope scope(context->GetIsolate());
4374   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
4375   CHECK_EQ(0u, array->Length());
4376   CHECK(array->Get(0)->IsUndefined());
4377   CHECK(!array->Has(0));
4378   CHECK(array->Get(100)->IsUndefined());
4379   CHECK(!array->Has(100));
4380   array->Set(2, v8_num(7));
4381   CHECK_EQ(3u, array->Length());
4382   CHECK(!array->Has(0));
4383   CHECK(!array->Has(1));
4384   CHECK(array->Has(2));
4385   CHECK_EQ(7, array->Get(2)->Int32Value());
4386   Local<Value> obj = CompileRun("[1, 2, 3]");
4387   Local<v8::Array> arr = obj.As<v8::Array>();
4388   CHECK_EQ(3u, arr->Length());
4389   CHECK_EQ(1, arr->Get(0)->Int32Value());
4390   CHECK_EQ(2, arr->Get(1)->Int32Value());
4391   CHECK_EQ(3, arr->Get(2)->Int32Value());
4392   array = v8::Array::New(context->GetIsolate(), 27);
4393   CHECK_EQ(27u, array->Length());
4394   array = v8::Array::New(context->GetIsolate(), -27);
4395   CHECK_EQ(0u, array->Length());
4396 }
4397
4398
4399 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
4400   v8::EscapableHandleScope scope(args.GetIsolate());
4401   ApiTestFuzzer::Fuzz();
4402   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
4403   for (int i = 0; i < args.Length(); i++) result->Set(i, args[i]);
4404   args.GetReturnValue().Set(scope.Escape(result));
4405 }
4406
4407
4408 THREADED_TEST(Vector) {
4409   v8::Isolate* isolate = CcTest::isolate();
4410   v8::HandleScope scope(isolate);
4411   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
4412   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
4413   LocalContext context(0, global);
4414
4415   const char* fun = "f()";
4416   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
4417   CHECK_EQ(0u, a0->Length());
4418
4419   const char* fun2 = "f(11)";
4420   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
4421   CHECK_EQ(1u, a1->Length());
4422   CHECK_EQ(11, a1->Get(0)->Int32Value());
4423
4424   const char* fun3 = "f(12, 13)";
4425   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
4426   CHECK_EQ(2u, a2->Length());
4427   CHECK_EQ(12, a2->Get(0)->Int32Value());
4428   CHECK_EQ(13, a2->Get(1)->Int32Value());
4429
4430   const char* fun4 = "f(14, 15, 16)";
4431   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
4432   CHECK_EQ(3u, a3->Length());
4433   CHECK_EQ(14, a3->Get(0)->Int32Value());
4434   CHECK_EQ(15, a3->Get(1)->Int32Value());
4435   CHECK_EQ(16, a3->Get(2)->Int32Value());
4436
4437   const char* fun5 = "f(17, 18, 19, 20)";
4438   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
4439   CHECK_EQ(4u, a4->Length());
4440   CHECK_EQ(17, a4->Get(0)->Int32Value());
4441   CHECK_EQ(18, a4->Get(1)->Int32Value());
4442   CHECK_EQ(19, a4->Get(2)->Int32Value());
4443   CHECK_EQ(20, a4->Get(3)->Int32Value());
4444 }
4445
4446
4447 THREADED_TEST(FunctionCall) {
4448   LocalContext context;
4449   v8::Isolate* isolate = context->GetIsolate();
4450   v8::HandleScope scope(isolate);
4451   CompileRun(
4452       "function Foo() {"
4453       "  var result = [];"
4454       "  for (var i = 0; i < arguments.length; i++) {"
4455       "    result.push(arguments[i]);"
4456       "  }"
4457       "  return result;"
4458       "}"
4459       "function ReturnThisSloppy() {"
4460       "  return this;"
4461       "}"
4462       "function ReturnThisStrict() {"
4463       "  'use strict';"
4464       "  return this;"
4465       "}");
4466   Local<Function> Foo =
4467       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4468   Local<Function> ReturnThisSloppy =
4469       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4470   Local<Function> ReturnThisStrict =
4471       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
4472
4473   v8::Handle<Value>* args0 = NULL;
4474   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4475   CHECK_EQ(0u, a0->Length());
4476
4477   v8::Handle<Value> args1[] = {v8_num(1.1)};
4478   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4479   CHECK_EQ(1u, a1->Length());
4480   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4481
4482   v8::Handle<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
4483   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4484   CHECK_EQ(2u, a2->Length());
4485   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4486   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4487
4488   v8::Handle<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
4489   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4490   CHECK_EQ(3u, a3->Length());
4491   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4492   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4493   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4494
4495   v8::Handle<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
4496                                v8_num(10.11)};
4497   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4498   CHECK_EQ(4u, a4->Length());
4499   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4500   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4501   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4502   CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4503
4504   Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4505   CHECK(r1->StrictEquals(context->Global()));
4506   Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4507   CHECK(r2->StrictEquals(context->Global()));
4508   Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4509   CHECK(r3->IsNumberObject());
4510   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4511   Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4512   CHECK(r4->IsStringObject());
4513   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4514   Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4515   CHECK(r5->IsBooleanObject());
4516   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4517
4518   Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4519   CHECK(r6->IsUndefined());
4520   Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4521   CHECK(r7->IsNull());
4522   Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4523   CHECK(r8->StrictEquals(v8_num(42)));
4524   Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4525   CHECK(r9->StrictEquals(v8_str("hello")));
4526   Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4527   CHECK(r10->StrictEquals(v8::True(isolate)));
4528 }
4529
4530
4531 THREADED_TEST(ConstructCall) {
4532   LocalContext context;
4533   v8::Isolate* isolate = context->GetIsolate();
4534   v8::HandleScope scope(isolate);
4535   CompileRun(
4536       "function Foo() {"
4537       "  var result = [];"
4538       "  for (var i = 0; i < arguments.length; i++) {"
4539       "    result.push(arguments[i]);"
4540       "  }"
4541       "  return result;"
4542       "}");
4543   Local<Function> Foo =
4544       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4545
4546   v8::Handle<Value>* args0 = NULL;
4547   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4548   CHECK_EQ(0u, a0->Length());
4549
4550   v8::Handle<Value> args1[] = {v8_num(1.1)};
4551   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4552   CHECK_EQ(1u, a1->Length());
4553   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4554
4555   v8::Handle<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
4556   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4557   CHECK_EQ(2u, a2->Length());
4558   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4559   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4560
4561   v8::Handle<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
4562   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4563   CHECK_EQ(3u, a3->Length());
4564   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4565   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4566   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4567
4568   v8::Handle<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
4569                                v8_num(10.11)};
4570   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4571   CHECK_EQ(4u, a4->Length());
4572   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4573   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4574   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4575   CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4576 }
4577
4578
4579 static void CheckUncle(v8::TryCatch* try_catch) {
4580   CHECK(try_catch->HasCaught());
4581   String::Utf8Value str_value(try_catch->Exception());
4582   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
4583   try_catch->Reset();
4584 }
4585
4586
4587 THREADED_TEST(ConversionNumber) {
4588   LocalContext env;
4589   v8::Isolate* isolate = env->GetIsolate();
4590   v8::HandleScope scope(isolate);
4591   // Very large number.
4592   CompileRun("var obj = Math.pow(2,32) * 1237;");
4593   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4594   CHECK_EQ(5312874545152.0, obj->ToNumber(isolate)->Value());
4595   CHECK_EQ(0, obj->ToInt32(isolate)->Value());
4596   CHECK(0u ==
4597         obj->ToUint32(isolate)->Value());  // NOLINT - no CHECK_EQ for unsigned.
4598   // Large number.
4599   CompileRun("var obj = -1234567890123;");
4600   obj = env->Global()->Get(v8_str("obj"));
4601   CHECK_EQ(-1234567890123.0, obj->ToNumber(isolate)->Value());
4602   CHECK_EQ(-1912276171, obj->ToInt32(isolate)->Value());
4603   CHECK(2382691125u == obj->ToUint32(isolate)->Value());  // NOLINT
4604   // Small positive integer.
4605   CompileRun("var obj = 42;");
4606   obj = env->Global()->Get(v8_str("obj"));
4607   CHECK_EQ(42.0, obj->ToNumber(isolate)->Value());
4608   CHECK_EQ(42, obj->ToInt32(isolate)->Value());
4609   CHECK(42u == obj->ToUint32(isolate)->Value());  // NOLINT
4610   // Negative integer.
4611   CompileRun("var obj = -37;");
4612   obj = env->Global()->Get(v8_str("obj"));
4613   CHECK_EQ(-37.0, obj->ToNumber(isolate)->Value());
4614   CHECK_EQ(-37, obj->ToInt32(isolate)->Value());
4615   CHECK(4294967259u == obj->ToUint32(isolate)->Value());  // NOLINT
4616   // Positive non-int32 integer.
4617   CompileRun("var obj = 0x81234567;");
4618   obj = env->Global()->Get(v8_str("obj"));
4619   CHECK_EQ(2166572391.0, obj->ToNumber(isolate)->Value());
4620   CHECK_EQ(-2128394905, obj->ToInt32(isolate)->Value());
4621   CHECK(2166572391u == obj->ToUint32(isolate)->Value());  // NOLINT
4622   // Fraction.
4623   CompileRun("var obj = 42.3;");
4624   obj = env->Global()->Get(v8_str("obj"));
4625   CHECK_EQ(42.3, obj->ToNumber(isolate)->Value());
4626   CHECK_EQ(42, obj->ToInt32(isolate)->Value());
4627   CHECK(42u == obj->ToUint32(isolate)->Value());  // NOLINT
4628   // Large negative fraction.
4629   CompileRun("var obj = -5726623061.75;");
4630   obj = env->Global()->Get(v8_str("obj"));
4631   CHECK_EQ(-5726623061.75, obj->ToNumber(isolate)->Value());
4632   CHECK_EQ(-1431655765, obj->ToInt32(isolate)->Value());
4633   CHECK(2863311531u == obj->ToUint32(isolate)->Value());  // NOLINT
4634 }
4635
4636
4637 THREADED_TEST(isNumberType) {
4638   LocalContext env;
4639   v8::HandleScope scope(env->GetIsolate());
4640   // Very large number.
4641   CompileRun("var obj = Math.pow(2,32) * 1237;");
4642   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4643   CHECK(!obj->IsInt32());
4644   CHECK(!obj->IsUint32());
4645   // Large negative number.
4646   CompileRun("var obj = -1234567890123;");
4647   obj = env->Global()->Get(v8_str("obj"));
4648   CHECK(!obj->IsInt32());
4649   CHECK(!obj->IsUint32());
4650   // Small positive integer.
4651   CompileRun("var obj = 42;");
4652   obj = env->Global()->Get(v8_str("obj"));
4653   CHECK(obj->IsInt32());
4654   CHECK(obj->IsUint32());
4655   // Negative integer.
4656   CompileRun("var obj = -37;");
4657   obj = env->Global()->Get(v8_str("obj"));
4658   CHECK(obj->IsInt32());
4659   CHECK(!obj->IsUint32());
4660   // Positive non-int32 integer.
4661   CompileRun("var obj = 0x81234567;");
4662   obj = env->Global()->Get(v8_str("obj"));
4663   CHECK(!obj->IsInt32());
4664   CHECK(obj->IsUint32());
4665   // Fraction.
4666   CompileRun("var obj = 42.3;");
4667   obj = env->Global()->Get(v8_str("obj"));
4668   CHECK(!obj->IsInt32());
4669   CHECK(!obj->IsUint32());
4670   // Large negative fraction.
4671   CompileRun("var obj = -5726623061.75;");
4672   obj = env->Global()->Get(v8_str("obj"));
4673   CHECK(!obj->IsInt32());
4674   CHECK(!obj->IsUint32());
4675   // Positive zero
4676   CompileRun("var obj = 0.0;");
4677   obj = env->Global()->Get(v8_str("obj"));
4678   CHECK(obj->IsInt32());
4679   CHECK(obj->IsUint32());
4680   // Positive zero
4681   CompileRun("var obj = -0.0;");
4682   obj = env->Global()->Get(v8_str("obj"));
4683   CHECK(!obj->IsInt32());
4684   CHECK(!obj->IsUint32());
4685 }
4686
4687
4688 THREADED_TEST(ConversionException) {
4689   LocalContext env;
4690   v8::Isolate* isolate = env->GetIsolate();
4691   v8::HandleScope scope(isolate);
4692   CompileRun(
4693       "function TestClass() { };"
4694       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4695       "var obj = new TestClass();");
4696   Local<Value> obj = env->Global()->Get(v8_str("obj"));
4697
4698   v8::TryCatch try_catch(isolate);
4699
4700   Local<Value> to_string_result = obj->ToString(isolate);
4701   CHECK(to_string_result.IsEmpty());
4702   CheckUncle(&try_catch);
4703
4704   Local<Value> to_number_result = obj->ToNumber(isolate);
4705   CHECK(to_number_result.IsEmpty());
4706   CheckUncle(&try_catch);
4707
4708   Local<Value> to_integer_result = obj->ToInteger(isolate);
4709   CHECK(to_integer_result.IsEmpty());
4710   CheckUncle(&try_catch);
4711
4712   Local<Value> to_uint32_result = obj->ToUint32(isolate);
4713   CHECK(to_uint32_result.IsEmpty());
4714   CheckUncle(&try_catch);
4715
4716   Local<Value> to_int32_result = obj->ToInt32(isolate);
4717   CHECK(to_int32_result.IsEmpty());
4718   CheckUncle(&try_catch);
4719
4720   Local<Value> to_object_result = v8::Undefined(isolate)->ToObject(isolate);
4721   CHECK(to_object_result.IsEmpty());
4722   CHECK(try_catch.HasCaught());
4723   try_catch.Reset();
4724
4725   int32_t int32_value = obj->Int32Value();
4726   CHECK_EQ(0, int32_value);
4727   CheckUncle(&try_catch);
4728
4729   uint32_t uint32_value = obj->Uint32Value();
4730   CHECK_EQ(0u, uint32_value);
4731   CheckUncle(&try_catch);
4732
4733   double number_value = obj->NumberValue();
4734   CHECK(std::isnan(number_value));
4735   CheckUncle(&try_catch);
4736
4737   int64_t integer_value = obj->IntegerValue();
4738   CHECK_EQ(0, integer_value);
4739   CheckUncle(&try_catch);
4740 }
4741
4742
4743 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
4744   ApiTestFuzzer::Fuzz();
4745   args.GetIsolate()->ThrowException(v8_str("konto"));
4746 }
4747
4748
4749 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4750   if (args.Length() < 1) {
4751     args.GetReturnValue().Set(false);
4752     return;
4753   }
4754   v8::HandleScope scope(args.GetIsolate());
4755   v8::TryCatch try_catch(args.GetIsolate());
4756   Local<Value> result = CompileRun(args[0]->ToString(args.GetIsolate()));
4757   CHECK(!try_catch.HasCaught() || result.IsEmpty());
4758   args.GetReturnValue().Set(try_catch.HasCaught());
4759 }
4760
4761
4762 THREADED_TEST(APICatch) {
4763   v8::Isolate* isolate = CcTest::isolate();
4764   v8::HandleScope scope(isolate);
4765   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4766   templ->Set(v8_str("ThrowFromC"),
4767              v8::FunctionTemplate::New(isolate, ThrowFromC));
4768   LocalContext context(0, templ);
4769   CompileRun(
4770       "var thrown = false;"
4771       "try {"
4772       "  ThrowFromC();"
4773       "} catch (e) {"
4774       "  thrown = true;"
4775       "}");
4776   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4777   CHECK(thrown->BooleanValue());
4778 }
4779
4780
4781 THREADED_TEST(APIThrowTryCatch) {
4782   v8::Isolate* isolate = CcTest::isolate();
4783   v8::HandleScope scope(isolate);
4784   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4785   templ->Set(v8_str("ThrowFromC"),
4786              v8::FunctionTemplate::New(isolate, ThrowFromC));
4787   LocalContext context(0, templ);
4788   v8::TryCatch try_catch(isolate);
4789   CompileRun("ThrowFromC();");
4790   CHECK(try_catch.HasCaught());
4791 }
4792
4793
4794 // Test that a try-finally block doesn't shadow a try-catch block
4795 // when setting up an external handler.
4796 //
4797 // BUG(271): Some of the exception propagation does not work on the
4798 // ARM simulator because the simulator separates the C++ stack and the
4799 // JS stack.  This test therefore fails on the simulator.  The test is
4800 // not threaded to allow the threading tests to run on the simulator.
4801 TEST(TryCatchInTryFinally) {
4802   v8::Isolate* isolate = CcTest::isolate();
4803   v8::HandleScope scope(isolate);
4804   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4805   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
4806   LocalContext context(0, templ);
4807   Local<Value> result = CompileRun(
4808       "try {"
4809       "  try {"
4810       "    CCatcher('throw 7;');"
4811       "  } finally {"
4812       "  }"
4813       "} catch (e) {"
4814       "}");
4815   CHECK(result->IsTrue());
4816 }
4817
4818
4819 static void check_reference_error_message(v8::Handle<v8::Message> message,
4820                                           v8::Handle<v8::Value> data) {
4821   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4822   CHECK(message->Get()->Equals(v8_str(reference_error)));
4823 }
4824
4825
4826 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
4827   ApiTestFuzzer::Fuzz();
4828   CHECK(false);
4829 }
4830
4831
4832 // Test that overwritten methods are not invoked on uncaught exception
4833 // formatting. However, they are invoked when performing normal error
4834 // string conversions.
4835 TEST(APIThrowMessageOverwrittenToString) {
4836   v8::Isolate* isolate = CcTest::isolate();
4837   v8::HandleScope scope(isolate);
4838   v8::V8::AddMessageListener(check_reference_error_message);
4839   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4840   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
4841   LocalContext context(NULL, templ);
4842   CompileRun("asdf;");
4843   CompileRun(
4844       "var limit = {};"
4845       "limit.valueOf = fail;"
4846       "Error.stackTraceLimit = limit;");
4847   CompileRun("asdf");
4848   CompileRun("Array.prototype.pop = fail;");
4849   CompileRun("Object.prototype.hasOwnProperty = fail;");
4850   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
4851   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4852   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
4853   CompileRun(
4854       "ReferenceError.prototype.toString ="
4855       "  function() { return 'Whoops' }");
4856   CompileRun("asdf;");
4857   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4858   CompileRun("asdf;");
4859   CompileRun("ReferenceError.prototype.constructor = void 0;");
4860   CompileRun("asdf;");
4861   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4862   CompileRun("asdf;");
4863   CompileRun("ReferenceError.prototype = new Object();");
4864   CompileRun("asdf;");
4865   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4866   CHECK(string->Equals(v8_str("Whoops")));
4867   CompileRun(
4868       "ReferenceError.prototype.constructor = new Object();"
4869       "ReferenceError.prototype.constructor.name = 1;"
4870       "Number.prototype.toString = function() { return 'Whoops'; };"
4871       "ReferenceError.prototype.toString = Object.prototype.toString;");
4872   CompileRun("asdf;");
4873   v8::V8::RemoveMessageListeners(check_reference_error_message);
4874 }
4875
4876
4877 static void check_custom_error_tostring(v8::Handle<v8::Message> message,
4878                                         v8::Handle<v8::Value> data) {
4879   const char* uncaught_error = "Uncaught MyError toString";
4880   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4881 }
4882
4883
4884 TEST(CustomErrorToString) {
4885   LocalContext context;
4886   v8::HandleScope scope(context->GetIsolate());
4887   v8::V8::AddMessageListener(check_custom_error_tostring);
4888   CompileRun(
4889       "function MyError(name, message) {                   "
4890       "  this.name = name;                                 "
4891       "  this.message = message;                           "
4892       "}                                                   "
4893       "MyError.prototype = Object.create(Error.prototype); "
4894       "MyError.prototype.toString = function() {           "
4895       "  return 'MyError toString';                        "
4896       "};                                                  "
4897       "throw new MyError('my name', 'my message');         ");
4898   v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4899 }
4900
4901
4902 static void check_custom_error_message(v8::Handle<v8::Message> message,
4903                                        v8::Handle<v8::Value> data) {
4904   const char* uncaught_error = "Uncaught MyError: my message";
4905   printf("%s\n", *v8::String::Utf8Value(message->Get()));
4906   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4907 }
4908
4909
4910 TEST(CustomErrorMessage) {
4911   LocalContext context;
4912   v8::HandleScope scope(context->GetIsolate());
4913   v8::V8::AddMessageListener(check_custom_error_message);
4914
4915   // Handlebars.
4916   CompileRun(
4917       "function MyError(msg) {                             "
4918       "  this.name = 'MyError';                            "
4919       "  this.message = msg;                               "
4920       "}                                                   "
4921       "MyError.prototype = new Error();                    "
4922       "throw new MyError('my message');                    ");
4923
4924   // Closure.
4925   CompileRun(
4926       "function MyError(msg) {                             "
4927       "  this.name = 'MyError';                            "
4928       "  this.message = msg;                               "
4929       "}                                                   "
4930       "inherits = function(childCtor, parentCtor) {        "
4931       "    function tempCtor() {};                         "
4932       "    tempCtor.prototype = parentCtor.prototype;      "
4933       "    childCtor.superClass_ = parentCtor.prototype;   "
4934       "    childCtor.prototype = new tempCtor();           "
4935       "    childCtor.prototype.constructor = childCtor;    "
4936       "};                                                  "
4937       "inherits(MyError, Error);                           "
4938       "throw new MyError('my message');                    ");
4939
4940   // Object.create.
4941   CompileRun(
4942       "function MyError(msg) {                             "
4943       "  this.name = 'MyError';                            "
4944       "  this.message = msg;                               "
4945       "}                                                   "
4946       "MyError.prototype = Object.create(Error.prototype); "
4947       "throw new MyError('my message');                    ");
4948
4949   v8::V8::RemoveMessageListeners(check_custom_error_message);
4950 }
4951
4952
4953 static void check_custom_rethrowing_message(v8::Handle<v8::Message> message,
4954                                             v8::Handle<v8::Value> data) {
4955   const char* uncaught_error = "Uncaught exception";
4956   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4957 }
4958
4959
4960 TEST(CustomErrorRethrowsOnToString) {
4961   LocalContext context;
4962   v8::HandleScope scope(context->GetIsolate());
4963   v8::V8::AddMessageListener(check_custom_rethrowing_message);
4964
4965   CompileRun(
4966       "var e = { toString: function() { throw e; } };"
4967       "try { throw e; } finally {}");
4968
4969   v8::V8::RemoveMessageListeners(check_custom_rethrowing_message);
4970 }
4971
4972
4973 static void receive_message(v8::Handle<v8::Message> message,
4974                             v8::Handle<v8::Value> data) {
4975   message->Get();
4976   message_received = true;
4977 }
4978
4979
4980 TEST(APIThrowMessage) {
4981   message_received = false;
4982   v8::Isolate* isolate = CcTest::isolate();
4983   v8::HandleScope scope(isolate);
4984   v8::V8::AddMessageListener(receive_message);
4985   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4986   templ->Set(v8_str("ThrowFromC"),
4987              v8::FunctionTemplate::New(isolate, ThrowFromC));
4988   LocalContext context(0, templ);
4989   CompileRun("ThrowFromC();");
4990   CHECK(message_received);
4991   v8::V8::RemoveMessageListeners(receive_message);
4992 }
4993
4994
4995 TEST(APIThrowMessageAndVerboseTryCatch) {
4996   message_received = false;
4997   v8::Isolate* isolate = CcTest::isolate();
4998   v8::HandleScope scope(isolate);
4999   v8::V8::AddMessageListener(receive_message);
5000   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5001   templ->Set(v8_str("ThrowFromC"),
5002              v8::FunctionTemplate::New(isolate, ThrowFromC));
5003   LocalContext context(0, templ);
5004   v8::TryCatch try_catch(isolate);
5005   try_catch.SetVerbose(true);
5006   Local<Value> result = CompileRun("ThrowFromC();");
5007   CHECK(try_catch.HasCaught());
5008   CHECK(result.IsEmpty());
5009   CHECK(message_received);
5010   v8::V8::RemoveMessageListeners(receive_message);
5011 }
5012
5013
5014 TEST(APIStackOverflowAndVerboseTryCatch) {
5015   message_received = false;
5016   LocalContext context;
5017   v8::HandleScope scope(context->GetIsolate());
5018   v8::V8::AddMessageListener(receive_message);
5019   v8::TryCatch try_catch(context->GetIsolate());
5020   try_catch.SetVerbose(true);
5021   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
5022   CHECK(try_catch.HasCaught());
5023   CHECK(result.IsEmpty());
5024   CHECK(message_received);
5025   v8::V8::RemoveMessageListeners(receive_message);
5026 }
5027
5028
5029 THREADED_TEST(ExternalScriptException) {
5030   v8::Isolate* isolate = CcTest::isolate();
5031   v8::HandleScope scope(isolate);
5032   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5033   templ->Set(v8_str("ThrowFromC"),
5034              v8::FunctionTemplate::New(isolate, ThrowFromC));
5035   LocalContext context(0, templ);
5036
5037   v8::TryCatch try_catch(isolate);
5038   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
5039   CHECK(result.IsEmpty());
5040   CHECK(try_catch.HasCaught());
5041   String::Utf8Value exception_value(try_catch.Exception());
5042   CHECK_EQ(0, strcmp("konto", *exception_value));
5043 }
5044
5045
5046 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
5047   ApiTestFuzzer::Fuzz();
5048   CHECK_EQ(4, args.Length());
5049   int count = args[0]->Int32Value();
5050   int cInterval = args[2]->Int32Value();
5051   if (count == 0) {
5052     args.GetIsolate()->ThrowException(v8_str("FromC"));
5053     return;
5054   } else {
5055     Local<v8::Object> global = args.GetIsolate()->GetCurrentContext()->Global();
5056     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5057     v8::Handle<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
5058     if (count % cInterval == 0) {
5059       v8::TryCatch try_catch(args.GetIsolate());
5060       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
5061       int expected = args[3]->Int32Value();
5062       if (try_catch.HasCaught()) {
5063         CHECK_EQ(expected, count);
5064         CHECK(result.IsEmpty());
5065         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
5066       } else {
5067         CHECK_NE(expected, count);
5068       }
5069       args.GetReturnValue().Set(result);
5070       return;
5071     } else {
5072       args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5073       return;
5074     }
5075   }
5076 }
5077
5078
5079 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
5080   ApiTestFuzzer::Fuzz();
5081   CHECK_EQ(3, args.Length());
5082   bool equality = args[0]->BooleanValue();
5083   int count = args[1]->Int32Value();
5084   int expected = args[2]->Int32Value();
5085   if (equality) {
5086     CHECK_EQ(count, expected);
5087   } else {
5088     CHECK_NE(count, expected);
5089   }
5090 }
5091
5092
5093 THREADED_TEST(EvalInTryFinally) {
5094   LocalContext context;
5095   v8::HandleScope scope(context->GetIsolate());
5096   v8::TryCatch try_catch(context->GetIsolate());
5097   CompileRun(
5098       "(function() {"
5099       "  try {"
5100       "    eval('asldkf (*&^&*^');"
5101       "  } finally {"
5102       "    return;"
5103       "  }"
5104       "})()");
5105   CHECK(!try_catch.HasCaught());
5106 }
5107
5108
5109 // This test works by making a stack of alternating JavaScript and C
5110 // activations.  These activations set up exception handlers with regular
5111 // intervals, one interval for C activations and another for JavaScript
5112 // activations.  When enough activations have been created an exception is
5113 // thrown and we check that the right activation catches the exception and that
5114 // no other activations do.  The right activation is always the topmost one with
5115 // a handler, regardless of whether it is in JavaScript or C.
5116 //
5117 // The notation used to describe a test case looks like this:
5118 //
5119 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
5120 //
5121 // Each entry is an activation, either JS or C.  The index is the count at that
5122 // level.  Stars identify activations with exception handlers, the @ identifies
5123 // the exception handler that should catch the exception.
5124 //
5125 // BUG(271): Some of the exception propagation does not work on the
5126 // ARM simulator because the simulator separates the C++ stack and the
5127 // JS stack.  This test therefore fails on the simulator.  The test is
5128 // not threaded to allow the threading tests to run on the simulator.
5129 TEST(ExceptionOrder) {
5130   v8::Isolate* isolate = CcTest::isolate();
5131   v8::HandleScope scope(isolate);
5132   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5133   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
5134   templ->Set(v8_str("CThrowCountDown"),
5135              v8::FunctionTemplate::New(isolate, CThrowCountDown));
5136   LocalContext context(0, templ);
5137   CompileRun(
5138       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5139       "  if (count == 0) throw 'FromJS';"
5140       "  if (count % jsInterval == 0) {"
5141       "    try {"
5142       "      var value = CThrowCountDown(count - 1,"
5143       "                                  jsInterval,"
5144       "                                  cInterval,"
5145       "                                  expected);"
5146       "      check(false, count, expected);"
5147       "      return value;"
5148       "    } catch (e) {"
5149       "      check(true, count, expected);"
5150       "    }"
5151       "  } else {"
5152       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5153       "  }"
5154       "}");
5155   Local<Function> fun =
5156       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5157
5158   const int argc = 4;
5159   //                             count      jsInterval cInterval  expected
5160
5161   // *JS[4] *C[3] @JS[2] C[1] JS[0]
5162   v8::Handle<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
5163   fun->Call(fun, argc, a0);
5164
5165   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
5166   v8::Handle<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
5167   fun->Call(fun, argc, a1);
5168
5169   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
5170   v8::Handle<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
5171   fun->Call(fun, argc, a2);
5172
5173   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
5174   v8::Handle<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
5175   fun->Call(fun, argc, a3);
5176
5177   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
5178   v8::Handle<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
5179   fun->Call(fun, argc, a4);
5180
5181   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
5182   v8::Handle<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
5183   fun->Call(fun, argc, a5);
5184 }
5185
5186
5187 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
5188   ApiTestFuzzer::Fuzz();
5189   CHECK_EQ(1, args.Length());
5190   args.GetIsolate()->ThrowException(args[0]);
5191 }
5192
5193
5194 THREADED_TEST(ThrowValues) {
5195   v8::Isolate* isolate = CcTest::isolate();
5196   v8::HandleScope scope(isolate);
5197   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5198   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
5199   LocalContext context(0, templ);
5200   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5201       "function Run(obj) {"
5202       "  try {"
5203       "    Throw(obj);"
5204       "  } catch (e) {"
5205       "    return e;"
5206       "  }"
5207       "  return 'no exception';"
5208       "}"
5209       "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5210   CHECK_EQ(5u, result->Length());
5211   CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5212   CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5213   CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5214   CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5215   CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5216   CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5217   CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
5218 }
5219
5220
5221 THREADED_TEST(CatchZero) {
5222   LocalContext context;
5223   v8::HandleScope scope(context->GetIsolate());
5224   v8::TryCatch try_catch(context->GetIsolate());
5225   CHECK(!try_catch.HasCaught());
5226   CompileRun("throw 10");
5227   CHECK(try_catch.HasCaught());
5228   CHECK_EQ(10, try_catch.Exception()->Int32Value());
5229   try_catch.Reset();
5230   CHECK(!try_catch.HasCaught());
5231   CompileRun("throw 0");
5232   CHECK(try_catch.HasCaught());
5233   CHECK_EQ(0, try_catch.Exception()->Int32Value());
5234 }
5235
5236
5237 THREADED_TEST(CatchExceptionFromWith) {
5238   LocalContext context;
5239   v8::HandleScope scope(context->GetIsolate());
5240   v8::TryCatch try_catch(context->GetIsolate());
5241   CHECK(!try_catch.HasCaught());
5242   CompileRun("var o = {}; with (o) { throw 42; }");
5243   CHECK(try_catch.HasCaught());
5244 }
5245
5246
5247 THREADED_TEST(TryCatchAndFinallyHidingException) {
5248   LocalContext context;
5249   v8::HandleScope scope(context->GetIsolate());
5250   v8::TryCatch try_catch(context->GetIsolate());
5251   CHECK(!try_catch.HasCaught());
5252   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5253   CompileRun("f({toString: function() { throw 42; }});");
5254   CHECK(!try_catch.HasCaught());
5255 }
5256
5257
5258 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
5259   v8::TryCatch try_catch(args.GetIsolate());
5260 }
5261
5262
5263 THREADED_TEST(TryCatchAndFinally) {
5264   LocalContext context;
5265   v8::Isolate* isolate = context->GetIsolate();
5266   v8::HandleScope scope(isolate);
5267   context->Global()->Set(
5268       v8_str("native_with_try_catch"),
5269       v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
5270   v8::TryCatch try_catch(isolate);
5271   CHECK(!try_catch.HasCaught());
5272   CompileRun(
5273       "try {\n"
5274       "  throw new Error('a');\n"
5275       "} finally {\n"
5276       "  native_with_try_catch();\n"
5277       "}\n");
5278   CHECK(try_catch.HasCaught());
5279 }
5280
5281
5282 static void TryCatchNested1Helper(int depth) {
5283   if (depth > 0) {
5284     v8::TryCatch try_catch(CcTest::isolate());
5285     try_catch.SetVerbose(true);
5286     TryCatchNested1Helper(depth - 1);
5287     CHECK(try_catch.HasCaught());
5288     try_catch.ReThrow();
5289   } else {
5290     CcTest::isolate()->ThrowException(v8_str("E1"));
5291   }
5292 }
5293
5294
5295 static void TryCatchNested2Helper(int depth) {
5296   if (depth > 0) {
5297     v8::TryCatch try_catch(CcTest::isolate());
5298     try_catch.SetVerbose(true);
5299     TryCatchNested2Helper(depth - 1);
5300     CHECK(try_catch.HasCaught());
5301     try_catch.ReThrow();
5302   } else {
5303     CompileRun("throw 'E2';");
5304   }
5305 }
5306
5307
5308 TEST(TryCatchNested) {
5309   v8::V8::Initialize();
5310   LocalContext context;
5311   v8::HandleScope scope(context->GetIsolate());
5312
5313   {
5314     // Test nested try-catch with a native throw in the end.
5315     v8::TryCatch try_catch(context->GetIsolate());
5316     TryCatchNested1Helper(5);
5317     CHECK(try_catch.HasCaught());
5318     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
5319   }
5320
5321   {
5322     // Test nested try-catch with a JavaScript throw in the end.
5323     v8::TryCatch try_catch(context->GetIsolate());
5324     TryCatchNested2Helper(5);
5325     CHECK(try_catch.HasCaught());
5326     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
5327   }
5328 }
5329
5330
5331 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5332   CHECK(try_catch->HasCaught());
5333   Handle<Message> message = try_catch->Message();
5334   Handle<Value> resource = message->GetScriptOrigin().ResourceName();
5335   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5336   CHECK_EQ(0,
5337            strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
5338   CHECK_EQ(1, message->GetLineNumber());
5339   CHECK_EQ(0, message->GetStartColumn());
5340 }
5341
5342
5343 void TryCatchMixedNestingHelper(
5344     const v8::FunctionCallbackInfo<v8::Value>& args) {
5345   ApiTestFuzzer::Fuzz();
5346   v8::TryCatch try_catch(args.GetIsolate());
5347   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5348   CHECK(try_catch.HasCaught());
5349   TryCatchMixedNestingCheck(&try_catch);
5350   try_catch.ReThrow();
5351 }
5352
5353
5354 // This test ensures that an outer TryCatch in the following situation:
5355 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5356 // does not clobber the Message object generated for the inner TryCatch.
5357 // This exercises the ability of TryCatch.ReThrow() to restore the
5358 // inner pending Message before throwing the exception again.
5359 TEST(TryCatchMixedNesting) {
5360   v8::Isolate* isolate = CcTest::isolate();
5361   v8::HandleScope scope(isolate);
5362   v8::V8::Initialize();
5363   v8::TryCatch try_catch(isolate);
5364   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5365   templ->Set(v8_str("TryCatchMixedNestingHelper"),
5366              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
5367   LocalContext context(0, templ);
5368   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5369   TryCatchMixedNestingCheck(&try_catch);
5370 }
5371
5372
5373 void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
5374   ApiTestFuzzer::Fuzz();
5375   v8::TryCatch try_catch(args.GetIsolate());
5376   args.GetIsolate()->ThrowException(v8_str("boom"));
5377   CHECK(try_catch.HasCaught());
5378 }
5379
5380
5381 TEST(TryCatchNative) {
5382   v8::Isolate* isolate = CcTest::isolate();
5383   v8::HandleScope scope(isolate);
5384   v8::V8::Initialize();
5385   v8::TryCatch try_catch(isolate);
5386   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5387   templ->Set(v8_str("TryCatchNativeHelper"),
5388              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
5389   LocalContext context(0, templ);
5390   CompileRun("TryCatchNativeHelper();");
5391   CHECK(!try_catch.HasCaught());
5392 }
5393
5394
5395 void TryCatchNativeResetHelper(
5396     const v8::FunctionCallbackInfo<v8::Value>& args) {
5397   ApiTestFuzzer::Fuzz();
5398   v8::TryCatch try_catch(args.GetIsolate());
5399   args.GetIsolate()->ThrowException(v8_str("boom"));
5400   CHECK(try_catch.HasCaught());
5401   try_catch.Reset();
5402   CHECK(!try_catch.HasCaught());
5403 }
5404
5405
5406 TEST(TryCatchNativeReset) {
5407   v8::Isolate* isolate = CcTest::isolate();
5408   v8::HandleScope scope(isolate);
5409   v8::V8::Initialize();
5410   v8::TryCatch try_catch(isolate);
5411   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5412   templ->Set(v8_str("TryCatchNativeResetHelper"),
5413              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
5414   LocalContext context(0, templ);
5415   CompileRun("TryCatchNativeResetHelper();");
5416   CHECK(!try_catch.HasCaught());
5417 }
5418
5419
5420 THREADED_TEST(Equality) {
5421   LocalContext context;
5422   v8::Isolate* isolate = context->GetIsolate();
5423   v8::HandleScope scope(context->GetIsolate());
5424   // Check that equality works at all before relying on CHECK_EQ
5425   CHECK(v8_str("a")->Equals(v8_str("a")));
5426   CHECK(!v8_str("a")->Equals(v8_str("b")));
5427
5428   CHECK(v8_str("a")->Equals(v8_str("a")));
5429   CHECK(!v8_str("a")->Equals(v8_str("b")));
5430   CHECK(v8_num(1)->Equals(v8_num(1)));
5431   CHECK(v8_num(1.00)->Equals(v8_num(1)));
5432   CHECK(!v8_num(1)->Equals(v8_num(2)));
5433
5434   // Assume String is not internalized.
5435   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5436   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5437   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5438   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5439   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
5440   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
5441   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
5442   CHECK(!not_a_number->StrictEquals(not_a_number));
5443   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5444   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
5445
5446   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
5447   v8::Persistent<v8::Object> alias(isolate, obj);
5448   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
5449   alias.Reset();
5450
5451   CHECK(v8_str("a")->SameValue(v8_str("a")));
5452   CHECK(!v8_str("a")->SameValue(v8_str("b")));
5453   CHECK(!v8_str("5")->SameValue(v8_num(5)));
5454   CHECK(v8_num(1)->SameValue(v8_num(1)));
5455   CHECK(!v8_num(1)->SameValue(v8_num(2)));
5456   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5457   CHECK(not_a_number->SameValue(not_a_number));
5458   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5459   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
5460 }
5461
5462
5463 THREADED_TEST(MultiRun) {
5464   LocalContext context;
5465   v8::HandleScope scope(context->GetIsolate());
5466   Local<Script> script = v8_compile("x");
5467   for (int i = 0; i < 10; i++) script->Run();
5468 }
5469
5470
5471 static void GetXValue(Local<String> name,
5472                       const v8::PropertyCallbackInfo<v8::Value>& info) {
5473   ApiTestFuzzer::Fuzz();
5474   CHECK(info.Data()->Equals(v8_str("donut")));
5475   CHECK(name->Equals(v8_str("x")));
5476   info.GetReturnValue().Set(name);
5477 }
5478
5479
5480 THREADED_TEST(SimplePropertyRead) {
5481   LocalContext context;
5482   v8::Isolate* isolate = context->GetIsolate();
5483   v8::HandleScope scope(isolate);
5484   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5485   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5486   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5487   Local<Script> script = v8_compile("obj.x");
5488   for (int i = 0; i < 10; i++) {
5489     Local<Value> result = script->Run();
5490     CHECK(result->Equals(v8_str("x")));
5491   }
5492 }
5493
5494
5495 THREADED_TEST(DefinePropertyOnAPIAccessor) {
5496   LocalContext context;
5497   v8::Isolate* isolate = context->GetIsolate();
5498   v8::HandleScope scope(isolate);
5499   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5500   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5501   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5502
5503   // Uses getOwnPropertyDescriptor to check the configurable status
5504   Local<Script> script_desc = v8_compile(
5505       "var prop = Object.getOwnPropertyDescriptor( "
5506       "obj, 'x');"
5507       "prop.configurable;");
5508   Local<Value> result = script_desc->Run();
5509   CHECK_EQ(result->BooleanValue(), true);
5510
5511   // Redefine get - but still configurable
5512   Local<Script> script_define = v8_compile(
5513       "var desc = { get: function(){return 42; },"
5514       "            configurable: true };"
5515       "Object.defineProperty(obj, 'x', desc);"
5516       "obj.x");
5517   result = script_define->Run();
5518   CHECK(result->Equals(v8_num(42)));
5519
5520   // Check that the accessor is still configurable
5521   result = script_desc->Run();
5522   CHECK_EQ(result->BooleanValue(), true);
5523
5524   // Redefine to a non-configurable
5525   script_define = v8_compile(
5526       "var desc = { get: function(){return 43; },"
5527       "             configurable: false };"
5528       "Object.defineProperty(obj, 'x', desc);"
5529       "obj.x");
5530   result = script_define->Run();
5531   CHECK(result->Equals(v8_num(43)));
5532   result = script_desc->Run();
5533   CHECK_EQ(result->BooleanValue(), false);
5534
5535   // Make sure that it is not possible to redefine again
5536   v8::TryCatch try_catch(isolate);
5537   result = script_define->Run();
5538   CHECK(try_catch.HasCaught());
5539   String::Utf8Value exception_value(try_catch.Exception());
5540   CHECK_EQ(0,
5541            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5542 }
5543
5544
5545 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
5546   v8::Isolate* isolate = CcTest::isolate();
5547   v8::HandleScope scope(isolate);
5548   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5549   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5550   LocalContext context;
5551   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5552
5553   Local<Script> script_desc = v8_compile(
5554       "var prop ="
5555       "Object.getOwnPropertyDescriptor( "
5556       "obj, 'x');"
5557       "prop.configurable;");
5558   Local<Value> result = script_desc->Run();
5559   CHECK_EQ(result->BooleanValue(), true);
5560
5561   Local<Script> script_define = v8_compile(
5562       "var desc = {get: function(){return 42; },"
5563       "            configurable: true };"
5564       "Object.defineProperty(obj, 'x', desc);"
5565       "obj.x");
5566   result = script_define->Run();
5567   CHECK(result->Equals(v8_num(42)));
5568
5569
5570   result = script_desc->Run();
5571   CHECK_EQ(result->BooleanValue(), true);
5572
5573
5574   script_define = v8_compile(
5575       "var desc = {get: function(){return 43; },"
5576       "            configurable: false };"
5577       "Object.defineProperty(obj, 'x', desc);"
5578       "obj.x");
5579   result = script_define->Run();
5580   CHECK(result->Equals(v8_num(43)));
5581   result = script_desc->Run();
5582
5583   CHECK_EQ(result->BooleanValue(), false);
5584
5585   v8::TryCatch try_catch(isolate);
5586   result = script_define->Run();
5587   CHECK(try_catch.HasCaught());
5588   String::Utf8Value exception_value(try_catch.Exception());
5589   CHECK_EQ(0,
5590            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5591 }
5592
5593
5594 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5595                                                 char const* name) {
5596   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5597 }
5598
5599
5600 THREADED_TEST(DefineAPIAccessorOnObject) {
5601   v8::Isolate* isolate = CcTest::isolate();
5602   v8::HandleScope scope(isolate);
5603   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5604   LocalContext context;
5605
5606   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5607   CompileRun("var obj2 = {};");
5608
5609   CHECK(CompileRun("obj1.x")->IsUndefined());
5610   CHECK(CompileRun("obj2.x")->IsUndefined());
5611
5612   CHECK(GetGlobalProperty(&context, "obj1")
5613             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5614
5615   ExpectString("obj1.x", "x");
5616   CHECK(CompileRun("obj2.x")->IsUndefined());
5617
5618   CHECK(GetGlobalProperty(&context, "obj2")
5619             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5620
5621   ExpectString("obj1.x", "x");
5622   ExpectString("obj2.x", "x");
5623
5624   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5625   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5626
5627   CompileRun(
5628       "Object.defineProperty(obj1, 'x',"
5629       "{ get: function() { return 'y'; }, configurable: true })");
5630
5631   ExpectString("obj1.x", "y");
5632   ExpectString("obj2.x", "x");
5633
5634   CompileRun(
5635       "Object.defineProperty(obj2, 'x',"
5636       "{ get: function() { return 'y'; }, configurable: true })");
5637
5638   ExpectString("obj1.x", "y");
5639   ExpectString("obj2.x", "y");
5640
5641   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5642   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5643
5644   CHECK(GetGlobalProperty(&context, "obj1")
5645             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5646   CHECK(GetGlobalProperty(&context, "obj2")
5647             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5648
5649   ExpectString("obj1.x", "x");
5650   ExpectString("obj2.x", "x");
5651
5652   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5653   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5654
5655   // Define getters/setters, but now make them not configurable.
5656   CompileRun(
5657       "Object.defineProperty(obj1, 'x',"
5658       "{ get: function() { return 'z'; }, configurable: false })");
5659   CompileRun(
5660       "Object.defineProperty(obj2, 'x',"
5661       "{ get: function() { return 'z'; }, configurable: false })");
5662
5663   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5664   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5665
5666   ExpectString("obj1.x", "z");
5667   ExpectString("obj2.x", "z");
5668
5669   CHECK(!GetGlobalProperty(&context, "obj1")
5670              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5671   CHECK(!GetGlobalProperty(&context, "obj2")
5672              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5673
5674   ExpectString("obj1.x", "z");
5675   ExpectString("obj2.x", "z");
5676 }
5677
5678
5679 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
5680   v8::Isolate* isolate = CcTest::isolate();
5681   v8::HandleScope scope(isolate);
5682   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5683   LocalContext context;
5684
5685   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5686   CompileRun("var obj2 = {};");
5687
5688   CHECK(GetGlobalProperty(&context, "obj1")
5689             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
5690                           v8::DEFAULT, v8::DontDelete));
5691   CHECK(GetGlobalProperty(&context, "obj2")
5692             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
5693                           v8::DEFAULT, v8::DontDelete));
5694
5695   ExpectString("obj1.x", "x");
5696   ExpectString("obj2.x", "x");
5697
5698   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5699   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5700
5701   CHECK(!GetGlobalProperty(&context, "obj1")
5702              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5703   CHECK(!GetGlobalProperty(&context, "obj2")
5704              ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5705
5706   {
5707     v8::TryCatch try_catch(isolate);
5708     CompileRun(
5709         "Object.defineProperty(obj1, 'x',"
5710         "{get: function() { return 'func'; }})");
5711     CHECK(try_catch.HasCaught());
5712     String::Utf8Value exception_value(try_catch.Exception());
5713     CHECK_EQ(
5714         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5715   }
5716   {
5717     v8::TryCatch try_catch(isolate);
5718     CompileRun(
5719         "Object.defineProperty(obj2, 'x',"
5720         "{get: function() { return 'func'; }})");
5721     CHECK(try_catch.HasCaught());
5722     String::Utf8Value exception_value(try_catch.Exception());
5723     CHECK_EQ(
5724         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5725   }
5726 }
5727
5728
5729 static void Get239Value(Local<String> name,
5730                         const v8::PropertyCallbackInfo<v8::Value>& info) {
5731   ApiTestFuzzer::Fuzz();
5732   CHECK(info.Data()->Equals(v8_str("donut")));
5733   CHECK(name->Equals(v8_str("239")));
5734   info.GetReturnValue().Set(name);
5735 }
5736
5737
5738 THREADED_TEST(ElementAPIAccessor) {
5739   v8::Isolate* isolate = CcTest::isolate();
5740   v8::HandleScope scope(isolate);
5741   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5742   LocalContext context;
5743
5744   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5745   CompileRun("var obj2 = {};");
5746
5747   CHECK(GetGlobalProperty(&context, "obj1")
5748             ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
5749   CHECK(GetGlobalProperty(&context, "obj2")
5750             ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
5751
5752   ExpectString("obj1[239]", "239");
5753   ExpectString("obj2[239]", "239");
5754   ExpectString("obj1['239']", "239");
5755   ExpectString("obj2['239']", "239");
5756 }
5757
5758
5759 v8::Persistent<Value> xValue;
5760
5761
5762 static void SetXValue(Local<String> name, Local<Value> value,
5763                       const v8::PropertyCallbackInfo<void>& info) {
5764   CHECK(value->Equals(v8_num(4)));
5765   CHECK(info.Data()->Equals(v8_str("donut")));
5766   CHECK(name->Equals(v8_str("x")));
5767   CHECK(xValue.IsEmpty());
5768   xValue.Reset(info.GetIsolate(), value);
5769 }
5770
5771
5772 THREADED_TEST(SimplePropertyWrite) {
5773   v8::Isolate* isolate = CcTest::isolate();
5774   v8::HandleScope scope(isolate);
5775   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5776   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5777   LocalContext context;
5778   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5779   Local<Script> script = v8_compile("obj.x = 4");
5780   for (int i = 0; i < 10; i++) {
5781     CHECK(xValue.IsEmpty());
5782     script->Run();
5783     CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
5784     xValue.Reset();
5785   }
5786 }
5787
5788
5789 THREADED_TEST(SetterOnly) {
5790   v8::Isolate* isolate = CcTest::isolate();
5791   v8::HandleScope scope(isolate);
5792   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5793   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5794   LocalContext context;
5795   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5796   Local<Script> script = v8_compile("obj.x = 4; obj.x");
5797   for (int i = 0; i < 10; i++) {
5798     CHECK(xValue.IsEmpty());
5799     script->Run();
5800     CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
5801     xValue.Reset();
5802   }
5803 }
5804
5805
5806 THREADED_TEST(NoAccessors) {
5807   v8::Isolate* isolate = CcTest::isolate();
5808   v8::HandleScope scope(isolate);
5809   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5810   templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
5811                      NULL, v8_str("donut"));
5812   LocalContext context;
5813   context->Global()->Set(v8_str("obj"), templ->NewInstance());
5814   Local<Script> script = v8_compile("obj.x = 4; obj.x");
5815   for (int i = 0; i < 10; i++) {
5816     script->Run();
5817   }
5818 }
5819
5820
5821 THREADED_TEST(MultiContexts) {
5822   v8::Isolate* isolate = CcTest::isolate();
5823   v8::HandleScope scope(isolate);
5824   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5825   templ->Set(v8_str("dummy"),
5826              v8::FunctionTemplate::New(isolate, DummyCallHandler));
5827
5828   Local<String> password = v8_str("Password");
5829
5830   // Create an environment
5831   LocalContext context0(0, templ);
5832   context0->SetSecurityToken(password);
5833   v8::Handle<v8::Object> global0 = context0->Global();
5834   global0->Set(v8_str("custom"), v8_num(1234));
5835   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5836
5837   // Create an independent environment
5838   LocalContext context1(0, templ);
5839   context1->SetSecurityToken(password);
5840   v8::Handle<v8::Object> global1 = context1->Global();
5841   global1->Set(v8_str("custom"), v8_num(1234));
5842   CHECK(!global0->Equals(global1));
5843   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5844   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
5845
5846   // Now create a new context with the old global
5847   LocalContext context2(0, templ, global1);
5848   context2->SetSecurityToken(password);
5849   v8::Handle<v8::Object> global2 = context2->Global();
5850   CHECK(global1->Equals(global2));
5851   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
5852   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
5853 }
5854
5855
5856 THREADED_TEST(FunctionPrototypeAcrossContexts) {
5857   // Make sure that functions created by cloning boilerplates cannot
5858   // communicate through their __proto__ field.
5859
5860   v8::HandleScope scope(CcTest::isolate());
5861
5862   LocalContext env0;
5863   v8::Handle<v8::Object> global0 = env0->Global();
5864   v8::Handle<v8::Object> object0 =
5865       global0->Get(v8_str("Object")).As<v8::Object>();
5866   v8::Handle<v8::Object> tostring0 =
5867       object0->Get(v8_str("toString")).As<v8::Object>();
5868   v8::Handle<v8::Object> proto0 =
5869       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
5870   proto0->Set(v8_str("custom"), v8_num(1234));
5871
5872   LocalContext env1;
5873   v8::Handle<v8::Object> global1 = env1->Global();
5874   v8::Handle<v8::Object> object1 =
5875       global1->Get(v8_str("Object")).As<v8::Object>();
5876   v8::Handle<v8::Object> tostring1 =
5877       object1->Get(v8_str("toString")).As<v8::Object>();
5878   v8::Handle<v8::Object> proto1 =
5879       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
5880   CHECK(!proto1->Has(v8_str("custom")));
5881 }
5882
5883
5884 THREADED_TEST(Regress892105) {
5885   // Make sure that object and array literals created by cloning
5886   // boilerplates cannot communicate through their __proto__
5887   // field. This is rather difficult to check, but we try to add stuff
5888   // to Object.prototype and Array.prototype and create a new
5889   // environment. This should succeed.
5890
5891   v8::HandleScope scope(CcTest::isolate());
5892
5893   Local<String> source = v8_str(
5894       "Object.prototype.obj = 1234;"
5895       "Array.prototype.arr = 4567;"
5896       "8901");
5897
5898   LocalContext env0;
5899   Local<Script> script0 = v8_compile(source);
5900   CHECK_EQ(8901.0, script0->Run()->NumberValue());
5901
5902   LocalContext env1;
5903   Local<Script> script1 = v8_compile(source);
5904   CHECK_EQ(8901.0, script1->Run()->NumberValue());
5905 }
5906
5907
5908 THREADED_TEST(UndetectableObject) {
5909   LocalContext env;
5910   v8::HandleScope scope(env->GetIsolate());
5911
5912   Local<v8::FunctionTemplate> desc =
5913       v8::FunctionTemplate::New(env->GetIsolate());
5914   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5915
5916   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5917   env->Global()->Set(v8_str("undetectable"), obj);
5918
5919   ExpectString("undetectable.toString()", "[object Object]");
5920   ExpectString("typeof undetectable", "undefined");
5921   ExpectString("typeof(undetectable)", "undefined");
5922   ExpectBoolean("typeof undetectable == 'undefined'", true);
5923   ExpectBoolean("typeof undetectable == 'object'", false);
5924   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
5925   ExpectBoolean("!undetectable", true);
5926
5927   ExpectObject("true&&undetectable", obj);
5928   ExpectBoolean("false&&undetectable", false);
5929   ExpectBoolean("true||undetectable", true);
5930   ExpectObject("false||undetectable", obj);
5931
5932   ExpectObject("undetectable&&true", obj);
5933   ExpectObject("undetectable&&false", obj);
5934   ExpectBoolean("undetectable||true", true);
5935   ExpectBoolean("undetectable||false", false);
5936
5937   ExpectBoolean("undetectable==null", true);
5938   ExpectBoolean("null==undetectable", true);
5939   ExpectBoolean("undetectable==undefined", true);
5940   ExpectBoolean("undefined==undetectable", true);
5941   ExpectBoolean("undetectable==undetectable", true);
5942
5943
5944   ExpectBoolean("undetectable===null", false);
5945   ExpectBoolean("null===undetectable", false);
5946   ExpectBoolean("undetectable===undefined", false);
5947   ExpectBoolean("undefined===undetectable", false);
5948   ExpectBoolean("undetectable===undetectable", true);
5949 }
5950
5951
5952 THREADED_TEST(VoidLiteral) {
5953   LocalContext env;
5954   v8::Isolate* isolate = env->GetIsolate();
5955   v8::HandleScope scope(isolate);
5956
5957   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
5958   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
5959
5960   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5961   env->Global()->Set(v8_str("undetectable"), obj);
5962
5963   ExpectBoolean("undefined == void 0", true);
5964   ExpectBoolean("undetectable == void 0", true);
5965   ExpectBoolean("null == void 0", true);
5966   ExpectBoolean("undefined === void 0", true);
5967   ExpectBoolean("undetectable === void 0", false);
5968   ExpectBoolean("null === void 0", false);
5969
5970   ExpectBoolean("void 0 == undefined", true);
5971   ExpectBoolean("void 0 == undetectable", true);
5972   ExpectBoolean("void 0 == null", true);
5973   ExpectBoolean("void 0 === undefined", true);
5974   ExpectBoolean("void 0 === undetectable", false);
5975   ExpectBoolean("void 0 === null", false);
5976
5977   ExpectString(
5978       "(function() {"
5979       "  try {"
5980       "    return x === void 0;"
5981       "  } catch(e) {"
5982       "    return e.toString();"
5983       "  }"
5984       "})()",
5985       "ReferenceError: x is not defined");
5986   ExpectString(
5987       "(function() {"
5988       "  try {"
5989       "    return void 0 === x;"
5990       "  } catch(e) {"
5991       "    return e.toString();"
5992       "  }"
5993       "})()",
5994       "ReferenceError: x is not defined");
5995 }
5996
5997
5998 THREADED_TEST(ExtensibleOnUndetectable) {
5999   LocalContext env;
6000   v8::Isolate* isolate = env->GetIsolate();
6001   v8::HandleScope scope(isolate);
6002
6003   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
6004   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
6005
6006   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6007   env->Global()->Set(v8_str("undetectable"), obj);
6008
6009   Local<String> source = v8_str(
6010       "undetectable.x = 42;"
6011       "undetectable.x");
6012
6013   Local<Script> script = v8_compile(source);
6014
6015   CHECK(v8::Integer::New(isolate, 42)->Equals(script->Run()));
6016
6017   ExpectBoolean("Object.isExtensible(undetectable)", true);
6018
6019   source = v8_str("Object.preventExtensions(undetectable);");
6020   script = v8_compile(source);
6021   script->Run();
6022   ExpectBoolean("Object.isExtensible(undetectable)", false);
6023
6024   source = v8_str("undetectable.y = 2000;");
6025   script = v8_compile(source);
6026   script->Run();
6027   ExpectBoolean("undetectable.y == undefined", true);
6028 }
6029
6030
6031 // The point of this test is type checking. We run it only so compilers
6032 // don't complain about an unused function.
6033 TEST(PersistentHandles) {
6034   LocalContext env;
6035   v8::Isolate* isolate = CcTest::isolate();
6036   v8::HandleScope scope(isolate);
6037   Local<String> str = v8_str("foo");
6038   v8::Persistent<String> p_str(isolate, str);
6039   p_str.Reset();
6040   Local<Script> scr = v8_compile("");
6041   v8::Persistent<Script> p_scr(isolate, scr);
6042   p_scr.Reset();
6043   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6044   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
6045   p_templ.Reset();
6046 }
6047
6048
6049 static void HandleLogDelegator(
6050     const v8::FunctionCallbackInfo<v8::Value>& args) {
6051   ApiTestFuzzer::Fuzz();
6052 }
6053
6054
6055 THREADED_TEST(GlobalObjectTemplate) {
6056   v8::Isolate* isolate = CcTest::isolate();
6057   v8::HandleScope handle_scope(isolate);
6058   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
6059   global_template->Set(v8_str("JSNI_Log"),
6060                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
6061   v8::Local<Context> context = Context::New(isolate, 0, global_template);
6062   Context::Scope context_scope(context);
6063   CompileRun("JSNI_Log('LOG')");
6064 }
6065
6066
6067 static const char* kSimpleExtensionSource =
6068     "function Foo() {"
6069     "  return 4;"
6070     "}";
6071
6072
6073 TEST(SimpleExtensions) {
6074   v8::HandleScope handle_scope(CcTest::isolate());
6075   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6076   const char* extension_names[] = {"simpletest"};
6077   v8::ExtensionConfiguration extensions(1, extension_names);
6078   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6079   Context::Scope lock(context);
6080   v8::Handle<Value> result = CompileRun("Foo()");
6081   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6082 }
6083
6084
6085 static const char* kStackTraceFromExtensionSource =
6086     "function foo() {"
6087     "  throw new Error();"
6088     "}"
6089     "function bar() {"
6090     "  foo();"
6091     "}";
6092
6093
6094 TEST(StackTraceInExtension) {
6095   v8::HandleScope handle_scope(CcTest::isolate());
6096   v8::RegisterExtension(
6097       new Extension("stacktracetest", kStackTraceFromExtensionSource));
6098   const char* extension_names[] = {"stacktracetest"};
6099   v8::ExtensionConfiguration extensions(1, extension_names);
6100   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6101   Context::Scope lock(context);
6102   CompileRun(
6103       "function user() { bar(); }"
6104       "var error;"
6105       "try{ user(); } catch (e) { error = e; }");
6106   CHECK_EQ(-1, CompileRun("error.stack.indexOf('foo')")->Int32Value());
6107   CHECK_EQ(-1, CompileRun("error.stack.indexOf('bar')")->Int32Value());
6108   CHECK_NE(-1, CompileRun("error.stack.indexOf('user')")->Int32Value());
6109 }
6110
6111
6112 TEST(NullExtensions) {
6113   v8::HandleScope handle_scope(CcTest::isolate());
6114   v8::RegisterExtension(new Extension("nulltest", NULL));
6115   const char* extension_names[] = {"nulltest"};
6116   v8::ExtensionConfiguration extensions(1, extension_names);
6117   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6118   Context::Scope lock(context);
6119   v8::Handle<Value> result = CompileRun("1+3");
6120   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6121 }
6122
6123
6124 static const char* kEmbeddedExtensionSource =
6125     "function Ret54321(){return 54321;}~~@@$"
6126     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6127 static const int kEmbeddedExtensionSourceValidLen = 34;
6128
6129
6130 TEST(ExtensionMissingSourceLength) {
6131   v8::HandleScope handle_scope(CcTest::isolate());
6132   v8::RegisterExtension(
6133       new Extension("srclentest_fail", kEmbeddedExtensionSource));
6134   const char* extension_names[] = {"srclentest_fail"};
6135   v8::ExtensionConfiguration extensions(1, extension_names);
6136   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6137   CHECK(0 == *context);
6138 }
6139
6140
6141 TEST(ExtensionWithSourceLength) {
6142   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6143        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
6144     v8::HandleScope handle_scope(CcTest::isolate());
6145     i::ScopedVector<char> extension_name(32);
6146     i::SNPrintF(extension_name, "ext #%d", source_len);
6147     v8::RegisterExtension(new Extension(
6148         extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
6149     const char* extension_names[1] = {extension_name.start()};
6150     v8::ExtensionConfiguration extensions(1, extension_names);
6151     v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6152     if (source_len == kEmbeddedExtensionSourceValidLen) {
6153       Context::Scope lock(context);
6154       v8::Handle<Value> result = CompileRun("Ret54321()");
6155       CHECK(v8::Integer::New(CcTest::isolate(), 54321)->Equals(result));
6156     } else {
6157       // Anything but exactly the right length should fail to compile.
6158       CHECK(0 == *context);
6159     }
6160   }
6161 }
6162
6163
6164 static const char* kEvalExtensionSource1 =
6165     "function UseEval1() {"
6166     "  var x = 42;"
6167     "  return eval('x');"
6168     "}";
6169
6170
6171 static const char* kEvalExtensionSource2 =
6172     "(function() {"
6173     "  var x = 42;"
6174     "  function e() {"
6175     "    return eval('x');"
6176     "  }"
6177     "  this.UseEval2 = e;"
6178     "})()";
6179
6180
6181 TEST(UseEvalFromExtension) {
6182   v8::HandleScope handle_scope(CcTest::isolate());
6183   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6184   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6185   const char* extension_names[] = {"evaltest1", "evaltest2"};
6186   v8::ExtensionConfiguration extensions(2, extension_names);
6187   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6188   Context::Scope lock(context);
6189   v8::Handle<Value> result = CompileRun("UseEval1()");
6190   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6191   result = CompileRun("UseEval2()");
6192   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6193 }
6194
6195
6196 static const char* kWithExtensionSource1 =
6197     "function UseWith1() {"
6198     "  var x = 42;"
6199     "  with({x:87}) { return x; }"
6200     "}";
6201
6202
6203 static const char* kWithExtensionSource2 =
6204     "(function() {"
6205     "  var x = 42;"
6206     "  function e() {"
6207     "    with ({x:87}) { return x; }"
6208     "  }"
6209     "  this.UseWith2 = e;"
6210     "})()";
6211
6212
6213 TEST(UseWithFromExtension) {
6214   v8::HandleScope handle_scope(CcTest::isolate());
6215   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6216   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6217   const char* extension_names[] = {"withtest1", "withtest2"};
6218   v8::ExtensionConfiguration extensions(2, extension_names);
6219   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6220   Context::Scope lock(context);
6221   v8::Handle<Value> result = CompileRun("UseWith1()");
6222   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
6223   result = CompileRun("UseWith2()");
6224   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
6225 }
6226
6227
6228 TEST(AutoExtensions) {
6229   v8::HandleScope handle_scope(CcTest::isolate());
6230   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6231   extension->set_auto_enable(true);
6232   v8::RegisterExtension(extension);
6233   v8::Handle<Context> context = Context::New(CcTest::isolate());
6234   Context::Scope lock(context);
6235   v8::Handle<Value> result = CompileRun("Foo()");
6236   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6237 }
6238
6239
6240 static const char* kSyntaxErrorInExtensionSource = "[";
6241
6242
6243 // Test that a syntax error in an extension does not cause a fatal
6244 // error but results in an empty context.
6245 TEST(SyntaxErrorExtensions) {
6246   v8::HandleScope handle_scope(CcTest::isolate());
6247   v8::RegisterExtension(
6248       new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
6249   const char* extension_names[] = {"syntaxerror"};
6250   v8::ExtensionConfiguration extensions(1, extension_names);
6251   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6252   CHECK(context.IsEmpty());
6253 }
6254
6255
6256 static const char* kExceptionInExtensionSource = "throw 42";
6257
6258
6259 // Test that an exception when installing an extension does not cause
6260 // a fatal error but results in an empty context.
6261 TEST(ExceptionExtensions) {
6262   v8::HandleScope handle_scope(CcTest::isolate());
6263   v8::RegisterExtension(
6264       new Extension("exception", kExceptionInExtensionSource));
6265   const char* extension_names[] = {"exception"};
6266   v8::ExtensionConfiguration extensions(1, extension_names);
6267   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6268   CHECK(context.IsEmpty());
6269 }
6270
6271
6272 static const char* kNativeCallInExtensionSource =
6273     "function call_runtime_last_index_of(x) {"
6274     "  return %StringLastIndexOf(x, 'bob', 10);"
6275     "}";
6276
6277
6278 static const char* kNativeCallTest =
6279     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6280
6281 // Test that a native runtime calls are supported in extensions.
6282 TEST(NativeCallInExtensions) {
6283   v8::HandleScope handle_scope(CcTest::isolate());
6284   v8::RegisterExtension(
6285       new Extension("nativecall", kNativeCallInExtensionSource));
6286   const char* extension_names[] = {"nativecall"};
6287   v8::ExtensionConfiguration extensions(1, extension_names);
6288   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6289   Context::Scope lock(context);
6290   v8::Handle<Value> result = CompileRun(kNativeCallTest);
6291   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 3)));
6292 }
6293
6294
6295 class NativeFunctionExtension : public Extension {
6296  public:
6297   NativeFunctionExtension(const char* name, const char* source,
6298                           v8::FunctionCallback fun = &Echo)
6299       : Extension(name, source), function_(fun) {}
6300
6301   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6302       v8::Isolate* isolate, v8::Handle<v8::String> name) {
6303     return v8::FunctionTemplate::New(isolate, function_);
6304   }
6305
6306   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6307     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
6308   }
6309
6310  private:
6311   v8::FunctionCallback function_;
6312 };
6313
6314
6315 TEST(NativeFunctionDeclaration) {
6316   v8::HandleScope handle_scope(CcTest::isolate());
6317   const char* name = "nativedecl";
6318   v8::RegisterExtension(
6319       new NativeFunctionExtension(name, "native function foo();"));
6320   const char* extension_names[] = {name};
6321   v8::ExtensionConfiguration extensions(1, extension_names);
6322   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6323   Context::Scope lock(context);
6324   v8::Handle<Value> result = CompileRun("foo(42);");
6325   CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6326 }
6327
6328
6329 TEST(NativeFunctionDeclarationError) {
6330   v8::HandleScope handle_scope(CcTest::isolate());
6331   const char* name = "nativedeclerr";
6332   // Syntax error in extension code.
6333   v8::RegisterExtension(
6334       new NativeFunctionExtension(name, "native\nfunction foo();"));
6335   const char* extension_names[] = {name};
6336   v8::ExtensionConfiguration extensions(1, extension_names);
6337   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6338   CHECK(context.IsEmpty());
6339 }
6340
6341
6342 TEST(NativeFunctionDeclarationErrorEscape) {
6343   v8::HandleScope handle_scope(CcTest::isolate());
6344   const char* name = "nativedeclerresc";
6345   // Syntax error in extension code - escape code in "native" means that
6346   // it's not treated as a keyword.
6347   v8::RegisterExtension(
6348       new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
6349   const char* extension_names[] = {name};
6350   v8::ExtensionConfiguration extensions(1, extension_names);
6351   v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6352   CHECK(context.IsEmpty());
6353 }
6354
6355
6356 static void CheckDependencies(const char* name, const char* expected) {
6357   v8::HandleScope handle_scope(CcTest::isolate());
6358   v8::ExtensionConfiguration config(1, &name);
6359   LocalContext context(&config);
6360   CHECK(String::NewFromUtf8(CcTest::isolate(), expected)
6361             ->Equals(context->Global()->Get(v8_str("loaded"))));
6362 }
6363
6364
6365 /*
6366  * Configuration:
6367  *
6368  *     /-- B <--\
6369  * A <-          -- D <-- E
6370  *     \-- C <--/
6371  */
6372 THREADED_TEST(ExtensionDependency) {
6373   static const char* kEDeps[] = {"D"};
6374   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6375   static const char* kDDeps[] = {"B", "C"};
6376   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6377   static const char* kBCDeps[] = {"A"};
6378   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6379   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6380   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6381   CheckDependencies("A", "undefinedA");
6382   CheckDependencies("B", "undefinedAB");
6383   CheckDependencies("C", "undefinedAC");
6384   CheckDependencies("D", "undefinedABCD");
6385   CheckDependencies("E", "undefinedABCDE");
6386   v8::HandleScope handle_scope(CcTest::isolate());
6387   static const char* exts[2] = {"C", "E"};
6388   v8::ExtensionConfiguration config(2, exts);
6389   LocalContext context(&config);
6390   CHECK(v8_str("undefinedACBDE")
6391             ->Equals(context->Global()->Get(v8_str("loaded"))));
6392 }
6393
6394
6395 static const char* kExtensionTestScript =
6396     "native function A();"
6397     "native function B();"
6398     "native function C();"
6399     "function Foo(i) {"
6400     "  if (i == 0) return A();"
6401     "  if (i == 1) return B();"
6402     "  if (i == 2) return C();"
6403     "}";
6404
6405
6406 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
6407   ApiTestFuzzer::Fuzz();
6408   if (args.IsConstructCall()) {
6409     args.This()->Set(v8_str("data"), args.Data());
6410     args.GetReturnValue().SetNull();
6411     return;
6412   }
6413   args.GetReturnValue().Set(args.Data());
6414 }
6415
6416
6417 class FunctionExtension : public Extension {
6418  public:
6419   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
6420   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6421       v8::Isolate* isolate, v8::Handle<String> name);
6422 };
6423
6424
6425 static int lookup_count = 0;
6426 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
6427     v8::Isolate* isolate, v8::Handle<String> name) {
6428   lookup_count++;
6429   if (name->Equals(v8_str("A"))) {
6430     return v8::FunctionTemplate::New(isolate, CallFun,
6431                                      v8::Integer::New(isolate, 8));
6432   } else if (name->Equals(v8_str("B"))) {
6433     return v8::FunctionTemplate::New(isolate, CallFun,
6434                                      v8::Integer::New(isolate, 7));
6435   } else if (name->Equals(v8_str("C"))) {
6436     return v8::FunctionTemplate::New(isolate, CallFun,
6437                                      v8::Integer::New(isolate, 6));
6438   } else {
6439     return v8::Handle<v8::FunctionTemplate>();
6440   }
6441 }
6442
6443
6444 THREADED_TEST(FunctionLookup) {
6445   v8::RegisterExtension(new FunctionExtension());
6446   v8::HandleScope handle_scope(CcTest::isolate());
6447   static const char* exts[1] = {"functiontest"};
6448   v8::ExtensionConfiguration config(1, exts);
6449   LocalContext context(&config);
6450   CHECK_EQ(3, lookup_count);
6451   CHECK(v8::Integer::New(CcTest::isolate(), 8)->Equals(CompileRun("Foo(0)")));
6452   CHECK(v8::Integer::New(CcTest::isolate(), 7)->Equals(CompileRun("Foo(1)")));
6453   CHECK(v8::Integer::New(CcTest::isolate(), 6)->Equals(CompileRun("Foo(2)")));
6454 }
6455
6456
6457 THREADED_TEST(NativeFunctionConstructCall) {
6458   v8::RegisterExtension(new FunctionExtension());
6459   v8::HandleScope handle_scope(CcTest::isolate());
6460   static const char* exts[1] = {"functiontest"};
6461   v8::ExtensionConfiguration config(1, exts);
6462   LocalContext context(&config);
6463   for (int i = 0; i < 10; i++) {
6464     // Run a few times to ensure that allocation of objects doesn't
6465     // change behavior of a constructor function.
6466     CHECK(v8::Integer::New(CcTest::isolate(), 8)
6467               ->Equals(CompileRun("(new A()).data")));
6468     CHECK(v8::Integer::New(CcTest::isolate(), 7)
6469               ->Equals(CompileRun("(new B()).data")));
6470     CHECK(v8::Integer::New(CcTest::isolate(), 6)
6471               ->Equals(CompileRun("(new C()).data")));
6472   }
6473 }
6474
6475
6476 static const char* last_location;
6477 static const char* last_message;
6478 void StoringErrorCallback(const char* location, const char* message) {
6479   if (last_location == NULL) {
6480     last_location = location;
6481     last_message = message;
6482   }
6483 }
6484
6485
6486 // ErrorReporting creates a circular extensions configuration and
6487 // tests that the fatal error handler gets called.  This renders V8
6488 // unusable and therefore this test cannot be run in parallel.
6489 TEST(ErrorReporting) {
6490   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
6491   static const char* aDeps[] = {"B"};
6492   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
6493   static const char* bDeps[] = {"A"};
6494   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
6495   last_location = NULL;
6496   v8::ExtensionConfiguration config(1, bDeps);
6497   v8::Handle<Context> context = Context::New(CcTest::isolate(), &config);
6498   CHECK(context.IsEmpty());
6499   CHECK(last_location);
6500 }
6501
6502
6503 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
6504                                              v8::Handle<Value> data) {
6505   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
6506   CHECK(v8::Undefined(CcTest::isolate())
6507             ->Equals(message->GetScriptOrigin().ResourceName()));
6508   message->GetLineNumber();
6509   message->GetSourceLine();
6510 }
6511
6512
6513 THREADED_TEST(ErrorWithMissingScriptInfo) {
6514   LocalContext context;
6515   v8::HandleScope scope(context->GetIsolate());
6516   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
6517   CompileRun("throw Error()");
6518   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
6519 }
6520
6521
6522 struct FlagAndPersistent {
6523   bool flag;
6524   v8::Global<v8::Object> handle;
6525 };
6526
6527
6528 static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6529   data.GetParameter()->flag = true;
6530   data.GetParameter()->handle.Reset();
6531 }
6532
6533
6534 static void IndependentWeakHandle(bool global_gc, bool interlinked) {
6535   v8::Isolate* iso = CcTest::isolate();
6536   v8::HandleScope scope(iso);
6537   v8::Handle<Context> context = Context::New(iso);
6538   Context::Scope context_scope(context);
6539
6540   FlagAndPersistent object_a, object_b;
6541
6542   intptr_t big_heap_size;
6543
6544   {
6545     v8::HandleScope handle_scope(iso);
6546     Local<Object> a(v8::Object::New(iso));
6547     Local<Object> b(v8::Object::New(iso));
6548     object_a.handle.Reset(iso, a);
6549     object_b.handle.Reset(iso, b);
6550     if (interlinked) {
6551       a->Set(v8_str("x"), b);
6552       b->Set(v8_str("x"), a);
6553     }
6554     if (global_gc) {
6555       CcTest::heap()->CollectAllGarbage();
6556     } else {
6557       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6558     }
6559     // We are relying on this creating a big flag array and reserving the space
6560     // up front.
6561     v8::Handle<Value> big_array = CompileRun("new Array(50000)");
6562     a->Set(v8_str("y"), big_array);
6563     big_heap_size = CcTest::heap()->SizeOfObjects();
6564   }
6565
6566   object_a.flag = false;
6567   object_b.flag = false;
6568   object_a.handle.SetWeak(&object_a, &SetFlag,
6569                           v8::WeakCallbackType::kParameter);
6570   object_b.handle.SetWeak(&object_b, &SetFlag,
6571                           v8::WeakCallbackType::kParameter);
6572   CHECK(!object_b.handle.IsIndependent());
6573   object_a.handle.MarkIndependent();
6574   object_b.handle.MarkIndependent();
6575   CHECK(object_b.handle.IsIndependent());
6576   if (global_gc) {
6577     CcTest::heap()->CollectAllGarbage();
6578   } else {
6579     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6580   }
6581   // A single GC should be enough to reclaim the memory, since we are using
6582   // phantom handles.
6583   CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 200000);
6584   CHECK(object_a.flag);
6585   CHECK(object_b.flag);
6586 }
6587
6588
6589 TEST(IndependentWeakHandle) {
6590   IndependentWeakHandle(false, false);
6591   IndependentWeakHandle(false, true);
6592   IndependentWeakHandle(true, false);
6593   IndependentWeakHandle(true, true);
6594 }
6595
6596
6597 class Trivial {
6598  public:
6599   explicit Trivial(int x) : x_(x) {}
6600
6601   int x() { return x_; }
6602   void set_x(int x) { x_ = x; }
6603
6604  private:
6605   int x_;
6606 };
6607
6608
6609 class Trivial2 {
6610  public:
6611   Trivial2(int x, int y) : y_(y), x_(x) {}
6612
6613   int x() { return x_; }
6614   void set_x(int x) { x_ = x; }
6615
6616   int y() { return y_; }
6617   void set_y(int y) { y_ = y; }
6618
6619  private:
6620   int y_;
6621   int x_;
6622 };
6623
6624
6625 void CheckInternalFields(
6626     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
6627   v8::Persistent<v8::Object>* handle = data.GetParameter();
6628   handle->Reset();
6629   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField1());
6630   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField2());
6631   CHECK_EQ(42, t1->x());
6632   CHECK_EQ(103, t2->x());
6633   t1->set_x(1729);
6634   t2->set_x(33550336);
6635 }
6636
6637
6638 void InternalFieldCallback(bool global_gc) {
6639   LocalContext env;
6640   v8::Isolate* isolate = env->GetIsolate();
6641   v8::HandleScope scope(isolate);
6642
6643   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
6644   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
6645   Trivial* t1;
6646   Trivial2* t2;
6647   instance_templ->SetInternalFieldCount(2);
6648   {
6649     v8::HandleScope scope(isolate);
6650     Local<v8::Object> obj = templ->GetFunction()->NewInstance();
6651     v8::Persistent<v8::Object> handle(isolate, obj);
6652     CHECK_EQ(2, obj->InternalFieldCount());
6653     CHECK(obj->GetInternalField(0)->IsUndefined());
6654     t1 = new Trivial(42);
6655     t2 = new Trivial2(103, 9);
6656
6657     obj->SetAlignedPointerInInternalField(0, t1);
6658     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
6659     CHECK_EQ(42, t1->x());
6660
6661     obj->SetAlignedPointerInInternalField(1, t2);
6662     t2 =
6663         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
6664     CHECK_EQ(103, t2->x());
6665
6666     handle.SetWeak<v8::Persistent<v8::Object>>(
6667         &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
6668     if (!global_gc) {
6669       handle.MarkIndependent();
6670     }
6671   }
6672   if (global_gc) {
6673     CcTest::heap()->CollectAllGarbage();
6674   } else {
6675     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6676   }
6677
6678   CHECK_EQ(1729, t1->x());
6679   CHECK_EQ(33550336, t2->x());
6680
6681   delete t1;
6682   delete t2;
6683 }
6684
6685
6686 THREADED_TEST(InternalFieldCallback) {
6687   InternalFieldCallback(false);
6688   InternalFieldCallback(true);
6689 }
6690
6691
6692 static void ResetUseValueAndSetFlag(
6693     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6694   // Blink will reset the handle, and then use the other handle, so they
6695   // can't use the same backing slot.
6696   data.GetParameter()->handle.Reset();
6697   data.GetParameter()->flag = true;
6698 }
6699
6700
6701 static void ResetWeakHandle(bool global_gc) {
6702   v8::Isolate* iso = CcTest::isolate();
6703   v8::HandleScope scope(iso);
6704   v8::Handle<Context> context = Context::New(iso);
6705   Context::Scope context_scope(context);
6706
6707   FlagAndPersistent object_a, object_b;
6708
6709   {
6710     v8::HandleScope handle_scope(iso);
6711     Local<Object> a(v8::Object::New(iso));
6712     Local<Object> b(v8::Object::New(iso));
6713     object_a.handle.Reset(iso, a);
6714     object_b.handle.Reset(iso, b);
6715     if (global_gc) {
6716       CcTest::heap()->CollectAllGarbage(
6717           TestHeap::Heap::kAbortIncrementalMarkingMask);
6718     } else {
6719       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6720     }
6721   }
6722
6723   object_a.flag = false;
6724   object_b.flag = false;
6725   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
6726                           v8::WeakCallbackType::kParameter);
6727   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
6728                           v8::WeakCallbackType::kParameter);
6729   if (!global_gc) {
6730     object_a.handle.MarkIndependent();
6731     object_b.handle.MarkIndependent();
6732     CHECK(object_b.handle.IsIndependent());
6733   }
6734   if (global_gc) {
6735     CcTest::heap()->CollectAllGarbage(
6736         TestHeap::Heap::kAbortIncrementalMarkingMask);
6737   } else {
6738     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6739   }
6740   CHECK(object_a.flag);
6741   CHECK(object_b.flag);
6742 }
6743
6744
6745 THREADED_TEST(ResetWeakHandle) {
6746   ResetWeakHandle(false);
6747   ResetWeakHandle(true);
6748 }
6749
6750
6751 static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
6752
6753
6754 static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
6755
6756
6757 static void ForceScavenge2(
6758     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6759   data.GetParameter()->flag = true;
6760   InvokeScavenge();
6761 }
6762
6763 static void ForceScavenge1(
6764     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6765   data.GetParameter()->handle.Reset();
6766   data.SetSecondPassCallback(ForceScavenge2);
6767 }
6768
6769
6770 static void ForceMarkSweep2(
6771     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6772   data.GetParameter()->flag = true;
6773   InvokeMarkSweep();
6774 }
6775
6776 static void ForceMarkSweep1(
6777     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6778   data.GetParameter()->handle.Reset();
6779   data.SetSecondPassCallback(ForceMarkSweep2);
6780 }
6781
6782
6783 THREADED_TEST(GCFromWeakCallbacks) {
6784   v8::Isolate* isolate = CcTest::isolate();
6785   v8::HandleScope scope(isolate);
6786   v8::Handle<Context> context = Context::New(isolate);
6787   Context::Scope context_scope(context);
6788
6789   static const int kNumberOfGCTypes = 2;
6790   typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
6791   Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
6792                                                     &ForceMarkSweep1};
6793
6794   typedef void (*GCInvoker)();
6795   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
6796
6797   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
6798     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
6799       FlagAndPersistent object;
6800       {
6801         v8::HandleScope handle_scope(isolate);
6802         object.handle.Reset(isolate, v8::Object::New(isolate));
6803       }
6804       object.flag = false;
6805       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
6806                             v8::WeakCallbackType::kParameter);
6807       object.handle.MarkIndependent();
6808       invoke_gc[outer_gc]();
6809       CHECK(object.flag);
6810     }
6811   }
6812 }
6813
6814
6815 v8::Handle<Function> args_fun;
6816
6817
6818 static void ArgumentsTestCallback(
6819     const v8::FunctionCallbackInfo<v8::Value>& args) {
6820   ApiTestFuzzer::Fuzz();
6821   v8::Isolate* isolate = args.GetIsolate();
6822   CHECK(args_fun->Equals(args.Callee()));
6823   CHECK_EQ(3, args.Length());
6824   CHECK(v8::Integer::New(isolate, 1)->Equals(args[0]));
6825   CHECK(v8::Integer::New(isolate, 2)->Equals(args[1]));
6826   CHECK(v8::Integer::New(isolate, 3)->Equals(args[2]));
6827   CHECK(v8::Undefined(isolate)->Equals(args[3]));
6828   v8::HandleScope scope(args.GetIsolate());
6829   CcTest::heap()->CollectAllGarbage();
6830 }
6831
6832
6833 THREADED_TEST(Arguments) {
6834   v8::Isolate* isolate = CcTest::isolate();
6835   v8::HandleScope scope(isolate);
6836   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
6837   global->Set(v8_str("f"),
6838               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
6839   LocalContext context(NULL, global);
6840   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
6841   v8_compile("f(1, 2, 3)")->Run();
6842 }
6843
6844
6845 static int p_getter_count;
6846 static int p_getter_count2;
6847
6848
6849 static void PGetter(Local<String> name,
6850                     const v8::PropertyCallbackInfo<v8::Value>& info) {
6851   ApiTestFuzzer::Fuzz();
6852   p_getter_count++;
6853   v8::Handle<v8::Object> global =
6854       info.GetIsolate()->GetCurrentContext()->Global();
6855   CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
6856   if (name->Equals(v8_str("p1"))) {
6857     CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
6858   } else if (name->Equals(v8_str("p2"))) {
6859     CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
6860   } else if (name->Equals(v8_str("p3"))) {
6861     CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
6862   } else if (name->Equals(v8_str("p4"))) {
6863     CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
6864   }
6865 }
6866
6867
6868 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
6869   ApiTestFuzzer::Fuzz();
6870   LocalContext context;
6871   context->Global()->Set(v8_str("o1"), obj->NewInstance());
6872   CompileRun(
6873     "o1.__proto__ = { };"
6874     "var o2 = { __proto__: o1 };"
6875     "var o3 = { __proto__: o2 };"
6876     "var o4 = { __proto__: o3 };"
6877     "for (var i = 0; i < 10; i++) o4.p4;"
6878     "for (var i = 0; i < 10; i++) o3.p3;"
6879     "for (var i = 0; i < 10; i++) o2.p2;"
6880     "for (var i = 0; i < 10; i++) o1.p1;");
6881 }
6882
6883
6884 static void PGetter2(Local<Name> name,
6885                      const v8::PropertyCallbackInfo<v8::Value>& info) {
6886   ApiTestFuzzer::Fuzz();
6887   p_getter_count2++;
6888   v8::Handle<v8::Object> global =
6889       info.GetIsolate()->GetCurrentContext()->Global();
6890   CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
6891   if (name->Equals(v8_str("p1"))) {
6892     CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
6893   } else if (name->Equals(v8_str("p2"))) {
6894     CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
6895   } else if (name->Equals(v8_str("p3"))) {
6896     CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
6897   } else if (name->Equals(v8_str("p4"))) {
6898     CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
6899   }
6900 }
6901
6902
6903 THREADED_TEST(GetterHolders) {
6904   v8::Isolate* isolate = CcTest::isolate();
6905   v8::HandleScope scope(isolate);
6906   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
6907   obj->SetAccessor(v8_str("p1"), PGetter);
6908   obj->SetAccessor(v8_str("p2"), PGetter);
6909   obj->SetAccessor(v8_str("p3"), PGetter);
6910   obj->SetAccessor(v8_str("p4"), PGetter);
6911   p_getter_count = 0;
6912   RunHolderTest(obj);
6913   CHECK_EQ(40, p_getter_count);
6914 }
6915
6916
6917 THREADED_TEST(PreInterceptorHolders) {
6918   v8::Isolate* isolate = CcTest::isolate();
6919   v8::HandleScope scope(isolate);
6920   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
6921   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
6922   p_getter_count2 = 0;
6923   RunHolderTest(obj);
6924   CHECK_EQ(40, p_getter_count2);
6925 }
6926
6927
6928 THREADED_TEST(ObjectInstantiation) {
6929   v8::Isolate* isolate = CcTest::isolate();
6930   v8::HandleScope scope(isolate);
6931   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
6932   templ->SetAccessor(v8_str("t"), PGetter2);
6933   LocalContext context;
6934   context->Global()->Set(v8_str("o"), templ->NewInstance());
6935   for (int i = 0; i < 100; i++) {
6936     v8::HandleScope inner_scope(CcTest::isolate());
6937     v8::Handle<v8::Object> obj = templ->NewInstance();
6938     CHECK(!obj->Equals(context->Global()->Get(v8_str("o"))));
6939     context->Global()->Set(v8_str("o2"), obj);
6940     v8::Handle<Value> value =
6941         CompileRun("o.__proto__ === o2.__proto__");
6942     CHECK(v8::True(isolate)->Equals(value));
6943     context->Global()->Set(v8_str("o"), obj);
6944   }
6945 }
6946
6947
6948 static int StrCmp16(uint16_t* a, uint16_t* b) {
6949   while (true) {
6950     if (*a == 0 && *b == 0) return 0;
6951     if (*a != *b) return 0 + *a - *b;
6952     a++;
6953     b++;
6954   }
6955 }
6956
6957
6958 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
6959   while (true) {
6960     if (n-- == 0) return 0;
6961     if (*a == 0 && *b == 0) return 0;
6962     if (*a != *b) return 0 + *a - *b;
6963     a++;
6964     b++;
6965   }
6966 }
6967
6968
6969 int GetUtf8Length(Handle<String> str) {
6970   int len = str->Utf8Length();
6971   if (len < 0) {
6972     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
6973     i::String::Flatten(istr);
6974     len = str->Utf8Length();
6975   }
6976   return len;
6977 }
6978
6979
6980 THREADED_TEST(StringWrite) {
6981   LocalContext context;
6982   v8::HandleScope scope(context->GetIsolate());
6983   v8::Handle<String> str = v8_str("abcde");
6984   // abc<Icelandic eth><Unicode snowman>.
6985   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
6986   v8::Handle<String> str3 = v8::String::NewFromUtf8(
6987       context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
6988   // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
6989   uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
6990   v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
6991       context->GetIsolate(), orphans, v8::String::kNormalString, 8);
6992   // single lead surrogate
6993   uint16_t lead[1] = { 0xd800 };
6994   v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
6995       context->GetIsolate(), lead, v8::String::kNormalString, 1);
6996   // single trail surrogate
6997   uint16_t trail[1] = { 0xdc00 };
6998   v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
6999       context->GetIsolate(), trail, v8::String::kNormalString, 1);
7000   // surrogate pair
7001   uint16_t pair[2] = { 0xd800,  0xdc00 };
7002   v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
7003       context->GetIsolate(), pair, v8::String::kNormalString, 2);
7004   const int kStride = 4;  // Must match stride in for loops in JS below.
7005   CompileRun(
7006       "var left = '';"
7007       "for (var i = 0; i < 0xd800; i += 4) {"
7008       "  left = left + String.fromCharCode(i);"
7009       "}");
7010   CompileRun(
7011       "var right = '';"
7012       "for (var i = 0; i < 0xd800; i += 4) {"
7013       "  right = String.fromCharCode(i) + right;"
7014       "}");
7015   v8::Handle<v8::Object> global = context->Global();
7016   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7017   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
7018
7019   CHECK_EQ(5, str2->Length());
7020   CHECK_EQ(0xd800 / kStride, left_tree->Length());
7021   CHECK_EQ(0xd800 / kStride, right_tree->Length());
7022
7023   char buf[100];
7024   char utf8buf[0xd800 * 3];
7025   uint16_t wbuf[100];
7026   int len;
7027   int charlen;
7028
7029   memset(utf8buf, 0x1, 1000);
7030   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7031   CHECK_EQ(9, len);
7032   CHECK_EQ(5, charlen);
7033   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7034
7035   memset(utf8buf, 0x1, 1000);
7036   len = str2->WriteUtf8(utf8buf, 8, &charlen);
7037   CHECK_EQ(8, len);
7038   CHECK_EQ(5, charlen);
7039   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
7040
7041   memset(utf8buf, 0x1, 1000);
7042   len = str2->WriteUtf8(utf8buf, 7, &charlen);
7043   CHECK_EQ(5, len);
7044   CHECK_EQ(4, charlen);
7045   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7046
7047   memset(utf8buf, 0x1, 1000);
7048   len = str2->WriteUtf8(utf8buf, 6, &charlen);
7049   CHECK_EQ(5, len);
7050   CHECK_EQ(4, charlen);
7051   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7052
7053   memset(utf8buf, 0x1, 1000);
7054   len = str2->WriteUtf8(utf8buf, 5, &charlen);
7055   CHECK_EQ(5, len);
7056   CHECK_EQ(4, charlen);
7057   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7058
7059   memset(utf8buf, 0x1, 1000);
7060   len = str2->WriteUtf8(utf8buf, 4, &charlen);
7061   CHECK_EQ(3, len);
7062   CHECK_EQ(3, charlen);
7063   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7064
7065   memset(utf8buf, 0x1, 1000);
7066   len = str2->WriteUtf8(utf8buf, 3, &charlen);
7067   CHECK_EQ(3, len);
7068   CHECK_EQ(3, charlen);
7069   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7070
7071   memset(utf8buf, 0x1, 1000);
7072   len = str2->WriteUtf8(utf8buf, 2, &charlen);
7073   CHECK_EQ(2, len);
7074   CHECK_EQ(2, charlen);
7075   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
7076
7077   // allow orphan surrogates by default
7078   memset(utf8buf, 0x1, 1000);
7079   len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7080   CHECK_EQ(13, len);
7081   CHECK_EQ(8, charlen);
7082   CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
7083
7084   // replace orphan surrogates with unicode replacement character
7085   memset(utf8buf, 0x1, 1000);
7086   len = orphans_str->WriteUtf8(utf8buf,
7087                                sizeof(utf8buf),
7088                                &charlen,
7089                                String::REPLACE_INVALID_UTF8);
7090   CHECK_EQ(13, len);
7091   CHECK_EQ(8, charlen);
7092   CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
7093
7094   // replace single lead surrogate with unicode replacement character
7095   memset(utf8buf, 0x1, 1000);
7096   len = lead_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   // replace single trail surrogate with unicode replacement character
7105   memset(utf8buf, 0x1, 1000);
7106   len = trail_str->WriteUtf8(utf8buf,
7107                              sizeof(utf8buf),
7108                              &charlen,
7109                              String::REPLACE_INVALID_UTF8);
7110   CHECK_EQ(4, len);
7111   CHECK_EQ(1, charlen);
7112   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7113
7114   // do not replace / write anything if surrogate pair does not fit the buffer
7115   // space
7116   memset(utf8buf, 0x1, 1000);
7117   len = pair_str->WriteUtf8(utf8buf,
7118                              3,
7119                              &charlen,
7120                              String::REPLACE_INVALID_UTF8);
7121   CHECK_EQ(0, len);
7122   CHECK_EQ(0, charlen);
7123
7124   memset(utf8buf, 0x1, sizeof(utf8buf));
7125   len = GetUtf8Length(left_tree);
7126   int utf8_expected =
7127       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7128   CHECK_EQ(utf8_expected, len);
7129   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7130   CHECK_EQ(utf8_expected, len);
7131   CHECK_EQ(0xd800 / kStride, charlen);
7132   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7133   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7134   CHECK_EQ(0xc0 - kStride,
7135            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7136   CHECK_EQ(1, utf8buf[utf8_expected]);
7137
7138   memset(utf8buf, 0x1, sizeof(utf8buf));
7139   len = GetUtf8Length(right_tree);
7140   CHECK_EQ(utf8_expected, len);
7141   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7142   CHECK_EQ(utf8_expected, len);
7143   CHECK_EQ(0xd800 / kStride, charlen);
7144   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7145   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7146   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7147   CHECK_EQ(1, utf8buf[utf8_expected]);
7148
7149   memset(buf, 0x1, sizeof(buf));
7150   memset(wbuf, 0x1, sizeof(wbuf));
7151   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7152   CHECK_EQ(5, len);
7153   len = str->Write(wbuf);
7154   CHECK_EQ(5, len);
7155   CHECK_EQ(0, strcmp("abcde", buf));
7156   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7157   CHECK_EQ(0, StrCmp16(answer1, wbuf));
7158
7159   memset(buf, 0x1, sizeof(buf));
7160   memset(wbuf, 0x1, sizeof(wbuf));
7161   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
7162   CHECK_EQ(4, len);
7163   len = str->Write(wbuf, 0, 4);
7164   CHECK_EQ(4, len);
7165   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
7166   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
7167   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
7168
7169   memset(buf, 0x1, sizeof(buf));
7170   memset(wbuf, 0x1, sizeof(wbuf));
7171   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
7172   CHECK_EQ(5, len);
7173   len = str->Write(wbuf, 0, 5);
7174   CHECK_EQ(5, len);
7175   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
7176   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
7177   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
7178
7179   memset(buf, 0x1, sizeof(buf));
7180   memset(wbuf, 0x1, sizeof(wbuf));
7181   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
7182   CHECK_EQ(5, len);
7183   len = str->Write(wbuf, 0, 6);
7184   CHECK_EQ(5, len);
7185   CHECK_EQ(0, strcmp("abcde", buf));
7186   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7187   CHECK_EQ(0, StrCmp16(answer4, wbuf));
7188
7189   memset(buf, 0x1, sizeof(buf));
7190   memset(wbuf, 0x1, sizeof(wbuf));
7191   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
7192   CHECK_EQ(1, len);
7193   len = str->Write(wbuf, 4, -1);
7194   CHECK_EQ(1, len);
7195   CHECK_EQ(0, strcmp("e", buf));
7196   uint16_t answer5[] = {'e', '\0'};
7197   CHECK_EQ(0, StrCmp16(answer5, wbuf));
7198
7199   memset(buf, 0x1, sizeof(buf));
7200   memset(wbuf, 0x1, sizeof(wbuf));
7201   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
7202   CHECK_EQ(1, len);
7203   len = str->Write(wbuf, 4, 6);
7204   CHECK_EQ(1, len);
7205   CHECK_EQ(0, strcmp("e", buf));
7206   CHECK_EQ(0, StrCmp16(answer5, wbuf));
7207
7208   memset(buf, 0x1, sizeof(buf));
7209   memset(wbuf, 0x1, sizeof(wbuf));
7210   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
7211   CHECK_EQ(1, len);
7212   len = str->Write(wbuf, 4, 1);
7213   CHECK_EQ(1, len);
7214   CHECK_EQ(0, strncmp("e\1", buf, 2));
7215   uint16_t answer6[] = {'e', 0x101};
7216   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
7217
7218   memset(buf, 0x1, sizeof(buf));
7219   memset(wbuf, 0x1, sizeof(wbuf));
7220   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
7221   CHECK_EQ(1, len);
7222   len = str->Write(wbuf, 3, 1);
7223   CHECK_EQ(1, len);
7224   CHECK_EQ(0, strncmp("d\1", buf, 2));
7225   uint16_t answer7[] = {'d', 0x101};
7226   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
7227
7228   memset(wbuf, 0x1, sizeof(wbuf));
7229   wbuf[5] = 'X';
7230   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7231   CHECK_EQ(5, len);
7232   CHECK_EQ('X', wbuf[5]);
7233   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7234   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7235   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7236   CHECK_NE(0, StrCmp16(answer8b, wbuf));
7237   wbuf[5] = '\0';
7238   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7239
7240   memset(buf, 0x1, sizeof(buf));
7241   buf[5] = 'X';
7242   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7243                           0,
7244                           6,
7245                           String::NO_NULL_TERMINATION);
7246   CHECK_EQ(5, len);
7247   CHECK_EQ('X', buf[5]);
7248   CHECK_EQ(0, strncmp("abcde", buf, 5));
7249   CHECK_NE(0, strcmp("abcde", buf));
7250   buf[5] = '\0';
7251   CHECK_EQ(0, strcmp("abcde", buf));
7252
7253   memset(utf8buf, 0x1, sizeof(utf8buf));
7254   utf8buf[8] = 'X';
7255   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7256                         String::NO_NULL_TERMINATION);
7257   CHECK_EQ(8, len);
7258   CHECK_EQ('X', utf8buf[8]);
7259   CHECK_EQ(5, charlen);
7260   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7261   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7262   utf8buf[8] = '\0';
7263   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7264
7265   memset(utf8buf, 0x1, sizeof(utf8buf));
7266   utf8buf[5] = 'X';
7267   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7268                         String::NO_NULL_TERMINATION);
7269   CHECK_EQ(5, len);
7270   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
7271   CHECK_EQ(5, charlen);
7272   utf8buf[5] = '\0';
7273   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7274
7275   memset(buf, 0x1, sizeof(buf));
7276   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7277   CHECK_EQ(7, len);
7278   CHECK_EQ(0, strcmp("abc", buf));
7279   CHECK_EQ(0, buf[3]);
7280   CHECK_EQ(0, strcmp("def", buf + 4));
7281
7282   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
7283   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7284   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
7285 }
7286
7287
7288 static void Utf16Helper(
7289     LocalContext& context,  // NOLINT
7290     const char* name,
7291     const char* lengths_name,
7292     int len) {
7293   Local<v8::Array> a =
7294       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7295   Local<v8::Array> alens =
7296       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7297   for (int i = 0; i < len; i++) {
7298     Local<v8::String> string =
7299       Local<v8::String>::Cast(a->Get(i));
7300     Local<v8::Number> expected_len =
7301       Local<v8::Number>::Cast(alens->Get(i));
7302     int length = GetUtf8Length(string);
7303     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7304   }
7305 }
7306
7307
7308 THREADED_TEST(Utf16) {
7309   LocalContext context;
7310   v8::HandleScope scope(context->GetIsolate());
7311   CompileRun(
7312       "var pad = '01234567890123456789';"
7313       "var p = [];"
7314       "var plens = [20, 3, 3];"
7315       "p.push('01234567890123456789');"
7316       "var lead = 0xd800;"
7317       "var trail = 0xdc00;"
7318       "p.push(String.fromCharCode(0xd800));"
7319       "p.push(String.fromCharCode(0xdc00));"
7320       "var a = [];"
7321       "var b = [];"
7322       "var c = [];"
7323       "var alens = [];"
7324       "for (var i = 0; i < 3; i++) {"
7325       "  p[1] = String.fromCharCode(lead++);"
7326       "  for (var j = 0; j < 3; j++) {"
7327       "    p[2] = String.fromCharCode(trail++);"
7328       "    a.push(p[i] + p[j]);"
7329       "    b.push(p[i] + p[j]);"
7330       "    c.push(p[i] + p[j]);"
7331       "    alens.push(plens[i] + plens[j]);"
7332       "  }"
7333       "}"
7334       "alens[5] -= 2;"  // Here the surrogate pairs match up.
7335       "var a2 = [];"
7336       "var b2 = [];"
7337       "var c2 = [];"
7338       "var a2lens = [];"
7339       "for (var m = 0; m < 9; m++) {"
7340       "  for (var n = 0; n < 9; n++) {"
7341       "    a2.push(a[m] + a[n]);"
7342       "    b2.push(b[m] + b[n]);"
7343       "    var newc = 'x' + c[m] + c[n] + 'y';"
7344       "    c2.push(newc.substring(1, newc.length - 1));"
7345       "    var utf = alens[m] + alens[n];"  // And here.
7346            // The 'n's that start with 0xdc.. are 6-8
7347            // The 'm's that end with 0xd8.. are 1, 4 and 7
7348       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
7349       "    a2lens.push(utf);"
7350       "  }"
7351       "}");
7352   Utf16Helper(context, "a", "alens", 9);
7353   Utf16Helper(context, "a2", "a2lens", 81);
7354 }
7355
7356
7357 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
7358   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
7359   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
7360   return *is1 == *is2;
7361 }
7362
7363
7364 THREADED_TEST(Utf16Symbol) {
7365   LocalContext context;
7366   v8::HandleScope scope(context->GetIsolate());
7367
7368   Handle<String> symbol1 = v8::String::NewFromUtf8(
7369       context->GetIsolate(), "abc", v8::String::kInternalizedString);
7370   Handle<String> symbol2 = v8::String::NewFromUtf8(
7371       context->GetIsolate(), "abc", v8::String::kInternalizedString);
7372   CHECK(SameSymbol(symbol1, symbol2));
7373
7374   CompileRun(
7375       "var sym0 = 'benedictus';"
7376       "var sym0b = 'S\303\270ren';"
7377       "var sym1 = '\355\240\201\355\260\207';"
7378       "var sym2 = '\360\220\220\210';"
7379       "var sym3 = 'x\355\240\201\355\260\207';"
7380       "var sym4 = 'x\360\220\220\210';"
7381       "if (sym1.length != 2) throw sym1;"
7382       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
7383       "if (sym2.length != 2) throw sym2;"
7384       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
7385       "if (sym3.length != 3) throw sym3;"
7386       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
7387       "if (sym4.length != 3) throw sym4;"
7388       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
7389   Handle<String> sym0 = v8::String::NewFromUtf8(
7390       context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
7391   Handle<String> sym0b = v8::String::NewFromUtf8(
7392       context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
7393   Handle<String> sym1 =
7394       v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
7395                               v8::String::kInternalizedString);
7396   Handle<String> sym2 =
7397       v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
7398                               v8::String::kInternalizedString);
7399   Handle<String> sym3 = v8::String::NewFromUtf8(
7400       context->GetIsolate(), "x\355\240\201\355\260\207",
7401       v8::String::kInternalizedString);
7402   Handle<String> sym4 =
7403       v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
7404                               v8::String::kInternalizedString);
7405   v8::Local<v8::Object> global = context->Global();
7406   Local<Value> s0 = global->Get(v8_str("sym0"));
7407   Local<Value> s0b = global->Get(v8_str("sym0b"));
7408   Local<Value> s1 = global->Get(v8_str("sym1"));
7409   Local<Value> s2 = global->Get(v8_str("sym2"));
7410   Local<Value> s3 = global->Get(v8_str("sym3"));
7411   Local<Value> s4 = global->Get(v8_str("sym4"));
7412   CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
7413   CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
7414   CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
7415   CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
7416   CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
7417   CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
7418 }
7419
7420
7421 THREADED_TEST(Utf16MissingTrailing) {
7422   LocalContext context;
7423   v8::HandleScope scope(context->GetIsolate());
7424
7425   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
7426   int size = 1024 * 64;
7427   uint8_t* buffer = new uint8_t[size];
7428   for (int i = 0; i < size; i += 4) {
7429     buffer[i] = 0xf0;
7430     buffer[i + 1] = 0x9d;
7431     buffer[i + 2] = 0x80;
7432     buffer[i + 3] = 0x9e;
7433   }
7434
7435   // Now invoke the decoder without last 3 bytes
7436   v8::Local<v8::String> str =
7437       v8::String::NewFromUtf8(
7438           context->GetIsolate(), reinterpret_cast<char*>(buffer),
7439           v8::NewStringType::kNormal, size - 3).ToLocalChecked();
7440   USE(str);
7441   delete[] buffer;
7442 }
7443
7444
7445 THREADED_TEST(Utf16Trailing3Byte) {
7446   LocalContext context;
7447   v8::HandleScope scope(context->GetIsolate());
7448
7449   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
7450   int size = 1024 * 63;
7451   uint8_t* buffer = new uint8_t[size];
7452   for (int i = 0; i < size; i += 3) {
7453     buffer[i] = 0xe2;
7454     buffer[i + 1] = 0x80;
7455     buffer[i + 2] = 0xa6;
7456   }
7457
7458   // Now invoke the decoder without last 3 bytes
7459   v8::Local<v8::String> str =
7460       v8::String::NewFromUtf8(
7461           context->GetIsolate(), reinterpret_cast<char*>(buffer),
7462           v8::NewStringType::kNormal, size).ToLocalChecked();
7463
7464   v8::String::Value value(str);
7465   CHECK_EQ(value.length(), size / 3);
7466   CHECK_EQ((*value)[value.length() - 1], 0x2026);
7467
7468   delete[] buffer;
7469 }
7470
7471
7472 THREADED_TEST(ToArrayIndex) {
7473   LocalContext context;
7474   v8::Isolate* isolate = context->GetIsolate();
7475   v8::HandleScope scope(isolate);
7476
7477   v8::Handle<String> str = v8_str("42");
7478   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
7479   CHECK(!index.IsEmpty());
7480   CHECK_EQ(42.0, index->Uint32Value());
7481   str = v8_str("42asdf");
7482   index = str->ToArrayIndex();
7483   CHECK(index.IsEmpty());
7484   str = v8_str("-42");
7485   index = str->ToArrayIndex();
7486   CHECK(index.IsEmpty());
7487   str = v8_str("4294967294");
7488   index = str->ToArrayIndex();
7489   CHECK(!index.IsEmpty());
7490   CHECK_EQ(4294967294.0, index->Uint32Value());
7491   v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
7492   index = num->ToArrayIndex();
7493   CHECK(!index.IsEmpty());
7494   CHECK_EQ(1.0, index->Uint32Value());
7495   num = v8::Number::New(isolate, -1);
7496   index = num->ToArrayIndex();
7497   CHECK(index.IsEmpty());
7498   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
7499   index = obj->ToArrayIndex();
7500   CHECK(index.IsEmpty());
7501 }
7502
7503
7504 THREADED_TEST(ErrorConstruction) {
7505   LocalContext context;
7506   v8::HandleScope scope(context->GetIsolate());
7507
7508   v8::Handle<String> foo = v8_str("foo");
7509   v8::Handle<String> message = v8_str("message");
7510   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
7511   CHECK(range_error->IsObject());
7512   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
7513   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
7514   CHECK(reference_error->IsObject());
7515   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
7516   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
7517   CHECK(syntax_error->IsObject());
7518   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
7519   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
7520   CHECK(type_error->IsObject());
7521   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
7522   v8::Handle<Value> error = v8::Exception::Error(foo);
7523   CHECK(error->IsObject());
7524   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7525 }
7526
7527
7528 static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
7529   ApiTestFuzzer::Fuzz();
7530   v8::Handle<String> foo = v8_str("foo");
7531   v8::Handle<String> message = v8_str("message");
7532   v8::Handle<Value> error = v8::Exception::Error(foo);
7533   CHECK(error->IsObject());
7534   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7535   info.GetIsolate()->ThrowException(error);
7536   info.GetReturnValue().SetUndefined();
7537 }
7538
7539
7540 THREADED_TEST(ExceptionCreateMessage) {
7541   LocalContext context;
7542   v8::HandleScope scope(context->GetIsolate());
7543   v8::Handle<String> foo_str = v8_str("foo");
7544   v8::Handle<String> message_str = v8_str("message");
7545
7546   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
7547
7548   Local<v8::FunctionTemplate> fun =
7549       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
7550   v8::Local<v8::Object> global = context->Global();
7551   global->Set(v8_str("throwV8Exception"), fun->GetFunction());
7552
7553   TryCatch try_catch(context->GetIsolate());
7554   CompileRun(
7555       "function f1() {\n"
7556       "  throwV8Exception();\n"
7557       "};\n"
7558       "f1();");
7559   CHECK(try_catch.HasCaught());
7560
7561   v8::Handle<v8::Value> error = try_catch.Exception();
7562   CHECK(error->IsObject());
7563   CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
7564
7565   v8::Handle<v8::Message> message = v8::Exception::CreateMessage(error);
7566   CHECK(!message.IsEmpty());
7567   CHECK_EQ(2, message->GetLineNumber());
7568   CHECK_EQ(2, message->GetStartColumn());
7569
7570   v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace();
7571   CHECK(!stackTrace.IsEmpty());
7572   CHECK_EQ(2, stackTrace->GetFrameCount());
7573
7574   stackTrace = v8::Exception::GetStackTrace(error);
7575   CHECK(!stackTrace.IsEmpty());
7576   CHECK_EQ(2, stackTrace->GetFrameCount());
7577
7578   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
7579
7580   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
7581   // is false.
7582   try_catch.Reset();
7583
7584   CompileRun(
7585       "function f2() {\n"
7586       "  return throwV8Exception();\n"
7587       "};\n"
7588       "f2();");
7589   CHECK(try_catch.HasCaught());
7590
7591   error = try_catch.Exception();
7592   CHECK(error->IsObject());
7593   CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
7594
7595   message = v8::Exception::CreateMessage(error);
7596   CHECK(!message.IsEmpty());
7597   CHECK_EQ(2, message->GetLineNumber());
7598   CHECK_EQ(9, message->GetStartColumn());
7599
7600   // Should be empty stack trace.
7601   stackTrace = message->GetStackTrace();
7602   CHECK(stackTrace.IsEmpty());
7603   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
7604 }
7605
7606
7607 THREADED_TEST(ExceptionCreateMessageLength) {
7608   LocalContext context;
7609   v8::HandleScope scope(context->GetIsolate());
7610
7611   // Test that the message is not truncated.
7612   TryCatch try_catch(context->GetIsolate());
7613   CompileRun(
7614       "var message = 'm';"
7615       "while (message.length < 1000) message += message;"
7616       "throw message;");
7617   CHECK(try_catch.HasCaught());
7618
7619   CHECK_LT(1000, try_catch.Message()->Get()->Length());
7620 }
7621
7622
7623 static void YGetter(Local<String> name,
7624                     const v8::PropertyCallbackInfo<v8::Value>& info) {
7625   ApiTestFuzzer::Fuzz();
7626   info.GetReturnValue().Set(v8_num(10));
7627 }
7628
7629
7630 static void YSetter(Local<String> name,
7631                     Local<Value> value,
7632                     const v8::PropertyCallbackInfo<void>& info) {
7633   Local<Object> this_obj = Local<Object>::Cast(info.This());
7634   if (this_obj->Has(name)) this_obj->Delete(name);
7635   this_obj->Set(name, value);
7636 }
7637
7638
7639 THREADED_TEST(DeleteAccessor) {
7640   v8::Isolate* isolate = CcTest::isolate();
7641   v8::HandleScope scope(isolate);
7642   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7643   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
7644   LocalContext context;
7645   v8::Handle<v8::Object> holder = obj->NewInstance();
7646   context->Global()->Set(v8_str("holder"), holder);
7647   v8::Handle<Value> result = CompileRun(
7648       "holder.y = 11; holder.y = 12; holder.y");
7649   CHECK_EQ(12u, result->Uint32Value());
7650 }
7651
7652
7653 THREADED_TEST(TypeSwitch) {
7654   v8::Isolate* isolate = CcTest::isolate();
7655   v8::HandleScope scope(isolate);
7656   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
7657   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
7658   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
7659   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
7660   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
7661   LocalContext context;
7662   v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
7663   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
7664   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
7665   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
7666   for (int i = 0; i < 10; i++) {
7667     CHECK_EQ(0, type_switch->match(obj0));
7668     CHECK_EQ(1, type_switch->match(obj1));
7669     CHECK_EQ(2, type_switch->match(obj2));
7670     CHECK_EQ(3, type_switch->match(obj3));
7671     CHECK_EQ(3, type_switch->match(obj3));
7672     CHECK_EQ(2, type_switch->match(obj2));
7673     CHECK_EQ(1, type_switch->match(obj1));
7674     CHECK_EQ(0, type_switch->match(obj0));
7675   }
7676 }
7677
7678
7679 static int trouble_nesting = 0;
7680 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
7681   ApiTestFuzzer::Fuzz();
7682   trouble_nesting++;
7683
7684   // Call a JS function that throws an uncaught exception.
7685   Local<v8::Object> arg_this =
7686       args.GetIsolate()->GetCurrentContext()->Global();
7687   Local<Value> trouble_callee = (trouble_nesting == 3) ?
7688     arg_this->Get(v8_str("trouble_callee")) :
7689     arg_this->Get(v8_str("trouble_caller"));
7690   CHECK(trouble_callee->IsFunction());
7691   args.GetReturnValue().Set(
7692       Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
7693 }
7694
7695
7696 static int report_count = 0;
7697 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
7698                                              v8::Handle<Value>) {
7699   report_count++;
7700 }
7701
7702
7703 // Counts uncaught exceptions, but other tests running in parallel
7704 // also have uncaught exceptions.
7705 TEST(ApiUncaughtException) {
7706   report_count = 0;
7707   LocalContext env;
7708   v8::Isolate* isolate = env->GetIsolate();
7709   v8::HandleScope scope(isolate);
7710   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7711
7712   Local<v8::FunctionTemplate> fun =
7713       v8::FunctionTemplate::New(isolate, TroubleCallback);
7714   v8::Local<v8::Object> global = env->Global();
7715   global->Set(v8_str("trouble"), fun->GetFunction());
7716
7717   CompileRun(
7718       "function trouble_callee() {"
7719       "  var x = null;"
7720       "  return x.foo;"
7721       "};"
7722       "function trouble_caller() {"
7723       "  trouble();"
7724       "};");
7725   Local<Value> trouble = global->Get(v8_str("trouble"));
7726   CHECK(trouble->IsFunction());
7727   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
7728   CHECK(trouble_callee->IsFunction());
7729   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
7730   CHECK(trouble_caller->IsFunction());
7731   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
7732   CHECK_EQ(1, report_count);
7733   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7734 }
7735
7736
7737 TEST(ApiUncaughtExceptionInObjectObserve) {
7738   v8::internal::FLAG_stack_size = 150;
7739   report_count = 0;
7740   LocalContext env;
7741   v8::Isolate* isolate = env->GetIsolate();
7742   v8::HandleScope scope(isolate);
7743   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7744   CompileRun(
7745       "var obj = {};"
7746       "var observe_count = 0;"
7747       "function observer1() { ++observe_count; };"
7748       "function observer2() { ++observe_count; };"
7749       "function observer_throws() { throw new Error(); };"
7750       "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
7751       "Object.observe(obj, observer_throws.bind());"
7752       "Object.observe(obj, observer1);"
7753       "Object.observe(obj, stack_overflow);"
7754       "Object.observe(obj, observer2);"
7755       "Object.observe(obj, observer_throws.bind());"
7756       "obj.foo = 'bar';");
7757   CHECK_EQ(3, report_count);
7758   ExpectInt32("observe_count", 2);
7759   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7760 }
7761
7762
7763 static const char* script_resource_name = "ExceptionInNativeScript.js";
7764 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
7765                                                 v8::Handle<Value>) {
7766   v8::Handle<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
7767   CHECK(!name_val.IsEmpty() && name_val->IsString());
7768   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
7769   CHECK_EQ(0, strcmp(script_resource_name, *name));
7770   CHECK_EQ(3, message->GetLineNumber());
7771   v8::String::Utf8Value source_line(message->GetSourceLine());
7772   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
7773 }
7774
7775
7776 TEST(ExceptionInNativeScript) {
7777   LocalContext env;
7778   v8::Isolate* isolate = env->GetIsolate();
7779   v8::HandleScope scope(isolate);
7780   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
7781
7782   Local<v8::FunctionTemplate> fun =
7783       v8::FunctionTemplate::New(isolate, TroubleCallback);
7784   v8::Local<v8::Object> global = env->Global();
7785   global->Set(v8_str("trouble"), fun->GetFunction());
7786
7787   CompileRunWithOrigin(
7788       "function trouble() {\n"
7789       "  var o = {};\n"
7790       "  new o.foo();\n"
7791       "};",
7792       script_resource_name);
7793   Local<Value> trouble = global->Get(v8_str("trouble"));
7794   CHECK(trouble->IsFunction());
7795   Function::Cast(*trouble)->Call(global, 0, NULL);
7796   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
7797 }
7798
7799
7800 TEST(CompilationErrorUsingTryCatchHandler) {
7801   LocalContext env;
7802   v8::HandleScope scope(env->GetIsolate());
7803   v8::TryCatch try_catch(env->GetIsolate());
7804   v8_compile("This doesn't &*&@#$&*^ compile.");
7805   CHECK(*try_catch.Exception());
7806   CHECK(try_catch.HasCaught());
7807 }
7808
7809
7810 TEST(TryCatchFinallyUsingTryCatchHandler) {
7811   LocalContext env;
7812   v8::HandleScope scope(env->GetIsolate());
7813   v8::TryCatch try_catch(env->GetIsolate());
7814   CompileRun("try { throw ''; } catch (e) {}");
7815   CHECK(!try_catch.HasCaught());
7816   CompileRun("try { throw ''; } finally {}");
7817   CHECK(try_catch.HasCaught());
7818   try_catch.Reset();
7819   CompileRun(
7820       "(function() {"
7821       "try { throw ''; } finally { return; }"
7822       "})()");
7823   CHECK(!try_catch.HasCaught());
7824   CompileRun(
7825       "(function()"
7826       "  { try { throw ''; } finally { throw 0; }"
7827       "})()");
7828   CHECK(try_catch.HasCaught());
7829 }
7830
7831
7832 void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
7833   v8::HandleScope scope(args.GetIsolate());
7834   CompileRun(args[0]->ToString(args.GetIsolate()));
7835 }
7836
7837
7838 TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
7839   v8::Isolate* isolate = CcTest::isolate();
7840   v8::HandleScope scope(isolate);
7841   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
7842   templ->Set(v8_str("CEvaluate"),
7843              v8::FunctionTemplate::New(isolate, CEvaluate));
7844   LocalContext context(0, templ);
7845   v8::TryCatch try_catch(isolate);
7846   CompileRun("try {"
7847              "  CEvaluate('throw 1;');"
7848              "} finally {"
7849              "}");
7850   CHECK(try_catch.HasCaught());
7851   CHECK(!try_catch.Message().IsEmpty());
7852   String::Utf8Value exception_value(try_catch.Exception());
7853   CHECK_EQ(0, strcmp(*exception_value, "1"));
7854   try_catch.Reset();
7855   CompileRun("try {"
7856              "  CEvaluate('throw 1;');"
7857              "} finally {"
7858              "  throw 2;"
7859              "}");
7860   CHECK(try_catch.HasCaught());
7861   CHECK(!try_catch.Message().IsEmpty());
7862   String::Utf8Value finally_exception_value(try_catch.Exception());
7863   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
7864 }
7865
7866
7867 // For use within the TestSecurityHandler() test.
7868 static bool g_security_callback_result = false;
7869 static bool SecurityTestCallback(Local<v8::Object> global, Local<Value> name,
7870                                  v8::AccessType type, Local<Value> data) {
7871   printf("a\n");
7872   return g_security_callback_result;
7873 }
7874
7875
7876 // SecurityHandler can't be run twice
7877 TEST(SecurityHandler) {
7878   v8::Isolate* isolate = CcTest::isolate();
7879   v8::HandleScope scope0(isolate);
7880   v8::Handle<v8::ObjectTemplate> global_template =
7881       v8::ObjectTemplate::New(isolate);
7882   global_template->SetAccessCheckCallbacks(SecurityTestCallback, NULL);
7883   // Create an environment
7884   v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
7885   context0->Enter();
7886
7887   v8::Handle<v8::Object> global0 = context0->Global();
7888   v8::Handle<Script> script0 = v8_compile("foo = 111");
7889   script0->Run();
7890   global0->Set(v8_str("0"), v8_num(999));
7891   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
7892   CHECK_EQ(111, foo0->Int32Value());
7893   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
7894   CHECK_EQ(999, z0->Int32Value());
7895
7896   // Create another environment, should fail security checks.
7897   v8::HandleScope scope1(isolate);
7898
7899   v8::Handle<Context> context1 =
7900     Context::New(isolate, NULL, global_template);
7901   context1->Enter();
7902
7903   v8::Handle<v8::Object> global1 = context1->Global();
7904   global1->Set(v8_str("othercontext"), global0);
7905   // This set will fail the security check.
7906   v8::Handle<Script> script1 =
7907     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
7908   script1->Run();
7909   g_security_callback_result = true;
7910   // This read will pass the security check.
7911   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
7912   CHECK_EQ(111, foo1->Int32Value());
7913   // This read will pass the security check.
7914   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
7915   CHECK_EQ(999, z1->Int32Value());
7916
7917   // Create another environment, should pass security checks.
7918   {
7919     v8::HandleScope scope2(isolate);
7920     LocalContext context2;
7921     v8::Handle<v8::Object> global2 = context2->Global();
7922     global2->Set(v8_str("othercontext"), global0);
7923     v8::Handle<Script> script2 =
7924         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
7925     script2->Run();
7926     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
7927     CHECK_EQ(333, foo2->Int32Value());
7928     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
7929     CHECK_EQ(888, z2->Int32Value());
7930   }
7931
7932   context1->Exit();
7933   context0->Exit();
7934 }
7935
7936
7937 THREADED_TEST(SecurityChecks) {
7938   LocalContext env1;
7939   v8::HandleScope handle_scope(env1->GetIsolate());
7940   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
7941
7942   Local<Value> foo = v8_str("foo");
7943   Local<Value> bar = v8_str("bar");
7944
7945   // Set to the same domain.
7946   env1->SetSecurityToken(foo);
7947
7948   // Create a function in env1.
7949   CompileRun("spy=function(){return spy;}");
7950   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
7951   CHECK(spy->IsFunction());
7952
7953   // Create another function accessing global objects.
7954   CompileRun("spy2=function(){return new this.Array();}");
7955   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
7956   CHECK(spy2->IsFunction());
7957
7958   // Switch to env2 in the same domain and invoke spy on env2.
7959   {
7960     env2->SetSecurityToken(foo);
7961     // Enter env2
7962     Context::Scope scope_env2(env2);
7963     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
7964     CHECK(result->IsFunction());
7965   }
7966
7967   {
7968     env2->SetSecurityToken(bar);
7969     Context::Scope scope_env2(env2);
7970
7971     // Call cross_domain_call, it should throw an exception
7972     v8::TryCatch try_catch(env1->GetIsolate());
7973     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
7974     CHECK(try_catch.HasCaught());
7975   }
7976 }
7977
7978
7979 // Regression test case for issue 1183439.
7980 THREADED_TEST(SecurityChecksForPrototypeChain) {
7981   LocalContext current;
7982   v8::HandleScope scope(current->GetIsolate());
7983   v8::Handle<Context> other = Context::New(current->GetIsolate());
7984
7985   // Change context to be able to get to the Object function in the
7986   // other context without hitting the security checks.
7987   v8::Local<Value> other_object;
7988   { Context::Scope scope(other);
7989     other_object = other->Global()->Get(v8_str("Object"));
7990     other->Global()->Set(v8_num(42), v8_num(87));
7991   }
7992
7993   current->Global()->Set(v8_str("other"), other->Global());
7994   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
7995
7996   // Make sure the security check fails here and we get an undefined
7997   // result instead of getting the Object function. Repeat in a loop
7998   // to make sure to exercise the IC code.
7999   v8::Local<Script> access_other0 = v8_compile("other.Object");
8000   v8::Local<Script> access_other1 = v8_compile("other[42]");
8001   for (int i = 0; i < 5; i++) {
8002     CHECK(access_other0->Run().IsEmpty());
8003     CHECK(access_other1->Run().IsEmpty());
8004   }
8005
8006   // Create an object that has 'other' in its prototype chain and make
8007   // sure we cannot access the Object function indirectly through
8008   // that. Repeat in a loop to make sure to exercise the IC code.
8009   v8_compile("function F() { };"
8010              "F.prototype = other;"
8011              "var f = new F();")->Run();
8012   v8::Local<Script> access_f0 = v8_compile("f.Object");
8013   v8::Local<Script> access_f1 = v8_compile("f[42]");
8014   for (int j = 0; j < 5; j++) {
8015     CHECK(access_f0->Run().IsEmpty());
8016     CHECK(access_f1->Run().IsEmpty());
8017   }
8018
8019   // Now it gets hairy: Set the prototype for the other global object
8020   // to be the current global object. The prototype chain for 'f' now
8021   // goes through 'other' but ends up in the current global object.
8022   { Context::Scope scope(other);
8023     other->Global()->Set(v8_str("__proto__"), current->Global());
8024   }
8025   // Set a named and an index property on the current global
8026   // object. To force the lookup to go through the other global object,
8027   // the properties must not exist in the other global object.
8028   current->Global()->Set(v8_str("foo"), v8_num(100));
8029   current->Global()->Set(v8_num(99), v8_num(101));
8030   // Try to read the properties from f and make sure that the access
8031   // gets stopped by the security checks on the other global object.
8032   Local<Script> access_f2 = v8_compile("f.foo");
8033   Local<Script> access_f3 = v8_compile("f[99]");
8034   for (int k = 0; k < 5; k++) {
8035     CHECK(access_f2->Run().IsEmpty());
8036     CHECK(access_f3->Run().IsEmpty());
8037   }
8038 }
8039
8040
8041 static bool security_check_with_gc_called;
8042
8043 static bool SecurityTestCallbackWithGC(Local<v8::Object> global,
8044                                        Local<v8::Value> name,
8045                                        v8::AccessType type, Local<Value> data) {
8046   CcTest::heap()->CollectAllGarbage();
8047   security_check_with_gc_called = true;
8048   return true;
8049 }
8050
8051
8052 TEST(SecurityTestGCAllowed) {
8053   v8::Isolate* isolate = CcTest::isolate();
8054   v8::HandleScope handle_scope(isolate);
8055   v8::Handle<v8::ObjectTemplate> object_template =
8056       v8::ObjectTemplate::New(isolate);
8057   object_template->SetAccessCheckCallbacks(SecurityTestCallbackWithGC, NULL);
8058
8059   v8::Handle<Context> context = Context::New(isolate);
8060   v8::Context::Scope context_scope(context);
8061
8062   context->Global()->Set(v8_str("obj"), object_template->NewInstance());
8063
8064   security_check_with_gc_called = false;
8065   CompileRun("obj[0] = new String(1002);");
8066   CHECK(security_check_with_gc_called);
8067
8068   security_check_with_gc_called = false;
8069   CHECK(CompileRun("obj[0]")->ToString(isolate)->Equals(v8_str("1002")));
8070   CHECK(security_check_with_gc_called);
8071 }
8072
8073
8074 THREADED_TEST(CrossDomainDelete) {
8075   LocalContext env1;
8076   v8::HandleScope handle_scope(env1->GetIsolate());
8077   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8078
8079   Local<Value> foo = v8_str("foo");
8080   Local<Value> bar = v8_str("bar");
8081
8082   // Set to the same domain.
8083   env1->SetSecurityToken(foo);
8084   env2->SetSecurityToken(foo);
8085
8086   env1->Global()->Set(v8_str("prop"), v8_num(3));
8087   env2->Global()->Set(v8_str("env1"), env1->Global());
8088
8089   // Change env2 to a different domain and delete env1.prop.
8090   env2->SetSecurityToken(bar);
8091   {
8092     Context::Scope scope_env2(env2);
8093     Local<Value> result =
8094         CompileRun("delete env1.prop");
8095     CHECK(result.IsEmpty());
8096   }
8097
8098   // Check that env1.prop still exists.
8099   Local<Value> v = env1->Global()->Get(v8_str("prop"));
8100   CHECK(v->IsNumber());
8101   CHECK_EQ(3, v->Int32Value());
8102 }
8103
8104
8105 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
8106   LocalContext env1;
8107   v8::HandleScope handle_scope(env1->GetIsolate());
8108   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8109
8110   Local<Value> foo = v8_str("foo");
8111   Local<Value> bar = v8_str("bar");
8112
8113   // Set to the same domain.
8114   env1->SetSecurityToken(foo);
8115   env2->SetSecurityToken(foo);
8116
8117   env1->Global()->Set(v8_str("prop"), v8_num(3));
8118   env2->Global()->Set(v8_str("env1"), env1->Global());
8119
8120   // env1.prop is enumerable in env2.
8121   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8122   {
8123     Context::Scope scope_env2(env2);
8124     Local<Value> result = CompileRun(test);
8125     CHECK(result->IsTrue());
8126   }
8127
8128   // Change env2 to a different domain and test again.
8129   env2->SetSecurityToken(bar);
8130   {
8131     Context::Scope scope_env2(env2);
8132     Local<Value> result = CompileRun(test);
8133     CHECK(result.IsEmpty());
8134   }
8135 }
8136
8137
8138 THREADED_TEST(CrossDomainForIn) {
8139   LocalContext env1;
8140   v8::HandleScope handle_scope(env1->GetIsolate());
8141   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8142
8143   Local<Value> foo = v8_str("foo");
8144   Local<Value> bar = v8_str("bar");
8145
8146   // Set to the same domain.
8147   env1->SetSecurityToken(foo);
8148   env2->SetSecurityToken(foo);
8149
8150   env1->Global()->Set(v8_str("prop"), v8_num(3));
8151   env2->Global()->Set(v8_str("env1"), env1->Global());
8152
8153   // Change env2 to a different domain and set env1's global object
8154   // as the __proto__ of an object in env2 and enumerate properties
8155   // in for-in. It shouldn't enumerate properties on env1's global
8156   // object.
8157   env2->SetSecurityToken(bar);
8158   {
8159     Context::Scope scope_env2(env2);
8160     Local<Value> result = CompileRun(
8161         "(function() {"
8162         "  var obj = { '__proto__': env1 };"
8163         "  try {"
8164         "    for (var p in obj) {"
8165         "      if (p == 'prop') return false;"
8166         "    }"
8167         "    return false;"
8168         "  } catch (e) {"
8169         "    return true;"
8170         "  }"
8171         "})()");
8172     CHECK(result->IsTrue());
8173   }
8174 }
8175
8176
8177 TEST(ContextDetachGlobal) {
8178   LocalContext env1;
8179   v8::HandleScope handle_scope(env1->GetIsolate());
8180   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8181
8182   Local<v8::Object> global1 = env1->Global();
8183
8184   Local<Value> foo = v8_str("foo");
8185
8186   // Set to the same domain.
8187   env1->SetSecurityToken(foo);
8188   env2->SetSecurityToken(foo);
8189
8190   // Enter env2
8191   env2->Enter();
8192
8193   // Create a function in env2 and add a reference to it in env1.
8194   Local<v8::Object> global2 = env2->Global();
8195   global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
8196   CompileRun("function getProp() {return prop;}");
8197
8198   env1->Global()->Set(v8_str("getProp"),
8199                       global2->Get(v8_str("getProp")));
8200
8201   // Detach env2's global, and reuse the global object of env2
8202   env2->Exit();
8203   env2->DetachGlobal();
8204
8205   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8206                                           0,
8207                                           v8::Handle<v8::ObjectTemplate>(),
8208                                           global2);
8209   env3->SetSecurityToken(v8_str("bar"));
8210   env3->Enter();
8211
8212   Local<v8::Object> global3 = env3->Global();
8213   CHECK(global2->Equals(global3));
8214   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8215   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
8216   global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8217   global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
8218   env3->Exit();
8219
8220   // Call getProp in env1, and it should return the value 1
8221   {
8222     Local<Value> get_prop = global1->Get(v8_str("getProp"));
8223     CHECK(get_prop->IsFunction());
8224     v8::TryCatch try_catch(env1->GetIsolate());
8225     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8226     CHECK(!try_catch.HasCaught());
8227     CHECK_EQ(1, r->Int32Value());
8228   }
8229
8230   // Check that env3 is not accessible from env1
8231   {
8232     Local<Value> r = global3->Get(v8_str("prop2"));
8233     CHECK(r.IsEmpty());
8234   }
8235 }
8236
8237
8238 TEST(DetachGlobal) {
8239   LocalContext env1;
8240   v8::HandleScope scope(env1->GetIsolate());
8241
8242   // Create second environment.
8243   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8244
8245   Local<Value> foo = v8_str("foo");
8246
8247   // Set same security token for env1 and env2.
8248   env1->SetSecurityToken(foo);
8249   env2->SetSecurityToken(foo);
8250
8251   // Create a property on the global object in env2.
8252   {
8253     v8::Context::Scope scope(env2);
8254     env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
8255   }
8256
8257   // Create a reference to env2 global from env1 global.
8258   env1->Global()->Set(v8_str("other"), env2->Global());
8259
8260   // Check that we have access to other.p in env2 from env1.
8261   Local<Value> result = CompileRun("other.p");
8262   CHECK(result->IsInt32());
8263   CHECK_EQ(42, result->Int32Value());
8264
8265   // Hold on to global from env2 and detach global from env2.
8266   Local<v8::Object> global2 = env2->Global();
8267   env2->DetachGlobal();
8268
8269   // Check that the global has been detached. No other.p property can
8270   // be found.
8271   result = CompileRun("other.p");
8272   CHECK(result.IsEmpty());
8273
8274   // Reuse global2 for env3.
8275   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8276                                           0,
8277                                           v8::Handle<v8::ObjectTemplate>(),
8278                                           global2);
8279   CHECK(global2->Equals(env3->Global()));
8280
8281   // Start by using the same security token for env3 as for env1 and env2.
8282   env3->SetSecurityToken(foo);
8283
8284   // Create a property on the global object in env3.
8285   {
8286     v8::Context::Scope scope(env3);
8287     env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
8288   }
8289
8290   // Check that other.p is now the property in env3 and that we have access.
8291   result = CompileRun("other.p");
8292   CHECK(result->IsInt32());
8293   CHECK_EQ(24, result->Int32Value());
8294
8295   // Change security token for env3 to something different from env1 and env2.
8296   env3->SetSecurityToken(v8_str("bar"));
8297
8298   // Check that we do not have access to other.p in env1. |other| is now
8299   // the global object for env3 which has a different security token,
8300   // so access should be blocked.
8301   result = CompileRun("other.p");
8302   CHECK(result.IsEmpty());
8303 }
8304
8305
8306 void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
8307   info.GetReturnValue().Set(
8308       info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8309 }
8310
8311
8312 TEST(DetachedAccesses) {
8313   LocalContext env1;
8314   v8::HandleScope scope(env1->GetIsolate());
8315
8316   // Create second environment.
8317   Local<ObjectTemplate> inner_global_template =
8318       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8319   inner_global_template ->SetAccessorProperty(
8320       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8321   v8::Local<Context> env2 =
8322       Context::New(env1->GetIsolate(), NULL, inner_global_template);
8323
8324   Local<Value> foo = v8_str("foo");
8325
8326   // Set same security token for env1 and env2.
8327   env1->SetSecurityToken(foo);
8328   env2->SetSecurityToken(foo);
8329
8330   env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8331
8332   {
8333     v8::Context::Scope scope(env2);
8334     env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
8335     CompileRun(
8336         "function bound_x() { return x; }"
8337         "function get_x()   { return this.x; }"
8338         "function get_x_w() { return (function() {return this.x;})(); }");
8339     env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
8340     env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8341     env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
8342     env1->Global()->Set(
8343         v8_str("this_x"),
8344         CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
8345   }
8346
8347   Local<Object> env2_global = env2->Global();
8348   env2->DetachGlobal();
8349
8350   Local<Value> result;
8351   result = CompileRun("bound_x()");
8352   CHECK(v8_str("env2_x")->Equals(result));
8353   result = CompileRun("get_x()");
8354   CHECK(result.IsEmpty());
8355   result = CompileRun("get_x_w()");
8356   CHECK(result.IsEmpty());
8357   result = CompileRun("this_x()");
8358   CHECK(v8_str("env2_x")->Equals(result));
8359
8360   // Reattach env2's proxy
8361   env2 = Context::New(env1->GetIsolate(),
8362                       0,
8363                       v8::Handle<v8::ObjectTemplate>(),
8364                       env2_global);
8365   env2->SetSecurityToken(foo);
8366   {
8367     v8::Context::Scope scope(env2);
8368     env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8369     env2->Global()->Set(v8_str("env1"), env1->Global());
8370     result = CompileRun(
8371         "results = [];"
8372         "for (var i = 0; i < 4; i++ ) {"
8373         "  results.push(env1.bound_x());"
8374         "  results.push(env1.get_x());"
8375         "  results.push(env1.get_x_w());"
8376         "  results.push(env1.this_x());"
8377         "}"
8378         "results");
8379     Local<v8::Array> results = Local<v8::Array>::Cast(result);
8380     CHECK_EQ(16u, results->Length());
8381     for (int i = 0; i < 16; i += 4) {
8382       CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8383       CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
8384       CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8385       CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8386     }
8387   }
8388
8389   result = CompileRun(
8390       "results = [];"
8391       "for (var i = 0; i < 4; i++ ) {"
8392       "  results.push(bound_x());"
8393       "  results.push(get_x());"
8394       "  results.push(get_x_w());"
8395       "  results.push(this_x());"
8396       "}"
8397       "results");
8398   Local<v8::Array> results = Local<v8::Array>::Cast(result);
8399   CHECK_EQ(16u, results->Length());
8400   for (int i = 0; i < 16; i += 4) {
8401     CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8402     CHECK(v8_str("env3_x")->Equals(results->Get(i + 1)));
8403     CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8404     CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8405   }
8406
8407   result = CompileRun(
8408       "results = [];"
8409       "for (var i = 0; i < 4; i++ ) {"
8410       "  results.push(this.bound_x());"
8411       "  results.push(this.get_x());"
8412       "  results.push(this.get_x_w());"
8413       "  results.push(this.this_x());"
8414       "}"
8415       "results");
8416   results = Local<v8::Array>::Cast(result);
8417   CHECK_EQ(16u, results->Length());
8418   for (int i = 0; i < 16; i += 4) {
8419     CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8420     CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
8421     CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8422     CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8423   }
8424 }
8425
8426
8427 static bool allowed_access = false;
8428 static bool AccessBlocker(Local<v8::Object> global, Local<Value> name,
8429                           v8::AccessType type, Local<Value> data) {
8430   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
8431          allowed_access;
8432 }
8433
8434
8435 static int g_echo_value = -1;
8436
8437
8438 static void EchoGetter(
8439     Local<String> name,
8440     const v8::PropertyCallbackInfo<v8::Value>& info) {
8441   info.GetReturnValue().Set(v8_num(g_echo_value));
8442 }
8443
8444
8445 static void EchoSetter(Local<String> name,
8446                        Local<Value> value,
8447                        const v8::PropertyCallbackInfo<void>&) {
8448   if (value->IsNumber())
8449     g_echo_value = value->Int32Value();
8450 }
8451
8452
8453 static void UnreachableGetter(
8454     Local<String> name,
8455     const v8::PropertyCallbackInfo<v8::Value>& info) {
8456   CHECK(false);  // This function should not be called..
8457 }
8458
8459
8460 static void UnreachableSetter(Local<String>,
8461                               Local<Value>,
8462                               const v8::PropertyCallbackInfo<void>&) {
8463   CHECK(false);  // This function should nto be called.
8464 }
8465
8466
8467 static void UnreachableFunction(
8468     const v8::FunctionCallbackInfo<v8::Value>& info) {
8469   CHECK(false);  // This function should not be called..
8470 }
8471
8472
8473 TEST(AccessControl) {
8474   v8::Isolate* isolate = CcTest::isolate();
8475   v8::HandleScope handle_scope(isolate);
8476   v8::Handle<v8::ObjectTemplate> global_template =
8477       v8::ObjectTemplate::New(isolate);
8478
8479   global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
8480
8481   // Add an accessor accessible by cross-domain JS code.
8482   global_template->SetAccessor(
8483       v8_str("accessible_prop"),
8484       EchoGetter, EchoSetter,
8485       v8::Handle<Value>(),
8486       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8487
8488
8489   // Add an accessor that is not accessible by cross-domain JS code.
8490   global_template->SetAccessor(v8_str("blocked_prop"),
8491                                UnreachableGetter, UnreachableSetter,
8492                                v8::Handle<Value>(),
8493                                v8::DEFAULT);
8494
8495   global_template->SetAccessorProperty(
8496       v8_str("blocked_js_prop"),
8497       v8::FunctionTemplate::New(isolate, UnreachableFunction),
8498       v8::FunctionTemplate::New(isolate, UnreachableFunction),
8499       v8::None,
8500       v8::DEFAULT);
8501
8502   // Create an environment
8503   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8504   context0->Enter();
8505
8506   v8::Handle<v8::Object> global0 = context0->Global();
8507
8508   // Define a property with JS getter and setter.
8509   CompileRun(
8510       "function getter() { return 'getter'; };\n"
8511       "function setter() { return 'setter'; }\n"
8512       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8513
8514   Local<Value> getter = global0->Get(v8_str("getter"));
8515   Local<Value> setter = global0->Get(v8_str("setter"));
8516
8517   // And define normal element.
8518   global0->Set(239, v8_str("239"));
8519
8520   // Define an element with JS getter and setter.
8521   CompileRun(
8522       "function el_getter() { return 'el_getter'; };\n"
8523       "function el_setter() { return 'el_setter'; };\n"
8524       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
8525
8526   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
8527   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
8528
8529   v8::HandleScope scope1(isolate);
8530
8531   v8::Local<Context> context1 = Context::New(isolate);
8532   context1->Enter();
8533
8534   v8::Handle<v8::Object> global1 = context1->Global();
8535   global1->Set(v8_str("other"), global0);
8536
8537   // Access blocked property.
8538   CompileRun("other.blocked_prop = 1");
8539
8540   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8541   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
8542             .IsEmpty());
8543   CHECK(
8544       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
8545
8546   // Access blocked element.
8547   CHECK(CompileRun("other[239] = 1").IsEmpty());
8548
8549   CHECK(CompileRun("other[239]").IsEmpty());
8550   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
8551   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
8552
8553   allowed_access = true;
8554   // Now we can enumerate the property.
8555   ExpectTrue("propertyIsEnumerable.call(other, '239')");
8556   allowed_access = false;
8557
8558   // Access a property with JS accessor.
8559   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
8560
8561   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
8562   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
8563             .IsEmpty());
8564
8565   allowed_access = true;
8566
8567   ExpectString("other.js_accessor_p", "getter");
8568   ExpectObject(
8569       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
8570   ExpectObject(
8571       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
8572   ExpectUndefined(
8573       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8574
8575   allowed_access = false;
8576
8577   // Access an element with JS accessor.
8578   CHECK(CompileRun("other[42] = 2").IsEmpty());
8579
8580   CHECK(CompileRun("other[42]").IsEmpty());
8581   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
8582
8583   allowed_access = true;
8584
8585   ExpectString("other[42]", "el_getter");
8586   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
8587   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
8588   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8589
8590   allowed_access = false;
8591
8592   v8::Handle<Value> value;
8593
8594   // Access accessible property
8595   value = CompileRun("other.accessible_prop = 3");
8596   CHECK(value->IsNumber());
8597   CHECK_EQ(3, value->Int32Value());
8598   CHECK_EQ(3, g_echo_value);
8599
8600   value = CompileRun("other.accessible_prop");
8601   CHECK(value->IsNumber());
8602   CHECK_EQ(3, value->Int32Value());
8603
8604   value = CompileRun(
8605       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
8606   CHECK(value->IsNumber());
8607   CHECK_EQ(3, value->Int32Value());
8608
8609   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
8610   CHECK(value->IsTrue());
8611
8612   // Enumeration doesn't enumerate accessors from inaccessible objects in
8613   // the prototype chain even if the accessors are in themselves accessible.
8614   value = CompileRun(
8615       "(function() {"
8616       "  var obj = { '__proto__': other };"
8617       "  try {"
8618       "    for (var p in obj) {"
8619       "      if (p == 'accessible_prop' ||"
8620       "          p == 'blocked_js_prop' ||"
8621       "          p == 'blocked_js_prop') {"
8622       "        return false;"
8623       "      }"
8624       "    }"
8625       "    return false;"
8626       "  } catch (e) {"
8627       "    return true;"
8628       "  }"
8629       "})()");
8630   CHECK(value->IsTrue());
8631
8632   context1->Exit();
8633   context0->Exit();
8634 }
8635
8636
8637 TEST(AccessControlES5) {
8638   v8::Isolate* isolate = CcTest::isolate();
8639   v8::HandleScope handle_scope(isolate);
8640   v8::Handle<v8::ObjectTemplate> global_template =
8641       v8::ObjectTemplate::New(isolate);
8642
8643   global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
8644
8645   // Add accessible accessor.
8646   global_template->SetAccessor(
8647       v8_str("accessible_prop"),
8648       EchoGetter, EchoSetter,
8649       v8::Handle<Value>(),
8650       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8651
8652
8653   // Add an accessor that is not accessible by cross-domain JS code.
8654   global_template->SetAccessor(v8_str("blocked_prop"),
8655                                UnreachableGetter, UnreachableSetter,
8656                                v8::Handle<Value>(),
8657                                v8::DEFAULT);
8658
8659   // Create an environment
8660   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8661   context0->Enter();
8662
8663   v8::Handle<v8::Object> global0 = context0->Global();
8664
8665   v8::Local<Context> context1 = Context::New(isolate);
8666   context1->Enter();
8667   v8::Handle<v8::Object> global1 = context1->Global();
8668   global1->Set(v8_str("other"), global0);
8669
8670   // Regression test for issue 1154.
8671   CHECK(CompileRun("Object.keys(other)").IsEmpty());
8672   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8673
8674   // Regression test for issue 1027.
8675   CompileRun("Object.defineProperty(\n"
8676              "  other, 'blocked_prop', {configurable: false})");
8677   CHECK(CompileRun("other.blocked_prop").IsEmpty());
8678   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
8679             .IsEmpty());
8680
8681   // Regression test for issue 1171.
8682   ExpectTrue("Object.isExtensible(other)");
8683   CompileRun("Object.preventExtensions(other)");
8684   ExpectTrue("Object.isExtensible(other)");
8685
8686   // Object.seal and Object.freeze.
8687   CompileRun("Object.freeze(other)");
8688   ExpectTrue("Object.isExtensible(other)");
8689
8690   CompileRun("Object.seal(other)");
8691   ExpectTrue("Object.isExtensible(other)");
8692
8693   // Regression test for issue 1250.
8694   // Make sure that we can set the accessible accessors value using normal
8695   // assignment.
8696   CompileRun("other.accessible_prop = 42");
8697   CHECK_EQ(42, g_echo_value);
8698
8699   v8::Handle<Value> value;
8700   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
8701   value = CompileRun("other.accessible_prop == 42");
8702   CHECK(value->IsTrue());
8703 }
8704
8705
8706 static bool AccessAlwaysBlocked(Local<v8::Object> global, Local<Value> name,
8707                                 v8::AccessType type, Local<Value> data) {
8708   i::PrintF("Access blocked.\n");
8709   return false;
8710 }
8711
8712
8713 THREADED_TEST(AccessControlGetOwnPropertyNames) {
8714   v8::Isolate* isolate = CcTest::isolate();
8715   v8::HandleScope handle_scope(isolate);
8716   v8::Handle<v8::ObjectTemplate> obj_template =
8717       v8::ObjectTemplate::New(isolate);
8718
8719   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
8720   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8721
8722   // Create an environment
8723   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
8724   context0->Enter();
8725
8726   v8::Handle<v8::Object> global0 = context0->Global();
8727
8728   v8::HandleScope scope1(CcTest::isolate());
8729
8730   v8::Local<Context> context1 = Context::New(isolate);
8731   context1->Enter();
8732
8733   v8::Handle<v8::Object> global1 = context1->Global();
8734   global1->Set(v8_str("other"), global0);
8735   global1->Set(v8_str("object"), obj_template->NewInstance());
8736
8737   v8::Handle<Value> value;
8738
8739   // Attempt to get the property names of the other global object and
8740   // of an object that requires access checks.  Accessing the other
8741   // global object should be blocked by access checks on the global
8742   // proxy object.  Accessing the object that requires access checks
8743   // is blocked by the access checks on the object itself.
8744   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
8745   CHECK(value.IsEmpty());
8746
8747   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
8748   CHECK(value.IsEmpty());
8749
8750   context1->Exit();
8751   context0->Exit();
8752 }
8753
8754
8755 TEST(SuperAccessControl) {
8756   i::FLAG_allow_natives_syntax = true;
8757   v8::Isolate* isolate = CcTest::isolate();
8758   v8::HandleScope handle_scope(isolate);
8759   v8::Handle<v8::ObjectTemplate> obj_template =
8760       v8::ObjectTemplate::New(isolate);
8761   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8762   LocalContext env;
8763   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
8764
8765   {
8766     v8::TryCatch try_catch(isolate);
8767     CompileRun(
8768         "var f = { m() { return super.hasOwnProperty; } }.m;"
8769         "var m = %ToMethod(f, prohibited);"
8770         "m();");
8771     CHECK(try_catch.HasCaught());
8772   }
8773
8774   {
8775     v8::TryCatch try_catch(isolate);
8776     CompileRun(
8777         "var f = {m() { return super[42]; } }.m;"
8778         "var m = %ToMethod(f, prohibited);"
8779         "m();");
8780     CHECK(try_catch.HasCaught());
8781   }
8782
8783   {
8784     v8::TryCatch try_catch(isolate);
8785     CompileRun(
8786         "var f = {m() { super.hasOwnProperty = function () {}; } }.m;"
8787         "var m = %ToMethod(f, prohibited);"
8788         "m();");
8789     CHECK(try_catch.HasCaught());
8790   }
8791
8792   {
8793     v8::TryCatch try_catch(isolate);
8794     CompileRun(
8795         "Object.defineProperty(Object.prototype, 'x', { set : function(){}});"
8796         "var f = {"
8797         "  m() { "
8798         "    'use strict';"
8799         "    super.x = function () {};"
8800         "  }"
8801         "}.m;"
8802         "var m = %ToMethod(f, prohibited);"
8803         "m();");
8804     CHECK(try_catch.HasCaught());
8805   }
8806 }
8807
8808
8809 TEST(Regress470113) {
8810   v8::Isolate* isolate = CcTest::isolate();
8811   v8::HandleScope handle_scope(isolate);
8812   v8::Handle<v8::ObjectTemplate> obj_template =
8813       v8::ObjectTemplate::New(isolate);
8814   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8815   LocalContext env;
8816   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
8817
8818   {
8819     v8::TryCatch try_catch(isolate);
8820     CompileRun(
8821         "'use strict';\n"
8822         "class C extends Object {\n"
8823         "   m() { super.powned = 'Powned!'; }\n"
8824         "}\n"
8825         "let c = new C();\n"
8826         "c.m.call(prohibited)");
8827
8828     CHECK(try_catch.HasCaught());
8829   }
8830 }
8831
8832
8833 static void ConstTenGetter(Local<String> name,
8834                            const v8::PropertyCallbackInfo<v8::Value>& info) {
8835   info.GetReturnValue().Set(v8_num(10));
8836 }
8837
8838
8839 THREADED_TEST(CrossDomainAccessors) {
8840   v8::Isolate* isolate = CcTest::isolate();
8841   v8::HandleScope handle_scope(isolate);
8842
8843   v8::Handle<v8::FunctionTemplate> func_template =
8844       v8::FunctionTemplate::New(isolate);
8845
8846   v8::Handle<v8::ObjectTemplate> global_template =
8847       func_template->InstanceTemplate();
8848
8849   v8::Handle<v8::ObjectTemplate> proto_template =
8850       func_template->PrototypeTemplate();
8851
8852   // Add an accessor to proto that's accessible by cross-domain JS code.
8853   proto_template->SetAccessor(v8_str("accessible"),
8854                               ConstTenGetter, 0,
8855                               v8::Handle<Value>(),
8856                               v8::ALL_CAN_READ);
8857
8858   // Add an accessor that is not accessible by cross-domain JS code.
8859   global_template->SetAccessor(v8_str("unreachable"),
8860                                UnreachableGetter, 0,
8861                                v8::Handle<Value>(),
8862                                v8::DEFAULT);
8863
8864   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8865   context0->Enter();
8866
8867   Local<v8::Object> global = context0->Global();
8868   // Add a normal property that shadows 'accessible'
8869   global->Set(v8_str("accessible"), v8_num(11));
8870
8871   // Enter a new context.
8872   v8::HandleScope scope1(CcTest::isolate());
8873   v8::Local<Context> context1 = Context::New(isolate);
8874   context1->Enter();
8875
8876   v8::Handle<v8::Object> global1 = context1->Global();
8877   global1->Set(v8_str("other"), global);
8878
8879   // Should return 10, instead of 11
8880   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
8881   CHECK(value->IsNumber());
8882   CHECK_EQ(10, value->Int32Value());
8883
8884   value = v8_compile("other.unreachable")->Run();
8885   CHECK(value.IsEmpty());
8886
8887   context1->Exit();
8888   context0->Exit();
8889 }
8890
8891
8892 static int access_count = 0;
8893
8894 static bool AccessCounter(Local<v8::Object> global, Local<Value> name,
8895                           v8::AccessType type, Local<Value> data) {
8896   access_count++;
8897   return true;
8898 }
8899
8900
8901 // This one is too easily disturbed by other tests.
8902 TEST(AccessControlIC) {
8903   access_count = 0;
8904
8905   v8::Isolate* isolate = CcTest::isolate();
8906   v8::HandleScope handle_scope(isolate);
8907
8908   // Create an environment.
8909   v8::Local<Context> context0 = Context::New(isolate);
8910   context0->Enter();
8911
8912   // Create an object that requires access-check functions to be
8913   // called for cross-domain access.
8914   v8::Handle<v8::ObjectTemplate> object_template =
8915       v8::ObjectTemplate::New(isolate);
8916   object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
8917   Local<v8::Object> object = object_template->NewInstance();
8918
8919   v8::HandleScope scope1(isolate);
8920
8921   // Create another environment.
8922   v8::Local<Context> context1 = Context::New(isolate);
8923   context1->Enter();
8924
8925   // Make easy access to the object from the other environment.
8926   v8::Handle<v8::Object> global1 = context1->Global();
8927   global1->Set(v8_str("obj"), object);
8928
8929   v8::Handle<Value> value;
8930
8931   // Check that the named access-control function is called every time.
8932   CompileRun("function testProp(obj) {"
8933              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
8934              "  for (var j = 0; j < 10; j++) obj.prop;"
8935              "  return obj.prop"
8936              "}");
8937   value = CompileRun("testProp(obj)");
8938   CHECK(value->IsNumber());
8939   CHECK_EQ(1, value->Int32Value());
8940   CHECK_EQ(21, access_count);
8941
8942   // Check that the named access-control function is called every time.
8943   CompileRun("var p = 'prop';"
8944              "function testKeyed(obj) {"
8945              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
8946              "  for (var j = 0; j < 10; j++) obj[p];"
8947              "  return obj[p];"
8948              "}");
8949   // Use obj which requires access checks.  No inline caching is used
8950   // in that case.
8951   value = CompileRun("testKeyed(obj)");
8952   CHECK(value->IsNumber());
8953   CHECK_EQ(1, value->Int32Value());
8954   CHECK_EQ(42, access_count);
8955   // Force the inline caches into generic state and try again.
8956   CompileRun("testKeyed({ a: 0 })");
8957   CompileRun("testKeyed({ b: 0 })");
8958   value = CompileRun("testKeyed(obj)");
8959   CHECK(value->IsNumber());
8960   CHECK_EQ(1, value->Int32Value());
8961   CHECK_EQ(63, access_count);
8962
8963   // Check that the indexed access-control function is called every time.
8964   access_count = 0;
8965
8966   CompileRun("function testIndexed(obj) {"
8967              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
8968              "  for (var j = 0; j < 10; j++) obj[0];"
8969              "  return obj[0]"
8970              "}");
8971   value = CompileRun("testIndexed(obj)");
8972   CHECK(value->IsNumber());
8973   CHECK_EQ(1, value->Int32Value());
8974   CHECK_EQ(21, access_count);
8975   // Force the inline caches into generic state.
8976   CompileRun("testIndexed(new Array(1))");
8977   // Test that the indexed access check is called.
8978   value = CompileRun("testIndexed(obj)");
8979   CHECK(value->IsNumber());
8980   CHECK_EQ(1, value->Int32Value());
8981   CHECK_EQ(42, access_count);
8982
8983   access_count = 0;
8984   // Check that the named access check is called when invoking
8985   // functions on an object that requires access checks.
8986   CompileRun("obj.f = function() {}");
8987   CompileRun("function testCallNormal(obj) {"
8988              "  for (var i = 0; i < 10; i++) obj.f();"
8989              "}");
8990   CompileRun("testCallNormal(obj)");
8991   printf("%i\n", access_count);
8992   CHECK_EQ(11, access_count);
8993
8994   // Force obj into slow case.
8995   value = CompileRun("delete obj.prop");
8996   CHECK(value->BooleanValue());
8997   // Force inline caches into dictionary probing mode.
8998   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
8999   // Test that the named access check is called.
9000   value = CompileRun("testProp(obj);");
9001   CHECK(value->IsNumber());
9002   CHECK_EQ(1, value->Int32Value());
9003   CHECK_EQ(33, access_count);
9004
9005   // Force the call inline cache into dictionary probing mode.
9006   CompileRun("o.f = function() {}; testCallNormal(o)");
9007   // Test that the named access check is still called for each
9008   // invocation of the function.
9009   value = CompileRun("testCallNormal(obj)");
9010   CHECK_EQ(43, access_count);
9011
9012   context1->Exit();
9013   context0->Exit();
9014 }
9015
9016
9017 THREADED_TEST(Version) { v8::V8::GetVersion(); }
9018
9019
9020 static void InstanceFunctionCallback(
9021     const v8::FunctionCallbackInfo<v8::Value>& args) {
9022   ApiTestFuzzer::Fuzz();
9023   args.GetReturnValue().Set(v8_num(12));
9024 }
9025
9026
9027 THREADED_TEST(InstanceProperties) {
9028   LocalContext context;
9029   v8::Isolate* isolate = context->GetIsolate();
9030   v8::HandleScope handle_scope(isolate);
9031
9032   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9033   Local<ObjectTemplate> instance = t->InstanceTemplate();
9034
9035   instance->Set(v8_str("x"), v8_num(42));
9036   instance->Set(v8_str("f"),
9037                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
9038
9039   Local<Value> o = t->GetFunction()->NewInstance();
9040
9041   context->Global()->Set(v8_str("i"), o);
9042   Local<Value> value = CompileRun("i.x");
9043   CHECK_EQ(42, value->Int32Value());
9044
9045   value = CompileRun("i.f()");
9046   CHECK_EQ(12, value->Int32Value());
9047 }
9048
9049
9050 static void GlobalObjectInstancePropertiesGet(
9051     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
9052   ApiTestFuzzer::Fuzz();
9053 }
9054
9055
9056 THREADED_TEST(GlobalObjectInstanceProperties) {
9057   v8::Isolate* isolate = CcTest::isolate();
9058   v8::HandleScope handle_scope(isolate);
9059
9060   Local<Value> global_object;
9061
9062   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9063   t->InstanceTemplate()->SetHandler(
9064       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
9065   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9066   instance_template->Set(v8_str("x"), v8_num(42));
9067   instance_template->Set(v8_str("f"),
9068                          v8::FunctionTemplate::New(isolate,
9069                                                    InstanceFunctionCallback));
9070
9071   // The script to check how Crankshaft compiles missing global function
9072   // invocations.  function g is not defined and should throw on call.
9073   const char* script =
9074       "function wrapper(call) {"
9075       "  var x = 0, y = 1;"
9076       "  for (var i = 0; i < 1000; i++) {"
9077       "    x += i * 100;"
9078       "    y += i * 100;"
9079       "  }"
9080       "  if (call) g();"
9081       "}"
9082       "for (var i = 0; i < 17; i++) wrapper(false);"
9083       "var thrown = 0;"
9084       "try { wrapper(true); } catch (e) { thrown = 1; };"
9085       "thrown";
9086
9087   {
9088     LocalContext env(NULL, instance_template);
9089     // Hold on to the global object so it can be used again in another
9090     // environment initialization.
9091     global_object = env->Global();
9092
9093     Local<Value> value = CompileRun("x");
9094     CHECK_EQ(42, value->Int32Value());
9095     value = CompileRun("f()");
9096     CHECK_EQ(12, value->Int32Value());
9097     value = CompileRun(script);
9098     CHECK_EQ(1, value->Int32Value());
9099   }
9100
9101   {
9102     // Create new environment reusing the global object.
9103     LocalContext env(NULL, instance_template, global_object);
9104     Local<Value> value = CompileRun("x");
9105     CHECK_EQ(42, value->Int32Value());
9106     value = CompileRun("f()");
9107     CHECK_EQ(12, value->Int32Value());
9108     value = CompileRun(script);
9109     CHECK_EQ(1, value->Int32Value());
9110   }
9111 }
9112
9113
9114 THREADED_TEST(CallKnownGlobalReceiver) {
9115   v8::Isolate* isolate = CcTest::isolate();
9116   v8::HandleScope handle_scope(isolate);
9117
9118   Local<Value> global_object;
9119
9120   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9121   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9122
9123   // The script to check that we leave global object not
9124   // global object proxy on stack when we deoptimize from inside
9125   // arguments evaluation.
9126   // To provoke error we need to both force deoptimization
9127   // from arguments evaluation and to force CallIC to take
9128   // CallIC_Miss code path that can't cope with global proxy.
9129   const char* script =
9130       "function bar(x, y) { try { } finally { } }"
9131       "function baz(x) { try { } finally { } }"
9132       "function bom(x) { try { } finally { } }"
9133       "function foo(x) { bar([x], bom(2)); }"
9134       "for (var i = 0; i < 10000; i++) foo(1);"
9135       "foo";
9136
9137   Local<Value> foo;
9138   {
9139     LocalContext env(NULL, instance_template);
9140     // Hold on to the global object so it can be used again in another
9141     // environment initialization.
9142     global_object = env->Global();
9143     foo = CompileRun(script);
9144   }
9145
9146   {
9147     // Create new environment reusing the global object.
9148     LocalContext env(NULL, instance_template, global_object);
9149     env->Global()->Set(v8_str("foo"), foo);
9150     CompileRun("foo()");
9151   }
9152 }
9153
9154
9155 static void ShadowFunctionCallback(
9156     const v8::FunctionCallbackInfo<v8::Value>& args) {
9157   ApiTestFuzzer::Fuzz();
9158   args.GetReturnValue().Set(v8_num(42));
9159 }
9160
9161
9162 static int shadow_y;
9163 static int shadow_y_setter_call_count;
9164 static int shadow_y_getter_call_count;
9165
9166
9167 static void ShadowYSetter(Local<String>,
9168                           Local<Value>,
9169                           const v8::PropertyCallbackInfo<void>&) {
9170   shadow_y_setter_call_count++;
9171   shadow_y = 42;
9172 }
9173
9174
9175 static void ShadowYGetter(Local<String> name,
9176                           const v8::PropertyCallbackInfo<v8::Value>& info) {
9177   ApiTestFuzzer::Fuzz();
9178   shadow_y_getter_call_count++;
9179   info.GetReturnValue().Set(v8_num(shadow_y));
9180 }
9181
9182
9183 static void ShadowIndexedGet(uint32_t index,
9184                              const v8::PropertyCallbackInfo<v8::Value>&) {
9185 }
9186
9187
9188 static void ShadowNamedGet(Local<Name> key,
9189                            const v8::PropertyCallbackInfo<v8::Value>&) {}
9190
9191
9192 THREADED_TEST(ShadowObject) {
9193   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
9194   v8::Isolate* isolate = CcTest::isolate();
9195   v8::HandleScope handle_scope(isolate);
9196
9197   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
9198   LocalContext context(NULL, global_template);
9199
9200   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9201   t->InstanceTemplate()->SetHandler(
9202       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
9203   t->InstanceTemplate()->SetHandler(
9204       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
9205   Local<ObjectTemplate> proto = t->PrototypeTemplate();
9206   Local<ObjectTemplate> instance = t->InstanceTemplate();
9207
9208   proto->Set(v8_str("f"),
9209              v8::FunctionTemplate::New(isolate,
9210                                        ShadowFunctionCallback,
9211                                        Local<Value>()));
9212   proto->Set(v8_str("x"), v8_num(12));
9213
9214   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9215
9216   Local<Value> o = t->GetFunction()->NewInstance();
9217   context->Global()->Set(v8_str("__proto__"), o);
9218
9219   Local<Value> value =
9220       CompileRun("this.propertyIsEnumerable(0)");
9221   CHECK(value->IsBoolean());
9222   CHECK(!value->BooleanValue());
9223
9224   value = CompileRun("x");
9225   CHECK_EQ(12, value->Int32Value());
9226
9227   value = CompileRun("f()");
9228   CHECK_EQ(42, value->Int32Value());
9229
9230   CompileRun("y = 43");
9231   CHECK_EQ(1, shadow_y_setter_call_count);
9232   value = CompileRun("y");
9233   CHECK_EQ(1, shadow_y_getter_call_count);
9234   CHECK_EQ(42, value->Int32Value());
9235 }
9236
9237
9238 THREADED_TEST(HiddenPrototype) {
9239   LocalContext context;
9240   v8::Isolate* isolate = context->GetIsolate();
9241   v8::HandleScope handle_scope(isolate);
9242
9243   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9244   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9245   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9246   t1->SetHiddenPrototype(true);
9247   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9248   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9249   t2->SetHiddenPrototype(true);
9250   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9251   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9252   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9253
9254   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9255   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9256   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9257   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9258
9259   // Setting the prototype on an object skips hidden prototypes.
9260   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9261   o0->Set(v8_str("__proto__"), o1);
9262   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9263   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9264   o0->Set(v8_str("__proto__"), o2);
9265   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9266   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9267   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9268   o0->Set(v8_str("__proto__"), o3);
9269   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9270   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9271   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9272   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9273
9274   // Getting the prototype of o0 should get the first visible one
9275   // which is o3.  Therefore, z should not be defined on the prototype
9276   // object.
9277   Local<Value> proto = o0->Get(v8_str("__proto__"));
9278   CHECK(proto->IsObject());
9279   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
9280 }
9281
9282
9283 THREADED_TEST(HiddenPrototypeSet) {
9284   LocalContext context;
9285   v8::Isolate* isolate = context->GetIsolate();
9286   v8::HandleScope handle_scope(isolate);
9287
9288   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
9289   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
9290   ht->SetHiddenPrototype(true);
9291   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
9292   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9293
9294   Local<v8::Object> o = ot->GetFunction()->NewInstance();
9295   Local<v8::Object> h = ht->GetFunction()->NewInstance();
9296   Local<v8::Object> p = pt->GetFunction()->NewInstance();
9297   o->Set(v8_str("__proto__"), h);
9298   h->Set(v8_str("__proto__"), p);
9299
9300   // Setting a property that exists on the hidden prototype goes there.
9301   o->Set(v8_str("x"), v8_num(7));
9302   CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
9303   CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
9304   CHECK(p->Get(v8_str("x"))->IsUndefined());
9305
9306   // Setting a new property should not be forwarded to the hidden prototype.
9307   o->Set(v8_str("y"), v8_num(6));
9308   CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
9309   CHECK(h->Get(v8_str("y"))->IsUndefined());
9310   CHECK(p->Get(v8_str("y"))->IsUndefined());
9311
9312   // Setting a property that only exists on a prototype of the hidden prototype
9313   // is treated normally again.
9314   p->Set(v8_str("z"), v8_num(8));
9315   CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
9316   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9317   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9318   o->Set(v8_str("z"), v8_num(9));
9319   CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
9320   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9321   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9322 }
9323
9324
9325 // Regression test for issue 2457.
9326 THREADED_TEST(HiddenPrototypeIdentityHash) {
9327   LocalContext context;
9328   v8::HandleScope handle_scope(context->GetIsolate());
9329
9330   Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
9331   t->SetHiddenPrototype(true);
9332   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
9333   Handle<Object> p = t->GetFunction()->NewInstance();
9334   Handle<Object> o = Object::New(context->GetIsolate());
9335   o->SetPrototype(p);
9336
9337   int hash = o->GetIdentityHash();
9338   USE(hash);
9339   o->Set(v8_str("foo"), v8_num(42));
9340   DCHECK_EQ(hash, o->GetIdentityHash());
9341 }
9342
9343
9344 THREADED_TEST(SetPrototype) {
9345   LocalContext context;
9346   v8::Isolate* isolate = context->GetIsolate();
9347   v8::HandleScope handle_scope(isolate);
9348
9349   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9350   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9351   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9352   t1->SetHiddenPrototype(true);
9353   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9354   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9355   t2->SetHiddenPrototype(true);
9356   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9357   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9358   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9359
9360   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9361   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9362   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9363   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9364
9365   // Setting the prototype on an object does not skip hidden prototypes.
9366   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9367   CHECK(o0->SetPrototype(o1));
9368   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9369   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9370   CHECK(o1->SetPrototype(o2));
9371   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9372   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9373   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9374   CHECK(o2->SetPrototype(o3));
9375   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9376   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9377   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9378   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9379
9380   // Getting the prototype of o0 should get the first visible one
9381   // which is o3.  Therefore, z should not be defined on the prototype
9382   // object.
9383   Local<Value> proto = o0->Get(v8_str("__proto__"));
9384   CHECK(proto->IsObject());
9385   CHECK(proto.As<v8::Object>()->Equals(o3));
9386
9387   // However, Object::GetPrototype ignores hidden prototype.
9388   Local<Value> proto0 = o0->GetPrototype();
9389   CHECK(proto0->IsObject());
9390   CHECK(proto0.As<v8::Object>()->Equals(o1));
9391
9392   Local<Value> proto1 = o1->GetPrototype();
9393   CHECK(proto1->IsObject());
9394   CHECK(proto1.As<v8::Object>()->Equals(o2));
9395
9396   Local<Value> proto2 = o2->GetPrototype();
9397   CHECK(proto2->IsObject());
9398   CHECK(proto2.As<v8::Object>()->Equals(o3));
9399 }
9400
9401
9402 // Getting property names of an object with a prototype chain that
9403 // triggers dictionary elements in GetOwnPropertyNames() shouldn't
9404 // crash the runtime.
9405 THREADED_TEST(Regress91517) {
9406   i::FLAG_allow_natives_syntax = true;
9407   LocalContext context;
9408   v8::Isolate* isolate = context->GetIsolate();
9409   v8::HandleScope handle_scope(isolate);
9410
9411   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9412   t1->SetHiddenPrototype(true);
9413   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
9414   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9415   t2->SetHiddenPrototype(true);
9416   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
9417   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
9418   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
9419   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9420   t3->SetHiddenPrototype(true);
9421   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
9422   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
9423   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
9424
9425   // Force dictionary-based properties.
9426   i::ScopedVector<char> name_buf(1024);
9427   for (int i = 1; i <= 1000; i++) {
9428     i::SNPrintF(name_buf, "sdf%d", i);
9429     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
9430   }
9431
9432   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9433   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9434   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9435   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
9436
9437   // Create prototype chain of hidden prototypes.
9438   CHECK(o4->SetPrototype(o3));
9439   CHECK(o3->SetPrototype(o2));
9440   CHECK(o2->SetPrototype(o1));
9441
9442   // Call the runtime version of GetOwnPropertyNames() on the natively
9443   // created object through JavaScript.
9444   context->Global()->Set(v8_str("obj"), o4);
9445   // PROPERTY_ATTRIBUTES_NONE = 0
9446   CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
9447
9448   ExpectInt32("names.length", 1006);
9449   ExpectTrue("names.indexOf(\"baz\") >= 0");
9450   ExpectTrue("names.indexOf(\"boo\") >= 0");
9451   ExpectTrue("names.indexOf(\"foo\") >= 0");
9452   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
9453   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
9454   ExpectFalse("names[1005] == undefined");
9455 }
9456
9457
9458 // Getting property names of an object with a hidden and inherited
9459 // prototype should not duplicate the accessor properties inherited.
9460 THREADED_TEST(Regress269562) {
9461   i::FLAG_allow_natives_syntax = true;
9462   LocalContext context;
9463   v8::HandleScope handle_scope(context->GetIsolate());
9464
9465   Local<v8::FunctionTemplate> t1 =
9466       v8::FunctionTemplate::New(context->GetIsolate());
9467   t1->SetHiddenPrototype(true);
9468
9469   Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
9470   i1->SetAccessor(v8_str("foo"),
9471                   SimpleAccessorGetter, SimpleAccessorSetter);
9472   i1->SetAccessor(v8_str("bar"),
9473                   SimpleAccessorGetter, SimpleAccessorSetter);
9474   i1->SetAccessor(v8_str("baz"),
9475                   SimpleAccessorGetter, SimpleAccessorSetter);
9476   i1->Set(v8_str("n1"), v8_num(1));
9477   i1->Set(v8_str("n2"), v8_num(2));
9478
9479   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9480   Local<v8::FunctionTemplate> t2 =
9481       v8::FunctionTemplate::New(context->GetIsolate());
9482   t2->SetHiddenPrototype(true);
9483
9484   // Inherit from t1 and mark prototype as hidden.
9485   t2->Inherit(t1);
9486   t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
9487
9488   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9489   CHECK(o2->SetPrototype(o1));
9490
9491   v8::Local<v8::Symbol> sym =
9492       v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
9493   o1->Set(sym, v8_num(3));
9494   o1->SetHiddenValue(
9495       v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
9496
9497   // Call the runtime version of GetOwnPropertyNames() on
9498   // the natively created object through JavaScript.
9499   context->Global()->Set(v8_str("obj"), o2);
9500   context->Global()->Set(v8_str("sym"), sym);
9501   // PROPERTY_ATTRIBUTES_NONE = 0
9502   CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
9503
9504   ExpectInt32("names.length", 7);
9505   ExpectTrue("names.indexOf(\"foo\") >= 0");
9506   ExpectTrue("names.indexOf(\"bar\") >= 0");
9507   ExpectTrue("names.indexOf(\"baz\") >= 0");
9508   ExpectTrue("names.indexOf(\"n1\") >= 0");
9509   ExpectTrue("names.indexOf(\"n2\") >= 0");
9510   ExpectTrue("names.indexOf(sym) >= 0");
9511   ExpectTrue("names.indexOf(\"mine\") >= 0");
9512 }
9513
9514
9515 THREADED_TEST(FunctionReadOnlyPrototype) {
9516   LocalContext context;
9517   v8::Isolate* isolate = context->GetIsolate();
9518   v8::HandleScope handle_scope(isolate);
9519
9520   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9521   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9522   t1->ReadOnlyPrototype();
9523   context->Global()->Set(v8_str("func1"), t1->GetFunction());
9524   // Configured value of ReadOnly flag.
9525   CHECK(CompileRun(
9526       "(function() {"
9527       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
9528       "  return (descriptor['writable'] == false);"
9529       "})()")->BooleanValue());
9530   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
9531   CHECK_EQ(42,
9532            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
9533
9534   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9535   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9536   context->Global()->Set(v8_str("func2"), t2->GetFunction());
9537   // Default value of ReadOnly flag.
9538   CHECK(CompileRun(
9539       "(function() {"
9540       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
9541       "  return (descriptor['writable'] == true);"
9542       "})()")->BooleanValue());
9543   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
9544 }
9545
9546
9547 THREADED_TEST(SetPrototypeThrows) {
9548   LocalContext context;
9549   v8::Isolate* isolate = context->GetIsolate();
9550   v8::HandleScope handle_scope(isolate);
9551
9552   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9553
9554   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
9555   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
9556
9557   CHECK(o0->SetPrototype(o1));
9558   // If setting the prototype leads to the cycle, SetPrototype should
9559   // return false and keep VM in sane state.
9560   v8::TryCatch try_catch(isolate);
9561   CHECK(!o1->SetPrototype(o0));
9562   CHECK(!try_catch.HasCaught());
9563   DCHECK(!CcTest::i_isolate()->has_pending_exception());
9564
9565   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
9566 }
9567
9568
9569 THREADED_TEST(FunctionRemovePrototype) {
9570   LocalContext context;
9571   v8::Isolate* isolate = context->GetIsolate();
9572   v8::HandleScope handle_scope(isolate);
9573
9574   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9575   t1->RemovePrototype();
9576   Local<v8::Function> fun = t1->GetFunction();
9577   context->Global()->Set(v8_str("fun"), fun);
9578   CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
9579
9580   v8::TryCatch try_catch(isolate);
9581   CompileRun("new fun()");
9582   CHECK(try_catch.HasCaught());
9583
9584   try_catch.Reset();
9585   fun->NewInstance();
9586   CHECK(try_catch.HasCaught());
9587 }
9588
9589
9590 THREADED_TEST(GetterSetterExceptions) {
9591   LocalContext context;
9592   v8::Isolate* isolate = context->GetIsolate();
9593   v8::HandleScope handle_scope(isolate);
9594   CompileRun(
9595       "function Foo() { };"
9596       "function Throw() { throw 5; };"
9597       "var x = { };"
9598       "x.__defineSetter__('set', Throw);"
9599       "x.__defineGetter__('get', Throw);");
9600   Local<v8::Object> x =
9601       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
9602   v8::TryCatch try_catch(isolate);
9603   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9604   x->Get(v8_str("get"));
9605   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9606   x->Get(v8_str("get"));
9607   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9608   x->Get(v8_str("get"));
9609   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9610   x->Get(v8_str("get"));
9611 }
9612
9613
9614 THREADED_TEST(Constructor) {
9615   LocalContext context;
9616   v8::Isolate* isolate = context->GetIsolate();
9617   v8::HandleScope handle_scope(isolate);
9618   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
9619   templ->SetClassName(v8_str("Fun"));
9620   Local<Function> cons = templ->GetFunction();
9621   context->Global()->Set(v8_str("Fun"), cons);
9622   Local<v8::Object> inst = cons->NewInstance();
9623   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
9624   CHECK(obj->IsJSObject());
9625   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
9626   CHECK(value->BooleanValue());
9627 }
9628
9629
9630 static void ConstructorCallback(
9631     const v8::FunctionCallbackInfo<v8::Value>& args) {
9632   ApiTestFuzzer::Fuzz();
9633   Local<Object> This;
9634
9635   if (args.IsConstructCall()) {
9636     Local<Object> Holder = args.Holder();
9637     This = Object::New(args.GetIsolate());
9638     Local<Value> proto = Holder->GetPrototype();
9639     if (proto->IsObject()) {
9640       This->SetPrototype(proto);
9641     }
9642   } else {
9643     This = args.This();
9644   }
9645
9646   This->Set(v8_str("a"), args[0]);
9647   args.GetReturnValue().Set(This);
9648 }
9649
9650
9651 static void FakeConstructorCallback(
9652     const v8::FunctionCallbackInfo<v8::Value>& args) {
9653   ApiTestFuzzer::Fuzz();
9654   args.GetReturnValue().Set(args[0]);
9655 }
9656
9657
9658 THREADED_TEST(ConstructorForObject) {
9659   LocalContext context;
9660   v8::Isolate* isolate = context->GetIsolate();
9661   v8::HandleScope handle_scope(isolate);
9662
9663   {
9664     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9665     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
9666     Local<Object> instance = instance_template->NewInstance();
9667     context->Global()->Set(v8_str("obj"), instance);
9668     v8::TryCatch try_catch(isolate);
9669     Local<Value> value;
9670     CHECK(!try_catch.HasCaught());
9671
9672     // Call the Object's constructor with a 32-bit signed integer.
9673     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
9674     CHECK(!try_catch.HasCaught());
9675     CHECK(value->IsInt32());
9676     CHECK_EQ(28, value->Int32Value());
9677
9678     Local<Value> args1[] = {v8_num(28)};
9679     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
9680     CHECK(value_obj1->IsObject());
9681     Local<Object> object1 = Local<Object>::Cast(value_obj1);
9682     value = object1->Get(v8_str("a"));
9683     CHECK(value->IsInt32());
9684     CHECK(!try_catch.HasCaught());
9685     CHECK_EQ(28, value->Int32Value());
9686
9687     // Call the Object's constructor with a String.
9688     value =
9689         CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
9690     CHECK(!try_catch.HasCaught());
9691     CHECK(value->IsString());
9692     String::Utf8Value string_value1(value->ToString(isolate));
9693     CHECK_EQ(0, strcmp("tipli", *string_value1));
9694
9695     Local<Value> args2[] = {v8_str("tipli")};
9696     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
9697     CHECK(value_obj2->IsObject());
9698     Local<Object> object2 = Local<Object>::Cast(value_obj2);
9699     value = object2->Get(v8_str("a"));
9700     CHECK(!try_catch.HasCaught());
9701     CHECK(value->IsString());
9702     String::Utf8Value string_value2(value->ToString(isolate));
9703     CHECK_EQ(0, strcmp("tipli", *string_value2));
9704
9705     // Call the Object's constructor with a Boolean.
9706     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
9707     CHECK(!try_catch.HasCaught());
9708     CHECK(value->IsBoolean());
9709     CHECK_EQ(true, value->BooleanValue());
9710
9711     Handle<Value> args3[] = {v8::True(isolate)};
9712     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
9713     CHECK(value_obj3->IsObject());
9714     Local<Object> object3 = Local<Object>::Cast(value_obj3);
9715     value = object3->Get(v8_str("a"));
9716     CHECK(!try_catch.HasCaught());
9717     CHECK(value->IsBoolean());
9718     CHECK_EQ(true, value->BooleanValue());
9719
9720     // Call the Object's constructor with undefined.
9721     Handle<Value> args4[] = {v8::Undefined(isolate)};
9722     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
9723     CHECK(value_obj4->IsObject());
9724     Local<Object> object4 = Local<Object>::Cast(value_obj4);
9725     value = object4->Get(v8_str("a"));
9726     CHECK(!try_catch.HasCaught());
9727     CHECK(value->IsUndefined());
9728
9729     // Call the Object's constructor with null.
9730     Handle<Value> args5[] = {v8::Null(isolate)};
9731     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
9732     CHECK(value_obj5->IsObject());
9733     Local<Object> object5 = Local<Object>::Cast(value_obj5);
9734     value = object5->Get(v8_str("a"));
9735     CHECK(!try_catch.HasCaught());
9736     CHECK(value->IsNull());
9737   }
9738
9739   // Check exception handling when there is no constructor set for the Object.
9740   {
9741     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9742     Local<Object> instance = instance_template->NewInstance();
9743     context->Global()->Set(v8_str("obj2"), instance);
9744     v8::TryCatch try_catch(isolate);
9745     Local<Value> value;
9746     CHECK(!try_catch.HasCaught());
9747
9748     value = CompileRun("new obj2(28)");
9749     CHECK(try_catch.HasCaught());
9750     String::Utf8Value exception_value1(try_catch.Exception());
9751     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
9752     try_catch.Reset();
9753
9754     Local<Value> args[] = {v8_num(29)};
9755     value = instance->CallAsConstructor(1, args);
9756     CHECK(try_catch.HasCaught());
9757     String::Utf8Value exception_value2(try_catch.Exception());
9758     CHECK_EQ(
9759         0, strcmp("TypeError: #<Object> is not a function", *exception_value2));
9760     try_catch.Reset();
9761   }
9762
9763   // Check the case when constructor throws exception.
9764   {
9765     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9766     instance_template->SetCallAsFunctionHandler(ThrowValue);
9767     Local<Object> instance = instance_template->NewInstance();
9768     context->Global()->Set(v8_str("obj3"), instance);
9769     v8::TryCatch try_catch(isolate);
9770     Local<Value> value;
9771     CHECK(!try_catch.HasCaught());
9772
9773     value = CompileRun("new obj3(22)");
9774     CHECK(try_catch.HasCaught());
9775     String::Utf8Value exception_value1(try_catch.Exception());
9776     CHECK_EQ(0, strcmp("22", *exception_value1));
9777     try_catch.Reset();
9778
9779     Local<Value> args[] = {v8_num(23)};
9780     value = instance->CallAsConstructor(1, args);
9781     CHECK(try_catch.HasCaught());
9782     String::Utf8Value exception_value2(try_catch.Exception());
9783     CHECK_EQ(0, strcmp("23", *exception_value2));
9784     try_catch.Reset();
9785   }
9786
9787   // Check whether constructor returns with an object or non-object.
9788   {
9789     Local<FunctionTemplate> function_template =
9790         FunctionTemplate::New(isolate, FakeConstructorCallback);
9791     Local<Function> function = function_template->GetFunction();
9792     Local<Object> instance1 = function;
9793     context->Global()->Set(v8_str("obj4"), instance1);
9794     v8::TryCatch try_catch(isolate);
9795     Local<Value> value;
9796     CHECK(!try_catch.HasCaught());
9797
9798     CHECK(instance1->IsObject());
9799     CHECK(instance1->IsFunction());
9800
9801     value = CompileRun("new obj4(28)");
9802     CHECK(!try_catch.HasCaught());
9803     CHECK(value->IsObject());
9804
9805     Local<Value> args1[] = {v8_num(28)};
9806     value = instance1->CallAsConstructor(1, args1);
9807     CHECK(!try_catch.HasCaught());
9808     CHECK(value->IsObject());
9809
9810     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9811     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
9812     Local<Object> instance2 = instance_template->NewInstance();
9813     context->Global()->Set(v8_str("obj5"), instance2);
9814     CHECK(!try_catch.HasCaught());
9815
9816     CHECK(instance2->IsObject());
9817     CHECK(!instance2->IsFunction());
9818
9819     value = CompileRun("new obj5(28)");
9820     CHECK(!try_catch.HasCaught());
9821     CHECK(!value->IsObject());
9822
9823     Local<Value> args2[] = {v8_num(28)};
9824     value = instance2->CallAsConstructor(1, args2);
9825     CHECK(!try_catch.HasCaught());
9826     CHECK(!value->IsObject());
9827   }
9828 }
9829
9830
9831 THREADED_TEST(FunctionDescriptorException) {
9832   LocalContext context;
9833   v8::Isolate* isolate = context->GetIsolate();
9834   v8::HandleScope handle_scope(isolate);
9835   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
9836   templ->SetClassName(v8_str("Fun"));
9837   Local<Function> cons = templ->GetFunction();
9838   context->Global()->Set(v8_str("Fun"), cons);
9839   Local<Value> value = CompileRun(
9840       "function test() {"
9841       "  try {"
9842       "    (new Fun()).blah()"
9843       "  } catch (e) {"
9844       "    var str = String(e);"
9845       // "    if (str.indexOf('TypeError') == -1) return 1;"
9846       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
9847       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
9848       "    return 0;"
9849       "  }"
9850       "  return 4;"
9851       "}"
9852       "test();");
9853   CHECK_EQ(0, value->Int32Value());
9854 }
9855
9856
9857 THREADED_TEST(EvalAliasedDynamic) {
9858   LocalContext current;
9859   v8::HandleScope scope(current->GetIsolate());
9860
9861   // Tests where aliased eval can only be resolved dynamically.
9862   Local<Script> script = v8_compile(
9863       "function f(x) { "
9864       "  var foo = 2;"
9865       "  with (x) { return eval('foo'); }"
9866       "}"
9867       "foo = 0;"
9868       "result1 = f(new Object());"
9869       "result2 = f(this);"
9870       "var x = new Object();"
9871       "x.eval = function(x) { return 1; };"
9872       "result3 = f(x);");
9873   script->Run();
9874   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
9875   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
9876   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
9877
9878   v8::TryCatch try_catch(current->GetIsolate());
9879   script = v8_compile(
9880       "function f(x) { "
9881       "  var bar = 2;"
9882       "  with (x) { return eval('bar'); }"
9883       "}"
9884       "result4 = f(this)");
9885   script->Run();
9886   CHECK(!try_catch.HasCaught());
9887   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
9888
9889   try_catch.Reset();
9890 }
9891
9892
9893 THREADED_TEST(CrossEval) {
9894   v8::HandleScope scope(CcTest::isolate());
9895   LocalContext other;
9896   LocalContext current;
9897
9898   Local<String> token = v8_str("<security token>");
9899   other->SetSecurityToken(token);
9900   current->SetSecurityToken(token);
9901
9902   // Set up reference from current to other.
9903   current->Global()->Set(v8_str("other"), other->Global());
9904
9905   // Check that new variables are introduced in other context.
9906   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
9907   script->Run();
9908   Local<Value> foo = other->Global()->Get(v8_str("foo"));
9909   CHECK_EQ(1234, foo->Int32Value());
9910   CHECK(!current->Global()->Has(v8_str("foo")));
9911
9912   // Check that writing to non-existing properties introduces them in
9913   // the other context.
9914   script = v8_compile("other.eval('na = 1234')");
9915   script->Run();
9916   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
9917   CHECK(!current->Global()->Has(v8_str("na")));
9918
9919   // Check that global variables in current context are not visible in other
9920   // context.
9921   v8::TryCatch try_catch(CcTest::isolate());
9922   script = v8_compile("var bar = 42; other.eval('bar');");
9923   Local<Value> result = script->Run();
9924   CHECK(try_catch.HasCaught());
9925   try_catch.Reset();
9926
9927   // Check that local variables in current context are not visible in other
9928   // context.
9929   script = v8_compile(
9930       "(function() { "
9931       "  var baz = 87;"
9932       "  return other.eval('baz');"
9933       "})();");
9934   result = script->Run();
9935   CHECK(try_catch.HasCaught());
9936   try_catch.Reset();
9937
9938   // Check that global variables in the other environment are visible
9939   // when evaluting code.
9940   other->Global()->Set(v8_str("bis"), v8_num(1234));
9941   script = v8_compile("other.eval('bis')");
9942   CHECK_EQ(1234, script->Run()->Int32Value());
9943   CHECK(!try_catch.HasCaught());
9944
9945   // Check that the 'this' pointer points to the global object evaluating
9946   // code.
9947   other->Global()->Set(v8_str("t"), other->Global());
9948   script = v8_compile("other.eval('this == t')");
9949   result = script->Run();
9950   CHECK(result->IsTrue());
9951   CHECK(!try_catch.HasCaught());
9952
9953   // Check that variables introduced in with-statement are not visible in
9954   // other context.
9955   script = v8_compile("with({x:2}){other.eval('x')}");
9956   result = script->Run();
9957   CHECK(try_catch.HasCaught());
9958   try_catch.Reset();
9959
9960   // Check that you cannot use 'eval.call' with another object than the
9961   // current global object.
9962   script = v8_compile("other.y = 1; eval.call(other, 'y')");
9963   result = script->Run();
9964   CHECK(try_catch.HasCaught());
9965 }
9966
9967
9968 // Test that calling eval in a context which has been detached from
9969 // its global proxy works.
9970 THREADED_TEST(EvalInDetachedGlobal) {
9971   v8::Isolate* isolate = CcTest::isolate();
9972   v8::HandleScope scope(isolate);
9973
9974   v8::Local<Context> context0 = Context::New(isolate);
9975   v8::Local<Context> context1 = Context::New(isolate);
9976
9977   // Set up function in context0 that uses eval from context0.
9978   context0->Enter();
9979   v8::Handle<v8::Value> fun = CompileRun(
9980       "var x = 42;"
9981       "(function() {"
9982       "  var e = eval;"
9983       "  return function(s) { return e(s); }"
9984       "})()");
9985   context0->Exit();
9986
9987   // Put the function into context1 and call it before and after
9988   // detaching the global.  Before detaching, the call succeeds and
9989   // after detaching and exception is thrown.
9990   context1->Enter();
9991   context1->Global()->Set(v8_str("fun"), fun);
9992   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
9993   CHECK_EQ(42, x_value->Int32Value());
9994   context0->DetachGlobal();
9995   v8::TryCatch catcher(isolate);
9996   x_value = CompileRun("fun('x')");
9997   CHECK_EQ(42, x_value->Int32Value());
9998   context1->Exit();
9999 }
10000
10001
10002 THREADED_TEST(CrossLazyLoad) {
10003   v8::HandleScope scope(CcTest::isolate());
10004   LocalContext other;
10005   LocalContext current;
10006
10007   Local<String> token = v8_str("<security token>");
10008   other->SetSecurityToken(token);
10009   current->SetSecurityToken(token);
10010
10011   // Set up reference from current to other.
10012   current->Global()->Set(v8_str("other"), other->Global());
10013
10014   // Trigger lazy loading in other context.
10015   Local<Script> script = v8_compile("other.eval('new Date(42)')");
10016   Local<Value> value = script->Run();
10017   CHECK_EQ(42.0, value->NumberValue());
10018 }
10019
10020
10021 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
10022   ApiTestFuzzer::Fuzz();
10023   if (args.IsConstructCall()) {
10024     if (args[0]->IsInt32()) {
10025       args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10026       return;
10027     }
10028   }
10029
10030   args.GetReturnValue().Set(args[0]);
10031 }
10032
10033
10034 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10035   args.GetReturnValue().Set(args.This());
10036 }
10037
10038
10039 // Test that a call handler can be set for objects which will allow
10040 // non-function objects created through the API to be called as
10041 // functions.
10042 THREADED_TEST(CallAsFunction) {
10043   LocalContext context;
10044   v8::Isolate* isolate = context->GetIsolate();
10045   v8::HandleScope scope(isolate);
10046
10047   {
10048     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10049     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10050     instance_template->SetCallAsFunctionHandler(call_as_function);
10051     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10052     context->Global()->Set(v8_str("obj"), instance);
10053     v8::TryCatch try_catch(isolate);
10054     Local<Value> value;
10055     CHECK(!try_catch.HasCaught());
10056
10057     value = CompileRun("obj(42)");
10058     CHECK(!try_catch.HasCaught());
10059     CHECK_EQ(42, value->Int32Value());
10060
10061     value = CompileRun("(function(o){return o(49)})(obj)");
10062     CHECK(!try_catch.HasCaught());
10063     CHECK_EQ(49, value->Int32Value());
10064
10065     // test special case of call as function
10066     value = CompileRun("[obj]['0'](45)");
10067     CHECK(!try_catch.HasCaught());
10068     CHECK_EQ(45, value->Int32Value());
10069
10070     value = CompileRun(
10071         "obj.call = Function.prototype.call;"
10072         "obj.call(null, 87)");
10073     CHECK(!try_catch.HasCaught());
10074     CHECK_EQ(87, value->Int32Value());
10075
10076     // Regression tests for bug #1116356: Calling call through call/apply
10077     // must work for non-function receivers.
10078     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10079     value = CompileRun(apply_99);
10080     CHECK(!try_catch.HasCaught());
10081     CHECK_EQ(99, value->Int32Value());
10082
10083     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10084     value = CompileRun(call_17);
10085     CHECK(!try_catch.HasCaught());
10086     CHECK_EQ(17, value->Int32Value());
10087
10088     // Check that the call-as-function handler can be called through
10089     // new.
10090     value = CompileRun("new obj(43)");
10091     CHECK(!try_catch.HasCaught());
10092     CHECK_EQ(-43, value->Int32Value());
10093
10094     // Check that the call-as-function handler can be called through
10095     // the API.
10096     v8::Handle<Value> args[] = {v8_num(28)};
10097     value = instance->CallAsFunction(instance, 1, args);
10098     CHECK(!try_catch.HasCaught());
10099     CHECK_EQ(28, value->Int32Value());
10100   }
10101
10102   {
10103     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10104     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
10105     USE(instance_template);
10106     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10107     context->Global()->Set(v8_str("obj2"), instance);
10108     v8::TryCatch try_catch(isolate);
10109     Local<Value> value;
10110     CHECK(!try_catch.HasCaught());
10111
10112     // Call an object without call-as-function handler through the JS
10113     value = CompileRun("obj2(28)");
10114     CHECK(value.IsEmpty());
10115     CHECK(try_catch.HasCaught());
10116     String::Utf8Value exception_value1(try_catch.Exception());
10117     // TODO(verwaest): Better message
10118     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
10119     try_catch.Reset();
10120
10121     // Call an object without call-as-function handler through the API
10122     value = CompileRun("obj2(28)");
10123     v8::Handle<Value> args[] = {v8_num(28)};
10124     value = instance->CallAsFunction(instance, 1, args);
10125     CHECK(value.IsEmpty());
10126     CHECK(try_catch.HasCaught());
10127     String::Utf8Value exception_value2(try_catch.Exception());
10128     CHECK_EQ(0, strcmp("TypeError: [object Object] is not a function",
10129                        *exception_value2));
10130     try_catch.Reset();
10131   }
10132
10133   {
10134     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10135     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10136     instance_template->SetCallAsFunctionHandler(ThrowValue);
10137     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10138     context->Global()->Set(v8_str("obj3"), instance);
10139     v8::TryCatch try_catch(isolate);
10140     Local<Value> value;
10141     CHECK(!try_catch.HasCaught());
10142
10143     // Catch the exception which is thrown by call-as-function handler
10144     value = CompileRun("obj3(22)");
10145     CHECK(try_catch.HasCaught());
10146     String::Utf8Value exception_value1(try_catch.Exception());
10147     CHECK_EQ(0, strcmp("22", *exception_value1));
10148     try_catch.Reset();
10149
10150     v8::Handle<Value> args[] = {v8_num(23)};
10151     value = instance->CallAsFunction(instance, 1, args);
10152     CHECK(try_catch.HasCaught());
10153     String::Utf8Value exception_value2(try_catch.Exception());
10154     CHECK_EQ(0, strcmp("23", *exception_value2));
10155     try_catch.Reset();
10156   }
10157
10158   {
10159     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10160     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10161     instance_template->SetCallAsFunctionHandler(ReturnThis);
10162     Local<v8::Object> instance = t->GetFunction()->NewInstance();
10163
10164     Local<v8::Value> a1 =
10165         instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10166     CHECK(a1->StrictEquals(instance));
10167     Local<v8::Value> a2 = instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10168     CHECK(a2->StrictEquals(instance));
10169     Local<v8::Value> a3 = instance->CallAsFunction(v8_num(42), 0, NULL);
10170     CHECK(a3->StrictEquals(instance));
10171     Local<v8::Value> a4 = instance->CallAsFunction(v8_str("hello"), 0, NULL);
10172     CHECK(a4->StrictEquals(instance));
10173     Local<v8::Value> a5 = instance->CallAsFunction(v8::True(isolate), 0, NULL);
10174     CHECK(a5->StrictEquals(instance));
10175   }
10176
10177   {
10178     CompileRun(
10179         "function ReturnThisSloppy() {"
10180         "  return this;"
10181         "}"
10182         "function ReturnThisStrict() {"
10183         "  'use strict';"
10184         "  return this;"
10185         "}");
10186     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
10187         context->Global()->Get(v8_str("ReturnThisSloppy")));
10188     Local<Function> ReturnThisStrict = Local<Function>::Cast(
10189         context->Global()->Get(v8_str("ReturnThisStrict")));
10190
10191     Local<v8::Value> a1 =
10192         ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10193     CHECK(a1->StrictEquals(context->Global()));
10194     Local<v8::Value> a2 =
10195         ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10196     CHECK(a2->StrictEquals(context->Global()));
10197     Local<v8::Value> a3 = ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10198     CHECK(a3->IsNumberObject());
10199     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10200     Local<v8::Value> a4 =
10201         ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10202     CHECK(a4->IsStringObject());
10203     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10204     Local<v8::Value> a5 =
10205         ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10206     CHECK(a5->IsBooleanObject());
10207     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10208
10209     Local<v8::Value> a6 =
10210         ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10211     CHECK(a6->IsUndefined());
10212     Local<v8::Value> a7 =
10213         ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10214     CHECK(a7->IsNull());
10215     Local<v8::Value> a8 = ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10216     CHECK(a8->StrictEquals(v8_num(42)));
10217     Local<v8::Value> a9 =
10218         ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10219     CHECK(a9->StrictEquals(v8_str("hello")));
10220     Local<v8::Value> a10 =
10221         ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10222     CHECK(a10->StrictEquals(v8::True(isolate)));
10223   }
10224 }
10225
10226
10227 // Check whether a non-function object is callable.
10228 THREADED_TEST(CallableObject) {
10229   LocalContext context;
10230   v8::Isolate* isolate = context->GetIsolate();
10231   v8::HandleScope scope(isolate);
10232
10233   {
10234     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10235     instance_template->SetCallAsFunctionHandler(call_as_function);
10236     Local<Object> instance = instance_template->NewInstance();
10237     v8::TryCatch try_catch(isolate);
10238
10239     CHECK(instance->IsCallable());
10240     CHECK(!try_catch.HasCaught());
10241   }
10242
10243   {
10244     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10245     Local<Object> instance = instance_template->NewInstance();
10246     v8::TryCatch try_catch(isolate);
10247
10248     CHECK(!instance->IsCallable());
10249     CHECK(!try_catch.HasCaught());
10250   }
10251
10252   {
10253     Local<FunctionTemplate> function_template =
10254         FunctionTemplate::New(isolate, call_as_function);
10255     Local<Function> function = function_template->GetFunction();
10256     Local<Object> instance = function;
10257     v8::TryCatch try_catch(isolate);
10258
10259     CHECK(instance->IsCallable());
10260     CHECK(!try_catch.HasCaught());
10261   }
10262
10263   {
10264     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
10265     Local<Function> function = function_template->GetFunction();
10266     Local<Object> instance = function;
10267     v8::TryCatch try_catch(isolate);
10268
10269     CHECK(instance->IsCallable());
10270     CHECK(!try_catch.HasCaught());
10271   }
10272 }
10273
10274
10275 static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
10276   v8::HandleScope scope(isolate);
10277   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
10278   for (int i = 0; i < iterations; i++) {
10279     Local<v8::Number> n(v8::Integer::New(isolate, 42));
10280   }
10281   return Recurse(isolate, depth - 1, iterations);
10282 }
10283
10284
10285 THREADED_TEST(HandleIteration) {
10286   static const int kIterations = 500;
10287   static const int kNesting = 200;
10288   LocalContext context;
10289   v8::Isolate* isolate = context->GetIsolate();
10290   v8::HandleScope scope0(isolate);
10291   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10292   {
10293     v8::HandleScope scope1(isolate);
10294     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10295     for (int i = 0; i < kIterations; i++) {
10296       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
10297       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
10298     }
10299
10300     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
10301     {
10302       v8::HandleScope scope2(CcTest::isolate());
10303       for (int j = 0; j < kIterations; j++) {
10304         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
10305         CHECK_EQ(j + 1 + kIterations,
10306                  v8::HandleScope::NumberOfHandles(isolate));
10307       }
10308     }
10309     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
10310   }
10311   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10312   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
10313 }
10314
10315
10316 static void InterceptorCallICFastApi(
10317     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
10318   ApiTestFuzzer::Fuzz();
10319   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
10320   int* call_count =
10321       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
10322   ++(*call_count);
10323   if ((*call_count) % 20 == 0) {
10324     CcTest::heap()->CollectAllGarbage();
10325   }
10326 }
10327
10328 static void FastApiCallback_TrivialSignature(
10329     const v8::FunctionCallbackInfo<v8::Value>& args) {
10330   ApiTestFuzzer::Fuzz();
10331   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
10332   v8::Isolate* isolate = CcTest::isolate();
10333   CHECK_EQ(isolate, args.GetIsolate());
10334   CHECK(args.This()->Equals(args.Holder()));
10335   CHECK(args.Data()->Equals(v8_str("method_data")));
10336   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
10337 }
10338
10339 static void FastApiCallback_SimpleSignature(
10340     const v8::FunctionCallbackInfo<v8::Value>& args) {
10341   ApiTestFuzzer::Fuzz();
10342   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
10343   v8::Isolate* isolate = CcTest::isolate();
10344   CHECK_EQ(isolate, args.GetIsolate());
10345   CHECK(args.This()->GetPrototype()->Equals(args.Holder()));
10346   CHECK(args.Data()->Equals(v8_str("method_data")));
10347   // Note, we're using HasRealNamedProperty instead of Has to avoid
10348   // invoking the interceptor again.
10349   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
10350   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
10351 }
10352
10353
10354 // Helper to maximize the odds of object moving.
10355 static void GenerateSomeGarbage() {
10356   CompileRun(
10357       "var garbage;"
10358       "for (var i = 0; i < 1000; i++) {"
10359       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
10360       "}"
10361       "garbage = undefined;");
10362 }
10363
10364
10365 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
10366   static int count = 0;
10367   if (count++ % 3 == 0) {
10368     CcTest::heap()->CollectAllGarbage();
10369         // This should move the stub
10370     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
10371   }
10372 }
10373
10374
10375 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
10376   LocalContext context;
10377   v8::Isolate* isolate = context->GetIsolate();
10378   v8::HandleScope scope(isolate);
10379   v8::Handle<v8::ObjectTemplate> nativeobject_templ =
10380       v8::ObjectTemplate::New(isolate);
10381   nativeobject_templ->Set(isolate, "callback",
10382                           v8::FunctionTemplate::New(isolate,
10383                                                     DirectApiCallback));
10384   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10385   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10386   // call the api function multiple times to ensure direct call stub creation.
10387   CompileRun(
10388         "function f() {"
10389         "  for (var i = 1; i <= 30; i++) {"
10390         "    nativeobject.callback();"
10391         "  }"
10392         "}"
10393         "f();");
10394 }
10395
10396
10397 void ThrowingDirectApiCallback(
10398     const v8::FunctionCallbackInfo<v8::Value>& args) {
10399   args.GetIsolate()->ThrowException(v8_str("g"));
10400 }
10401
10402
10403 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
10404   LocalContext context;
10405   v8::Isolate* isolate = context->GetIsolate();
10406   v8::HandleScope scope(isolate);
10407   v8::Handle<v8::ObjectTemplate> nativeobject_templ =
10408       v8::ObjectTemplate::New(isolate);
10409   nativeobject_templ->Set(isolate, "callback",
10410                           v8::FunctionTemplate::New(isolate,
10411                                                     ThrowingDirectApiCallback));
10412   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10413   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10414   // call the api function multiple times to ensure direct call stub creation.
10415   v8::Handle<Value> result = CompileRun(
10416       "var result = '';"
10417       "function f() {"
10418       "  for (var i = 1; i <= 5; i++) {"
10419       "    try { nativeobject.callback(); } catch (e) { result += e; }"
10420       "  }"
10421       "}"
10422       "f(); result;");
10423   CHECK(v8_str("ggggg")->Equals(result));
10424 }
10425
10426
10427 static int p_getter_count_3;
10428
10429
10430 static Handle<Value> DoDirectGetter() {
10431   if (++p_getter_count_3 % 3 == 0) {
10432     CcTest::heap()->CollectAllGarbage();
10433     GenerateSomeGarbage();
10434   }
10435   return v8_str("Direct Getter Result");
10436 }
10437
10438
10439 static void DirectGetterCallback(
10440     Local<String> name,
10441     const v8::PropertyCallbackInfo<v8::Value>& info) {
10442   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
10443   info.GetReturnValue().Set(DoDirectGetter());
10444 }
10445
10446
10447 template<typename Accessor>
10448 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
10449   LocalContext context;
10450   v8::Isolate* isolate = context->GetIsolate();
10451   v8::HandleScope scope(isolate);
10452   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
10453   obj->SetAccessor(v8_str("p1"), accessor);
10454   context->Global()->Set(v8_str("o1"), obj->NewInstance());
10455   p_getter_count_3 = 0;
10456   v8::Handle<v8::Value> result = CompileRun(
10457       "function f() {"
10458       "  for (var i = 0; i < 30; i++) o1.p1;"
10459       "  return o1.p1"
10460       "}"
10461       "f();");
10462   CHECK(v8_str("Direct Getter Result")->Equals(result));
10463   CHECK_EQ(31, p_getter_count_3);
10464 }
10465
10466
10467 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
10468   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
10469 }
10470
10471
10472 void ThrowingDirectGetterCallback(
10473     Local<String> name,
10474     const v8::PropertyCallbackInfo<v8::Value>& info) {
10475   info.GetIsolate()->ThrowException(v8_str("g"));
10476 }
10477
10478
10479 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
10480   LocalContext context;
10481   v8::Isolate* isolate = context->GetIsolate();
10482   v8::HandleScope scope(isolate);
10483   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
10484   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
10485   context->Global()->Set(v8_str("o1"), obj->NewInstance());
10486   v8::Handle<Value> result = CompileRun(
10487       "var result = '';"
10488       "for (var i = 0; i < 5; i++) {"
10489       "    try { o1.p1; } catch (e) { result += e; }"
10490       "}"
10491       "result;");
10492   CHECK(v8_str("ggggg")->Equals(result));
10493 }
10494
10495
10496 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
10497   int interceptor_call_count = 0;
10498   v8::Isolate* isolate = CcTest::isolate();
10499   v8::HandleScope scope(isolate);
10500   v8::Handle<v8::FunctionTemplate> fun_templ =
10501       v8::FunctionTemplate::New(isolate);
10502   v8::Handle<v8::FunctionTemplate> method_templ =
10503       v8::FunctionTemplate::New(isolate,
10504                                 FastApiCallback_TrivialSignature,
10505                                 v8_str("method_data"),
10506                                 v8::Handle<v8::Signature>());
10507   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10508   proto_templ->Set(v8_str("method"), method_templ);
10509   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10510   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10511       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10512       v8::External::New(isolate, &interceptor_call_count)));
10513   LocalContext context;
10514   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10515   GenerateSomeGarbage();
10516   context->Global()->Set(v8_str("o"), fun->NewInstance());
10517   CompileRun(
10518       "var result = 0;"
10519       "for (var i = 0; i < 100; i++) {"
10520       "  result = o.method(41);"
10521       "}");
10522   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10523   CHECK_EQ(100, interceptor_call_count);
10524 }
10525
10526
10527 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
10528   int interceptor_call_count = 0;
10529   v8::Isolate* isolate = CcTest::isolate();
10530   v8::HandleScope scope(isolate);
10531   v8::Handle<v8::FunctionTemplate> fun_templ =
10532       v8::FunctionTemplate::New(isolate);
10533   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10534       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10535       v8::Signature::New(isolate, fun_templ));
10536   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10537   proto_templ->Set(v8_str("method"), method_templ);
10538   fun_templ->SetHiddenPrototype(true);
10539   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10540   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10541       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10542       v8::External::New(isolate, &interceptor_call_count)));
10543   LocalContext context;
10544   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10545   GenerateSomeGarbage();
10546   context->Global()->Set(v8_str("o"), fun->NewInstance());
10547   CompileRun(
10548       "o.foo = 17;"
10549       "var receiver = {};"
10550       "receiver.__proto__ = o;"
10551       "var result = 0;"
10552       "for (var i = 0; i < 100; i++) {"
10553       "  result = receiver.method(41);"
10554       "}");
10555   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10556   CHECK_EQ(100, interceptor_call_count);
10557 }
10558
10559
10560 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
10561   int interceptor_call_count = 0;
10562   v8::Isolate* isolate = CcTest::isolate();
10563   v8::HandleScope scope(isolate);
10564   v8::Handle<v8::FunctionTemplate> fun_templ =
10565       v8::FunctionTemplate::New(isolate);
10566   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10567       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10568       v8::Signature::New(isolate, fun_templ));
10569   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10570   proto_templ->Set(v8_str("method"), method_templ);
10571   fun_templ->SetHiddenPrototype(true);
10572   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10573   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10574       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10575       v8::External::New(isolate, &interceptor_call_count)));
10576   LocalContext context;
10577   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10578   GenerateSomeGarbage();
10579   context->Global()->Set(v8_str("o"), fun->NewInstance());
10580   CompileRun(
10581       "o.foo = 17;"
10582       "var receiver = {};"
10583       "receiver.__proto__ = o;"
10584       "var result = 0;"
10585       "var saved_result = 0;"
10586       "for (var i = 0; i < 100; i++) {"
10587       "  result = receiver.method(41);"
10588       "  if (i == 50) {"
10589       "    saved_result = result;"
10590       "    receiver = {method: function(x) { return x - 1 }};"
10591       "  }"
10592       "}");
10593   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10594   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10595   CHECK_GE(interceptor_call_count, 50);
10596 }
10597
10598
10599 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
10600   int interceptor_call_count = 0;
10601   v8::Isolate* isolate = CcTest::isolate();
10602   v8::HandleScope scope(isolate);
10603   v8::Handle<v8::FunctionTemplate> fun_templ =
10604       v8::FunctionTemplate::New(isolate);
10605   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10606       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10607       v8::Signature::New(isolate, fun_templ));
10608   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10609   proto_templ->Set(v8_str("method"), method_templ);
10610   fun_templ->SetHiddenPrototype(true);
10611   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10612   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10613       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10614       v8::External::New(isolate, &interceptor_call_count)));
10615   LocalContext context;
10616   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10617   GenerateSomeGarbage();
10618   context->Global()->Set(v8_str("o"), fun->NewInstance());
10619   CompileRun(
10620       "o.foo = 17;"
10621       "var receiver = {};"
10622       "receiver.__proto__ = o;"
10623       "var result = 0;"
10624       "var saved_result = 0;"
10625       "for (var i = 0; i < 100; i++) {"
10626       "  result = receiver.method(41);"
10627       "  if (i == 50) {"
10628       "    saved_result = result;"
10629       "    o.method = function(x) { return x - 1 };"
10630       "  }"
10631       "}");
10632   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10633   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10634   CHECK_GE(interceptor_call_count, 50);
10635 }
10636
10637
10638 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
10639   int interceptor_call_count = 0;
10640   v8::Isolate* isolate = CcTest::isolate();
10641   v8::HandleScope scope(isolate);
10642   v8::Handle<v8::FunctionTemplate> fun_templ =
10643       v8::FunctionTemplate::New(isolate);
10644   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10645       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10646       v8::Signature::New(isolate, fun_templ));
10647   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10648   proto_templ->Set(v8_str("method"), method_templ);
10649   fun_templ->SetHiddenPrototype(true);
10650   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10651   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10652       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10653       v8::External::New(isolate, &interceptor_call_count)));
10654   LocalContext context;
10655   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10656   GenerateSomeGarbage();
10657   context->Global()->Set(v8_str("o"), fun->NewInstance());
10658   v8::TryCatch try_catch(isolate);
10659   CompileRun(
10660       "o.foo = 17;"
10661       "var receiver = {};"
10662       "receiver.__proto__ = o;"
10663       "var result = 0;"
10664       "var saved_result = 0;"
10665       "for (var i = 0; i < 100; i++) {"
10666       "  result = receiver.method(41);"
10667       "  if (i == 50) {"
10668       "    saved_result = result;"
10669       "    receiver = 333;"
10670       "  }"
10671       "}");
10672   CHECK(try_catch.HasCaught());
10673   // TODO(verwaest): Adjust message.
10674   CHECK(v8_str("TypeError: receiver.method is not a function")
10675             ->Equals(try_catch.Exception()->ToString(isolate)));
10676   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10677   CHECK_GE(interceptor_call_count, 50);
10678 }
10679
10680
10681 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
10682   int interceptor_call_count = 0;
10683   v8::Isolate* isolate = CcTest::isolate();
10684   v8::HandleScope scope(isolate);
10685   v8::Handle<v8::FunctionTemplate> fun_templ =
10686       v8::FunctionTemplate::New(isolate);
10687   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10688       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10689       v8::Signature::New(isolate, fun_templ));
10690   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10691   proto_templ->Set(v8_str("method"), method_templ);
10692   fun_templ->SetHiddenPrototype(true);
10693   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10694   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10695       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10696       v8::External::New(isolate, &interceptor_call_count)));
10697   LocalContext context;
10698   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10699   GenerateSomeGarbage();
10700   context->Global()->Set(v8_str("o"), fun->NewInstance());
10701   v8::TryCatch try_catch(isolate);
10702   CompileRun(
10703       "o.foo = 17;"
10704       "var receiver = {};"
10705       "receiver.__proto__ = o;"
10706       "var result = 0;"
10707       "var saved_result = 0;"
10708       "for (var i = 0; i < 100; i++) {"
10709       "  result = receiver.method(41);"
10710       "  if (i == 50) {"
10711       "    saved_result = result;"
10712       "    receiver = {method: receiver.method};"
10713       "  }"
10714       "}");
10715   CHECK(try_catch.HasCaught());
10716   CHECK(v8_str("TypeError: Illegal invocation")
10717             ->Equals(try_catch.Exception()->ToString(isolate)));
10718   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10719   CHECK_GE(interceptor_call_count, 50);
10720 }
10721
10722
10723 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
10724   v8::Isolate* isolate = CcTest::isolate();
10725   v8::HandleScope scope(isolate);
10726   v8::Handle<v8::FunctionTemplate> fun_templ =
10727       v8::FunctionTemplate::New(isolate);
10728   v8::Handle<v8::FunctionTemplate> method_templ =
10729       v8::FunctionTemplate::New(isolate,
10730                                 FastApiCallback_TrivialSignature,
10731                                 v8_str("method_data"),
10732                                 v8::Handle<v8::Signature>());
10733   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10734   proto_templ->Set(v8_str("method"), method_templ);
10735   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10736   USE(templ);
10737   LocalContext context;
10738   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10739   GenerateSomeGarbage();
10740   context->Global()->Set(v8_str("o"), fun->NewInstance());
10741   CompileRun(
10742       "var result = 0;"
10743       "for (var i = 0; i < 100; i++) {"
10744       "  result = o.method(41);"
10745       "}");
10746
10747   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10748 }
10749
10750
10751 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
10752   v8::Isolate* isolate = CcTest::isolate();
10753   v8::HandleScope scope(isolate);
10754   v8::Handle<v8::FunctionTemplate> fun_templ =
10755       v8::FunctionTemplate::New(isolate);
10756   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10757       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10758       v8::Signature::New(isolate, fun_templ));
10759   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10760   proto_templ->Set(v8_str("method"), method_templ);
10761   fun_templ->SetHiddenPrototype(true);
10762   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10763   CHECK(!templ.IsEmpty());
10764   LocalContext context;
10765   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10766   GenerateSomeGarbage();
10767   context->Global()->Set(v8_str("o"), fun->NewInstance());
10768   CompileRun(
10769       "o.foo = 17;"
10770       "var receiver = {};"
10771       "receiver.__proto__ = o;"
10772       "var result = 0;"
10773       "for (var i = 0; i < 100; i++) {"
10774       "  result = receiver.method(41);"
10775       "}");
10776
10777   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10778 }
10779
10780
10781 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
10782   v8::Isolate* isolate = CcTest::isolate();
10783   v8::HandleScope scope(isolate);
10784   v8::Handle<v8::FunctionTemplate> fun_templ =
10785       v8::FunctionTemplate::New(isolate);
10786   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10787       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10788       v8::Signature::New(isolate, fun_templ));
10789   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10790   proto_templ->Set(v8_str("method"), method_templ);
10791   fun_templ->SetHiddenPrototype(true);
10792   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10793   CHECK(!templ.IsEmpty());
10794   LocalContext context;
10795   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10796   GenerateSomeGarbage();
10797   context->Global()->Set(v8_str("o"), fun->NewInstance());
10798   CompileRun(
10799       "o.foo = 17;"
10800       "var receiver = {};"
10801       "receiver.__proto__ = o;"
10802       "var result = 0;"
10803       "var saved_result = 0;"
10804       "for (var i = 0; i < 100; i++) {"
10805       "  result = receiver.method(41);"
10806       "  if (i == 50) {"
10807       "    saved_result = result;"
10808       "    receiver = {method: function(x) { return x - 1 }};"
10809       "  }"
10810       "}");
10811   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10812   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10813 }
10814
10815
10816 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
10817   v8::Isolate* isolate = CcTest::isolate();
10818   v8::HandleScope scope(isolate);
10819   v8::Handle<v8::FunctionTemplate> fun_templ =
10820       v8::FunctionTemplate::New(isolate);
10821   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10822       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10823       v8::Signature::New(isolate, fun_templ));
10824   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10825   proto_templ->Set(v8_str("method"), method_templ);
10826   fun_templ->SetHiddenPrototype(true);
10827   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10828   CHECK(!templ.IsEmpty());
10829   LocalContext context;
10830   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10831   GenerateSomeGarbage();
10832   context->Global()->Set(v8_str("o"), fun->NewInstance());
10833   v8::TryCatch try_catch(isolate);
10834   CompileRun(
10835       "o.foo = 17;"
10836       "var receiver = {};"
10837       "receiver.__proto__ = o;"
10838       "var result = 0;"
10839       "var saved_result = 0;"
10840       "for (var i = 0; i < 100; i++) {"
10841       "  result = receiver.method(41);"
10842       "  if (i == 50) {"
10843       "    saved_result = result;"
10844       "    receiver = 333;"
10845       "  }"
10846       "}");
10847   CHECK(try_catch.HasCaught());
10848   // TODO(verwaest): Adjust message.
10849   CHECK(v8_str("TypeError: receiver.method is not a function")
10850             ->Equals(try_catch.Exception()->ToString(isolate)));
10851   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10852 }
10853
10854
10855 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
10856   v8::Isolate* isolate = CcTest::isolate();
10857   v8::HandleScope scope(isolate);
10858   v8::Handle<v8::FunctionTemplate> fun_templ =
10859       v8::FunctionTemplate::New(isolate);
10860   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10861       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10862       v8::Signature::New(isolate, fun_templ));
10863   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10864   proto_templ->Set(v8_str("method"), method_templ);
10865   fun_templ->SetHiddenPrototype(true);
10866   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10867   CHECK(!templ.IsEmpty());
10868   LocalContext context;
10869   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10870   GenerateSomeGarbage();
10871   context->Global()->Set(v8_str("o"), fun->NewInstance());
10872   v8::TryCatch try_catch(isolate);
10873   CompileRun(
10874       "o.foo = 17;"
10875       "var receiver = {};"
10876       "receiver.__proto__ = o;"
10877       "var result = 0;"
10878       "var saved_result = 0;"
10879       "for (var i = 0; i < 100; i++) {"
10880       "  result = receiver.method(41);"
10881       "  if (i == 50) {"
10882       "    saved_result = result;"
10883       "    receiver = Object.create(receiver);"
10884       "  }"
10885       "}");
10886   CHECK(try_catch.HasCaught());
10887   CHECK(v8_str("TypeError: Illegal invocation")
10888             ->Equals(try_catch.Exception()->ToString(isolate)));
10889   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10890 }
10891
10892
10893 static void ThrowingGetter(Local<String> name,
10894                            const v8::PropertyCallbackInfo<v8::Value>& info) {
10895   ApiTestFuzzer::Fuzz();
10896   info.GetIsolate()->ThrowException(Handle<Value>());
10897   info.GetReturnValue().SetUndefined();
10898 }
10899
10900
10901 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
10902   LocalContext context;
10903   HandleScope scope(context->GetIsolate());
10904
10905   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
10906   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
10907   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
10908
10909   Local<Object> instance = templ->GetFunction()->NewInstance();
10910
10911   Local<Object> another = Object::New(context->GetIsolate());
10912   another->SetPrototype(instance);
10913
10914   Local<Object> with_js_getter = CompileRun(
10915       "o = {};\n"
10916       "o.__defineGetter__('f', function() { throw undefined; });\n"
10917       "o\n").As<Object>();
10918   CHECK(!with_js_getter.IsEmpty());
10919
10920   TryCatch try_catch(context->GetIsolate());
10921
10922   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
10923   CHECK(try_catch.HasCaught());
10924   try_catch.Reset();
10925   CHECK(result.IsEmpty());
10926
10927   Maybe<PropertyAttribute> attr =
10928       instance->GetRealNamedPropertyAttributes(v8_str("f"));
10929   CHECK(!try_catch.HasCaught());
10930   CHECK(Just(None) == attr);
10931
10932   result = another->GetRealNamedProperty(v8_str("f"));
10933   CHECK(try_catch.HasCaught());
10934   try_catch.Reset();
10935   CHECK(result.IsEmpty());
10936
10937   attr = another->GetRealNamedPropertyAttributes(v8_str("f"));
10938   CHECK(!try_catch.HasCaught());
10939   CHECK(Just(None) == attr);
10940
10941   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
10942   CHECK(try_catch.HasCaught());
10943   try_catch.Reset();
10944   CHECK(result.IsEmpty());
10945
10946   attr = another->GetRealNamedPropertyAttributesInPrototypeChain(v8_str("f"));
10947   CHECK(!try_catch.HasCaught());
10948   CHECK(Just(None) == attr);
10949
10950   result = another->Get(v8_str("f"));
10951   CHECK(try_catch.HasCaught());
10952   try_catch.Reset();
10953   CHECK(result.IsEmpty());
10954
10955   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
10956   CHECK(try_catch.HasCaught());
10957   try_catch.Reset();
10958   CHECK(result.IsEmpty());
10959
10960   attr = with_js_getter->GetRealNamedPropertyAttributes(v8_str("f"));
10961   CHECK(!try_catch.HasCaught());
10962   CHECK(Just(None) == attr);
10963
10964   result = with_js_getter->Get(v8_str("f"));
10965   CHECK(try_catch.HasCaught());
10966   try_catch.Reset();
10967   CHECK(result.IsEmpty());
10968 }
10969
10970
10971 static void ThrowingCallbackWithTryCatch(
10972     const v8::FunctionCallbackInfo<v8::Value>& args) {
10973   TryCatch try_catch(args.GetIsolate());
10974   // Verboseness is important: it triggers message delivery which can call into
10975   // external code.
10976   try_catch.SetVerbose(true);
10977   CompileRun("throw 'from JS';");
10978   CHECK(try_catch.HasCaught());
10979   CHECK(!CcTest::i_isolate()->has_pending_exception());
10980   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
10981 }
10982
10983
10984 static int call_depth;
10985
10986
10987 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
10988   TryCatch try_catch(CcTest::isolate());
10989 }
10990
10991
10992 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
10993   if (--call_depth) CompileRun("throw 'ThrowInJS';");
10994 }
10995
10996
10997 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
10998   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
10999 }
11000
11001
11002 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
11003   Handle<String> errorMessageString = message->Get();
11004   CHECK(!errorMessageString.IsEmpty());
11005   message->GetStackTrace();
11006   message->GetScriptOrigin().ResourceName();
11007 }
11008
11009
11010 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
11011   LocalContext context;
11012   v8::Isolate* isolate = context->GetIsolate();
11013   HandleScope scope(isolate);
11014
11015   Local<Function> func =
11016       FunctionTemplate::New(isolate,
11017                             ThrowingCallbackWithTryCatch)->GetFunction();
11018   context->Global()->Set(v8_str("func"), func);
11019
11020   MessageCallback callbacks[] =
11021       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
11022   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
11023     MessageCallback callback = callbacks[i];
11024     if (callback != NULL) {
11025       V8::AddMessageListener(callback);
11026     }
11027     // Some small number to control number of times message handler should
11028     // throw an exception.
11029     call_depth = 5;
11030     ExpectFalse(
11031         "var thrown = false;\n"
11032         "try { func(); } catch(e) { thrown = true; }\n"
11033         "thrown\n");
11034     if (callback != NULL) {
11035       V8::RemoveMessageListeners(callback);
11036     }
11037   }
11038 }
11039
11040
11041 static void ParentGetter(Local<String> name,
11042                          const v8::PropertyCallbackInfo<v8::Value>& info) {
11043   ApiTestFuzzer::Fuzz();
11044   info.GetReturnValue().Set(v8_num(1));
11045 }
11046
11047
11048 static void ChildGetter(Local<String> name,
11049                         const v8::PropertyCallbackInfo<v8::Value>& info) {
11050   ApiTestFuzzer::Fuzz();
11051   info.GetReturnValue().Set(v8_num(42));
11052 }
11053
11054
11055 THREADED_TEST(Overriding) {
11056   LocalContext context;
11057   v8::Isolate* isolate = context->GetIsolate();
11058   v8::HandleScope scope(isolate);
11059
11060   // Parent template.
11061   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
11062   Local<ObjectTemplate> parent_instance_templ =
11063       parent_templ->InstanceTemplate();
11064   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
11065
11066   // Template that inherits from the parent template.
11067   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
11068   Local<ObjectTemplate> child_instance_templ =
11069       child_templ->InstanceTemplate();
11070   child_templ->Inherit(parent_templ);
11071   // Override 'f'.  The child version of 'f' should get called for child
11072   // instances.
11073   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
11074   // Add 'g' twice.  The 'g' added last should get called for instances.
11075   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
11076   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
11077
11078   // Add 'h' as an accessor to the proto template with ReadOnly attributes
11079   // so 'h' can be shadowed on the instance object.
11080   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
11081   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
11082       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
11083
11084   // Add 'i' as an accessor to the instance template with ReadOnly attributes
11085   // but the attribute does not have effect because it is duplicated with
11086   // NULL setter.
11087   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
11088       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
11089
11090
11091
11092   // Instantiate the child template.
11093   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
11094
11095   // Check that the child function overrides the parent one.
11096   context->Global()->Set(v8_str("o"), instance);
11097   Local<Value> value = v8_compile("o.f")->Run();
11098   // Check that the 'g' that was added last is hit.
11099   CHECK_EQ(42, value->Int32Value());
11100   value = v8_compile("o.g")->Run();
11101   CHECK_EQ(42, value->Int32Value());
11102
11103   // Check that 'h' cannot be shadowed.
11104   value = v8_compile("o.h = 3; o.h")->Run();
11105   CHECK_EQ(1, value->Int32Value());
11106
11107   // Check that 'i' cannot be shadowed or changed.
11108   value = v8_compile("o.i = 3; o.i")->Run();
11109   CHECK_EQ(42, value->Int32Value());
11110 }
11111
11112
11113 static void IsConstructHandler(
11114     const v8::FunctionCallbackInfo<v8::Value>& args) {
11115   ApiTestFuzzer::Fuzz();
11116   args.GetReturnValue().Set(args.IsConstructCall());
11117 }
11118
11119
11120 THREADED_TEST(IsConstructCall) {
11121   v8::Isolate* isolate = CcTest::isolate();
11122   v8::HandleScope scope(isolate);
11123
11124   // Function template with call handler.
11125   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11126   templ->SetCallHandler(IsConstructHandler);
11127
11128   LocalContext context;
11129
11130   context->Global()->Set(v8_str("f"), templ->GetFunction());
11131   Local<Value> value = v8_compile("f()")->Run();
11132   CHECK(!value->BooleanValue());
11133   value = v8_compile("new f()")->Run();
11134   CHECK(value->BooleanValue());
11135 }
11136
11137
11138 THREADED_TEST(ObjectProtoToString) {
11139   v8::Isolate* isolate = CcTest::isolate();
11140   v8::HandleScope scope(isolate);
11141   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11142   templ->SetClassName(v8_str("MyClass"));
11143
11144   LocalContext context;
11145
11146   Local<String> customized_tostring = v8_str("customized toString");
11147
11148   // Replace Object.prototype.toString
11149   v8_compile("Object.prototype.toString = function() {"
11150                   "  return 'customized toString';"
11151                   "}")->Run();
11152
11153   // Normal ToString call should call replaced Object.prototype.toString
11154   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
11155   Local<String> value = instance->ToString(isolate);
11156   CHECK(value->IsString() && value->Equals(customized_tostring));
11157
11158   // ObjectProtoToString should not call replace toString function.
11159   value = instance->ObjectProtoToString();
11160   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
11161
11162   // Check global
11163   value = context->Global()->ObjectProtoToString();
11164   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
11165
11166   // Check ordinary object
11167   Local<Value> object = v8_compile("new Object()")->Run();
11168   value = object.As<v8::Object>()->ObjectProtoToString();
11169   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11170 }
11171
11172
11173 TEST(ObjectProtoToStringES6) {
11174   // TODO(dslomov, caitp): merge into ObjectProtoToString test once shipped.
11175   i::FLAG_harmony_tostring = true;
11176   LocalContext context;
11177   v8::Isolate* isolate = CcTest::isolate();
11178   v8::HandleScope scope(isolate);
11179   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11180   templ->SetClassName(v8_str("MyClass"));
11181
11182   Local<String> customized_tostring = v8_str("customized toString");
11183
11184   // Replace Object.prototype.toString
11185   CompileRun(
11186       "Object.prototype.toString = function() {"
11187       "  return 'customized toString';"
11188       "}");
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 = CompileRun("new Object()");
11205   value = object.As<v8::Object>()->ObjectProtoToString();
11206   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11207
11208   // Check that ES6 semantics using @@toStringTag work
11209   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
11210
11211 #define TEST_TOSTRINGTAG(type, tag, expected)                \
11212   do {                                                       \
11213     object = CompileRun("new " #type "()");                  \
11214     object.As<v8::Object>()->Set(toStringTag, v8_str(#tag)); \
11215     value = object.As<v8::Object>()->ObjectProtoToString();  \
11216     CHECK(value->IsString() &&                               \
11217           value->Equals(v8_str("[object " #expected "]")));  \
11218   } while (0)
11219
11220   TEST_TOSTRINGTAG(Array, Object, Object);
11221   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
11222   TEST_TOSTRINGTAG(Object, Array, Array);
11223   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
11224   TEST_TOSTRINGTAG(Object, Date, Date);
11225   TEST_TOSTRINGTAG(Object, Error, Error);
11226   TEST_TOSTRINGTAG(Object, Function, Function);
11227   TEST_TOSTRINGTAG(Object, Number, Number);
11228   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
11229   TEST_TOSTRINGTAG(Object, String, String);
11230   TEST_TOSTRINGTAG(Object, Foo, Foo);
11231
11232 #undef TEST_TOSTRINGTAG
11233
11234   Local<v8::RegExp> valueRegExp = v8::RegExp::New(v8_str("^$"),
11235                                                   v8::RegExp::kNone);
11236   Local<Value> valueNumber = v8_num(123);
11237   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
11238   Local<v8::Function> valueFunction =
11239       CompileRun("(function fn() {})").As<v8::Function>();
11240   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
11241   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
11242   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
11243
11244 #define TEST_TOSTRINGTAG(type, tagValue, expected)          \
11245   do {                                                      \
11246     object = CompileRun("new " #type "()");                 \
11247     object.As<v8::Object>()->Set(toStringTag, tagValue);    \
11248     value = object.As<v8::Object>()->ObjectProtoToString(); \
11249     CHECK(value->IsString() &&                              \
11250           value->Equals(v8_str("[object " #expected "]"))); \
11251   } while (0)
11252
11253 #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
11254   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
11255   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
11256   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
11257   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
11258   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
11259   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
11260
11261   // Test non-String-valued @@toStringTag
11262   TEST_TOSTRINGTAG_TYPES(valueRegExp);
11263   TEST_TOSTRINGTAG_TYPES(valueNumber);
11264   TEST_TOSTRINGTAG_TYPES(valueSymbol);
11265   TEST_TOSTRINGTAG_TYPES(valueFunction);
11266   TEST_TOSTRINGTAG_TYPES(valueObject);
11267   TEST_TOSTRINGTAG_TYPES(valueNull);
11268   TEST_TOSTRINGTAG_TYPES(valueUndef);
11269
11270 #undef TEST_TOSTRINGTAG
11271 #undef TEST_TOSTRINGTAG_TYPES
11272
11273   // @@toStringTag getter throws
11274   Local<Value> obj = v8::Object::New(isolate);
11275   obj.As<v8::Object>()->SetAccessor(toStringTag, ThrowingSymbolAccessorGetter);
11276   {
11277     TryCatch try_catch(isolate);
11278     value = obj.As<v8::Object>()->ObjectProtoToString();
11279     CHECK(value.IsEmpty());
11280     CHECK(try_catch.HasCaught());
11281   }
11282
11283   // @@toStringTag getter does not throw
11284   obj = v8::Object::New(isolate);
11285   obj.As<v8::Object>()->SetAccessor(
11286       toStringTag, SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"));
11287   {
11288     TryCatch try_catch(isolate);
11289     value = obj.As<v8::Object>()->ObjectProtoToString();
11290     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11291     CHECK(!try_catch.HasCaught());
11292   }
11293
11294   // JS @@toStringTag value
11295   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
11296   {
11297     TryCatch try_catch(isolate);
11298     value = obj.As<v8::Object>()->ObjectProtoToString();
11299     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11300     CHECK(!try_catch.HasCaught());
11301   }
11302
11303   // JS @@toStringTag getter throws
11304   obj = CompileRun(
11305       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
11306       "  get: function() { throw 'Test'; }"
11307       "}); obj");
11308   {
11309     TryCatch try_catch(isolate);
11310     value = obj.As<v8::Object>()->ObjectProtoToString();
11311     CHECK(value.IsEmpty());
11312     CHECK(try_catch.HasCaught());
11313   }
11314
11315   // JS @@toStringTag getter does not throw
11316   obj = CompileRun(
11317       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
11318       "  get: function() { return 'Test'; }"
11319       "}); obj");
11320   {
11321     TryCatch try_catch(isolate);
11322     value = obj.As<v8::Object>()->ObjectProtoToString();
11323     CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11324     CHECK(!try_catch.HasCaught());
11325   }
11326 }
11327
11328
11329 THREADED_TEST(ObjectGetConstructorName) {
11330   v8::Isolate* isolate = CcTest::isolate();
11331   LocalContext context;
11332   v8::HandleScope scope(isolate);
11333   v8_compile(
11334       "function Parent() {};"
11335       "function Child() {};"
11336       "Child.prototype = new Parent();"
11337       "var outer = { inner: function() { } };"
11338       "var p = new Parent();"
11339       "var c = new Child();"
11340       "var x = new outer.inner();"
11341       "var proto = Child.prototype;")->Run();
11342
11343   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
11344   CHECK(p->IsObject() &&
11345         p->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Parent")));
11346
11347   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
11348   CHECK(c->IsObject() &&
11349         c->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Child")));
11350
11351   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
11352   CHECK(x->IsObject() &&
11353         x->ToObject(isolate)->GetConstructorName()->Equals(
11354             v8_str("outer.inner")));
11355
11356   Local<v8::Value> child_prototype = context->Global()->Get(v8_str("proto"));
11357   CHECK(child_prototype->IsObject() &&
11358         child_prototype->ToObject(isolate)->GetConstructorName()->Equals(
11359             v8_str("Parent")));
11360 }
11361
11362
11363 bool ApiTestFuzzer::fuzzing_ = false;
11364 v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
11365 int ApiTestFuzzer::active_tests_;
11366 int ApiTestFuzzer::tests_being_run_;
11367 int ApiTestFuzzer::current_;
11368
11369
11370 // We are in a callback and want to switch to another thread (if we
11371 // are currently running the thread fuzzing test).
11372 void ApiTestFuzzer::Fuzz() {
11373   if (!fuzzing_) return;
11374   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
11375   test->ContextSwitch();
11376 }
11377
11378
11379 // Let the next thread go.  Since it is also waiting on the V8 lock it may
11380 // not start immediately.
11381 bool ApiTestFuzzer::NextThread() {
11382   int test_position = GetNextTestNumber();
11383   const char* test_name = RegisterThreadedTest::nth(current_)->name();
11384   if (test_position == current_) {
11385     if (kLogThreading)
11386       printf("Stay with %s\n", test_name);
11387     return false;
11388   }
11389   if (kLogThreading) {
11390     printf("Switch from %s to %s\n",
11391            test_name,
11392            RegisterThreadedTest::nth(test_position)->name());
11393   }
11394   current_ = test_position;
11395   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
11396   return true;
11397 }
11398
11399
11400 void ApiTestFuzzer::Run() {
11401   // When it is our turn...
11402   gate_.Wait();
11403   {
11404     // ... get the V8 lock and start running the test.
11405     v8::Locker locker(CcTest::isolate());
11406     CallTest();
11407   }
11408   // This test finished.
11409   active_ = false;
11410   active_tests_--;
11411   // If it was the last then signal that fact.
11412   if (active_tests_ == 0) {
11413     all_tests_done_.Signal();
11414   } else {
11415     // Otherwise select a new test and start that.
11416     NextThread();
11417   }
11418 }
11419
11420
11421 static unsigned linear_congruential_generator;
11422
11423
11424 void ApiTestFuzzer::SetUp(PartOfTest part) {
11425   linear_congruential_generator = i::FLAG_testing_prng_seed;
11426   fuzzing_ = true;
11427   int count = RegisterThreadedTest::count();
11428   int start =  count * part / (LAST_PART + 1);
11429   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
11430   active_tests_ = tests_being_run_ = end - start + 1;
11431   for (int i = 0; i < tests_being_run_; i++) {
11432     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
11433   }
11434   for (int i = 0; i < active_tests_; i++) {
11435     RegisterThreadedTest::nth(i)->fuzzer_->Start();
11436   }
11437 }
11438
11439
11440 static void CallTestNumber(int test_number) {
11441   (RegisterThreadedTest::nth(test_number)->callback())();
11442 }
11443
11444
11445 void ApiTestFuzzer::RunAllTests() {
11446   // Set off the first test.
11447   current_ = -1;
11448   NextThread();
11449   // Wait till they are all done.
11450   all_tests_done_.Wait();
11451 }
11452
11453
11454 int ApiTestFuzzer::GetNextTestNumber() {
11455   int next_test;
11456   do {
11457     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
11458     linear_congruential_generator *= 1664525u;
11459     linear_congruential_generator += 1013904223u;
11460   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
11461   return next_test;
11462 }
11463
11464
11465 void ApiTestFuzzer::ContextSwitch() {
11466   // If the new thread is the same as the current thread there is nothing to do.
11467   if (NextThread()) {
11468     // Now it can start.
11469     v8::Unlocker unlocker(CcTest::isolate());
11470     // Wait till someone starts us again.
11471     gate_.Wait();
11472     // And we're off.
11473   }
11474 }
11475
11476
11477 void ApiTestFuzzer::TearDown() {
11478   fuzzing_ = false;
11479   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
11480     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
11481     if (fuzzer != NULL) fuzzer->Join();
11482   }
11483 }
11484
11485
11486 // Lets not be needlessly self-referential.
11487 TEST(Threading1) {
11488   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
11489   ApiTestFuzzer::RunAllTests();
11490   ApiTestFuzzer::TearDown();
11491 }
11492
11493
11494 TEST(Threading2) {
11495   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
11496   ApiTestFuzzer::RunAllTests();
11497   ApiTestFuzzer::TearDown();
11498 }
11499
11500
11501 TEST(Threading3) {
11502   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
11503   ApiTestFuzzer::RunAllTests();
11504   ApiTestFuzzer::TearDown();
11505 }
11506
11507
11508 TEST(Threading4) {
11509   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
11510   ApiTestFuzzer::RunAllTests();
11511   ApiTestFuzzer::TearDown();
11512 }
11513
11514
11515 void ApiTestFuzzer::CallTest() {
11516   v8::Isolate::Scope scope(CcTest::isolate());
11517   if (kLogThreading)
11518     printf("Start test %d\n", test_number_);
11519   CallTestNumber(test_number_);
11520   if (kLogThreading)
11521     printf("End test %d\n", test_number_);
11522 }
11523
11524
11525 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
11526   v8::Isolate* isolate = args.GetIsolate();
11527   CHECK(v8::Locker::IsLocked(isolate));
11528   ApiTestFuzzer::Fuzz();
11529   v8::Unlocker unlocker(isolate);
11530   const char* code = "throw 7;";
11531   {
11532     v8::Locker nested_locker(isolate);
11533     v8::HandleScope scope(isolate);
11534     v8::Handle<Value> exception;
11535     {
11536       v8::TryCatch try_catch(isolate);
11537       v8::Handle<Value> value = CompileRun(code);
11538       CHECK(value.IsEmpty());
11539       CHECK(try_catch.HasCaught());
11540       // Make sure to wrap the exception in a new handle because
11541       // the handle returned from the TryCatch is destroyed
11542       // when the TryCatch is destroyed.
11543       exception = Local<Value>::New(isolate, try_catch.Exception());
11544     }
11545     args.GetIsolate()->ThrowException(exception);
11546   }
11547 }
11548
11549
11550 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
11551   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
11552   ApiTestFuzzer::Fuzz();
11553   v8::Unlocker unlocker(CcTest::isolate());
11554   const char* code = "throw 7;";
11555   {
11556     v8::Locker nested_locker(CcTest::isolate());
11557     v8::HandleScope scope(args.GetIsolate());
11558     v8::Handle<Value> value = CompileRun(code);
11559     CHECK(value.IsEmpty());
11560     args.GetReturnValue().Set(v8_str("foo"));
11561   }
11562 }
11563
11564
11565 // These are locking tests that don't need to be run again
11566 // as part of the locking aggregation tests.
11567 TEST(NestedLockers) {
11568   v8::Isolate* isolate = CcTest::isolate();
11569   v8::Locker locker(isolate);
11570   CHECK(v8::Locker::IsLocked(isolate));
11571   LocalContext env;
11572   v8::HandleScope scope(env->GetIsolate());
11573   Local<v8::FunctionTemplate> fun_templ =
11574       v8::FunctionTemplate::New(isolate, ThrowInJS);
11575   Local<Function> fun = fun_templ->GetFunction();
11576   env->Global()->Set(v8_str("throw_in_js"), fun);
11577   Local<Script> script = v8_compile("(function () {"
11578                                     "  try {"
11579                                     "    throw_in_js();"
11580                                     "    return 42;"
11581                                     "  } catch (e) {"
11582                                     "    return e * 13;"
11583                                     "  }"
11584                                     "})();");
11585   CHECK_EQ(91, script->Run()->Int32Value());
11586 }
11587
11588
11589 // These are locking tests that don't need to be run again
11590 // as part of the locking aggregation tests.
11591 TEST(NestedLockersNoTryCatch) {
11592   v8::Locker locker(CcTest::isolate());
11593   LocalContext env;
11594   v8::HandleScope scope(env->GetIsolate());
11595   Local<v8::FunctionTemplate> fun_templ =
11596       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
11597   Local<Function> fun = fun_templ->GetFunction();
11598   env->Global()->Set(v8_str("throw_in_js"), fun);
11599   Local<Script> script = v8_compile("(function () {"
11600                                     "  try {"
11601                                     "    throw_in_js();"
11602                                     "    return 42;"
11603                                     "  } catch (e) {"
11604                                     "    return e * 13;"
11605                                     "  }"
11606                                     "})();");
11607   CHECK_EQ(91, script->Run()->Int32Value());
11608 }
11609
11610
11611 THREADED_TEST(RecursiveLocking) {
11612   v8::Locker locker(CcTest::isolate());
11613   {
11614     v8::Locker locker2(CcTest::isolate());
11615     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
11616   }
11617 }
11618
11619
11620 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
11621   ApiTestFuzzer::Fuzz();
11622   v8::Unlocker unlocker(CcTest::isolate());
11623 }
11624
11625
11626 THREADED_TEST(LockUnlockLock) {
11627   {
11628     v8::Locker locker(CcTest::isolate());
11629     v8::HandleScope scope(CcTest::isolate());
11630     LocalContext env;
11631     Local<v8::FunctionTemplate> fun_templ =
11632         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
11633     Local<Function> fun = fun_templ->GetFunction();
11634     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11635     Local<Script> script = v8_compile("(function () {"
11636                                       "  unlock_for_a_moment();"
11637                                       "  return 42;"
11638                                       "})();");
11639     CHECK_EQ(42, script->Run()->Int32Value());
11640   }
11641   {
11642     v8::Locker locker(CcTest::isolate());
11643     v8::HandleScope scope(CcTest::isolate());
11644     LocalContext env;
11645     Local<v8::FunctionTemplate> fun_templ =
11646         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
11647     Local<Function> fun = fun_templ->GetFunction();
11648     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11649     Local<Script> script = v8_compile("(function () {"
11650                                       "  unlock_for_a_moment();"
11651                                       "  return 42;"
11652                                       "})();");
11653     CHECK_EQ(42, script->Run()->Int32Value());
11654   }
11655 }
11656
11657
11658 static int GetGlobalObjectsCount() {
11659   int count = 0;
11660   i::HeapIterator it(CcTest::heap());
11661   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
11662     if (object->IsJSGlobalObject()) count++;
11663   return count;
11664 }
11665
11666
11667 static void CheckSurvivingGlobalObjectsCount(int expected) {
11668   // We need to collect all garbage twice to be sure that everything
11669   // has been collected.  This is because inline caches are cleared in
11670   // the first garbage collection but some of the maps have already
11671   // been marked at that point.  Therefore some of the maps are not
11672   // collected until the second garbage collection.
11673   CcTest::heap()->CollectAllGarbage();
11674   CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
11675   int count = GetGlobalObjectsCount();
11676 #ifdef DEBUG
11677   if (count != expected) CcTest::heap()->TracePathToGlobal();
11678 #endif
11679   CHECK_EQ(expected, count);
11680 }
11681
11682
11683 TEST(DontLeakGlobalObjects) {
11684   // Regression test for issues 1139850 and 1174891.
11685
11686   i::FLAG_expose_gc = true;
11687   v8::V8::Initialize();
11688
11689   for (int i = 0; i < 5; i++) {
11690     { v8::HandleScope scope(CcTest::isolate());
11691       LocalContext context;
11692     }
11693     CcTest::isolate()->ContextDisposedNotification();
11694     CheckSurvivingGlobalObjectsCount(0);
11695
11696     { v8::HandleScope scope(CcTest::isolate());
11697       LocalContext context;
11698       v8_compile("Date")->Run();
11699     }
11700     CcTest::isolate()->ContextDisposedNotification();
11701     CheckSurvivingGlobalObjectsCount(0);
11702
11703     { v8::HandleScope scope(CcTest::isolate());
11704       LocalContext context;
11705       v8_compile("/aaa/")->Run();
11706     }
11707     CcTest::isolate()->ContextDisposedNotification();
11708     CheckSurvivingGlobalObjectsCount(0);
11709
11710     { v8::HandleScope scope(CcTest::isolate());
11711       const char* extension_list[] = { "v8/gc" };
11712       v8::ExtensionConfiguration extensions(1, extension_list);
11713       LocalContext context(&extensions);
11714       v8_compile("gc();")->Run();
11715     }
11716     CcTest::isolate()->ContextDisposedNotification();
11717     CheckSurvivingGlobalObjectsCount(0);
11718   }
11719 }
11720
11721
11722 TEST(CopyablePersistent) {
11723   LocalContext context;
11724   v8::Isolate* isolate = context->GetIsolate();
11725   i::GlobalHandles* globals =
11726       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
11727   int initial_handles = globals->global_handles_count();
11728   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
11729       CopyableObject;
11730   {
11731     CopyableObject handle1;
11732     {
11733       v8::HandleScope scope(isolate);
11734       handle1.Reset(isolate, v8::Object::New(isolate));
11735     }
11736     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
11737     CopyableObject  handle2;
11738     handle2 = handle1;
11739     CHECK(handle1 == handle2);
11740     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
11741     CopyableObject handle3(handle2);
11742     CHECK(handle1 == handle3);
11743     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
11744   }
11745   // Verify autodispose
11746   CHECK_EQ(initial_handles, globals->global_handles_count());
11747 }
11748
11749
11750 static void WeakApiCallback(
11751     const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
11752   data.GetParameter()->Reset();
11753   delete data.GetParameter();
11754 }
11755
11756
11757 TEST(WeakCallbackApi) {
11758   LocalContext context;
11759   v8::Isolate* isolate = context->GetIsolate();
11760   i::GlobalHandles* globals =
11761       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
11762   int initial_handles = globals->global_handles_count();
11763   {
11764     v8::HandleScope scope(isolate);
11765     v8::Local<v8::Object> obj = v8::Object::New(isolate);
11766     obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
11767     v8::Persistent<v8::Object>* handle =
11768         new v8::Persistent<v8::Object>(isolate, obj);
11769     handle->SetWeak<v8::Persistent<v8::Object>>(
11770         handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
11771   }
11772   reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
11773       i::Heap::kAbortIncrementalMarkingMask);
11774   // Verify disposed.
11775   CHECK_EQ(initial_handles, globals->global_handles_count());
11776 }
11777
11778
11779 v8::Persistent<v8::Object> some_object;
11780 v8::Persistent<v8::Object> bad_handle;
11781
11782
11783 void NewPersistentHandleCallback2(
11784     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11785   v8::HandleScope scope(data.GetIsolate());
11786   bad_handle.Reset(data.GetIsolate(), some_object);
11787 }
11788
11789
11790 void NewPersistentHandleCallback1(
11791     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11792   data.GetParameter()->Reset();
11793   data.SetSecondPassCallback(NewPersistentHandleCallback2);
11794 }
11795
11796
11797 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
11798   LocalContext context;
11799   v8::Isolate* isolate = context->GetIsolate();
11800
11801   v8::Persistent<v8::Object> handle1, handle2;
11802   {
11803     v8::HandleScope scope(isolate);
11804     some_object.Reset(isolate, v8::Object::New(isolate));
11805     handle1.Reset(isolate, v8::Object::New(isolate));
11806     handle2.Reset(isolate, v8::Object::New(isolate));
11807   }
11808   // Note: order is implementation dependent alas: currently
11809   // global handle nodes are processed by PostGarbageCollectionProcessing
11810   // in reverse allocation order, so if second allocated handle is deleted,
11811   // weak callback of the first handle would be able to 'reallocate' it.
11812   handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
11813                   v8::WeakCallbackType::kParameter);
11814   handle2.Reset();
11815   CcTest::heap()->CollectAllGarbage();
11816 }
11817
11818
11819 v8::Persistent<v8::Object> to_be_disposed;
11820
11821
11822 void DisposeAndForceGcCallback2(
11823     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11824   to_be_disposed.Reset();
11825   CcTest::heap()->CollectAllGarbage();
11826 }
11827
11828
11829 void DisposeAndForceGcCallback1(
11830     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11831   data.GetParameter()->Reset();
11832   data.SetSecondPassCallback(DisposeAndForceGcCallback2);
11833 }
11834
11835
11836 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
11837   LocalContext context;
11838   v8::Isolate* isolate = context->GetIsolate();
11839
11840   v8::Persistent<v8::Object> handle1, handle2;
11841   {
11842     v8::HandleScope scope(isolate);
11843     handle1.Reset(isolate, v8::Object::New(isolate));
11844     handle2.Reset(isolate, v8::Object::New(isolate));
11845   }
11846   handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
11847                   v8::WeakCallbackType::kParameter);
11848   to_be_disposed.Reset(isolate, handle2);
11849   CcTest::heap()->CollectAllGarbage();
11850 }
11851
11852 void DisposingCallback(
11853     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11854   data.GetParameter()->Reset();
11855 }
11856
11857 void HandleCreatingCallback2(
11858     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11859   v8::HandleScope scope(data.GetIsolate());
11860   v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
11861 }
11862
11863
11864 void HandleCreatingCallback1(
11865     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11866   data.GetParameter()->Reset();
11867   data.SetSecondPassCallback(HandleCreatingCallback2);
11868 }
11869
11870
11871 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
11872   LocalContext context;
11873   v8::Isolate* isolate = context->GetIsolate();
11874
11875   v8::Persistent<v8::Object> handle1, handle2, handle3;
11876   {
11877     v8::HandleScope scope(isolate);
11878     handle3.Reset(isolate, v8::Object::New(isolate));
11879     handle2.Reset(isolate, v8::Object::New(isolate));
11880     handle1.Reset(isolate, v8::Object::New(isolate));
11881   }
11882   handle2.SetWeak(&handle2, DisposingCallback,
11883                   v8::WeakCallbackType::kParameter);
11884   handle3.SetWeak(&handle3, HandleCreatingCallback1,
11885                   v8::WeakCallbackType::kParameter);
11886   CcTest::heap()->CollectAllGarbage();
11887 }
11888
11889
11890 THREADED_TEST(CheckForCrossContextObjectLiterals) {
11891   v8::V8::Initialize();
11892
11893   const int nof = 2;
11894   const char* sources[nof] = {
11895     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
11896     "Object()"
11897   };
11898
11899   for (int i = 0; i < nof; i++) {
11900     const char* source = sources[i];
11901     { v8::HandleScope scope(CcTest::isolate());
11902       LocalContext context;
11903       CompileRun(source);
11904     }
11905     { v8::HandleScope scope(CcTest::isolate());
11906       LocalContext context;
11907       CompileRun(source);
11908     }
11909   }
11910 }
11911
11912
11913 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
11914   v8::EscapableHandleScope inner(env->GetIsolate());
11915   env->Enter();
11916   v8::Local<Value> three = v8_num(3);
11917   v8::Local<Value> value = inner.Escape(three);
11918   env->Exit();
11919   return value;
11920 }
11921
11922
11923 THREADED_TEST(NestedHandleScopeAndContexts) {
11924   v8::Isolate* isolate = CcTest::isolate();
11925   v8::HandleScope outer(isolate);
11926   v8::Local<Context> env = Context::New(isolate);
11927   env->Enter();
11928   v8::Handle<Value> value = NestedScope(env);
11929   v8::Handle<String> str(value->ToString(isolate));
11930   CHECK(!str.IsEmpty());
11931   env->Exit();
11932 }
11933
11934
11935 static bool MatchPointers(void* key1, void* key2) {
11936   return key1 == key2;
11937 }
11938
11939
11940 struct SymbolInfo {
11941   size_t id;
11942   size_t size;
11943   std::string name;
11944 };
11945
11946
11947 class SetFunctionEntryHookTest {
11948  public:
11949   SetFunctionEntryHookTest() {
11950     CHECK(instance_ == NULL);
11951     instance_ = this;
11952   }
11953   ~SetFunctionEntryHookTest() {
11954     CHECK(instance_ == this);
11955     instance_ = NULL;
11956   }
11957   void Reset() {
11958     symbols_.clear();
11959     symbol_locations_.clear();
11960     invocations_.clear();
11961   }
11962   void RunTest();
11963   void OnJitEvent(const v8::JitCodeEvent* event);
11964   static void JitEvent(const v8::JitCodeEvent* event) {
11965     CHECK(instance_ != NULL);
11966     instance_->OnJitEvent(event);
11967   }
11968
11969   void OnEntryHook(uintptr_t function,
11970                    uintptr_t return_addr_location);
11971   static void EntryHook(uintptr_t function,
11972                         uintptr_t return_addr_location) {
11973     CHECK(instance_ != NULL);
11974     instance_->OnEntryHook(function, return_addr_location);
11975   }
11976
11977   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
11978     CHECK(instance_ != NULL);
11979     args.GetReturnValue().Set(v8_num(42));
11980   }
11981   void RunLoopInNewEnv(v8::Isolate* isolate);
11982
11983   // Records addr as location of symbol.
11984   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
11985
11986   // Finds the symbol containing addr
11987   SymbolInfo* FindSymbolForAddr(i::Address addr);
11988   // Returns the number of invocations where the caller name contains
11989   // \p caller_name and the function name contains \p function_name.
11990   int CountInvocations(const char* caller_name,
11991                        const char* function_name);
11992
11993   i::Handle<i::JSFunction> foo_func_;
11994   i::Handle<i::JSFunction> bar_func_;
11995
11996   typedef std::map<size_t, SymbolInfo> SymbolMap;
11997   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
11998   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
11999   SymbolMap symbols_;
12000   SymbolLocationMap symbol_locations_;
12001   InvocationMap invocations_;
12002
12003   static SetFunctionEntryHookTest* instance_;
12004 };
12005 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
12006
12007
12008 // Returns true if addr is in the range [start, start+len).
12009 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
12010   if (start <= addr && start + len > addr)
12011     return true;
12012
12013   return false;
12014 }
12015
12016 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
12017                                               SymbolInfo* symbol) {
12018   // Insert the symbol at the new location.
12019   SymbolLocationMap::iterator it =
12020       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
12021   // Now erase symbols to the left and right that overlap this one.
12022   while (it != symbol_locations_.begin()) {
12023     SymbolLocationMap::iterator left = it;
12024     --left;
12025     if (!Overlaps(left->first, left->second->size, addr))
12026       break;
12027     symbol_locations_.erase(left);
12028   }
12029
12030   // Now erase symbols to the left and right that overlap this one.
12031   while (true) {
12032     SymbolLocationMap::iterator right = it;
12033     ++right;
12034     if (right == symbol_locations_.end())
12035         break;
12036     if (!Overlaps(addr, symbol->size, right->first))
12037       break;
12038     symbol_locations_.erase(right);
12039   }
12040 }
12041
12042
12043 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
12044   switch (event->type) {
12045     case v8::JitCodeEvent::CODE_ADDED: {
12046         CHECK(event->code_start != NULL);
12047         CHECK_NE(0, static_cast<int>(event->code_len));
12048         CHECK(event->name.str != NULL);
12049         size_t symbol_id = symbols_.size();
12050
12051         // Record the new symbol.
12052         SymbolInfo& info = symbols_[symbol_id];
12053         info.id = symbol_id;
12054         info.size = event->code_len;
12055         info.name.assign(event->name.str, event->name.str + event->name.len);
12056
12057         // And record it's location.
12058         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
12059       }
12060       break;
12061
12062     case v8::JitCodeEvent::CODE_MOVED: {
12063         // We would like to never see code move that we haven't seen before,
12064         // but the code creation event does not happen until the line endings
12065         // have been calculated (this is so that we can report the line in the
12066         // script at which the function source is found, see
12067         // Compiler::RecordFunctionCompilation) and the line endings
12068         // calculations can cause a GC, which can move the newly created code
12069         // before its existence can be logged.
12070         SymbolLocationMap::iterator it(
12071             symbol_locations_.find(
12072                 reinterpret_cast<i::Address>(event->code_start)));
12073         if (it != symbol_locations_.end()) {
12074           // Found a symbol at this location, move it.
12075           SymbolInfo* info = it->second;
12076           symbol_locations_.erase(it);
12077           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
12078                          info);
12079         }
12080       }
12081     default:
12082       break;
12083   }
12084 }
12085
12086 void SetFunctionEntryHookTest::OnEntryHook(
12087     uintptr_t function, uintptr_t return_addr_location) {
12088   // Get the function's code object.
12089   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
12090       reinterpret_cast<i::Address>(function));
12091   CHECK(function_code != NULL);
12092
12093   // Then try and look up the caller's code object.
12094   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
12095
12096   // Count the invocation.
12097   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
12098   SymbolInfo* function_symbol =
12099       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
12100   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
12101
12102   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
12103     // Check that we have a symbol for the "bar" function at the right location.
12104     SymbolLocationMap::iterator it(
12105         symbol_locations_.find(function_code->instruction_start()));
12106     CHECK(it != symbol_locations_.end());
12107   }
12108
12109   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
12110     // Check that we have a symbol for "foo" at the right location.
12111     SymbolLocationMap::iterator it(
12112         symbol_locations_.find(function_code->instruction_start()));
12113     CHECK(it != symbol_locations_.end());
12114   }
12115 }
12116
12117
12118 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
12119   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
12120   // Do we have a direct hit on a symbol?
12121   if (it != symbol_locations_.end()) {
12122     if (it->first == addr)
12123       return it->second;
12124   }
12125
12126   // If not a direct hit, it'll have to be the previous symbol.
12127   if (it == symbol_locations_.begin())
12128     return NULL;
12129
12130   --it;
12131   size_t offs = addr - it->first;
12132   if (offs < it->second->size)
12133     return it->second;
12134
12135   return NULL;
12136 }
12137
12138
12139 int SetFunctionEntryHookTest::CountInvocations(
12140     const char* caller_name, const char* function_name) {
12141   InvocationMap::iterator it(invocations_.begin());
12142   int invocations = 0;
12143   for (; it != invocations_.end(); ++it) {
12144     SymbolInfo* caller = it->first.first;
12145     SymbolInfo* function = it->first.second;
12146
12147     // Filter out non-matching functions.
12148     if (function_name != NULL) {
12149       if (function->name.find(function_name) == std::string::npos)
12150         continue;
12151     }
12152
12153     // Filter out non-matching callers.
12154     if (caller_name != NULL) {
12155       if (caller == NULL)
12156         continue;
12157       if (caller->name.find(caller_name) == std::string::npos)
12158         continue;
12159     }
12160
12161     // It matches add the invocation count to the tally.
12162     invocations += it->second;
12163   }
12164
12165   return invocations;
12166 }
12167
12168
12169 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
12170   v8::HandleScope outer(isolate);
12171   v8::Local<Context> env = Context::New(isolate);
12172   env->Enter();
12173
12174   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
12175   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
12176   env->Global()->Set(v8_str("obj"), t->NewInstance());
12177
12178   const char* script =
12179       "function bar() {\n"
12180       "  var sum = 0;\n"
12181       "  for (i = 0; i < 100; ++i)\n"
12182       "    sum = foo(i);\n"
12183       "  return sum;\n"
12184       "}\n"
12185       "function foo(i) { return i * i; }\n"
12186       "// Invoke on the runtime function.\n"
12187       "obj.asdf()";
12188   CompileRun(script);
12189   bar_func_ = i::Handle<i::JSFunction>::cast(
12190           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
12191   DCHECK(!bar_func_.is_null());
12192
12193   foo_func_ =
12194       i::Handle<i::JSFunction>::cast(
12195            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
12196   DCHECK(!foo_func_.is_null());
12197
12198   v8::Handle<v8::Value> value = CompileRun("bar();");
12199   CHECK(value->IsNumber());
12200   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
12201
12202   // Test the optimized codegen path.
12203   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
12204                      "bar();");
12205   CHECK(value->IsNumber());
12206   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
12207
12208   env->Exit();
12209 }
12210
12211
12212 void SetFunctionEntryHookTest::RunTest() {
12213   // Work in a new isolate throughout.
12214   v8::Isolate::CreateParams create_params;
12215   create_params.entry_hook = EntryHook;
12216   create_params.code_event_handler = JitEvent;
12217   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12218   v8::Isolate* isolate = v8::Isolate::New(create_params);
12219
12220   {
12221     v8::Isolate::Scope scope(isolate);
12222
12223     RunLoopInNewEnv(isolate);
12224
12225     // Check the exepected invocation counts.
12226     CHECK_EQ(2, CountInvocations(NULL, "bar"));
12227     CHECK_EQ(200, CountInvocations("bar", "foo"));
12228     CHECK_EQ(200, CountInvocations(NULL, "foo"));
12229
12230     // Verify that we have an entry hook on some specific stubs.
12231     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
12232     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
12233     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
12234   }
12235   isolate->Dispose();
12236
12237   Reset();
12238
12239   // Make sure a second isolate is unaffected by the previous entry hook.
12240   create_params = v8::Isolate::CreateParams();
12241   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12242   isolate = v8::Isolate::New(create_params);
12243   {
12244     v8::Isolate::Scope scope(isolate);
12245
12246     // Reset the entry count to zero and set the entry hook.
12247     RunLoopInNewEnv(isolate);
12248
12249     // We should record no invocations in this isolate.
12250     CHECK_EQ(0, static_cast<int>(invocations_.size()));
12251   }
12252
12253   isolate->Dispose();
12254 }
12255
12256
12257 TEST(SetFunctionEntryHook) {
12258   // FunctionEntryHook does not work well with experimental natives.
12259   // Experimental natives are compiled during snapshot deserialization.
12260   // This test breaks because InstallGetter (function from snapshot that
12261   // only gets called from experimental natives) is compiled with entry hooks.
12262   i::FLAG_allow_natives_syntax = true;
12263   i::FLAG_use_inlining = false;
12264
12265   SetFunctionEntryHookTest test;
12266   test.RunTest();
12267 }
12268
12269
12270 static i::HashMap* code_map = NULL;
12271 static i::HashMap* jitcode_line_info = NULL;
12272 static int saw_bar = 0;
12273 static int move_events = 0;
12274
12275
12276 static bool FunctionNameIs(const char* expected,
12277                            const v8::JitCodeEvent* event) {
12278   // Log lines for functions are of the general form:
12279   // "LazyCompile:<type><function_name>", where the type is one of
12280   // "*", "~" or "".
12281   static const char kPreamble[] = "LazyCompile:";
12282   static size_t kPreambleLen = sizeof(kPreamble) - 1;
12283
12284   if (event->name.len < sizeof(kPreamble) - 1 ||
12285       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
12286     return false;
12287   }
12288
12289   const char* tail = event->name.str + kPreambleLen;
12290   size_t tail_len = event->name.len - kPreambleLen;
12291   size_t expected_len = strlen(expected);
12292   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
12293     --tail_len;
12294     ++tail;
12295   }
12296
12297   // Check for tails like 'bar :1'.
12298   if (tail_len > expected_len + 2 &&
12299       tail[expected_len] == ' ' &&
12300       tail[expected_len + 1] == ':' &&
12301       tail[expected_len + 2] &&
12302       !strncmp(tail, expected, expected_len)) {
12303     return true;
12304   }
12305
12306   if (tail_len != expected_len)
12307     return false;
12308
12309   return strncmp(tail, expected, expected_len) == 0;
12310 }
12311
12312
12313 static void event_handler(const v8::JitCodeEvent* event) {
12314   CHECK(event != NULL);
12315   CHECK(code_map != NULL);
12316   CHECK(jitcode_line_info != NULL);
12317
12318   class DummyJitCodeLineInfo {
12319   };
12320
12321   switch (event->type) {
12322     case v8::JitCodeEvent::CODE_ADDED: {
12323         CHECK(event->code_start != NULL);
12324         CHECK_NE(0, static_cast<int>(event->code_len));
12325         CHECK(event->name.str != NULL);
12326         i::HashMap::Entry* entry = code_map->LookupOrInsert(
12327             event->code_start, i::ComputePointerHash(event->code_start));
12328         entry->value = reinterpret_cast<void*>(event->code_len);
12329
12330         if (FunctionNameIs("bar", event)) {
12331           ++saw_bar;
12332         }
12333       }
12334       break;
12335
12336     case v8::JitCodeEvent::CODE_MOVED: {
12337         uint32_t hash = i::ComputePointerHash(event->code_start);
12338         // We would like to never see code move that we haven't seen before,
12339         // but the code creation event does not happen until the line endings
12340         // have been calculated (this is so that we can report the line in the
12341         // script at which the function source is found, see
12342         // Compiler::RecordFunctionCompilation) and the line endings
12343         // calculations can cause a GC, which can move the newly created code
12344         // before its existence can be logged.
12345         i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
12346         if (entry != NULL) {
12347           ++move_events;
12348
12349           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
12350           code_map->Remove(event->code_start, hash);
12351
12352           entry = code_map->LookupOrInsert(
12353               event->new_code_start,
12354               i::ComputePointerHash(event->new_code_start));
12355           entry->value = reinterpret_cast<void*>(event->code_len);
12356         }
12357       }
12358       break;
12359
12360     case v8::JitCodeEvent::CODE_REMOVED:
12361       // Object/code removal events are currently not dispatched from the GC.
12362       CHECK(false);
12363       break;
12364
12365     // For CODE_START_LINE_INFO_RECORDING event, we will create one
12366     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
12367     // record it in jitcode_line_info.
12368     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
12369         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
12370         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
12371         temp_event->user_data = line_info;
12372         i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
12373             line_info, i::ComputePointerHash(line_info));
12374         entry->value = reinterpret_cast<void*>(line_info);
12375       }
12376       break;
12377     // For these two events, we will check whether the event->user_data
12378     // data structure is created before during CODE_START_LINE_INFO_RECORDING
12379     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
12380     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
12381         CHECK(event->user_data != NULL);
12382         uint32_t hash = i::ComputePointerHash(event->user_data);
12383         i::HashMap::Entry* entry =
12384             jitcode_line_info->Lookup(event->user_data, hash);
12385         CHECK(entry != NULL);
12386         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
12387       }
12388       break;
12389
12390     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
12391         CHECK(event->user_data != NULL);
12392         uint32_t hash = i::ComputePointerHash(event->user_data);
12393         i::HashMap::Entry* entry =
12394             jitcode_line_info->Lookup(event->user_data, hash);
12395         CHECK(entry != NULL);
12396       }
12397       break;
12398
12399     default:
12400       // Impossible event.
12401       CHECK(false);
12402       break;
12403   }
12404 }
12405
12406
12407 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
12408   i::FLAG_stress_compaction = true;
12409   i::FLAG_incremental_marking = false;
12410   if (i::FLAG_never_compact) return;
12411   const char* script =
12412       "function bar() {"
12413       "  var sum = 0;"
12414       "  for (i = 0; i < 10; ++i)"
12415       "    sum = foo(i);"
12416       "  return sum;"
12417       "}"
12418       "function foo(i) { return i; };"
12419       "bar();";
12420
12421   // Run this test in a new isolate to make sure we don't
12422   // have remnants of state from other code.
12423   v8::Isolate::CreateParams create_params;
12424   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12425   v8::Isolate* isolate = v8::Isolate::New(create_params);
12426   isolate->Enter();
12427   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
12428   i::Heap* heap = i_isolate->heap();
12429
12430   // Start with a clean slate.
12431   heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
12432
12433   {
12434     v8::HandleScope scope(isolate);
12435     i::HashMap code(MatchPointers);
12436     code_map = &code;
12437
12438     i::HashMap lineinfo(MatchPointers);
12439     jitcode_line_info = &lineinfo;
12440
12441     saw_bar = 0;
12442     move_events = 0;
12443
12444     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
12445
12446     // Generate new code objects sparsely distributed across several
12447     // different fragmented code-space pages.
12448     const int kIterations = 10;
12449     for (int i = 0; i < kIterations; ++i) {
12450       LocalContext env(isolate);
12451       i::AlwaysAllocateScope always_allocate(i_isolate);
12452       SimulateFullSpace(heap->code_space());
12453       CompileRun(script);
12454
12455       // Keep a strong reference to the code object in the handle scope.
12456       i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
12457           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
12458       i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
12459           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
12460
12461       // Clear the compilation cache to get more wastage.
12462       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
12463     }
12464
12465     // Force code movement.
12466     heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
12467
12468     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
12469
12470     CHECK_LE(kIterations, saw_bar);
12471     CHECK_LT(0, move_events);
12472
12473     code_map = NULL;
12474     jitcode_line_info = NULL;
12475   }
12476
12477   isolate->Exit();
12478   isolate->Dispose();
12479
12480   // Do this in a new isolate.
12481   isolate = v8::Isolate::New(create_params);
12482   isolate->Enter();
12483
12484   // Verify that we get callbacks for existing code objects when we
12485   // request enumeration of existing code.
12486   {
12487     v8::HandleScope scope(isolate);
12488     LocalContext env(isolate);
12489     CompileRun(script);
12490
12491     // Now get code through initial iteration.
12492     i::HashMap code(MatchPointers);
12493     code_map = &code;
12494
12495     i::HashMap lineinfo(MatchPointers);
12496     jitcode_line_info = &lineinfo;
12497
12498     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
12499                                     event_handler);
12500     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
12501
12502     jitcode_line_info = NULL;
12503     // We expect that we got some events. Note that if we could get code removal
12504     // notifications, we could compare two collections, one created by listening
12505     // from the time of creation of an isolate, and the other by subscribing
12506     // with EnumExisting.
12507     CHECK_LT(0u, code.occupancy());
12508
12509     code_map = NULL;
12510   }
12511
12512   isolate->Exit();
12513   isolate->Dispose();
12514 }
12515
12516
12517 THREADED_TEST(ExternalAllocatedMemory) {
12518   v8::Isolate* isolate = CcTest::isolate();
12519   v8::HandleScope outer(isolate);
12520   v8::Local<Context> env(Context::New(isolate));
12521   CHECK(!env.IsEmpty());
12522   const int64_t kSize = 1024*1024;
12523   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
12524   CHECK_EQ(baseline + kSize,
12525            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
12526   CHECK_EQ(baseline,
12527            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
12528   const int64_t kTriggerGCSize =
12529       v8::internal::Internals::kExternalAllocationLimit + 1;
12530   CHECK_EQ(baseline + kTriggerGCSize,
12531            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
12532   CHECK_EQ(baseline,
12533            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
12534 }
12535
12536
12537 // Regression test for issue 54, object templates with internal fields
12538 // but no accessors or interceptors did not get their internal field
12539 // count set on instances.
12540 THREADED_TEST(Regress54) {
12541   LocalContext context;
12542   v8::Isolate* isolate = context->GetIsolate();
12543   v8::HandleScope outer(isolate);
12544   static v8::Persistent<v8::ObjectTemplate> templ;
12545   if (templ.IsEmpty()) {
12546     v8::EscapableHandleScope inner(isolate);
12547     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
12548     local->SetInternalFieldCount(1);
12549     templ.Reset(isolate, inner.Escape(local));
12550   }
12551   v8::Handle<v8::Object> result =
12552       v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
12553   CHECK_EQ(1, result->InternalFieldCount());
12554 }
12555
12556
12557 // If part of the threaded tests, this test makes ThreadingTest fail
12558 // on mac.
12559 TEST(CatchStackOverflow) {
12560   LocalContext context;
12561   v8::HandleScope scope(context->GetIsolate());
12562   v8::TryCatch try_catch(context->GetIsolate());
12563   v8::Handle<v8::Value> result = CompileRun(
12564     "function f() {"
12565     "  return f();"
12566     "}"
12567     ""
12568     "f();");
12569   CHECK(result.IsEmpty());
12570 }
12571
12572
12573 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
12574                                     const char* resource_name,
12575                                     int line_offset) {
12576   v8::HandleScope scope(CcTest::isolate());
12577   v8::TryCatch try_catch(CcTest::isolate());
12578   v8::Handle<v8::Value> result = script->Run();
12579   CHECK(result.IsEmpty());
12580   CHECK(try_catch.HasCaught());
12581   v8::Handle<v8::Message> message = try_catch.Message();
12582   CHECK(!message.IsEmpty());
12583   CHECK_EQ(10 + line_offset, message->GetLineNumber());
12584   CHECK_EQ(91, message->GetStartPosition());
12585   CHECK_EQ(92, message->GetEndPosition());
12586   CHECK_EQ(2, message->GetStartColumn());
12587   CHECK_EQ(3, message->GetEndColumn());
12588   v8::String::Utf8Value line(message->GetSourceLine());
12589   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
12590   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
12591   CHECK_EQ(0, strcmp(resource_name, *name));
12592 }
12593
12594
12595 THREADED_TEST(TryCatchSourceInfo) {
12596   LocalContext context;
12597   v8::HandleScope scope(context->GetIsolate());
12598   v8::Local<v8::String> source = v8_str(
12599       "function Foo() {\n"
12600       "  return Bar();\n"
12601       "}\n"
12602       "\n"
12603       "function Bar() {\n"
12604       "  return Baz();\n"
12605       "}\n"
12606       "\n"
12607       "function Baz() {\n"
12608       "  throw 'nirk';\n"
12609       "}\n"
12610       "\n"
12611       "Foo();\n");
12612
12613   const char* resource_name;
12614   v8::Handle<v8::Script> script;
12615   resource_name = "test.js";
12616   script = CompileWithOrigin(source, resource_name);
12617   CheckTryCatchSourceInfo(script, resource_name, 0);
12618
12619   resource_name = "test1.js";
12620   v8::ScriptOrigin origin1(
12621       v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
12622   script = v8::Script::Compile(source, &origin1);
12623   CheckTryCatchSourceInfo(script, resource_name, 0);
12624
12625   resource_name = "test2.js";
12626   v8::ScriptOrigin origin2(
12627       v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
12628       v8::Integer::New(context->GetIsolate(), 7));
12629   script = v8::Script::Compile(source, &origin2);
12630   CheckTryCatchSourceInfo(script, resource_name, 7);
12631 }
12632
12633
12634 THREADED_TEST(TryCatchSourceInfoForEOSError) {
12635   LocalContext context;
12636   v8::HandleScope scope(context->GetIsolate());
12637   v8::TryCatch try_catch(context->GetIsolate());
12638   v8::Script::Compile(v8_str("!\n"));
12639   CHECK(try_catch.HasCaught());
12640   v8::Handle<v8::Message> message = try_catch.Message();
12641   CHECK_EQ(1, message->GetLineNumber());
12642   CHECK_EQ(0, message->GetStartColumn());
12643 }
12644
12645
12646 THREADED_TEST(CompilationCache) {
12647   LocalContext context;
12648   v8::HandleScope scope(context->GetIsolate());
12649   v8::Handle<v8::String> source0 =
12650       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
12651   v8::Handle<v8::String> source1 =
12652       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
12653   v8::Handle<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
12654   v8::Handle<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
12655   v8::Handle<v8::Script> script2 =
12656       v8::Script::Compile(source0);  // different origin
12657   CHECK_EQ(1234, script0->Run()->Int32Value());
12658   CHECK_EQ(1234, script1->Run()->Int32Value());
12659   CHECK_EQ(1234, script2->Run()->Int32Value());
12660 }
12661
12662
12663 static void FunctionNameCallback(
12664     const v8::FunctionCallbackInfo<v8::Value>& args) {
12665   ApiTestFuzzer::Fuzz();
12666   args.GetReturnValue().Set(v8_num(42));
12667 }
12668
12669
12670 THREADED_TEST(CallbackFunctionName) {
12671   LocalContext context;
12672   v8::Isolate* isolate = context->GetIsolate();
12673   v8::HandleScope scope(isolate);
12674   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
12675   t->Set(v8_str("asdf"),
12676          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
12677   context->Global()->Set(v8_str("obj"), t->NewInstance());
12678   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
12679   CHECK(value->IsString());
12680   v8::String::Utf8Value name(value);
12681   CHECK_EQ(0, strcmp("asdf", *name));
12682 }
12683
12684
12685 THREADED_TEST(DateAccess) {
12686   LocalContext context;
12687   v8::HandleScope scope(context->GetIsolate());
12688   v8::Handle<v8::Value> date =
12689       v8::Date::New(context->GetIsolate(), 1224744689038.0);
12690   CHECK(date->IsDate());
12691   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
12692 }
12693
12694
12695 void CheckProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
12696                      unsigned elmc, const char* elmv[]) {
12697   v8::Handle<v8::Object> obj = val.As<v8::Object>();
12698   v8::Handle<v8::Array> props = obj->GetPropertyNames();
12699   CHECK_EQ(elmc, props->Length());
12700   for (unsigned i = 0; i < elmc; i++) {
12701     v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
12702     CHECK_EQ(0, strcmp(elmv[i], *elm));
12703   }
12704 }
12705
12706
12707 void CheckOwnProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
12708                         unsigned elmc, const char* elmv[]) {
12709   v8::Handle<v8::Object> obj = val.As<v8::Object>();
12710   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
12711   CHECK_EQ(elmc, props->Length());
12712   for (unsigned i = 0; i < elmc; i++) {
12713     v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
12714     CHECK_EQ(0, strcmp(elmv[i], *elm));
12715   }
12716 }
12717
12718
12719 THREADED_TEST(PropertyEnumeration) {
12720   LocalContext context;
12721   v8::Isolate* isolate = context->GetIsolate();
12722   v8::HandleScope scope(isolate);
12723   v8::Handle<v8::Value> obj = CompileRun(
12724       "var result = [];"
12725       "result[0] = {};"
12726       "result[1] = {a: 1, b: 2};"
12727       "result[2] = [1, 2, 3];"
12728       "var proto = {x: 1, y: 2, z: 3};"
12729       "var x = { __proto__: proto, w: 0, z: 1 };"
12730       "result[3] = x;"
12731       "result;");
12732   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12733   CHECK_EQ(4u, elms->Length());
12734   int elmc0 = 0;
12735   const char** elmv0 = NULL;
12736   CheckProperties(
12737       isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12738   CheckOwnProperties(
12739       isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12740   int elmc1 = 2;
12741   const char* elmv1[] = {"a", "b"};
12742   CheckProperties(
12743       isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
12744   CheckOwnProperties(
12745       isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
12746   int elmc2 = 3;
12747   const char* elmv2[] = {"0", "1", "2"};
12748   CheckProperties(
12749       isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
12750   CheckOwnProperties(
12751       isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
12752   int elmc3 = 4;
12753   const char* elmv3[] = {"w", "z", "x", "y"};
12754   CheckProperties(
12755       isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
12756   int elmc4 = 2;
12757   const char* elmv4[] = {"w", "z"};
12758   CheckOwnProperties(
12759       isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
12760 }
12761
12762
12763 THREADED_TEST(PropertyEnumeration2) {
12764   LocalContext context;
12765   v8::Isolate* isolate = context->GetIsolate();
12766   v8::HandleScope scope(isolate);
12767   v8::Handle<v8::Value> obj = CompileRun(
12768       "var result = [];"
12769       "result[0] = {};"
12770       "result[1] = {a: 1, b: 2};"
12771       "result[2] = [1, 2, 3];"
12772       "var proto = {x: 1, y: 2, z: 3};"
12773       "var x = { __proto__: proto, w: 0, z: 1 };"
12774       "result[3] = x;"
12775       "result;");
12776   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12777   CHECK_EQ(4u, elms->Length());
12778   int elmc0 = 0;
12779   const char** elmv0 = NULL;
12780   CheckProperties(isolate,
12781                   elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12782
12783   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
12784   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
12785   CHECK_EQ(0u, props->Length());
12786   for (uint32_t i = 0; i < props->Length(); i++) {
12787     printf("p[%u]\n", i);
12788   }
12789 }
12790
12791
12792 THREADED_TEST(AccessChecksReenabledCorrectly) {
12793   LocalContext context;
12794   v8::Isolate* isolate = context->GetIsolate();
12795   v8::HandleScope scope(isolate);
12796   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
12797   templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
12798   templ->Set(v8_str("a"), v8_str("a"));
12799   // Add more than 8 (see kMaxFastProperties) properties
12800   // so that the constructor will force copying map.
12801   // Cannot sprintf, gcc complains unsafety.
12802   char buf[4];
12803   for (char i = '0'; i <= '9' ; i++) {
12804     buf[0] = i;
12805     for (char j = '0'; j <= '9'; j++) {
12806       buf[1] = j;
12807       for (char k = '0'; k <= '9'; k++) {
12808         buf[2] = k;
12809         buf[3] = 0;
12810         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
12811       }
12812     }
12813   }
12814
12815   Local<v8::Object> instance_1 = templ->NewInstance();
12816   context->Global()->Set(v8_str("obj_1"), instance_1);
12817
12818   Local<Value> value_1 = CompileRun("obj_1.a");
12819   CHECK(value_1.IsEmpty());
12820
12821   Local<v8::Object> instance_2 = templ->NewInstance();
12822   context->Global()->Set(v8_str("obj_2"), instance_2);
12823
12824   Local<Value> value_2 = CompileRun("obj_2.a");
12825   CHECK(value_2.IsEmpty());
12826 }
12827
12828
12829 // Tests that ScriptData can be serialized and deserialized.
12830 TEST(PreCompileSerialization) {
12831   v8::V8::Initialize();
12832   LocalContext env;
12833   v8::Isolate* isolate = env->GetIsolate();
12834   HandleScope handle_scope(isolate);
12835
12836   i::FLAG_min_preparse_length = 0;
12837   const char* script = "function foo(a) { return a+1; }";
12838   v8::ScriptCompiler::Source source(v8_str(script));
12839   v8::ScriptCompiler::Compile(isolate, &source,
12840                               v8::ScriptCompiler::kProduceParserCache);
12841   // Serialize.
12842   const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
12843   i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
12844   i::MemCopy(serialized_data, cd->data, cd->length);
12845
12846   // Deserialize.
12847   i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
12848
12849   // Verify that the original is the same as the deserialized.
12850   CHECK_EQ(cd->length, deserialized->length());
12851   CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
12852
12853   delete deserialized;
12854   i::DeleteArray(serialized_data);
12855 }
12856
12857
12858 // This tests that we do not allow dictionary load/call inline caches
12859 // to use functions that have not yet been compiled.  The potential
12860 // problem of loading a function that has not yet been compiled can
12861 // arise because we share code between contexts via the compilation
12862 // cache.
12863 THREADED_TEST(DictionaryICLoadedFunction) {
12864   v8::HandleScope scope(CcTest::isolate());
12865   // Test LoadIC.
12866   for (int i = 0; i < 2; i++) {
12867     LocalContext context;
12868     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
12869     context->Global()->Delete(v8_str("tmp"));
12870     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
12871   }
12872   // Test CallIC.
12873   for (int i = 0; i < 2; i++) {
12874     LocalContext context;
12875     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
12876     context->Global()->Delete(v8_str("tmp"));
12877     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
12878   }
12879 }
12880
12881
12882 // Test that cross-context new calls use the context of the callee to
12883 // create the new JavaScript object.
12884 THREADED_TEST(CrossContextNew) {
12885   v8::Isolate* isolate = CcTest::isolate();
12886   v8::HandleScope scope(isolate);
12887   v8::Local<Context> context0 = Context::New(isolate);
12888   v8::Local<Context> context1 = Context::New(isolate);
12889
12890   // Allow cross-domain access.
12891   Local<String> token = v8_str("<security token>");
12892   context0->SetSecurityToken(token);
12893   context1->SetSecurityToken(token);
12894
12895   // Set an 'x' property on the Object prototype and define a
12896   // constructor function in context0.
12897   context0->Enter();
12898   CompileRun("Object.prototype.x = 42; function C() {};");
12899   context0->Exit();
12900
12901   // Call the constructor function from context0 and check that the
12902   // result has the 'x' property.
12903   context1->Enter();
12904   context1->Global()->Set(v8_str("other"), context0->Global());
12905   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
12906   CHECK(value->IsInt32());
12907   CHECK_EQ(42, value->Int32Value());
12908   context1->Exit();
12909 }
12910
12911
12912 // Verify that we can clone an object
12913 TEST(ObjectClone) {
12914   LocalContext env;
12915   v8::Isolate* isolate = env->GetIsolate();
12916   v8::HandleScope scope(isolate);
12917
12918   const char* sample =
12919     "var rv = {};"      \
12920     "rv.alpha = 'hello';" \
12921     "rv.beta = 123;"     \
12922     "rv;";
12923
12924   // Create an object, verify basics.
12925   Local<Value> val = CompileRun(sample);
12926   CHECK(val->IsObject());
12927   Local<v8::Object> obj = val.As<v8::Object>();
12928   obj->Set(v8_str("gamma"), v8_str("cloneme"));
12929
12930   CHECK(v8_str("hello")->Equals(obj->Get(v8_str("alpha"))));
12931   CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
12932   CHECK(v8_str("cloneme")->Equals(obj->Get(v8_str("gamma"))));
12933
12934   // Clone it.
12935   Local<v8::Object> clone = obj->Clone();
12936   CHECK(v8_str("hello")->Equals(clone->Get(v8_str("alpha"))));
12937   CHECK(v8::Integer::New(isolate, 123)->Equals(clone->Get(v8_str("beta"))));
12938   CHECK(v8_str("cloneme")->Equals(clone->Get(v8_str("gamma"))));
12939
12940   // Set a property on the clone, verify each object.
12941   clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
12942   CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
12943   CHECK(v8::Integer::New(isolate, 456)->Equals(clone->Get(v8_str("beta"))));
12944 }
12945
12946
12947 class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
12948  public:
12949   explicit OneByteVectorResource(i::Vector<const char> vector)
12950       : data_(vector) {}
12951   virtual ~OneByteVectorResource() {}
12952   virtual size_t length() const { return data_.length(); }
12953   virtual const char* data() const { return data_.start(); }
12954  private:
12955   i::Vector<const char> data_;
12956 };
12957
12958
12959 class UC16VectorResource : public v8::String::ExternalStringResource {
12960  public:
12961   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
12962       : data_(vector) {}
12963   virtual ~UC16VectorResource() {}
12964   virtual size_t length() const { return data_.length(); }
12965   virtual const i::uc16* data() const { return data_.start(); }
12966  private:
12967   i::Vector<const i::uc16> data_;
12968 };
12969
12970
12971 static void MorphAString(i::String* string,
12972                          OneByteVectorResource* one_byte_resource,
12973                          UC16VectorResource* uc16_resource) {
12974   CHECK(i::StringShape(string).IsExternal());
12975   if (string->IsOneByteRepresentation()) {
12976     // Check old map is not internalized or long.
12977     CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
12978     // Morph external string to be TwoByte string.
12979     string->set_map(CcTest::heap()->external_string_map());
12980     i::ExternalTwoByteString* morphed =
12981          i::ExternalTwoByteString::cast(string);
12982     morphed->set_resource(uc16_resource);
12983   } else {
12984     // Check old map is not internalized or long.
12985     CHECK(string->map() == CcTest::heap()->external_string_map());
12986     // Morph external string to be one-byte string.
12987     string->set_map(CcTest::heap()->external_one_byte_string_map());
12988     i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
12989     morphed->set_resource(one_byte_resource);
12990   }
12991 }
12992
12993
12994 // Test that we can still flatten a string if the components it is built up
12995 // from have been turned into 16 bit strings in the mean time.
12996 THREADED_TEST(MorphCompositeStringTest) {
12997   char utf_buffer[129];
12998   const char* c_string = "Now is the time for all good men"
12999                          " to come to the aid of the party";
13000   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
13001   {
13002     LocalContext env;
13003     i::Factory* factory = CcTest::i_isolate()->factory();
13004     v8::HandleScope scope(env->GetIsolate());
13005     OneByteVectorResource one_byte_resource(
13006         i::Vector<const char>(c_string, i::StrLength(c_string)));
13007     UC16VectorResource uc16_resource(
13008         i::Vector<const uint16_t>(two_byte_string,
13009                                   i::StrLength(c_string)));
13010
13011     Local<String> lhs(
13012         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
13013                                         &one_byte_resource).ToHandleChecked()));
13014     Local<String> rhs(
13015         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
13016                                         &one_byte_resource).ToHandleChecked()));
13017
13018     env->Global()->Set(v8_str("lhs"), lhs);
13019     env->Global()->Set(v8_str("rhs"), rhs);
13020
13021     CompileRun(
13022         "var cons = lhs + rhs;"
13023         "var slice = lhs.substring(1, lhs.length - 1);"
13024         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
13025
13026     CHECK(lhs->IsOneByte());
13027     CHECK(rhs->IsOneByte());
13028
13029     MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
13030                  &uc16_resource);
13031     MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
13032                  &uc16_resource);
13033
13034     // This should UTF-8 without flattening, since everything is ASCII.
13035     Handle<String> cons = v8_compile("cons")->Run().As<String>();
13036     CHECK_EQ(128, cons->Utf8Length());
13037     int nchars = -1;
13038     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
13039     CHECK_EQ(128, nchars);
13040     CHECK_EQ(0, strcmp(
13041         utf_buffer,
13042         "Now is the time for all good men to come to the aid of the party"
13043         "Now is the time for all good men to come to the aid of the party"));
13044
13045     // Now do some stuff to make sure the strings are flattened, etc.
13046     CompileRun(
13047         "/[^a-z]/.test(cons);"
13048         "/[^a-z]/.test(slice);"
13049         "/[^a-z]/.test(slice_on_cons);");
13050     const char* expected_cons =
13051         "Now is the time for all good men to come to the aid of the party"
13052         "Now is the time for all good men to come to the aid of the party";
13053     const char* expected_slice =
13054         "ow is the time for all good men to come to the aid of the part";
13055     const char* expected_slice_on_cons =
13056         "ow is the time for all good men to come to the aid of the party"
13057         "Now is the time for all good men to come to the aid of the part";
13058     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_cons)
13059               ->Equals(env->Global()->Get(v8_str("cons"))));
13060     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice)
13061               ->Equals(env->Global()->Get(v8_str("slice"))));
13062     CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons)
13063               ->Equals(env->Global()->Get(v8_str("slice_on_cons"))));
13064   }
13065   i::DeleteArray(two_byte_string);
13066 }
13067
13068
13069 TEST(CompileExternalTwoByteSource) {
13070   LocalContext context;
13071   v8::HandleScope scope(context->GetIsolate());
13072
13073   // This is a very short list of sources, which currently is to check for a
13074   // regression caused by r2703.
13075   const char* one_byte_sources[] = {
13076       "0.5",
13077       "-0.5",   // This mainly testes PushBack in the Scanner.
13078       "--0.5",  // This mainly testes PushBack in the Scanner.
13079       NULL};
13080
13081   // Compile the sources as external two byte strings.
13082   for (int i = 0; one_byte_sources[i] != NULL; i++) {
13083     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
13084     TestResource* uc16_resource = new TestResource(two_byte_string);
13085     v8::Local<v8::String> source =
13086         v8::String::NewExternal(context->GetIsolate(), uc16_resource);
13087     v8::Script::Compile(source);
13088   }
13089 }
13090
13091
13092 #ifndef V8_INTERPRETED_REGEXP
13093
13094 struct RegExpInterruptionData {
13095   v8::base::Atomic32 loop_count;
13096   UC16VectorResource* string_resource;
13097   v8::Persistent<v8::String> string;
13098 } regexp_interruption_data;
13099
13100
13101 class RegExpInterruptionThread : public v8::base::Thread {
13102  public:
13103   explicit RegExpInterruptionThread(v8::Isolate* isolate)
13104       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
13105
13106   virtual void Run() {
13107     for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
13108          v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
13109          v8::base::NoBarrier_AtomicIncrement(
13110              &regexp_interruption_data.loop_count, 1)) {
13111       // Wait a bit before requesting GC.
13112       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
13113       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
13114     }
13115     // Wait a bit before terminating.
13116     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
13117     v8::V8::TerminateExecution(isolate_);
13118   }
13119
13120  private:
13121   v8::Isolate* isolate_;
13122 };
13123
13124
13125 void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
13126   if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
13127     return;
13128   }
13129   v8::HandleScope scope(CcTest::isolate());
13130   v8::Local<v8::String> string = v8::Local<v8::String>::New(
13131       CcTest::isolate(), regexp_interruption_data.string);
13132   string->MakeExternal(regexp_interruption_data.string_resource);
13133 }
13134
13135
13136 // Test that RegExp execution can be interrupted.  Specifically, we test
13137 // * interrupting with GC
13138 // * turn the subject string from one-byte internal to two-byte external string
13139 // * force termination
13140 TEST(RegExpInterruption) {
13141   v8::HandleScope scope(CcTest::isolate());
13142   LocalContext env;
13143
13144   RegExpInterruptionThread timeout_thread(CcTest::isolate());
13145
13146   v8::V8::AddGCPrologueCallback(RunBeforeGC);
13147   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
13148   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
13149   v8::Local<v8::String> string = v8_str(one_byte_content);
13150
13151   CcTest::global()->Set(v8_str("a"), string);
13152   regexp_interruption_data.string.Reset(CcTest::isolate(), string);
13153   regexp_interruption_data.string_resource = new UC16VectorResource(
13154       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
13155
13156   v8::TryCatch try_catch(CcTest::isolate());
13157   timeout_thread.Start();
13158
13159   CompileRun("/((a*)*)*b/.exec(a)");
13160   CHECK(try_catch.HasTerminated());
13161
13162   timeout_thread.Join();
13163
13164   regexp_interruption_data.string.Reset();
13165   i::DeleteArray(uc16_content);
13166 }
13167
13168 #endif  // V8_INTERPRETED_REGEXP
13169
13170
13171 // Test that we cannot set a property on the global object if there
13172 // is a read-only property in the prototype chain.
13173 TEST(ReadOnlyPropertyInGlobalProto) {
13174   v8::Isolate* isolate = CcTest::isolate();
13175   v8::HandleScope scope(isolate);
13176   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13177   LocalContext context(0, templ);
13178   v8::Handle<v8::Object> global = context->Global();
13179   v8::Handle<v8::Object> global_proto =
13180       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
13181   global_proto->ForceSet(v8_str("x"), v8::Integer::New(isolate, 0),
13182                          v8::ReadOnly);
13183   global_proto->ForceSet(v8_str("y"), v8::Integer::New(isolate, 0),
13184                          v8::ReadOnly);
13185   // Check without 'eval' or 'with'.
13186   v8::Handle<v8::Value> res =
13187       CompileRun("function f() { x = 42; return x; }; f()");
13188   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13189   // Check with 'eval'.
13190   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
13191   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13192   // Check with 'with'.
13193   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
13194   CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13195 }
13196
13197 static int force_set_set_count = 0;
13198 static int force_set_get_count = 0;
13199 bool pass_on_get = false;
13200
13201 static void ForceSetGetter(v8::Local<v8::String> name,
13202                            const v8::PropertyCallbackInfo<v8::Value>& info) {
13203   force_set_get_count++;
13204   if (pass_on_get) {
13205     return;
13206   }
13207   info.GetReturnValue().Set(3);
13208 }
13209
13210 static void ForceSetSetter(v8::Local<v8::String> name,
13211                            v8::Local<v8::Value> value,
13212                            const v8::PropertyCallbackInfo<void>& info) {
13213   force_set_set_count++;
13214 }
13215
13216 static void ForceSetInterceptGetter(
13217     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
13218   CHECK(name->IsString());
13219   ForceSetGetter(Local<String>::Cast(name), info);
13220 }
13221
13222 static void ForceSetInterceptSetter(
13223     v8::Local<v8::Name> name, v8::Local<v8::Value> value,
13224     const v8::PropertyCallbackInfo<v8::Value>& info) {
13225   force_set_set_count++;
13226   info.GetReturnValue().SetUndefined();
13227 }
13228
13229
13230 TEST(ForceSet) {
13231   force_set_get_count = 0;
13232   force_set_set_count = 0;
13233   pass_on_get = false;
13234
13235   v8::Isolate* isolate = CcTest::isolate();
13236   v8::HandleScope scope(isolate);
13237   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13238   v8::Handle<v8::String> access_property =
13239       v8::String::NewFromUtf8(isolate, "a");
13240   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
13241   LocalContext context(NULL, templ);
13242   v8::Handle<v8::Object> global = context->Global();
13243
13244   // Ordinary properties
13245   v8::Handle<v8::String> simple_property =
13246       v8::String::NewFromUtf8(isolate, "p");
13247   global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
13248   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13249   // This should fail because the property is read-only
13250   global->Set(simple_property, v8::Int32::New(isolate, 5));
13251   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13252   // This should succeed even though the property is read-only
13253   global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
13254   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
13255
13256   // Accessors
13257   CHECK_EQ(0, force_set_set_count);
13258   CHECK_EQ(0, force_set_get_count);
13259   CHECK_EQ(3, global->Get(access_property)->Int32Value());
13260   // CHECK_EQ the property shouldn't override it, just call the setter
13261   // which in this case does nothing.
13262   global->Set(access_property, v8::Int32::New(isolate, 7));
13263   CHECK_EQ(3, global->Get(access_property)->Int32Value());
13264   CHECK_EQ(1, force_set_set_count);
13265   CHECK_EQ(2, force_set_get_count);
13266   // ForceSet doesn't call the accessors for now.
13267   // TODO(verwaest): Update once blink doesn't rely on ForceSet to delete api
13268   // accessors.
13269   global->ForceSet(access_property, v8::Int32::New(isolate, 8));
13270   CHECK_EQ(8, global->Get(access_property)->Int32Value());
13271   CHECK_EQ(1, force_set_set_count);
13272   CHECK_EQ(2, force_set_get_count);
13273 }
13274
13275
13276 TEST(ForceSetWithInterceptor) {
13277   v8::Isolate* isolate = CcTest::isolate();
13278   v8::HandleScope scope(isolate);
13279   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13280   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
13281       ForceSetInterceptGetter, ForceSetInterceptSetter));
13282   pass_on_get = true;
13283   LocalContext context(NULL, templ);
13284   v8::Handle<v8::Object> global = context->Global();
13285
13286   force_set_get_count = 0;
13287   force_set_set_count = 0;
13288   pass_on_get = false;
13289
13290   v8::Handle<v8::String> some_property =
13291       v8::String::NewFromUtf8(isolate, "a");
13292   CHECK_EQ(0, force_set_set_count);
13293   CHECK_EQ(0, force_set_get_count);
13294   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13295   // Setting the property shouldn't override it, just call the setter
13296   // which in this case does nothing.
13297   global->Set(some_property, v8::Int32::New(isolate, 7));
13298   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13299   CHECK_EQ(1, force_set_set_count);
13300   CHECK_EQ(2, force_set_get_count);
13301   // Getting the property when the interceptor returns an empty handle
13302   // should yield undefined, since the property isn't present on the
13303   // object itself yet.
13304   pass_on_get = true;
13305   CHECK(global->Get(some_property)->IsUndefined());
13306   CHECK_EQ(1, force_set_set_count);
13307   CHECK_EQ(3, force_set_get_count);
13308   // Forcing the property to be set should cause the value to be
13309   // set locally without calling the interceptor.
13310   global->ForceSet(some_property, v8::Int32::New(isolate, 8));
13311   CHECK_EQ(8, global->Get(some_property)->Int32Value());
13312   CHECK_EQ(1, force_set_set_count);
13313   CHECK_EQ(4, force_set_get_count);
13314   // Reenabling the interceptor should cause it to take precedence over
13315   // the property
13316   pass_on_get = false;
13317   CHECK_EQ(3, global->Get(some_property)->Int32Value());
13318   CHECK_EQ(1, force_set_set_count);
13319   CHECK_EQ(5, force_set_get_count);
13320   // The interceptor should also work for other properties
13321   CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
13322                   ->Int32Value());
13323   CHECK_EQ(1, force_set_set_count);
13324   CHECK_EQ(6, force_set_get_count);
13325 }
13326
13327
13328 TEST(CreateDataProperty) {
13329   LocalContext env;
13330   v8::Isolate* isolate = env->GetIsolate();
13331   v8::HandleScope handle_scope(isolate);
13332
13333   CompileRun(
13334       "var a = {};"
13335       "var b = [];"
13336       "Object.defineProperty(a, 'foo', {value: 23});"
13337       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
13338
13339   v8::Local<v8::Object> obj =
13340       v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
13341   v8::Local<v8::Array> arr =
13342       v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
13343   {
13344     // Can't change a non-configurable properties.
13345     v8::TryCatch try_catch(isolate);
13346     CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
13347                                    v8::Integer::New(isolate, 42)).FromJust());
13348     CHECK(!try_catch.HasCaught());
13349     CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
13350                                   v8::Integer::New(isolate, 42)).FromJust());
13351     CHECK(!try_catch.HasCaught());
13352     v8::Local<v8::Value> val =
13353         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
13354     CHECK(val->IsNumber());
13355     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13356   }
13357
13358   {
13359     // Set a regular property.
13360     v8::TryCatch try_catch(isolate);
13361     CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
13362                                   v8::Integer::New(isolate, 42)).FromJust());
13363     CHECK(!try_catch.HasCaught());
13364     v8::Local<v8::Value> val =
13365         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
13366     CHECK(val->IsNumber());
13367     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13368   }
13369
13370   {
13371     // Set an indexed property.
13372     v8::TryCatch try_catch(isolate);
13373     CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
13374                                   v8::Integer::New(isolate, 42)).FromJust());
13375     CHECK(!try_catch.HasCaught());
13376     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
13377     CHECK(val->IsNumber());
13378     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13379   }
13380
13381   {
13382     // Special cases for arrays.
13383     v8::TryCatch try_catch(isolate);
13384     CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
13385                                    v8::Integer::New(isolate, 1)).FromJust());
13386     CHECK(!try_catch.HasCaught());
13387   }
13388   {
13389     // Special cases for arrays: index exceeds the array's length
13390     v8::TryCatch try_catch(isolate);
13391     CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
13392               .FromJust());
13393     CHECK(!try_catch.HasCaught());
13394     CHECK_EQ(2U, arr->Length());
13395     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
13396     CHECK(val->IsNumber());
13397     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
13398
13399     // Set an existing entry.
13400     CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
13401               .FromJust());
13402     CHECK(!try_catch.HasCaught());
13403     val = arr->Get(env.local(), 0).ToLocalChecked();
13404     CHECK(val->IsNumber());
13405     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13406   }
13407
13408   CompileRun("Object.freeze(a);");
13409   {
13410     // Can't change non-extensible objects.
13411     v8::TryCatch try_catch(isolate);
13412     CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
13413                                    v8::Integer::New(isolate, 42)).FromJust());
13414     CHECK(!try_catch.HasCaught());
13415   }
13416
13417   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13418   templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
13419   v8::Local<v8::Object> access_checked =
13420       templ->NewInstance(env.local()).ToLocalChecked();
13421   {
13422     v8::TryCatch try_catch(isolate);
13423     CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
13424                                              v8::Integer::New(isolate, 42))
13425               .IsNothing());
13426     CHECK(try_catch.HasCaught());
13427   }
13428 }
13429
13430
13431 TEST(DefineOwnProperty) {
13432   LocalContext env;
13433   v8::Isolate* isolate = env->GetIsolate();
13434   v8::HandleScope handle_scope(isolate);
13435
13436   CompileRun(
13437       "var a = {};"
13438       "var b = [];"
13439       "Object.defineProperty(a, 'foo', {value: 23});"
13440       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
13441
13442   v8::Local<v8::Object> obj =
13443       v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
13444   v8::Local<v8::Array> arr =
13445       v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
13446   {
13447     // Can't change a non-configurable properties.
13448     v8::TryCatch try_catch(isolate);
13449     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
13450                                   v8::Integer::New(isolate, 42)).FromJust());
13451     CHECK(!try_catch.HasCaught());
13452     CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
13453                                  v8::Integer::New(isolate, 42)).FromJust());
13454     CHECK(!try_catch.HasCaught());
13455     v8::Local<v8::Value> val =
13456         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
13457     CHECK(val->IsNumber());
13458     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13459   }
13460
13461   {
13462     // Set a regular property.
13463     v8::TryCatch try_catch(isolate);
13464     CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
13465                                  v8::Integer::New(isolate, 42)).FromJust());
13466     CHECK(!try_catch.HasCaught());
13467     v8::Local<v8::Value> val =
13468         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
13469     CHECK(val->IsNumber());
13470     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13471   }
13472
13473   {
13474     // Set an indexed property.
13475     v8::TryCatch try_catch(isolate);
13476     CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
13477                                  v8::Integer::New(isolate, 42)).FromJust());
13478     CHECK(!try_catch.HasCaught());
13479     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
13480     CHECK(val->IsNumber());
13481     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13482   }
13483
13484   {
13485     // Special cases for arrays.
13486     v8::TryCatch try_catch(isolate);
13487     CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
13488                                   v8::Integer::New(isolate, 1)).FromJust());
13489     CHECK(!try_catch.HasCaught());
13490   }
13491   {
13492     // Special cases for arrays: index exceeds the array's length
13493     v8::TryCatch try_catch(isolate);
13494     CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
13495                                  v8::Integer::New(isolate, 23)).FromJust());
13496     CHECK(!try_catch.HasCaught());
13497     CHECK_EQ(2U, arr->Length());
13498     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
13499     CHECK(val->IsNumber());
13500     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
13501
13502     // Set an existing entry.
13503     CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
13504                                  v8::Integer::New(isolate, 42)).FromJust());
13505     CHECK(!try_catch.HasCaught());
13506     val = arr->Get(env.local(), 0).ToLocalChecked();
13507     CHECK(val->IsNumber());
13508     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13509   }
13510
13511   {
13512     // Set a non-writable property.
13513     v8::TryCatch try_catch(isolate);
13514     CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
13515                                  v8::Integer::New(isolate, 42),
13516                                  v8::ReadOnly).FromJust());
13517     CHECK(!try_catch.HasCaught());
13518     v8::Local<v8::Value> val =
13519         obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
13520     CHECK(val->IsNumber());
13521     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13522     CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
13523                                     env.local(), v8_str("lala")).FromJust());
13524     CHECK(!try_catch.HasCaught());
13525   }
13526
13527   CompileRun("Object.freeze(a);");
13528   {
13529     // Can't change non-extensible objects.
13530     v8::TryCatch try_catch(isolate);
13531     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
13532                                   v8::Integer::New(isolate, 42)).FromJust());
13533     CHECK(!try_catch.HasCaught());
13534   }
13535
13536   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13537   templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
13538   v8::Local<v8::Object> access_checked =
13539       templ->NewInstance(env.local()).ToLocalChecked();
13540   {
13541     v8::TryCatch try_catch(isolate);
13542     CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
13543                                             v8::Integer::New(isolate, 42))
13544               .IsNothing());
13545     CHECK(try_catch.HasCaught());
13546   }
13547 }
13548
13549
13550 static v8::Local<Context> calling_context0;
13551 static v8::Local<Context> calling_context1;
13552 static v8::Local<Context> calling_context2;
13553
13554
13555 // Check that the call to the callback is initiated in
13556 // calling_context2, the directly calling context is calling_context1
13557 // and the callback itself is in calling_context0.
13558 static void GetCallingContextCallback(
13559     const v8::FunctionCallbackInfo<v8::Value>& args) {
13560   ApiTestFuzzer::Fuzz();
13561   CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
13562   CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
13563   CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
13564   args.GetReturnValue().Set(42);
13565 }
13566
13567
13568 THREADED_TEST(GetCurrentContextWhenNotInContext) {
13569   i::Isolate* isolate = CcTest::i_isolate();
13570   CHECK(isolate != NULL);
13571   CHECK(isolate->context() == NULL);
13572   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
13573   v8::HandleScope scope(v8_isolate);
13574   // The following should not crash, but return an empty handle.
13575   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
13576   CHECK(current.IsEmpty());
13577 }
13578
13579
13580 THREADED_TEST(GetCallingContext) {
13581   v8::Isolate* isolate = CcTest::isolate();
13582   v8::HandleScope scope(isolate);
13583
13584   Local<Context> calling_context0(Context::New(isolate));
13585   Local<Context> calling_context1(Context::New(isolate));
13586   Local<Context> calling_context2(Context::New(isolate));
13587   ::calling_context0 = calling_context0;
13588   ::calling_context1 = calling_context1;
13589   ::calling_context2 = calling_context2;
13590
13591   // Allow cross-domain access.
13592   Local<String> token = v8_str("<security token>");
13593   calling_context0->SetSecurityToken(token);
13594   calling_context1->SetSecurityToken(token);
13595   calling_context2->SetSecurityToken(token);
13596
13597   // Create an object with a C++ callback in context0.
13598   calling_context0->Enter();
13599   Local<v8::FunctionTemplate> callback_templ =
13600       v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
13601   calling_context0->Global()->Set(v8_str("callback"),
13602                                   callback_templ->GetFunction());
13603   calling_context0->Exit();
13604
13605   // Expose context0 in context1 and set up a function that calls the
13606   // callback function.
13607   calling_context1->Enter();
13608   calling_context1->Global()->Set(v8_str("context0"),
13609                                   calling_context0->Global());
13610   CompileRun("function f() { context0.callback() }");
13611   calling_context1->Exit();
13612
13613   // Expose context1 in context2 and call the callback function in
13614   // context0 indirectly through f in context1.
13615   calling_context2->Enter();
13616   calling_context2->Global()->Set(v8_str("context1"),
13617                                   calling_context1->Global());
13618   CompileRun("context1.f()");
13619   calling_context2->Exit();
13620   ::calling_context0.Clear();
13621   ::calling_context1.Clear();
13622   ::calling_context2.Clear();
13623 }
13624
13625
13626 // Check that a variable declaration with no explicit initialization
13627 // value does shadow an existing property in the prototype chain.
13628 THREADED_TEST(InitGlobalVarInProtoChain) {
13629   LocalContext context;
13630   v8::HandleScope scope(context->GetIsolate());
13631   // Introduce a variable in the prototype chain.
13632   CompileRun("__proto__.x = 42");
13633   v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
13634   CHECK(!result->IsUndefined());
13635   CHECK_EQ(43, result->Int32Value());
13636 }
13637
13638
13639 // Regression test for issue 398.
13640 // If a function is added to an object, creating a constant function
13641 // field, and the result is cloned, replacing the constant function on the
13642 // original should not affect the clone.
13643 // See http://code.google.com/p/v8/issues/detail?id=398
13644 THREADED_TEST(ReplaceConstantFunction) {
13645   LocalContext context;
13646   v8::Isolate* isolate = context->GetIsolate();
13647   v8::HandleScope scope(isolate);
13648   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
13649   v8::Handle<v8::FunctionTemplate> func_templ =
13650       v8::FunctionTemplate::New(isolate);
13651   v8::Handle<v8::String> foo_string =
13652       v8::String::NewFromUtf8(isolate, "foo");
13653   obj->Set(foo_string, func_templ->GetFunction());
13654   v8::Handle<v8::Object> obj_clone = obj->Clone();
13655   obj_clone->Set(foo_string,
13656                  v8::String::NewFromUtf8(isolate, "Hello"));
13657   CHECK(!obj->Get(foo_string)->IsUndefined());
13658 }
13659
13660
13661 static void CheckElementValue(i::Isolate* isolate,
13662                               int expected,
13663                               i::Handle<i::Object> obj,
13664                               int offset) {
13665   i::Object* element =
13666       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
13667   CHECK_EQ(expected, i::Smi::cast(element)->value());
13668 }
13669
13670
13671 template <class ExternalArrayClass, class ElementType>
13672 static void ObjectWithExternalArrayTestHelper(Handle<Context> context,
13673                                               v8::Handle<Object> obj,
13674                                               int element_count,
13675                                               i::ExternalArrayType array_type,
13676                                               int64_t low, int64_t high) {
13677   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
13678   i::Isolate* isolate = jsobj->GetIsolate();
13679   obj->Set(v8_str("field"),
13680            v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
13681   context->Global()->Set(v8_str("ext_array"), obj);
13682   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
13683   CHECK_EQ(1503, result->Int32Value());
13684   result = CompileRun("ext_array[1]");
13685   CHECK_EQ(1, result->Int32Value());
13686
13687   // Check assigned smis
13688   result = CompileRun("for (var i = 0; i < 8; i++) {"
13689                       "  ext_array[i] = i;"
13690                       "}"
13691                       "var sum = 0;"
13692                       "for (var i = 0; i < 8; i++) {"
13693                       "  sum += ext_array[i];"
13694                       "}"
13695                       "sum;");
13696
13697   CHECK_EQ(28, result->Int32Value());
13698   // Check pass through of assigned smis
13699   result = CompileRun("var sum = 0;"
13700                       "for (var i = 0; i < 8; i++) {"
13701                       "  sum += ext_array[i] = ext_array[i] = -i;"
13702                       "}"
13703                       "sum;");
13704   CHECK_EQ(-28, result->Int32Value());
13705
13706
13707   // Check assigned smis in reverse order
13708   result = CompileRun("for (var i = 8; --i >= 0; ) {"
13709                       "  ext_array[i] = i;"
13710                       "}"
13711                       "var sum = 0;"
13712                       "for (var i = 0; i < 8; i++) {"
13713                       "  sum += ext_array[i];"
13714                       "}"
13715                       "sum;");
13716   CHECK_EQ(28, result->Int32Value());
13717
13718   // Check pass through of assigned HeapNumbers
13719   result = CompileRun("var sum = 0;"
13720                       "for (var i = 0; i < 16; i+=2) {"
13721                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
13722                       "}"
13723                       "sum;");
13724   CHECK_EQ(-28, result->Int32Value());
13725
13726   // Check assigned HeapNumbers
13727   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
13728                       "  ext_array[i] = (i * 0.5);"
13729                       "}"
13730                       "var sum = 0;"
13731                       "for (var i = 0; i < 16; i+=2) {"
13732                       "  sum += ext_array[i];"
13733                       "}"
13734                       "sum;");
13735   CHECK_EQ(28, result->Int32Value());
13736
13737   // Check assigned HeapNumbers in reverse order
13738   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
13739                       "  ext_array[i] = (i * 0.5);"
13740                       "}"
13741                       "var sum = 0;"
13742                       "for (var i = 0; i < 16; i+=2) {"
13743                       "  sum += ext_array[i];"
13744                       "}"
13745                       "sum;");
13746   CHECK_EQ(28, result->Int32Value());
13747
13748   i::ScopedVector<char> test_buf(1024);
13749
13750   // Check legal boundary conditions.
13751   // The repeated loads and stores ensure the ICs are exercised.
13752   const char* boundary_program =
13753       "var res = 0;"
13754       "for (var i = 0; i < 16; i++) {"
13755       "  ext_array[i] = %lld;"
13756       "  if (i > 8) {"
13757       "    res = ext_array[i];"
13758       "  }"
13759       "}"
13760       "res;";
13761   i::SNPrintF(test_buf,
13762               boundary_program,
13763               low);
13764   result = CompileRun(test_buf.start());
13765   CHECK_EQ(low, result->IntegerValue());
13766
13767   i::SNPrintF(test_buf,
13768               boundary_program,
13769               high);
13770   result = CompileRun(test_buf.start());
13771   CHECK_EQ(high, result->IntegerValue());
13772
13773   // Check misprediction of type in IC.
13774   result = CompileRun("var tmp_array = ext_array;"
13775                       "var sum = 0;"
13776                       "for (var i = 0; i < 8; i++) {"
13777                       "  tmp_array[i] = i;"
13778                       "  sum += tmp_array[i];"
13779                       "  if (i == 4) {"
13780                       "    tmp_array = {};"
13781                       "  }"
13782                       "}"
13783                       "sum;");
13784   // Force GC to trigger verification.
13785   CcTest::heap()->CollectAllGarbage();
13786   CHECK_EQ(28, result->Int32Value());
13787
13788   // Make sure out-of-range loads do not throw.
13789   i::SNPrintF(test_buf,
13790               "var caught_exception = false;"
13791               "try {"
13792               "  ext_array[%d];"
13793               "} catch (e) {"
13794               "  caught_exception = true;"
13795               "}"
13796               "caught_exception;",
13797               element_count);
13798   result = CompileRun(test_buf.start());
13799   CHECK_EQ(false, result->BooleanValue());
13800
13801   // Make sure out-of-range stores do not throw.
13802   i::SNPrintF(test_buf,
13803               "var caught_exception = false;"
13804               "try {"
13805               "  ext_array[%d] = 1;"
13806               "} catch (e) {"
13807               "  caught_exception = true;"
13808               "}"
13809               "caught_exception;",
13810               element_count);
13811   result = CompileRun(test_buf.start());
13812   CHECK_EQ(false, result->BooleanValue());
13813
13814   // Check other boundary conditions, values and operations.
13815   result = CompileRun("for (var i = 0; i < 8; i++) {"
13816                       "  ext_array[7] = undefined;"
13817                       "}"
13818                       "ext_array[7];");
13819   CHECK_EQ(0, result->Int32Value());
13820   if (array_type == i::kExternalFloat64Array ||
13821       array_type == i::kExternalFloat32Array) {
13822     CHECK(std::isnan(
13823         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
13824   } else {
13825     CheckElementValue(isolate, 0, jsobj, 7);
13826   }
13827
13828   result = CompileRun("for (var i = 0; i < 8; i++) {"
13829                       "  ext_array[6] = '2.3';"
13830                       "}"
13831                       "ext_array[6];");
13832   CHECK_EQ(2, result->Int32Value());
13833   CHECK_EQ(2,
13834            static_cast<int>(
13835                i::Object::GetElement(
13836                    isolate, jsobj, 6).ToHandleChecked()->Number()));
13837
13838   if (array_type != i::kExternalFloat32Array &&
13839       array_type != i::kExternalFloat64Array) {
13840     // Though the specification doesn't state it, be explicit about
13841     // converting NaNs and +/-Infinity to zero.
13842     result = CompileRun("for (var i = 0; i < 8; i++) {"
13843                         "  ext_array[i] = 5;"
13844                         "}"
13845                         "for (var i = 0; i < 8; i++) {"
13846                         "  ext_array[i] = NaN;"
13847                         "}"
13848                         "ext_array[5];");
13849     CHECK_EQ(0, result->Int32Value());
13850     CheckElementValue(isolate, 0, jsobj, 5);
13851
13852     result = CompileRun("for (var i = 0; i < 8; i++) {"
13853                         "  ext_array[i] = 5;"
13854                         "}"
13855                         "for (var i = 0; i < 8; i++) {"
13856                         "  ext_array[i] = Infinity;"
13857                         "}"
13858                         "ext_array[5];");
13859     int expected_value =
13860         (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
13861     CHECK_EQ(expected_value, result->Int32Value());
13862     CheckElementValue(isolate, expected_value, jsobj, 5);
13863
13864     result = CompileRun("for (var i = 0; i < 8; i++) {"
13865                         "  ext_array[i] = 5;"
13866                         "}"
13867                         "for (var i = 0; i < 8; i++) {"
13868                         "  ext_array[i] = -Infinity;"
13869                         "}"
13870                         "ext_array[5];");
13871     CHECK_EQ(0, result->Int32Value());
13872     CheckElementValue(isolate, 0, jsobj, 5);
13873
13874     // Check truncation behavior of integral arrays.
13875     const char* unsigned_data =
13876         "var source_data = [0.6, 10.6];"
13877         "var expected_results = [0, 10];";
13878     const char* signed_data =
13879         "var source_data = [0.6, 10.6, -0.6, -10.6];"
13880         "var expected_results = [0, 10, 0, -10];";
13881     const char* pixel_data =
13882         "var source_data = [0.6, 10.6];"
13883         "var expected_results = [1, 11];";
13884     bool is_unsigned = (array_type == i::kExternalUint8Array ||
13885                         array_type == i::kExternalUint16Array ||
13886                         array_type == i::kExternalUint32Array);
13887     bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
13888
13889     i::SNPrintF(test_buf,
13890                 "%s"
13891                 "var all_passed = true;"
13892                 "for (var i = 0; i < source_data.length; i++) {"
13893                 "  for (var j = 0; j < 8; j++) {"
13894                 "    ext_array[j] = source_data[i];"
13895                 "  }"
13896                 "  all_passed = all_passed &&"
13897                 "               (ext_array[5] == expected_results[i]);"
13898                 "}"
13899                 "all_passed;",
13900                 (is_unsigned ?
13901                      unsigned_data :
13902                      (is_pixel_data ? pixel_data : signed_data)));
13903     result = CompileRun(test_buf.start());
13904     CHECK_EQ(true, result->BooleanValue());
13905   }
13906
13907   i::Handle<ExternalArrayClass> array(
13908       ExternalArrayClass::cast(jsobj->elements()));
13909   for (int i = 0; i < element_count; i++) {
13910     array->set(i, static_cast<ElementType>(i));
13911   }
13912
13913   // Test complex assignments
13914   result = CompileRun("function ee_op_test_complex_func(sum) {"
13915                       " for (var i = 0; i < 40; ++i) {"
13916                       "   sum += (ext_array[i] += 1);"
13917                       "   sum += (ext_array[i] -= 1);"
13918                       " } "
13919                       " return sum;"
13920                       "}"
13921                       "sum=0;"
13922                       "for (var i=0;i<10000;++i) {"
13923                       "  sum=ee_op_test_complex_func(sum);"
13924                       "}"
13925                       "sum;");
13926   CHECK_EQ(16000000, result->Int32Value());
13927
13928   // Test count operations
13929   result = CompileRun("function ee_op_test_count_func(sum) {"
13930                       " for (var i = 0; i < 40; ++i) {"
13931                       "   sum += (++ext_array[i]);"
13932                       "   sum += (--ext_array[i]);"
13933                       " } "
13934                       " return sum;"
13935                       "}"
13936                       "sum=0;"
13937                       "for (var i=0;i<10000;++i) {"
13938                       "  sum=ee_op_test_count_func(sum);"
13939                       "}"
13940                       "sum;");
13941   CHECK_EQ(16000000, result->Int32Value());
13942
13943   result = CompileRun("ext_array[3] = 33;"
13944                       "delete ext_array[3];"
13945                       "ext_array[3];");
13946   CHECK_EQ(33, result->Int32Value());
13947
13948   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
13949                       "ext_array[2] = 12; ext_array[3] = 13;"
13950                       "ext_array.__defineGetter__('2',"
13951                       "function() { return 120; });"
13952                       "ext_array[2];");
13953   CHECK_EQ(12, result->Int32Value());
13954
13955   result = CompileRun("var js_array = new Array(40);"
13956                       "js_array[0] = 77;"
13957                       "js_array;");
13958   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13959
13960   result = CompileRun("ext_array[1] = 23;"
13961                       "ext_array.__proto__ = [];"
13962                       "js_array.__proto__ = ext_array;"
13963                       "js_array.concat(ext_array);");
13964   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13965   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
13966
13967   result = CompileRun("ext_array[1] = 23;");
13968   CHECK_EQ(23, result->Int32Value());
13969 }
13970
13971
13972 template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
13973           class ElementType>
13974 static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
13975                                       ElementType low, ElementType high) {
13976   i::FLAG_allow_natives_syntax = true;
13977   LocalContext context;
13978   i::Isolate* isolate = CcTest::i_isolate();
13979   i::Factory* factory = isolate->factory();
13980   v8::HandleScope scope(context->GetIsolate());
13981   const int kElementCount = 260;
13982   i::Handle<i::JSTypedArray> jsobj =
13983       factory->NewJSTypedArray(elements_kind, kElementCount);
13984   i::Handle<FixedTypedArrayClass> fixed_array(
13985       FixedTypedArrayClass::cast(jsobj->elements()));
13986   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
13987            fixed_array->map()->instance_type());
13988   CHECK_EQ(kElementCount, fixed_array->length());
13989   CcTest::heap()->CollectAllGarbage();
13990   for (int i = 0; i < kElementCount; i++) {
13991     fixed_array->set(i, static_cast<ElementType>(i));
13992   }
13993   // Force GC to trigger verification.
13994   CcTest::heap()->CollectAllGarbage();
13995   for (int i = 0; i < kElementCount; i++) {
13996     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
13997              static_cast<int64_t>(fixed_array->get_scalar(i)));
13998   }
13999   v8::Handle<v8::Object> obj = v8::Utils::ToLocal(jsobj);
14000
14001   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
14002       context.local(), obj, kElementCount, array_type,
14003       static_cast<int64_t>(low),
14004       static_cast<int64_t>(high));
14005 }
14006
14007
14008 THREADED_TEST(FixedUint8Array) {
14009   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
14010       i::kExternalUint8Array, 0x0, 0xFF);
14011 }
14012
14013
14014 THREADED_TEST(FixedUint8ClampedArray) {
14015   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
14016                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
14017       i::kExternalUint8ClampedArray, 0x0, 0xFF);
14018 }
14019
14020
14021 THREADED_TEST(FixedInt8Array) {
14022   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
14023       i::kExternalInt8Array, -0x80, 0x7F);
14024 }
14025
14026
14027 THREADED_TEST(FixedUint16Array) {
14028   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
14029       i::kExternalUint16Array, 0x0, 0xFFFF);
14030 }
14031
14032
14033 THREADED_TEST(FixedInt16Array) {
14034   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
14035       i::kExternalInt16Array, -0x8000, 0x7FFF);
14036 }
14037
14038
14039 THREADED_TEST(FixedUint32Array) {
14040   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
14041       i::kExternalUint32Array, 0x0, UINT_MAX);
14042 }
14043
14044
14045 THREADED_TEST(FixedInt32Array) {
14046   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
14047       i::kExternalInt32Array, INT_MIN, INT_MAX);
14048 }
14049
14050
14051 THREADED_TEST(FixedFloat32Array) {
14052   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
14053       i::kExternalFloat32Array, -500, 500);
14054 }
14055
14056
14057 THREADED_TEST(FixedFloat64Array) {
14058   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
14059       i::kExternalFloat64Array, -500, 500);
14060 }
14061
14062
14063 template <typename ElementType, typename TypedArray, class ExternalArrayClass,
14064           class ArrayBufferType>
14065 void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
14066                           int64_t high) {
14067   const int kElementCount = 50;
14068
14069   i::ScopedVector<ElementType> backing_store(kElementCount+2);
14070
14071   LocalContext env;
14072   v8::Isolate* isolate = env->GetIsolate();
14073   v8::HandleScope handle_scope(isolate);
14074
14075   Local<ArrayBufferType> ab =
14076       ArrayBufferType::New(isolate, backing_store.start(),
14077                            (kElementCount + 2) * sizeof(ElementType));
14078   Local<TypedArray> ta =
14079       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
14080   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
14081   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
14082   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
14083   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
14084   CHECK(ab->Equals(ta->Buffer()));
14085
14086   ElementType* data = backing_store.start() + 2;
14087   for (int i = 0; i < kElementCount; i++) {
14088     data[i] = static_cast<ElementType>(i);
14089   }
14090
14091   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
14092       env.local(), ta, kElementCount, array_type, low, high);
14093 }
14094
14095
14096 THREADED_TEST(Uint8Array) {
14097   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,
14098                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
14099 }
14100
14101
14102 THREADED_TEST(Int8Array) {
14103   TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array,
14104                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
14105 }
14106
14107
14108 THREADED_TEST(Uint16Array) {
14109   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array,
14110                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
14111 }
14112
14113
14114 THREADED_TEST(Int16Array) {
14115   TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array,
14116                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
14117                                         0x7FFF);
14118 }
14119
14120
14121 THREADED_TEST(Uint32Array) {
14122   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array,
14123                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
14124 }
14125
14126
14127 THREADED_TEST(Int32Array) {
14128   TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array,
14129                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
14130                                         INT_MAX);
14131 }
14132
14133
14134 THREADED_TEST(Float32Array) {
14135   TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array,
14136                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
14137 }
14138
14139
14140 THREADED_TEST(Float64Array) {
14141   TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array,
14142                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
14143 }
14144
14145
14146 THREADED_TEST(Uint8ClampedArray) {
14147   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
14148                        i::ExternalUint8ClampedArray, v8::ArrayBuffer>(
14149       i::kExternalUint8ClampedArray, 0, 0xFF);
14150 }
14151
14152
14153 THREADED_TEST(DataView) {
14154   const int kSize = 50;
14155
14156   i::ScopedVector<uint8_t> backing_store(kSize+2);
14157
14158   LocalContext env;
14159   v8::Isolate* isolate = env->GetIsolate();
14160   v8::HandleScope handle_scope(isolate);
14161
14162   Local<v8::ArrayBuffer> ab =
14163       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
14164   Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
14165   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
14166   CHECK_EQ(2u, dv->ByteOffset());
14167   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
14168   CHECK(ab->Equals(dv->Buffer()));
14169 }
14170
14171
14172 THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
14173   LocalContext env;
14174   v8::Isolate* isolate = env->GetIsolate();
14175   v8::HandleScope handle_scope(isolate);
14176
14177   // Make sure the pointer looks like a heap object
14178   uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
14179
14180   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
14181   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
14182
14183   // Should not crash
14184   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
14185   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
14186   CcTest::heap()->CollectAllGarbage();
14187   CcTest::heap()->CollectAllGarbage();
14188
14189   // Should not move the pointer
14190   CHECK_EQ(ab->GetContents().Data(), store_ptr);
14191 }
14192
14193
14194 THREADED_TEST(SkipArrayBufferDuringScavenge) {
14195   LocalContext env;
14196   v8::Isolate* isolate = env->GetIsolate();
14197   v8::HandleScope handle_scope(isolate);
14198
14199   // Make sure the pointer looks like a heap object
14200   Local<v8::Object> tmp = v8::Object::New(isolate);
14201   uint8_t* store_ptr =
14202       reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
14203
14204   // Make `store_ptr` point to from space
14205   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
14206
14207   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
14208   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
14209
14210   // Should not crash,
14211   // i.e. backing store pointer should not be treated as a heap object pointer
14212   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
14213   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
14214
14215   // Use `ab` to silence compiler warning
14216   CHECK_EQ(ab->GetContents().Data(), store_ptr);
14217 }
14218
14219
14220 THREADED_TEST(SharedUint8Array) {
14221   i::FLAG_harmony_sharedarraybuffer = true;
14222   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,
14223                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
14224 }
14225
14226
14227 THREADED_TEST(SharedInt8Array) {
14228   i::FLAG_harmony_sharedarraybuffer = true;
14229   TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array,
14230                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
14231                                               0x7F);
14232 }
14233
14234
14235 THREADED_TEST(SharedUint16Array) {
14236   i::FLAG_harmony_sharedarraybuffer = true;
14237   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array,
14238                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
14239                                               0xFFFF);
14240 }
14241
14242
14243 THREADED_TEST(SharedInt16Array) {
14244   i::FLAG_harmony_sharedarraybuffer = true;
14245   TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array,
14246                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
14247                                               0x7FFF);
14248 }
14249
14250
14251 THREADED_TEST(SharedUint32Array) {
14252   i::FLAG_harmony_sharedarraybuffer = true;
14253   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array,
14254                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
14255                                               UINT_MAX);
14256 }
14257
14258
14259 THREADED_TEST(SharedInt32Array) {
14260   i::FLAG_harmony_sharedarraybuffer = true;
14261   TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array,
14262                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
14263                                               INT_MAX);
14264 }
14265
14266
14267 THREADED_TEST(SharedFloat32Array) {
14268   i::FLAG_harmony_sharedarraybuffer = true;
14269   TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array,
14270                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
14271                                               500);
14272 }
14273
14274
14275 THREADED_TEST(SharedFloat64Array) {
14276   i::FLAG_harmony_sharedarraybuffer = true;
14277   TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array,
14278                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
14279                                               500);
14280 }
14281
14282
14283 THREADED_TEST(SharedUint8ClampedArray) {
14284   i::FLAG_harmony_sharedarraybuffer = true;
14285   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
14286                        i::ExternalUint8ClampedArray, v8::SharedArrayBuffer>(
14287       i::kExternalUint8ClampedArray, 0, 0xFF);
14288 }
14289
14290
14291 THREADED_TEST(SharedDataView) {
14292   i::FLAG_harmony_sharedarraybuffer = true;
14293   const int kSize = 50;
14294
14295   i::ScopedVector<uint8_t> backing_store(kSize + 2);
14296
14297   LocalContext env;
14298   v8::Isolate* isolate = env->GetIsolate();
14299   v8::HandleScope handle_scope(isolate);
14300
14301   Local<v8::SharedArrayBuffer> ab =
14302       v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
14303   Local<v8::DataView> dv =
14304       v8::DataView::New(ab, 2, kSize);
14305   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
14306   CHECK_EQ(2u, dv->ByteOffset());
14307   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
14308   CHECK(ab->Equals(dv->Buffer()));
14309 }
14310
14311
14312 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
14313   THREADED_TEST(Is##View) {                                                   \
14314     LocalContext env;                                                         \
14315     v8::Isolate* isolate = env->GetIsolate();                                 \
14316     v8::HandleScope handle_scope(isolate);                                    \
14317                                                                               \
14318     Handle<Value> result = CompileRun(                                        \
14319         "var ab = new ArrayBuffer(128);"                                      \
14320         "new " #View "(ab)");                                                 \
14321     CHECK(result->IsArrayBufferView());                                       \
14322     CHECK(result->Is##View());                                                \
14323     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
14324   }
14325
14326 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
14327 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
14328 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
14329 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
14330 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
14331 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
14332 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
14333 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
14334 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
14335 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
14336
14337 #undef IS_ARRAY_BUFFER_VIEW_TEST
14338
14339
14340
14341 THREADED_TEST(ScriptContextDependence) {
14342   LocalContext c1;
14343   v8::HandleScope scope(c1->GetIsolate());
14344   const char *source = "foo";
14345   v8::Handle<v8::Script> dep = v8_compile(source);
14346   v8::ScriptCompiler::Source script_source(v8::String::NewFromUtf8(
14347       c1->GetIsolate(), source));
14348   v8::Handle<v8::UnboundScript> indep =
14349       v8::ScriptCompiler::CompileUnbound(c1->GetIsolate(), &script_source);
14350   c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
14351                     v8::Integer::New(c1->GetIsolate(), 100));
14352   CHECK_EQ(dep->Run()->Int32Value(), 100);
14353   CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 100);
14354   LocalContext c2;
14355   c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
14356                     v8::Integer::New(c2->GetIsolate(), 101));
14357   CHECK_EQ(dep->Run()->Int32Value(), 100);
14358   CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 101);
14359 }
14360
14361
14362 THREADED_TEST(StackTrace) {
14363   LocalContext context;
14364   v8::HandleScope scope(context->GetIsolate());
14365   v8::TryCatch try_catch(context->GetIsolate());
14366   const char *source = "function foo() { FAIL.FAIL; }; foo();";
14367   v8::Handle<v8::String> src =
14368       v8::String::NewFromUtf8(context->GetIsolate(), source);
14369   v8::Handle<v8::String> origin =
14370       v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
14371   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
14372   v8::ScriptCompiler::CompileUnbound(context->GetIsolate(), &script_source)
14373       ->BindToCurrentContext()
14374       ->Run();
14375   CHECK(try_catch.HasCaught());
14376   v8::String::Utf8Value stack(try_catch.StackTrace());
14377   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
14378 }
14379
14380
14381 // Checks that a StackFrame has certain expected values.
14382 void checkStackFrame(const char* expected_script_name,
14383     const char* expected_func_name, int expected_line_number,
14384     int expected_column, bool is_eval, bool is_constructor,
14385     v8::Handle<v8::StackFrame> frame) {
14386   v8::HandleScope scope(CcTest::isolate());
14387   v8::String::Utf8Value func_name(frame->GetFunctionName());
14388   v8::String::Utf8Value script_name(frame->GetScriptName());
14389   if (*script_name == NULL) {
14390     // The situation where there is no associated script, like for evals.
14391     CHECK(expected_script_name == NULL);
14392   } else {
14393     CHECK(strstr(*script_name, expected_script_name) != NULL);
14394   }
14395   CHECK(strstr(*func_name, expected_func_name) != NULL);
14396   CHECK_EQ(expected_line_number, frame->GetLineNumber());
14397   CHECK_EQ(expected_column, frame->GetColumn());
14398   CHECK_EQ(is_eval, frame->IsEval());
14399   CHECK_EQ(is_constructor, frame->IsConstructor());
14400 }
14401
14402
14403 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
14404   v8::HandleScope scope(args.GetIsolate());
14405   const char* origin = "capture-stack-trace-test";
14406   const int kOverviewTest = 1;
14407   const int kDetailedTest = 2;
14408
14409   DCHECK(args.Length() == 1);
14410
14411   int testGroup = args[0]->Int32Value();
14412   if (testGroup == kOverviewTest) {
14413     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
14414         args.GetIsolate(), 10, v8::StackTrace::kOverview);
14415     CHECK_EQ(4, stackTrace->GetFrameCount());
14416     checkStackFrame(origin, "bar", 2, 10, false, false,
14417                     stackTrace->GetFrame(0));
14418     checkStackFrame(origin, "foo", 6, 3, false, false,
14419                     stackTrace->GetFrame(1));
14420     // This is the source string inside the eval which has the call to foo.
14421     checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
14422     // The last frame is an anonymous function which has the initial eval call.
14423     checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
14424
14425     CHECK(stackTrace->AsArray()->IsArray());
14426   } else if (testGroup == kDetailedTest) {
14427     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
14428         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
14429     CHECK_EQ(4, stackTrace->GetFrameCount());
14430     checkStackFrame(origin, "bat", 4, 22, false, false,
14431                     stackTrace->GetFrame(0));
14432     checkStackFrame(origin, "baz", 8, 3, false, true,
14433                     stackTrace->GetFrame(1));
14434     bool is_eval = true;
14435     // This is the source string inside the eval which has the call to baz.
14436     checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
14437     // The last frame is an anonymous function which has the initial eval call.
14438     checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
14439
14440     CHECK(stackTrace->AsArray()->IsArray());
14441   }
14442 }
14443
14444
14445 // Tests the C++ StackTrace API.
14446 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
14447 // THREADED_TEST(CaptureStackTrace) {
14448 TEST(CaptureStackTrace) {
14449   v8::Isolate* isolate = CcTest::isolate();
14450   v8::HandleScope scope(isolate);
14451   v8::Handle<v8::String> origin =
14452       v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
14453   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
14454   templ->Set(v8_str("AnalyzeStackInNativeCode"),
14455              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
14456   LocalContext context(0, templ);
14457
14458   // Test getting OVERVIEW information. Should ignore information that is not
14459   // script name, function name, line number, and column offset.
14460   const char *overview_source =
14461     "function bar() {\n"
14462     "  var y; AnalyzeStackInNativeCode(1);\n"
14463     "}\n"
14464     "function foo() {\n"
14465     "\n"
14466     "  bar();\n"
14467     "}\n"
14468     "var x;eval('new foo();');";
14469   v8::Handle<v8::String> overview_src =
14470       v8::String::NewFromUtf8(isolate, overview_source);
14471   v8::ScriptCompiler::Source script_source(overview_src,
14472                                            v8::ScriptOrigin(origin));
14473   v8::Handle<Value> overview_result(
14474       v8::ScriptCompiler::CompileUnbound(isolate, &script_source)
14475           ->BindToCurrentContext()
14476           ->Run());
14477   CHECK(!overview_result.IsEmpty());
14478   CHECK(overview_result->IsObject());
14479
14480   // Test getting DETAILED information.
14481   const char *detailed_source =
14482     "function bat() {AnalyzeStackInNativeCode(2);\n"
14483     "}\n"
14484     "\n"
14485     "function baz() {\n"
14486     "  bat();\n"
14487     "}\n"
14488     "eval('new baz();');";
14489   v8::Handle<v8::String> detailed_src =
14490       v8::String::NewFromUtf8(isolate, detailed_source);
14491   // Make the script using a non-zero line and column offset.
14492   v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
14493   v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
14494   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
14495   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
14496   v8::Handle<v8::UnboundScript> detailed_script(
14497       v8::ScriptCompiler::CompileUnbound(isolate, &script_source2));
14498   v8::Handle<Value> detailed_result(
14499       detailed_script->BindToCurrentContext()->Run());
14500   CHECK(!detailed_result.IsEmpty());
14501   CHECK(detailed_result->IsObject());
14502 }
14503
14504
14505 static void StackTraceForUncaughtExceptionListener(
14506     v8::Handle<v8::Message> message,
14507     v8::Handle<Value>) {
14508   report_count++;
14509   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14510   CHECK_EQ(2, stack_trace->GetFrameCount());
14511   checkStackFrame("origin", "foo", 2, 3, false, false,
14512                   stack_trace->GetFrame(0));
14513   checkStackFrame("origin", "bar", 5, 3, false, false,
14514                   stack_trace->GetFrame(1));
14515 }
14516
14517
14518 TEST(CaptureStackTraceForUncaughtException) {
14519   report_count = 0;
14520   LocalContext env;
14521   v8::HandleScope scope(env->GetIsolate());
14522   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
14523   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14524
14525   CompileRunWithOrigin(
14526       "function foo() {\n"
14527       "  throw 1;\n"
14528       "};\n"
14529       "function bar() {\n"
14530       "  foo();\n"
14531       "};",
14532       "origin");
14533   v8::Local<v8::Object> global = env->Global();
14534   Local<Value> trouble = global->Get(v8_str("bar"));
14535   CHECK(trouble->IsFunction());
14536   Function::Cast(*trouble)->Call(global, 0, NULL);
14537   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14538   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
14539   CHECK_EQ(1, report_count);
14540 }
14541
14542
14543 TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
14544   report_count = 0;
14545   LocalContext env;
14546   v8::HandleScope scope(env->GetIsolate());
14547
14548   // Create an Error object first.
14549   CompileRunWithOrigin(
14550       "function foo() {\n"
14551       "e=new Error('err');\n"
14552       "};\n"
14553       "function bar() {\n"
14554       "  foo();\n"
14555       "};\n"
14556       "var e;",
14557       "origin");
14558   v8::Local<v8::Object> global = env->Global();
14559   Local<Value> trouble = global->Get(v8_str("bar"));
14560   CHECK(trouble->IsFunction());
14561   Function::Cast(*trouble)->Call(global, 0, NULL);
14562
14563   // Enable capturing detailed stack trace late, and throw the exception.
14564   // The detailed stack trace should be extracted from the simple stack.
14565   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
14566   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14567   CompileRunWithOrigin("throw e", "origin");
14568   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14569   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
14570   CHECK_EQ(1, report_count);
14571 }
14572
14573
14574 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
14575   LocalContext env;
14576   v8::HandleScope scope(env->GetIsolate());
14577   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
14578                                                     1024,
14579                                                     v8::StackTrace::kDetailed);
14580
14581   CompileRun(
14582       "var setters = ['column', 'lineNumber', 'scriptName',\n"
14583       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
14584       "    'isConstructor'];\n"
14585       "for (var i = 0; i < setters.length; i++) {\n"
14586       "  var prop = setters[i];\n"
14587       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
14588       "}\n");
14589   CompileRun("throw 'exception';");
14590   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14591 }
14592
14593
14594 static void StackTraceFunctionNameListener(v8::Handle<v8::Message> message,
14595                                            v8::Handle<Value>) {
14596   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14597   CHECK_EQ(5, stack_trace->GetFrameCount());
14598   checkStackFrame("origin", "foo:0", 4, 7, false, false,
14599                   stack_trace->GetFrame(0));
14600   checkStackFrame("origin", "foo:1", 5, 27, false, false,
14601                   stack_trace->GetFrame(1));
14602   checkStackFrame("origin", "foo", 5, 27, false, false,
14603                   stack_trace->GetFrame(2));
14604   checkStackFrame("origin", "foo", 5, 27, false, false,
14605                   stack_trace->GetFrame(3));
14606   checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
14607 }
14608
14609
14610 TEST(GetStackTraceContainsFunctionsWithFunctionName) {
14611   LocalContext env;
14612   v8::HandleScope scope(env->GetIsolate());
14613
14614   CompileRunWithOrigin(
14615       "function gen(name, counter) {\n"
14616       "  var f = function foo() {\n"
14617       "    if (counter === 0)\n"
14618       "      throw 1;\n"
14619       "    gen(name, counter - 1)();\n"
14620       "  };\n"
14621       "  if (counter == 3) {\n"
14622       "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
14623       "  } else {\n"
14624       "    Object.defineProperty(f, 'name', {writable:true});\n"
14625       "    if (counter == 2)\n"
14626       "      f.name = 42;\n"
14627       "    else\n"
14628       "      f.name = name + ':' + counter;\n"
14629       "  }\n"
14630       "  return f;\n"
14631       "};",
14632       "origin");
14633
14634   v8::V8::AddMessageListener(StackTraceFunctionNameListener);
14635   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14636   CompileRunWithOrigin("gen('foo', 3)();", "origin");
14637   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14638   v8::V8::RemoveMessageListeners(StackTraceFunctionNameListener);
14639 }
14640
14641
14642 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
14643                                      v8::Handle<v8::Value> data) {
14644   // Use the frame where JavaScript is called from.
14645   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14646   CHECK(!stack_trace.IsEmpty());
14647   int frame_count = stack_trace->GetFrameCount();
14648   CHECK_EQ(3, frame_count);
14649   int line_number[] = {1, 2, 5};
14650   for (int i = 0; i < frame_count; i++) {
14651     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14652   }
14653 }
14654
14655
14656 // Test that we only return the stack trace at the site where the exception
14657 // is first thrown (not where it is rethrown).
14658 TEST(RethrowStackTrace) {
14659   LocalContext env;
14660   v8::HandleScope scope(env->GetIsolate());
14661   // We make sure that
14662   // - the stack trace of the ReferenceError in g() is reported.
14663   // - the stack trace is not overwritten when e1 is rethrown by t().
14664   // - the stack trace of e2 does not overwrite that of e1.
14665   const char* source =
14666       "function g() { error; }          \n"
14667       "function f() { g(); }            \n"
14668       "function t(e) { throw e; }       \n"
14669       "try {                            \n"
14670       "  f();                           \n"
14671       "} catch (e1) {                   \n"
14672       "  try {                          \n"
14673       "    error;                       \n"
14674       "  } catch (e2) {                 \n"
14675       "    t(e1);                       \n"
14676       "  }                              \n"
14677       "}                                \n";
14678   v8::V8::AddMessageListener(RethrowStackTraceHandler);
14679   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14680   CompileRun(source);
14681   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14682   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
14683 }
14684
14685
14686 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
14687                                               v8::Handle<v8::Value> data) {
14688   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14689   CHECK(!stack_trace.IsEmpty());
14690   int frame_count = stack_trace->GetFrameCount();
14691   CHECK_EQ(2, frame_count);
14692   int line_number[] = {3, 7};
14693   for (int i = 0; i < frame_count; i++) {
14694     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14695   }
14696 }
14697
14698
14699 // Test that we do not recognize identity for primitive exceptions.
14700 TEST(RethrowPrimitiveStackTrace) {
14701   LocalContext env;
14702   v8::HandleScope scope(env->GetIsolate());
14703   // We do not capture stack trace for non Error objects on creation time.
14704   // Instead, we capture the stack trace on last throw.
14705   const char* source =
14706       "function g() { throw 404; }      \n"
14707       "function f() { g(); }            \n"
14708       "function t(e) { throw e; }       \n"
14709       "try {                            \n"
14710       "  f();                           \n"
14711       "} catch (e1) {                   \n"
14712       "  t(e1)                          \n"
14713       "}                                \n";
14714   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
14715   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14716   CompileRun(source);
14717   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14718   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
14719 }
14720
14721
14722 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
14723                                               v8::Handle<v8::Value> data) {
14724   // Use the frame where JavaScript is called from.
14725   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14726   CHECK(!stack_trace.IsEmpty());
14727   CHECK_EQ(1, stack_trace->GetFrameCount());
14728   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
14729 }
14730
14731
14732 // Test that the stack trace is captured when the error object is created and
14733 // not where it is thrown.
14734 TEST(RethrowExistingStackTrace) {
14735   LocalContext env;
14736   v8::HandleScope scope(env->GetIsolate());
14737   const char* source =
14738       "var e = new Error();           \n"
14739       "throw e;                       \n";
14740   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
14741   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14742   CompileRun(source);
14743   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14744   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
14745 }
14746
14747
14748 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
14749                                                v8::Handle<v8::Value> data) {
14750   // Use the frame where JavaScript is called from.
14751   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14752   CHECK(!stack_trace.IsEmpty());
14753   CHECK_EQ(1, stack_trace->GetFrameCount());
14754   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
14755 }
14756
14757
14758 // Test that the stack trace is captured where the bogus Error object is thrown.
14759 TEST(RethrowBogusErrorStackTrace) {
14760   LocalContext env;
14761   v8::HandleScope scope(env->GetIsolate());
14762   const char* source =
14763       "var e = {__proto__: new Error()} \n"
14764       "throw e;                         \n";
14765   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
14766   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14767   CompileRun(source);
14768   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14769   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
14770 }
14771
14772
14773 v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
14774 int promise_reject_counter = 0;
14775 int promise_revoke_counter = 0;
14776 int promise_reject_msg_line_number = -1;
14777 int promise_reject_msg_column_number = -1;
14778 int promise_reject_line_number = -1;
14779 int promise_reject_column_number = -1;
14780 int promise_reject_frame_count = -1;
14781
14782 void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
14783   if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
14784     promise_reject_counter++;
14785     CcTest::global()->Set(v8_str("rejected"), reject_message.GetPromise());
14786     CcTest::global()->Set(v8_str("value"), reject_message.GetValue());
14787     v8::Handle<v8::Message> message =
14788         v8::Exception::CreateMessage(reject_message.GetValue());
14789     v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14790
14791     promise_reject_msg_line_number = message->GetLineNumber();
14792     promise_reject_msg_column_number = message->GetStartColumn() + 1;
14793
14794     if (!stack_trace.IsEmpty()) {
14795       promise_reject_frame_count = stack_trace->GetFrameCount();
14796       if (promise_reject_frame_count > 0) {
14797         CHECK(stack_trace->GetFrame(0)->GetScriptName()->Equals(v8_str("pro")));
14798         promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
14799         promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
14800       } else {
14801         promise_reject_line_number = -1;
14802         promise_reject_column_number = -1;
14803       }
14804     }
14805   } else {
14806     promise_revoke_counter++;
14807     CcTest::global()->Set(v8_str("revoked"), reject_message.GetPromise());
14808     CHECK(reject_message.GetValue().IsEmpty());
14809   }
14810 }
14811
14812
14813 v8::Handle<v8::Promise> GetPromise(const char* name) {
14814   return v8::Handle<v8::Promise>::Cast(CcTest::global()->Get(v8_str(name)));
14815 }
14816
14817
14818 v8::Handle<v8::Value> RejectValue() {
14819   return CcTest::global()->Get(v8_str("value"));
14820 }
14821
14822
14823 void ResetPromiseStates() {
14824   promise_reject_counter = 0;
14825   promise_revoke_counter = 0;
14826   promise_reject_msg_line_number = -1;
14827   promise_reject_msg_column_number = -1;
14828   promise_reject_line_number = -1;
14829   promise_reject_column_number = -1;
14830   promise_reject_frame_count = -1;
14831   CcTest::global()->Set(v8_str("rejected"), v8_str(""));
14832   CcTest::global()->Set(v8_str("value"), v8_str(""));
14833   CcTest::global()->Set(v8_str("revoked"), v8_str(""));
14834 }
14835
14836
14837 TEST(PromiseRejectCallback) {
14838   LocalContext env;
14839   v8::Isolate* isolate = env->GetIsolate();
14840   v8::HandleScope scope(isolate);
14841
14842   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
14843
14844   ResetPromiseStates();
14845
14846   // Create promise p0.
14847   CompileRun(
14848       "var reject;            \n"
14849       "var p0 = new Promise(  \n"
14850       "  function(res, rej) { \n"
14851       "    reject = rej;      \n"
14852       "  }                    \n"
14853       ");                     \n");
14854   CHECK(!GetPromise("p0")->HasHandler());
14855   CHECK_EQ(0, promise_reject_counter);
14856   CHECK_EQ(0, promise_revoke_counter);
14857
14858   // Add resolve handler (and default reject handler) to p0.
14859   CompileRun("var p1 = p0.then(function(){});");
14860   CHECK(GetPromise("p0")->HasHandler());
14861   CHECK(!GetPromise("p1")->HasHandler());
14862   CHECK_EQ(0, promise_reject_counter);
14863   CHECK_EQ(0, promise_revoke_counter);
14864
14865   // Reject p0.
14866   CompileRun("reject('ppp');");
14867   CHECK(GetPromise("p0")->HasHandler());
14868   CHECK(!GetPromise("p1")->HasHandler());
14869   CHECK_EQ(1, promise_reject_counter);
14870   CHECK_EQ(0, promise_revoke_counter);
14871   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
14872   CHECK(GetPromise("rejected")->Equals(GetPromise("p1")));
14873   CHECK(RejectValue()->Equals(v8_str("ppp")));
14874
14875   // Reject p0 again. Callback is not triggered again.
14876   CompileRun("reject();");
14877   CHECK(GetPromise("p0")->HasHandler());
14878   CHECK(!GetPromise("p1")->HasHandler());
14879   CHECK_EQ(1, promise_reject_counter);
14880   CHECK_EQ(0, promise_revoke_counter);
14881
14882   // Add resolve handler to p1.
14883   CompileRun("var p2 = p1.then(function(){});");
14884   CHECK(GetPromise("p0")->HasHandler());
14885   CHECK(GetPromise("p1")->HasHandler());
14886   CHECK(!GetPromise("p2")->HasHandler());
14887   CHECK_EQ(2, promise_reject_counter);
14888   CHECK_EQ(1, promise_revoke_counter);
14889   CHECK(GetPromise("rejected")->Equals(GetPromise("p2")));
14890   CHECK(RejectValue()->Equals(v8_str("ppp")));
14891   CHECK(GetPromise("revoked")->Equals(GetPromise("p1")));
14892
14893   ResetPromiseStates();
14894
14895   // Create promise q0.
14896   CompileRun(
14897       "var q0 = new Promise(  \n"
14898       "  function(res, rej) { \n"
14899       "    reject = rej;      \n"
14900       "  }                    \n"
14901       ");                     \n");
14902   CHECK(!GetPromise("q0")->HasHandler());
14903   CHECK_EQ(0, promise_reject_counter);
14904   CHECK_EQ(0, promise_revoke_counter);
14905
14906   // Add reject handler to q0.
14907   CompileRun("var q1 = q0.catch(function() {});");
14908   CHECK(GetPromise("q0")->HasHandler());
14909   CHECK(!GetPromise("q1")->HasHandler());
14910   CHECK_EQ(0, promise_reject_counter);
14911   CHECK_EQ(0, promise_revoke_counter);
14912
14913   // Reject q0.
14914   CompileRun("reject('qq')");
14915   CHECK(GetPromise("q0")->HasHandler());
14916   CHECK(!GetPromise("q1")->HasHandler());
14917   CHECK_EQ(0, promise_reject_counter);
14918   CHECK_EQ(0, promise_revoke_counter);
14919
14920   // Add a new reject handler, which rejects by returning Promise.reject().
14921   // The returned promise q_ triggers a reject callback at first, only to
14922   // revoke it when returning it causes q2 to be rejected.
14923   CompileRun(
14924       "var q_;"
14925       "var q2 = q0.catch(               \n"
14926       "   function() {                  \n"
14927       "     q_ = Promise.reject('qqq'); \n"
14928       "     return q_;                  \n"
14929       "   }                             \n"
14930       ");                               \n");
14931   CHECK(GetPromise("q0")->HasHandler());
14932   CHECK(!GetPromise("q1")->HasHandler());
14933   CHECK(!GetPromise("q2")->HasHandler());
14934   CHECK(GetPromise("q_")->HasHandler());
14935   CHECK_EQ(2, promise_reject_counter);
14936   CHECK_EQ(1, promise_revoke_counter);
14937   CHECK(GetPromise("rejected")->Equals(GetPromise("q2")));
14938   CHECK(GetPromise("revoked")->Equals(GetPromise("q_")));
14939   CHECK(RejectValue()->Equals(v8_str("qqq")));
14940
14941   // Add a reject handler to the resolved q1, which rejects by throwing.
14942   CompileRun(
14943       "var q3 = q1.then(  \n"
14944       "   function() {    \n"
14945       "     throw 'qqqq'; \n"
14946       "   }               \n"
14947       ");                 \n");
14948   CHECK(GetPromise("q0")->HasHandler());
14949   CHECK(GetPromise("q1")->HasHandler());
14950   CHECK(!GetPromise("q2")->HasHandler());
14951   CHECK(!GetPromise("q3")->HasHandler());
14952   CHECK_EQ(3, promise_reject_counter);
14953   CHECK_EQ(1, promise_revoke_counter);
14954   CHECK(GetPromise("rejected")->Equals(GetPromise("q3")));
14955   CHECK(RejectValue()->Equals(v8_str("qqqq")));
14956
14957   ResetPromiseStates();
14958
14959   // Create promise r0, which has three handlers, two of which handle rejects.
14960   CompileRun(
14961       "var r0 = new Promise(             \n"
14962       "  function(res, rej) {            \n"
14963       "    reject = rej;                 \n"
14964       "  }                               \n"
14965       ");                                \n"
14966       "var r1 = r0.catch(function() {}); \n"
14967       "var r2 = r0.then(function() {});  \n"
14968       "var r3 = r0.then(function() {},   \n"
14969       "                 function() {});  \n");
14970   CHECK(GetPromise("r0")->HasHandler());
14971   CHECK(!GetPromise("r1")->HasHandler());
14972   CHECK(!GetPromise("r2")->HasHandler());
14973   CHECK(!GetPromise("r3")->HasHandler());
14974   CHECK_EQ(0, promise_reject_counter);
14975   CHECK_EQ(0, promise_revoke_counter);
14976
14977   // Reject r0.
14978   CompileRun("reject('rrr')");
14979   CHECK(GetPromise("r0")->HasHandler());
14980   CHECK(!GetPromise("r1")->HasHandler());
14981   CHECK(!GetPromise("r2")->HasHandler());
14982   CHECK(!GetPromise("r3")->HasHandler());
14983   CHECK_EQ(1, promise_reject_counter);
14984   CHECK_EQ(0, promise_revoke_counter);
14985   CHECK(GetPromise("rejected")->Equals(GetPromise("r2")));
14986   CHECK(RejectValue()->Equals(v8_str("rrr")));
14987
14988   // Add reject handler to r2.
14989   CompileRun("var r4 = r2.catch(function() {});");
14990   CHECK(GetPromise("r0")->HasHandler());
14991   CHECK(!GetPromise("r1")->HasHandler());
14992   CHECK(GetPromise("r2")->HasHandler());
14993   CHECK(!GetPromise("r3")->HasHandler());
14994   CHECK(!GetPromise("r4")->HasHandler());
14995   CHECK_EQ(1, promise_reject_counter);
14996   CHECK_EQ(1, promise_revoke_counter);
14997   CHECK(GetPromise("revoked")->Equals(GetPromise("r2")));
14998   CHECK(RejectValue()->Equals(v8_str("rrr")));
14999
15000   // Add reject handlers to r4.
15001   CompileRun("var r5 = r4.then(function() {}, function() {});");
15002   CHECK(GetPromise("r0")->HasHandler());
15003   CHECK(!GetPromise("r1")->HasHandler());
15004   CHECK(GetPromise("r2")->HasHandler());
15005   CHECK(!GetPromise("r3")->HasHandler());
15006   CHECK(GetPromise("r4")->HasHandler());
15007   CHECK(!GetPromise("r5")->HasHandler());
15008   CHECK_EQ(1, promise_reject_counter);
15009   CHECK_EQ(1, promise_revoke_counter);
15010
15011   ResetPromiseStates();
15012
15013   // Create promise s0, which has three handlers, none of which handle rejects.
15014   CompileRun(
15015       "var s0 = new Promise(            \n"
15016       "  function(res, rej) {           \n"
15017       "    reject = rej;                \n"
15018       "  }                              \n"
15019       ");                               \n"
15020       "var s1 = s0.then(function() {}); \n"
15021       "var s2 = s0.then(function() {}); \n"
15022       "var s3 = s0.then(function() {}); \n");
15023   CHECK(GetPromise("s0")->HasHandler());
15024   CHECK(!GetPromise("s1")->HasHandler());
15025   CHECK(!GetPromise("s2")->HasHandler());
15026   CHECK(!GetPromise("s3")->HasHandler());
15027   CHECK_EQ(0, promise_reject_counter);
15028   CHECK_EQ(0, promise_revoke_counter);
15029
15030   // Reject s0.
15031   CompileRun("reject('sss')");
15032   CHECK(GetPromise("s0")->HasHandler());
15033   CHECK(!GetPromise("s1")->HasHandler());
15034   CHECK(!GetPromise("s2")->HasHandler());
15035   CHECK(!GetPromise("s3")->HasHandler());
15036   CHECK_EQ(3, promise_reject_counter);
15037   CHECK_EQ(0, promise_revoke_counter);
15038   CHECK(RejectValue()->Equals(v8_str("sss")));
15039
15040   // Test stack frames.
15041   V8::SetCaptureStackTraceForUncaughtExceptions(true);
15042
15043   ResetPromiseStates();
15044
15045   // Create promise t0, which is rejected in the constructor with an error.
15046   CompileRunWithOrigin(
15047       "var t0 = new Promise(  \n"
15048       "  function(res, rej) { \n"
15049       "    reference_error;   \n"
15050       "  }                    \n"
15051       ");                     \n",
15052       "pro", 0, 0);
15053   CHECK(!GetPromise("t0")->HasHandler());
15054   CHECK_EQ(1, promise_reject_counter);
15055   CHECK_EQ(0, promise_revoke_counter);
15056   CHECK_EQ(2, promise_reject_frame_count);
15057   CHECK_EQ(3, promise_reject_line_number);
15058   CHECK_EQ(5, promise_reject_column_number);
15059   CHECK_EQ(3, promise_reject_msg_line_number);
15060   CHECK_EQ(5, promise_reject_msg_column_number);
15061
15062   ResetPromiseStates();
15063
15064   // Create promise u0 and chain u1 to it, which is rejected via throw.
15065   CompileRunWithOrigin(
15066       "var u0 = Promise.resolve();        \n"
15067       "var u1 = u0.then(                  \n"
15068       "           function() {            \n"
15069       "             (function() {         \n"
15070       "                throw new Error(); \n"
15071       "              })();                \n"
15072       "           }                       \n"
15073       "         );                        \n",
15074       "pro", 0, 0);
15075   CHECK(GetPromise("u0")->HasHandler());
15076   CHECK(!GetPromise("u1")->HasHandler());
15077   CHECK_EQ(1, promise_reject_counter);
15078   CHECK_EQ(0, promise_revoke_counter);
15079   CHECK_EQ(2, promise_reject_frame_count);
15080   CHECK_EQ(5, promise_reject_line_number);
15081   CHECK_EQ(23, promise_reject_column_number);
15082   CHECK_EQ(5, promise_reject_msg_line_number);
15083   CHECK_EQ(23, promise_reject_msg_column_number);
15084
15085   // Throw in u3, which handles u1's rejection.
15086   CompileRunWithOrigin(
15087       "function f() {                \n"
15088       "  return (function() {        \n"
15089       "    return new Error();       \n"
15090       "  })();                       \n"
15091       "}                             \n"
15092       "var u2 = Promise.reject(f()); \n"
15093       "var u3 = u1.catch(            \n"
15094       "           function() {       \n"
15095       "             return u2;       \n"
15096       "           }                  \n"
15097       "         );                   \n",
15098       "pro", 0, 0);
15099   CHECK(GetPromise("u0")->HasHandler());
15100   CHECK(GetPromise("u1")->HasHandler());
15101   CHECK(GetPromise("u2")->HasHandler());
15102   CHECK(!GetPromise("u3")->HasHandler());
15103   CHECK_EQ(3, promise_reject_counter);
15104   CHECK_EQ(2, promise_revoke_counter);
15105   CHECK_EQ(3, promise_reject_frame_count);
15106   CHECK_EQ(3, promise_reject_line_number);
15107   CHECK_EQ(12, promise_reject_column_number);
15108   CHECK_EQ(3, promise_reject_msg_line_number);
15109   CHECK_EQ(12, promise_reject_msg_column_number);
15110
15111   ResetPromiseStates();
15112
15113   // Create promise rejected promise v0, which is incorrectly handled by v1
15114   // via chaining cycle.
15115   CompileRunWithOrigin(
15116       "var v0 = Promise.reject(); \n"
15117       "var v1 = v0.catch(         \n"
15118       "           function() {    \n"
15119       "             return v1;    \n"
15120       "           }               \n"
15121       "         );                \n",
15122       "pro", 0, 0);
15123   CHECK(GetPromise("v0")->HasHandler());
15124   CHECK(!GetPromise("v1")->HasHandler());
15125   CHECK_EQ(2, promise_reject_counter);
15126   CHECK_EQ(1, promise_revoke_counter);
15127   CHECK_EQ(0, promise_reject_frame_count);
15128   CHECK_EQ(-1, promise_reject_line_number);
15129   CHECK_EQ(-1, promise_reject_column_number);
15130
15131   ResetPromiseStates();
15132
15133   // Create promise t1, which rejects by throwing syntax error from eval.
15134   CompileRunWithOrigin(
15135       "var t1 = new Promise(   \n"
15136       "  function(res, rej) {  \n"
15137       "    var content = '\\n\\\n"
15138       "      }';               \n"
15139       "    eval(content);      \n"
15140       "  }                     \n"
15141       ");                      \n",
15142       "pro", 0, 0);
15143   CHECK(!GetPromise("t1")->HasHandler());
15144   CHECK_EQ(1, promise_reject_counter);
15145   CHECK_EQ(0, promise_revoke_counter);
15146   CHECK_EQ(2, promise_reject_frame_count);
15147   CHECK_EQ(5, promise_reject_line_number);
15148   CHECK_EQ(10, promise_reject_column_number);
15149   CHECK_EQ(2, promise_reject_msg_line_number);
15150   CHECK_EQ(7, promise_reject_msg_column_number);
15151 }
15152
15153
15154 void AnalyzeStackOfEvalWithSourceURL(
15155     const v8::FunctionCallbackInfo<v8::Value>& args) {
15156   v8::HandleScope scope(args.GetIsolate());
15157   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15158       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15159   CHECK_EQ(5, stackTrace->GetFrameCount());
15160   v8::Handle<v8::String> url = v8_str("eval_url");
15161   for (int i = 0; i < 3; i++) {
15162     v8::Handle<v8::String> name =
15163         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15164     CHECK(!name.IsEmpty());
15165     CHECK(url->Equals(name));
15166   }
15167 }
15168
15169
15170 TEST(SourceURLInStackTrace) {
15171   v8::Isolate* isolate = CcTest::isolate();
15172   v8::HandleScope scope(isolate);
15173   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15174   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
15175              v8::FunctionTemplate::New(isolate,
15176                                        AnalyzeStackOfEvalWithSourceURL));
15177   LocalContext context(0, templ);
15178
15179   const char *source =
15180     "function outer() {\n"
15181     "function bar() {\n"
15182     "  AnalyzeStackOfEvalWithSourceURL();\n"
15183     "}\n"
15184     "function foo() {\n"
15185     "\n"
15186     "  bar();\n"
15187     "}\n"
15188     "foo();\n"
15189     "}\n"
15190     "eval('(' + outer +')()%s');";
15191
15192   i::ScopedVector<char> code(1024);
15193   i::SNPrintF(code, source, "//# sourceURL=eval_url");
15194   CHECK(CompileRun(code.start())->IsUndefined());
15195   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
15196   CHECK(CompileRun(code.start())->IsUndefined());
15197 }
15198
15199
15200 static int scriptIdInStack[2];
15201
15202 void AnalyzeScriptIdInStack(
15203     const v8::FunctionCallbackInfo<v8::Value>& args) {
15204   v8::HandleScope scope(args.GetIsolate());
15205   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15206       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
15207   CHECK_EQ(2, stackTrace->GetFrameCount());
15208   for (int i = 0; i < 2; i++) {
15209     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
15210   }
15211 }
15212
15213
15214 TEST(ScriptIdInStackTrace) {
15215   v8::Isolate* isolate = CcTest::isolate();
15216   v8::HandleScope scope(isolate);
15217   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15218   templ->Set(v8_str("AnalyzeScriptIdInStack"),
15219              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
15220   LocalContext context(0, templ);
15221
15222   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
15223     isolate,
15224     "function foo() {\n"
15225     "  AnalyzeScriptIdInStack();"
15226     "}\n"
15227     "foo();\n");
15228   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
15229   script->Run();
15230   for (int i = 0; i < 2; i++) {
15231     CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
15232     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
15233   }
15234 }
15235
15236
15237 void AnalyzeStackOfInlineScriptWithSourceURL(
15238     const v8::FunctionCallbackInfo<v8::Value>& args) {
15239   v8::HandleScope scope(args.GetIsolate());
15240   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15241       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15242   CHECK_EQ(4, stackTrace->GetFrameCount());
15243   v8::Handle<v8::String> url = v8_str("source_url");
15244   for (int i = 0; i < 3; i++) {
15245     v8::Handle<v8::String> name =
15246         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15247     CHECK(!name.IsEmpty());
15248     CHECK(url->Equals(name));
15249   }
15250 }
15251
15252
15253 TEST(InlineScriptWithSourceURLInStackTrace) {
15254   v8::Isolate* isolate = CcTest::isolate();
15255   v8::HandleScope scope(isolate);
15256   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15257   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
15258              v8::FunctionTemplate::New(
15259                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
15260   LocalContext context(0, templ);
15261
15262   const char *source =
15263     "function outer() {\n"
15264     "function bar() {\n"
15265     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
15266     "}\n"
15267     "function foo() {\n"
15268     "\n"
15269     "  bar();\n"
15270     "}\n"
15271     "foo();\n"
15272     "}\n"
15273     "outer()\n%s";
15274
15275   i::ScopedVector<char> code(1024);
15276   i::SNPrintF(code, source, "//# sourceURL=source_url");
15277   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
15278   i::SNPrintF(code, source, "//@ sourceURL=source_url");
15279   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
15280 }
15281
15282
15283 void AnalyzeStackOfDynamicScriptWithSourceURL(
15284     const v8::FunctionCallbackInfo<v8::Value>& args) {
15285   v8::HandleScope scope(args.GetIsolate());
15286   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15287       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15288   CHECK_EQ(4, stackTrace->GetFrameCount());
15289   v8::Handle<v8::String> url = v8_str("source_url");
15290   for (int i = 0; i < 3; i++) {
15291     v8::Handle<v8::String> name =
15292         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15293     CHECK(!name.IsEmpty());
15294     CHECK(url->Equals(name));
15295   }
15296 }
15297
15298
15299 TEST(DynamicWithSourceURLInStackTrace) {
15300   v8::Isolate* isolate = CcTest::isolate();
15301   v8::HandleScope scope(isolate);
15302   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15303   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
15304              v8::FunctionTemplate::New(
15305                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
15306   LocalContext context(0, templ);
15307
15308   const char *source =
15309     "function outer() {\n"
15310     "function bar() {\n"
15311     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
15312     "}\n"
15313     "function foo() {\n"
15314     "\n"
15315     "  bar();\n"
15316     "}\n"
15317     "foo();\n"
15318     "}\n"
15319     "outer()\n%s";
15320
15321   i::ScopedVector<char> code(1024);
15322   i::SNPrintF(code, source, "//# sourceURL=source_url");
15323   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
15324   i::SNPrintF(code, source, "//@ sourceURL=source_url");
15325   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
15326 }
15327
15328
15329 TEST(DynamicWithSourceURLInStackTraceString) {
15330   LocalContext context;
15331   v8::HandleScope scope(context->GetIsolate());
15332
15333   const char *source =
15334     "function outer() {\n"
15335     "  function foo() {\n"
15336     "    FAIL.FAIL;\n"
15337     "  }\n"
15338     "  foo();\n"
15339     "}\n"
15340     "outer()\n%s";
15341
15342   i::ScopedVector<char> code(1024);
15343   i::SNPrintF(code, source, "//# sourceURL=source_url");
15344   v8::TryCatch try_catch(context->GetIsolate());
15345   CompileRunWithOrigin(code.start(), "", 0, 0);
15346   CHECK(try_catch.HasCaught());
15347   v8::String::Utf8Value stack(try_catch.StackTrace());
15348   CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
15349 }
15350
15351
15352 TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
15353   LocalContext context;
15354   v8::HandleScope scope(context->GetIsolate());
15355
15356   const char *source =
15357     "function outer() {\n"
15358     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
15359     "  //# sourceURL=source_url\";\n"
15360     "  eval(scriptContents);\n"
15361     "  foo(); }\n"
15362     "outer();\n"
15363     "//# sourceURL=outer_url";
15364
15365   v8::TryCatch try_catch(context->GetIsolate());
15366   CompileRun(source);
15367   CHECK(try_catch.HasCaught());
15368
15369   Local<v8::Message> message = try_catch.Message();
15370   Handle<Value> sourceURL =
15371     message->GetScriptOrigin().ResourceName();
15372   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
15373 }
15374
15375
15376 TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
15377   LocalContext context;
15378   v8::HandleScope scope(context->GetIsolate());
15379
15380   const char *source =
15381     "function outer() {\n"
15382     "  var scriptContents = \"function boo(){ boo(); }\\\n"
15383     "  //# sourceURL=source_url\";\n"
15384     "  eval(scriptContents);\n"
15385     "  boo(); }\n"
15386     "outer();\n"
15387     "//# sourceURL=outer_url";
15388
15389   v8::TryCatch try_catch(context->GetIsolate());
15390   CompileRun(source);
15391   CHECK(try_catch.HasCaught());
15392
15393   Local<v8::Message> message = try_catch.Message();
15394   Handle<Value> sourceURL =
15395     message->GetScriptOrigin().ResourceName();
15396   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
15397 }
15398
15399
15400 static void CreateGarbageInOldSpace() {
15401   i::Factory* factory = CcTest::i_isolate()->factory();
15402   v8::HandleScope scope(CcTest::isolate());
15403   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
15404   for (int i = 0; i < 1000; i++) {
15405     factory->NewFixedArray(1000, i::TENURED);
15406   }
15407 }
15408
15409
15410 // Test that idle notification can be handled and eventually collects garbage.
15411 TEST(TestIdleNotification) {
15412   if (!i::FLAG_incremental_marking) return;
15413   const intptr_t MB = 1024 * 1024;
15414   const double IdlePauseInSeconds = 1.0;
15415   LocalContext env;
15416   v8::HandleScope scope(env->GetIsolate());
15417   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
15418   CreateGarbageInOldSpace();
15419   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
15420   CHECK_GT(size_with_garbage, initial_size + MB);
15421   bool finished = false;
15422   for (int i = 0; i < 200 && !finished; i++) {
15423     if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
15424       CcTest::heap()->StartIdleIncrementalMarking();
15425     }
15426     finished = env->GetIsolate()->IdleNotificationDeadline(
15427         (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
15428          static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
15429         IdlePauseInSeconds);
15430     if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
15431       CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
15432     }
15433   }
15434   intptr_t final_size = CcTest::heap()->SizeOfObjects();
15435   CHECK(finished);
15436   CHECK_LT(final_size, initial_size + 1);
15437 }
15438
15439
15440 TEST(Regress2333) {
15441   LocalContext env;
15442   for (int i = 0; i < 3; i++) {
15443     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
15444   }
15445 }
15446
15447 static uint32_t* stack_limit;
15448
15449 static void GetStackLimitCallback(
15450     const v8::FunctionCallbackInfo<v8::Value>& args) {
15451   stack_limit = reinterpret_cast<uint32_t*>(
15452       CcTest::i_isolate()->stack_guard()->real_climit());
15453 }
15454
15455
15456 // Uses the address of a local variable to determine the stack top now.
15457 // Given a size, returns an address that is that far from the current
15458 // top of stack.
15459 static uint32_t* ComputeStackLimit(uint32_t size) {
15460   uint32_t* answer = &size - (size / sizeof(size));
15461   // If the size is very large and the stack is very near the bottom of
15462   // memory then the calculation above may wrap around and give an address
15463   // that is above the (downwards-growing) stack.  In that case we return
15464   // a very low address.
15465   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
15466   return answer;
15467 }
15468
15469
15470 // We need at least 165kB for an x64 debug build with clang and ASAN.
15471 static const int stack_breathing_room = 256 * i::KB;
15472
15473
15474 TEST(SetStackLimit) {
15475   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
15476
15477   // Set stack limit.
15478   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
15479
15480   // Execute a script.
15481   LocalContext env;
15482   v8::HandleScope scope(env->GetIsolate());
15483   Local<v8::FunctionTemplate> fun_templ =
15484       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
15485   Local<Function> fun = fun_templ->GetFunction();
15486   env->Global()->Set(v8_str("get_stack_limit"), fun);
15487   CompileRun("get_stack_limit();");
15488
15489   CHECK(stack_limit == set_limit);
15490 }
15491
15492
15493 TEST(SetStackLimitInThread) {
15494   uint32_t* set_limit;
15495   {
15496     v8::Locker locker(CcTest::isolate());
15497     set_limit = ComputeStackLimit(stack_breathing_room);
15498
15499     // Set stack limit.
15500     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
15501
15502     // Execute a script.
15503     v8::HandleScope scope(CcTest::isolate());
15504     LocalContext env;
15505     Local<v8::FunctionTemplate> fun_templ =
15506         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
15507     Local<Function> fun = fun_templ->GetFunction();
15508     env->Global()->Set(v8_str("get_stack_limit"), fun);
15509     CompileRun("get_stack_limit();");
15510
15511     CHECK(stack_limit == set_limit);
15512   }
15513   {
15514     v8::Locker locker(CcTest::isolate());
15515     CHECK(stack_limit == set_limit);
15516   }
15517 }
15518
15519
15520 THREADED_TEST(GetHeapStatistics) {
15521   LocalContext c1;
15522   v8::HandleScope scope(c1->GetIsolate());
15523   v8::HeapStatistics heap_statistics;
15524   CHECK_EQ(0u, heap_statistics.total_heap_size());
15525   CHECK_EQ(0u, heap_statistics.used_heap_size());
15526   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
15527   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
15528   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
15529 }
15530
15531
15532 class VisitorImpl : public v8::ExternalResourceVisitor {
15533  public:
15534   explicit VisitorImpl(TestResource** resource) {
15535     for (int i = 0; i < 4; i++) {
15536       resource_[i] = resource[i];
15537       found_resource_[i] = false;
15538     }
15539   }
15540   virtual ~VisitorImpl() {}
15541   virtual void VisitExternalString(v8::Handle<v8::String> string) {
15542     if (!string->IsExternal()) {
15543       CHECK(string->IsExternalOneByte());
15544       return;
15545     }
15546     v8::String::ExternalStringResource* resource =
15547         string->GetExternalStringResource();
15548     CHECK(resource);
15549     for (int i = 0; i < 4; i++) {
15550       if (resource_[i] == resource) {
15551         CHECK(!found_resource_[i]);
15552         found_resource_[i] = true;
15553       }
15554     }
15555   }
15556   void CheckVisitedResources() {
15557     for (int i = 0; i < 4; i++) {
15558       CHECK(found_resource_[i]);
15559     }
15560   }
15561
15562  private:
15563   v8::String::ExternalStringResource* resource_[4];
15564   bool found_resource_[4];
15565 };
15566
15567
15568 TEST(ExternalizeOldSpaceTwoByteCons) {
15569   v8::Isolate* isolate = CcTest::isolate();
15570   LocalContext env;
15571   v8::HandleScope scope(isolate);
15572   v8::Local<v8::String> cons =
15573       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
15574   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
15575   CcTest::heap()->CollectAllAvailableGarbage();
15576   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
15577
15578   TestResource* resource = new TestResource(
15579       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
15580   cons->MakeExternal(resource);
15581
15582   CHECK(cons->IsExternal());
15583   CHECK_EQ(resource, cons->GetExternalStringResource());
15584   String::Encoding encoding;
15585   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
15586   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
15587 }
15588
15589
15590 TEST(ExternalizeOldSpaceOneByteCons) {
15591   v8::Isolate* isolate = CcTest::isolate();
15592   LocalContext env;
15593   v8::HandleScope scope(isolate);
15594   v8::Local<v8::String> cons =
15595       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
15596   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
15597   CcTest::heap()->CollectAllAvailableGarbage();
15598   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
15599
15600   TestOneByteResource* resource =
15601       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
15602   cons->MakeExternal(resource);
15603
15604   CHECK(cons->IsExternalOneByte());
15605   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
15606   String::Encoding encoding;
15607   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
15608   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
15609 }
15610
15611
15612 TEST(VisitExternalStrings) {
15613   v8::Isolate* isolate = CcTest::isolate();
15614   LocalContext env;
15615   v8::HandleScope scope(isolate);
15616   const char* string = "Some string";
15617   uint16_t* two_byte_string = AsciiToTwoByteString(string);
15618   TestResource* resource[4];
15619   resource[0] = new TestResource(two_byte_string);
15620   v8::Local<v8::String> string0 =
15621       v8::String::NewExternal(env->GetIsolate(), resource[0]);
15622   resource[1] = new TestResource(two_byte_string, NULL, false);
15623   v8::Local<v8::String> string1 =
15624       v8::String::NewExternal(env->GetIsolate(), resource[1]);
15625
15626   // Externalized symbol.
15627   resource[2] = new TestResource(two_byte_string, NULL, false);
15628   v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
15629       env->GetIsolate(), string, v8::String::kInternalizedString);
15630   CHECK(string2->MakeExternal(resource[2]));
15631
15632   // Symbolized External.
15633   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
15634   v8::Local<v8::String> string3 =
15635       v8::String::NewExternal(env->GetIsolate(), resource[3]);
15636   CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
15637   // Turn into a symbol.
15638   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
15639   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
15640       string3_i).is_null());
15641   CHECK(string3_i->IsInternalizedString());
15642
15643   // We need to add usages for string* to avoid warnings in GCC 4.7
15644   CHECK(string0->IsExternal());
15645   CHECK(string1->IsExternal());
15646   CHECK(string2->IsExternal());
15647   CHECK(string3->IsExternal());
15648
15649   VisitorImpl visitor(resource);
15650   v8::V8::VisitExternalResources(&visitor);
15651   visitor.CheckVisitedResources();
15652 }
15653
15654
15655 TEST(ExternalStringCollectedAtTearDown) {
15656   int destroyed = 0;
15657   v8::Isolate::CreateParams create_params;
15658   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
15659   v8::Isolate* isolate = v8::Isolate::New(create_params);
15660   { v8::Isolate::Scope isolate_scope(isolate);
15661     v8::HandleScope handle_scope(isolate);
15662     const char* s = "One string to test them all, one string to find them.";
15663     TestOneByteResource* inscription =
15664         new TestOneByteResource(i::StrDup(s), &destroyed);
15665     v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
15666     // Ring is still alive.  Orcs are roaming freely across our lands.
15667     CHECK_EQ(0, destroyed);
15668     USE(ring);
15669   }
15670
15671   isolate->Dispose();
15672   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
15673   CHECK_EQ(1, destroyed);
15674 }
15675
15676
15677 TEST(ExternalInternalizedStringCollectedAtTearDown) {
15678   int destroyed = 0;
15679   v8::Isolate::CreateParams create_params;
15680   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
15681   v8::Isolate* isolate = v8::Isolate::New(create_params);
15682   { v8::Isolate::Scope isolate_scope(isolate);
15683     LocalContext env(isolate);
15684     v8::HandleScope handle_scope(isolate);
15685     CompileRun("var ring = 'One string to test them all';");
15686     const char* s = "One string to test them all";
15687     TestOneByteResource* inscription =
15688         new TestOneByteResource(i::StrDup(s), &destroyed);
15689     v8::Local<v8::String> ring = CompileRun("ring")->ToString(isolate);
15690     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
15691     ring->MakeExternal(inscription);
15692     // Ring is still alive.  Orcs are roaming freely across our lands.
15693     CHECK_EQ(0, destroyed);
15694     USE(ring);
15695   }
15696
15697   isolate->Dispose();
15698   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
15699   CHECK_EQ(1, destroyed);
15700 }
15701
15702
15703 TEST(ExternalInternalizedStringCollectedAtGC) {
15704   int destroyed = 0;
15705   { LocalContext env;
15706     v8::HandleScope handle_scope(env->GetIsolate());
15707     CompileRun("var ring = 'One string to test them all';");
15708     const char* s = "One string to test them all";
15709     TestOneByteResource* inscription =
15710         new TestOneByteResource(i::StrDup(s), &destroyed);
15711     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
15712     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
15713     ring->MakeExternal(inscription);
15714     // Ring is still alive.  Orcs are roaming freely across our lands.
15715     CHECK_EQ(0, destroyed);
15716     USE(ring);
15717   }
15718
15719   // Garbage collector deals swift blows to evil.
15720   CcTest::i_isolate()->compilation_cache()->Clear();
15721   CcTest::heap()->CollectAllAvailableGarbage();
15722
15723   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
15724   CHECK_EQ(1, destroyed);
15725 }
15726
15727
15728 static double DoubleFromBits(uint64_t value) {
15729   double target;
15730   i::MemCopy(&target, &value, sizeof(target));
15731   return target;
15732 }
15733
15734
15735 static uint64_t DoubleToBits(double value) {
15736   uint64_t target;
15737   i::MemCopy(&target, &value, sizeof(target));
15738   return target;
15739 }
15740
15741
15742 static double DoubleToDateTime(double input) {
15743   double date_limit = 864e13;
15744   if (std::isnan(input) || input < -date_limit || input > date_limit) {
15745     return std::numeric_limits<double>::quiet_NaN();
15746   }
15747   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
15748 }
15749
15750
15751 // We don't have a consistent way to write 64-bit constants syntactically, so we
15752 // split them into two 32-bit constants and combine them programmatically.
15753 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
15754   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
15755 }
15756
15757
15758 THREADED_TEST(QuietSignalingNaNs) {
15759   LocalContext context;
15760   v8::Isolate* isolate = context->GetIsolate();
15761   v8::HandleScope scope(isolate);
15762   v8::TryCatch try_catch(isolate);
15763
15764   // Special double values.
15765   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
15766   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
15767   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
15768   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
15769   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
15770   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
15771   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
15772
15773   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
15774   // on either side of the epoch.
15775   double date_limit = 864e13;
15776
15777   double test_values[] = {
15778       snan,
15779       qnan,
15780       infinity,
15781       max_normal,
15782       date_limit + 1,
15783       date_limit,
15784       min_normal,
15785       max_denormal,
15786       min_denormal,
15787       0,
15788       -0,
15789       -min_denormal,
15790       -max_denormal,
15791       -min_normal,
15792       -date_limit,
15793       -date_limit - 1,
15794       -max_normal,
15795       -infinity,
15796       -qnan,
15797       -snan
15798   };
15799   int num_test_values = 20;
15800
15801   for (int i = 0; i < num_test_values; i++) {
15802     double test_value = test_values[i];
15803
15804     // Check that Number::New preserves non-NaNs and quiets SNaNs.
15805     v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
15806     double stored_number = number->NumberValue();
15807     if (!std::isnan(test_value)) {
15808       CHECK_EQ(test_value, stored_number);
15809     } else {
15810       uint64_t stored_bits = DoubleToBits(stored_number);
15811       // Check if quiet nan (bits 51..62 all set).
15812 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
15813     !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
15814       // Most significant fraction bit for quiet nan is set to 0
15815       // on MIPS architecture. Allowed by IEEE-754.
15816       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
15817 #else
15818       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
15819 #endif
15820     }
15821
15822     // Check that Date::New preserves non-NaNs in the date range and
15823     // quiets SNaNs.
15824     v8::Handle<v8::Value> date =
15825         v8::Date::New(isolate, test_value);
15826     double expected_stored_date = DoubleToDateTime(test_value);
15827     double stored_date = date->NumberValue();
15828     if (!std::isnan(expected_stored_date)) {
15829       CHECK_EQ(expected_stored_date, stored_date);
15830     } else {
15831       uint64_t stored_bits = DoubleToBits(stored_date);
15832       // Check if quiet nan (bits 51..62 all set).
15833 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
15834     !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
15835       // Most significant fraction bit for quiet nan is set to 0
15836       // on MIPS architecture. Allowed by IEEE-754.
15837       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
15838 #else
15839       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
15840 #endif
15841     }
15842   }
15843 }
15844
15845
15846 static void SpaghettiIncident(
15847     const v8::FunctionCallbackInfo<v8::Value>& args) {
15848   v8::HandleScope scope(args.GetIsolate());
15849   v8::TryCatch tc(args.GetIsolate());
15850   v8::Handle<v8::String> str(args[0]->ToString(args.GetIsolate()));
15851   USE(str);
15852   if (tc.HasCaught())
15853     tc.ReThrow();
15854 }
15855
15856
15857 // Test that an exception can be propagated down through a spaghetti
15858 // stack using ReThrow.
15859 THREADED_TEST(SpaghettiStackReThrow) {
15860   v8::Isolate* isolate = CcTest::isolate();
15861   v8::HandleScope scope(isolate);
15862   LocalContext context;
15863   context->Global()->Set(
15864       v8::String::NewFromUtf8(isolate, "s"),
15865       v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
15866   v8::TryCatch try_catch(isolate);
15867   CompileRun(
15868       "var i = 0;"
15869       "var o = {"
15870       "  toString: function () {"
15871       "    if (i == 10) {"
15872       "      throw 'Hey!';"
15873       "    } else {"
15874       "      i++;"
15875       "      return s(o);"
15876       "    }"
15877       "  }"
15878       "};"
15879       "s(o);");
15880   CHECK(try_catch.HasCaught());
15881   v8::String::Utf8Value value(try_catch.Exception());
15882   CHECK_EQ(0, strcmp(*value, "Hey!"));
15883 }
15884
15885
15886 TEST(Regress528) {
15887   v8::V8::Initialize();
15888   v8::Isolate* isolate = CcTest::isolate();
15889   i::FLAG_retain_maps_for_n_gc = 0;
15890   v8::HandleScope scope(isolate);
15891   v8::Local<Context> other_context;
15892   int gc_count;
15893
15894   // Create a context used to keep the code from aging in the compilation
15895   // cache.
15896   other_context = Context::New(isolate);
15897
15898   // Context-dependent context data creates reference from the compilation
15899   // cache to the global object.
15900   const char* source_simple = "1";
15901   {
15902     v8::HandleScope scope(isolate);
15903     v8::Local<Context> context = Context::New(isolate);
15904
15905     context->Enter();
15906     Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
15907     context->SetEmbedderData(0, obj);
15908     CompileRun(source_simple);
15909     context->Exit();
15910   }
15911   isolate->ContextDisposedNotification();
15912   for (gc_count = 1; gc_count < 10; gc_count++) {
15913     other_context->Enter();
15914     CompileRun(source_simple);
15915     other_context->Exit();
15916     CcTest::heap()->CollectAllGarbage();
15917     if (GetGlobalObjectsCount() == 1) break;
15918   }
15919   CHECK_GE(2, gc_count);
15920   CHECK_EQ(1, GetGlobalObjectsCount());
15921
15922   // Eval in a function creates reference from the compilation cache to the
15923   // global object.
15924   const char* source_eval = "function f(){eval('1')}; f()";
15925   {
15926     v8::HandleScope scope(isolate);
15927     v8::Local<Context> context = Context::New(isolate);
15928
15929     context->Enter();
15930     CompileRun(source_eval);
15931     context->Exit();
15932   }
15933   isolate->ContextDisposedNotification();
15934   for (gc_count = 1; gc_count < 10; gc_count++) {
15935     other_context->Enter();
15936     CompileRun(source_eval);
15937     other_context->Exit();
15938     CcTest::heap()->CollectAllGarbage();
15939     if (GetGlobalObjectsCount() == 1) break;
15940   }
15941   CHECK_GE(2, gc_count);
15942   CHECK_EQ(1, GetGlobalObjectsCount());
15943
15944   // Looking up the line number for an exception creates reference from the
15945   // compilation cache to the global object.
15946   const char* source_exception = "function f(){throw 1;} f()";
15947   {
15948     v8::HandleScope scope(isolate);
15949     v8::Local<Context> context = Context::New(isolate);
15950
15951     context->Enter();
15952     v8::TryCatch try_catch(isolate);
15953     CompileRun(source_exception);
15954     CHECK(try_catch.HasCaught());
15955     v8::Handle<v8::Message> message = try_catch.Message();
15956     CHECK(!message.IsEmpty());
15957     CHECK_EQ(1, message->GetLineNumber());
15958     context->Exit();
15959   }
15960   isolate->ContextDisposedNotification();
15961   for (gc_count = 1; gc_count < 10; gc_count++) {
15962     other_context->Enter();
15963     CompileRun(source_exception);
15964     other_context->Exit();
15965     CcTest::heap()->CollectAllGarbage();
15966     if (GetGlobalObjectsCount() == 1) break;
15967   }
15968   CHECK_GE(2, gc_count);
15969   CHECK_EQ(1, GetGlobalObjectsCount());
15970
15971   isolate->ContextDisposedNotification();
15972 }
15973
15974
15975 THREADED_TEST(ScriptOrigin) {
15976   LocalContext env;
15977   v8::HandleScope scope(env->GetIsolate());
15978   v8::ScriptOrigin origin = v8::ScriptOrigin(
15979       v8::String::NewFromUtf8(env->GetIsolate(), "test"),
15980       v8::Integer::New(env->GetIsolate(), 1),
15981       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
15982       v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()),
15983       v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl"),
15984       v8::True(env->GetIsolate()));
15985   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
15986       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
15987   v8::Script::Compile(script, &origin)->Run();
15988   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15989       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
15990   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
15991       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
15992
15993   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
15994   CHECK_EQ(0, strcmp("test",
15995                      *v8::String::Utf8Value(script_origin_f.ResourceName())));
15996   CHECK_EQ(1, script_origin_f.ResourceLineOffset()->Int32Value());
15997   CHECK(script_origin_f.Options().IsSharedCrossOrigin());
15998   CHECK(script_origin_f.Options().IsEmbedderDebugScript());
15999   CHECK(script_origin_f.Options().IsOpaque());
16000   printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
16001
16002   CHECK_EQ(0, strcmp("http://sourceMapUrl",
16003                      *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
16004
16005   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
16006   CHECK_EQ(0, strcmp("test",
16007                      *v8::String::Utf8Value(script_origin_g.ResourceName())));
16008   CHECK_EQ(1, script_origin_g.ResourceLineOffset()->Int32Value());
16009   CHECK(script_origin_g.Options().IsSharedCrossOrigin());
16010   CHECK(script_origin_g.Options().IsEmbedderDebugScript());
16011   CHECK(script_origin_g.Options().IsOpaque());
16012   CHECK_EQ(0, strcmp("http://sourceMapUrl",
16013                      *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
16014 }
16015
16016
16017 THREADED_TEST(FunctionGetInferredName) {
16018   LocalContext env;
16019   v8::HandleScope scope(env->GetIsolate());
16020   v8::ScriptOrigin origin =
16021       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16022   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16023       env->GetIsolate(),
16024       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
16025   v8::Script::Compile(script, &origin)->Run();
16026   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16027       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16028   CHECK_EQ(0,
16029            strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
16030 }
16031
16032
16033 THREADED_TEST(FunctionGetDisplayName) {
16034   LocalContext env;
16035   v8::HandleScope scope(env->GetIsolate());
16036   const char* code = "var error = false;"
16037                      "function a() { this.x = 1; };"
16038                      "a.displayName = 'display_a';"
16039                      "var b = (function() {"
16040                      "  var f = function() { this.x = 2; };"
16041                      "  f.displayName = 'display_b';"
16042                      "  return f;"
16043                      "})();"
16044                      "var c = function() {};"
16045                      "c.__defineGetter__('displayName', function() {"
16046                      "  error = true;"
16047                      "  throw new Error();"
16048                      "});"
16049                      "function d() {};"
16050                      "d.__defineGetter__('displayName', function() {"
16051                      "  error = true;"
16052                      "  return 'wrong_display_name';"
16053                      "});"
16054                      "function e() {};"
16055                      "e.displayName = 'wrong_display_name';"
16056                      "e.__defineSetter__('displayName', function() {"
16057                      "  error = true;"
16058                      "  throw new Error();"
16059                      "});"
16060                      "function f() {};"
16061                      "f.displayName = { 'foo': 6, toString: function() {"
16062                      "  error = true;"
16063                      "  return 'wrong_display_name';"
16064                      "}};"
16065                      "var g = function() {"
16066                      "  arguments.callee.displayName = 'set_in_runtime';"
16067                      "}; g();"
16068                      ;
16069   v8::ScriptOrigin origin =
16070       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16071   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
16072       ->Run();
16073   v8::Local<v8::Value> error =
16074       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
16075   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
16076       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
16077   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
16078       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
16079   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
16080       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
16081   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
16082       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
16083   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
16084       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
16085   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16086       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16087   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16088       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16089   CHECK_EQ(false, error->BooleanValue());
16090   CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
16091   CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
16092   CHECK(c->GetDisplayName()->IsUndefined());
16093   CHECK(d->GetDisplayName()->IsUndefined());
16094   CHECK(e->GetDisplayName()->IsUndefined());
16095   CHECK(f->GetDisplayName()->IsUndefined());
16096   CHECK_EQ(
16097       0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
16098 }
16099
16100
16101 THREADED_TEST(ScriptLineNumber) {
16102   LocalContext env;
16103   v8::HandleScope scope(env->GetIsolate());
16104   v8::ScriptOrigin origin =
16105       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16106   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16107       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
16108   v8::Script::Compile(script, &origin)->Run();
16109   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16110       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16111   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16112       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16113   CHECK_EQ(0, f->GetScriptLineNumber());
16114   CHECK_EQ(2, g->GetScriptLineNumber());
16115 }
16116
16117
16118 THREADED_TEST(ScriptColumnNumber) {
16119   LocalContext env;
16120   v8::Isolate* isolate = env->GetIsolate();
16121   v8::HandleScope scope(isolate);
16122   v8::ScriptOrigin origin =
16123       v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
16124                        v8::Integer::New(isolate, 3),
16125                        v8::Integer::New(isolate, 2));
16126   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16127       isolate, "function foo() {}\n\n     function bar() {}");
16128   v8::Script::Compile(script, &origin)->Run();
16129   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
16130       env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
16131   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
16132       env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
16133   CHECK_EQ(14, foo->GetScriptColumnNumber());
16134   CHECK_EQ(17, bar->GetScriptColumnNumber());
16135 }
16136
16137
16138 THREADED_TEST(FunctionIsBuiltin) {
16139   LocalContext env;
16140   v8::Isolate* isolate = env->GetIsolate();
16141   v8::HandleScope scope(isolate);
16142   v8::Local<v8::Function> f;
16143   f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
16144   CHECK(f->IsBuiltin());
16145   f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
16146   CHECK(f->IsBuiltin());
16147   f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
16148   CHECK(f->IsBuiltin());
16149   f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
16150   CHECK(f->IsBuiltin());
16151   f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
16152   CHECK(!f->IsBuiltin());
16153 }
16154
16155
16156 THREADED_TEST(FunctionGetScriptId) {
16157   LocalContext env;
16158   v8::Isolate* isolate = env->GetIsolate();
16159   v8::HandleScope scope(isolate);
16160   v8::ScriptOrigin origin =
16161       v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
16162                        v8::Integer::New(isolate, 3),
16163                        v8::Integer::New(isolate, 2));
16164   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
16165       isolate, "function foo() {}\n\n     function bar() {}");
16166   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
16167   script->Run();
16168   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
16169       env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
16170   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
16171       env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
16172   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
16173   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
16174 }
16175
16176
16177 THREADED_TEST(FunctionGetBoundFunction) {
16178   LocalContext env;
16179   v8::HandleScope scope(env->GetIsolate());
16180   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
16181       env->GetIsolate(), "test"));
16182   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16183       env->GetIsolate(),
16184       "var a = new Object();\n"
16185       "a.x = 1;\n"
16186       "function f () { return this.x };\n"
16187       "var g = f.bind(a);\n"
16188       "var b = g();");
16189   v8::Script::Compile(script, &origin)->Run();
16190   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16191       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16192   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16193       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16194   CHECK(g->GetBoundFunction()->IsFunction());
16195   Local<v8::Function> original_function = Local<v8::Function>::Cast(
16196       g->GetBoundFunction());
16197   CHECK(f->GetName()->Equals(original_function->GetName()));
16198   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
16199   CHECK_EQ(f->GetScriptColumnNumber(),
16200            original_function->GetScriptColumnNumber());
16201 }
16202
16203
16204 static void GetterWhichReturns42(
16205     Local<String> name,
16206     const v8::PropertyCallbackInfo<v8::Value>& info) {
16207   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16208   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16209   info.GetReturnValue().Set(v8_num(42));
16210 }
16211
16212
16213 static void SetterWhichSetsYOnThisTo23(
16214     Local<String> name,
16215     Local<Value> value,
16216     const v8::PropertyCallbackInfo<void>& info) {
16217   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16218   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16219   Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16220 }
16221
16222
16223 void FooGetInterceptor(Local<Name> name,
16224                        const v8::PropertyCallbackInfo<v8::Value>& info) {
16225   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16226   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16227   if (!name->Equals(v8_str("foo"))) return;
16228   info.GetReturnValue().Set(v8_num(42));
16229 }
16230
16231
16232 void FooSetInterceptor(Local<Name> name, Local<Value> value,
16233                        const v8::PropertyCallbackInfo<v8::Value>& info) {
16234   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16235   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16236   if (!name->Equals(v8_str("foo"))) return;
16237   Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16238   info.GetReturnValue().Set(v8_num(23));
16239 }
16240
16241
16242 TEST(SetterOnConstructorPrototype) {
16243   v8::Isolate* isolate = CcTest::isolate();
16244   v8::HandleScope scope(isolate);
16245   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16246   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
16247                      SetterWhichSetsYOnThisTo23);
16248   LocalContext context;
16249   context->Global()->Set(v8_str("P"), templ->NewInstance());
16250   CompileRun("function C1() {"
16251              "  this.x = 23;"
16252              "};"
16253              "C1.prototype = P;"
16254              "function C2() {"
16255              "  this.x = 23"
16256              "};"
16257              "C2.prototype = { };"
16258              "C2.prototype.__proto__ = P;");
16259
16260   v8::Local<v8::Script> script;
16261   script = v8_compile("new C1();");
16262   for (int i = 0; i < 10; i++) {
16263     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16264     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
16265     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
16266   }
16267
16268 script = v8_compile("new C2();");
16269   for (int i = 0; i < 10; i++) {
16270     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
16271     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
16272     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
16273   }
16274 }
16275
16276
16277 static void NamedPropertyGetterWhichReturns42(
16278     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
16279   info.GetReturnValue().Set(v8_num(42));
16280 }
16281
16282
16283 static void NamedPropertySetterWhichSetsYOnThisTo23(
16284     Local<Name> name, Local<Value> value,
16285     const v8::PropertyCallbackInfo<v8::Value>& info) {
16286   if (name->Equals(v8_str("x"))) {
16287     Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16288   }
16289 }
16290
16291
16292 THREADED_TEST(InterceptorOnConstructorPrototype) {
16293   v8::Isolate* isolate = CcTest::isolate();
16294   v8::HandleScope scope(isolate);
16295   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16296   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
16297       NamedPropertyGetterWhichReturns42,
16298       NamedPropertySetterWhichSetsYOnThisTo23));
16299   LocalContext context;
16300   context->Global()->Set(v8_str("P"), templ->NewInstance());
16301   CompileRun("function C1() {"
16302              "  this.x = 23;"
16303              "};"
16304              "C1.prototype = P;"
16305              "function C2() {"
16306              "  this.x = 23"
16307              "};"
16308              "C2.prototype = { };"
16309              "C2.prototype.__proto__ = P;");
16310
16311   v8::Local<v8::Script> script;
16312   script = v8_compile("new C1();");
16313   for (int i = 0; i < 10; i++) {
16314     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16315     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
16316     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
16317   }
16318
16319   script = v8_compile("new C2();");
16320   for (int i = 0; i < 10; i++) {
16321     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
16322     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
16323     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
16324   }
16325 }
16326
16327
16328 TEST(Regress618) {
16329   const char* source = "function C1() {"
16330                        "  this.x = 23;"
16331                        "};"
16332                        "C1.prototype = P;";
16333
16334   LocalContext context;
16335   v8::Isolate* isolate = context->GetIsolate();
16336   v8::HandleScope scope(isolate);
16337   v8::Local<v8::Script> script;
16338
16339   // Use a simple object as prototype.
16340   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
16341   prototype->Set(v8_str("y"), v8_num(42));
16342   context->Global()->Set(v8_str("P"), prototype);
16343
16344   // This compile will add the code to the compilation cache.
16345   CompileRun(source);
16346
16347   script = v8_compile("new C1();");
16348   // Allow enough iterations for the inobject slack tracking logic
16349   // to finalize instance size and install the fast construct stub.
16350   for (int i = 0; i < 256; i++) {
16351     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16352     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
16353     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
16354   }
16355
16356   // Use an API object with accessors as prototype.
16357   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16358   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
16359                      SetterWhichSetsYOnThisTo23);
16360   context->Global()->Set(v8_str("P"), templ->NewInstance());
16361
16362   // This compile will get the code from the compilation cache.
16363   CompileRun(source);
16364
16365   script = v8_compile("new C1();");
16366   for (int i = 0; i < 10; i++) {
16367     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16368     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
16369     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
16370   }
16371 }
16372
16373 v8::Isolate* gc_callbacks_isolate = NULL;
16374 int prologue_call_count = 0;
16375 int epilogue_call_count = 0;
16376 int prologue_call_count_second = 0;
16377 int epilogue_call_count_second = 0;
16378 int prologue_call_count_alloc = 0;
16379 int epilogue_call_count_alloc = 0;
16380
16381 void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
16382   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16383   ++prologue_call_count;
16384 }
16385
16386
16387 void PrologueCallback(v8::Isolate* isolate,
16388                       v8::GCType,
16389                       v8::GCCallbackFlags flags) {
16390   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16391   CHECK_EQ(gc_callbacks_isolate, isolate);
16392   ++prologue_call_count;
16393 }
16394
16395
16396 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
16397   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16398   ++epilogue_call_count;
16399 }
16400
16401
16402 void EpilogueCallback(v8::Isolate* isolate,
16403                       v8::GCType,
16404                       v8::GCCallbackFlags flags) {
16405   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16406   CHECK_EQ(gc_callbacks_isolate, isolate);
16407   ++epilogue_call_count;
16408 }
16409
16410
16411 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
16412   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16413   ++prologue_call_count_second;
16414 }
16415
16416
16417 void PrologueCallbackSecond(v8::Isolate* isolate,
16418                             v8::GCType,
16419                             v8::GCCallbackFlags flags) {
16420   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16421   CHECK_EQ(gc_callbacks_isolate, isolate);
16422   ++prologue_call_count_second;
16423 }
16424
16425
16426 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
16427   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16428   ++epilogue_call_count_second;
16429 }
16430
16431
16432 void EpilogueCallbackSecond(v8::Isolate* isolate,
16433                             v8::GCType,
16434                             v8::GCCallbackFlags flags) {
16435   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16436   CHECK_EQ(gc_callbacks_isolate, isolate);
16437   ++epilogue_call_count_second;
16438 }
16439
16440
16441 void PrologueCallbackAlloc(v8::Isolate* isolate,
16442                            v8::GCType,
16443                            v8::GCCallbackFlags flags) {
16444   v8::HandleScope scope(isolate);
16445
16446   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16447   CHECK_EQ(gc_callbacks_isolate, isolate);
16448   ++prologue_call_count_alloc;
16449
16450   // Simulate full heap to see if we will reenter this callback
16451   SimulateFullSpace(CcTest::heap()->new_space());
16452
16453   Local<Object> obj = Object::New(isolate);
16454   CHECK(!obj.IsEmpty());
16455
16456   CcTest::heap()->CollectAllGarbage(
16457       i::Heap::kAbortIncrementalMarkingMask);
16458 }
16459
16460
16461 void EpilogueCallbackAlloc(v8::Isolate* isolate,
16462                            v8::GCType,
16463                            v8::GCCallbackFlags flags) {
16464   v8::HandleScope scope(isolate);
16465
16466   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16467   CHECK_EQ(gc_callbacks_isolate, isolate);
16468   ++epilogue_call_count_alloc;
16469
16470   // Simulate full heap to see if we will reenter this callback
16471   SimulateFullSpace(CcTest::heap()->new_space());
16472
16473   Local<Object> obj = Object::New(isolate);
16474   CHECK(!obj.IsEmpty());
16475
16476   CcTest::heap()->CollectAllGarbage(
16477       i::Heap::kAbortIncrementalMarkingMask);
16478 }
16479
16480
16481 TEST(GCCallbacksOld) {
16482   LocalContext context;
16483
16484   v8::V8::AddGCPrologueCallback(PrologueCallback);
16485   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
16486   CHECK_EQ(0, prologue_call_count);
16487   CHECK_EQ(0, epilogue_call_count);
16488   CcTest::heap()->CollectAllGarbage();
16489   CHECK_EQ(1, prologue_call_count);
16490   CHECK_EQ(1, epilogue_call_count);
16491   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
16492   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
16493   CcTest::heap()->CollectAllGarbage();
16494   CHECK_EQ(2, prologue_call_count);
16495   CHECK_EQ(2, epilogue_call_count);
16496   CHECK_EQ(1, prologue_call_count_second);
16497   CHECK_EQ(1, epilogue_call_count_second);
16498   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
16499   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
16500   CcTest::heap()->CollectAllGarbage();
16501   CHECK_EQ(2, prologue_call_count);
16502   CHECK_EQ(2, epilogue_call_count);
16503   CHECK_EQ(2, prologue_call_count_second);
16504   CHECK_EQ(2, epilogue_call_count_second);
16505   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
16506   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
16507   CcTest::heap()->CollectAllGarbage();
16508   CHECK_EQ(2, prologue_call_count);
16509   CHECK_EQ(2, epilogue_call_count);
16510   CHECK_EQ(2, prologue_call_count_second);
16511   CHECK_EQ(2, epilogue_call_count_second);
16512 }
16513
16514
16515 TEST(GCCallbacks) {
16516   LocalContext context;
16517   v8::Isolate* isolate = context->GetIsolate();
16518   gc_callbacks_isolate = isolate;
16519   isolate->AddGCPrologueCallback(PrologueCallback);
16520   isolate->AddGCEpilogueCallback(EpilogueCallback);
16521   CHECK_EQ(0, prologue_call_count);
16522   CHECK_EQ(0, epilogue_call_count);
16523   CcTest::heap()->CollectAllGarbage();
16524   CHECK_EQ(1, prologue_call_count);
16525   CHECK_EQ(1, epilogue_call_count);
16526   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
16527   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
16528   CcTest::heap()->CollectAllGarbage();
16529   CHECK_EQ(2, prologue_call_count);
16530   CHECK_EQ(2, epilogue_call_count);
16531   CHECK_EQ(1, prologue_call_count_second);
16532   CHECK_EQ(1, epilogue_call_count_second);
16533   isolate->RemoveGCPrologueCallback(PrologueCallback);
16534   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
16535   CcTest::heap()->CollectAllGarbage();
16536   CHECK_EQ(2, prologue_call_count);
16537   CHECK_EQ(2, epilogue_call_count);
16538   CHECK_EQ(2, prologue_call_count_second);
16539   CHECK_EQ(2, epilogue_call_count_second);
16540   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
16541   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
16542   CcTest::heap()->CollectAllGarbage();
16543   CHECK_EQ(2, prologue_call_count);
16544   CHECK_EQ(2, epilogue_call_count);
16545   CHECK_EQ(2, prologue_call_count_second);
16546   CHECK_EQ(2, epilogue_call_count_second);
16547
16548   CHECK_EQ(0, prologue_call_count_alloc);
16549   CHECK_EQ(0, epilogue_call_count_alloc);
16550   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
16551   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
16552   CcTest::heap()->CollectAllGarbage(
16553       i::Heap::kAbortIncrementalMarkingMask);
16554   CHECK_EQ(1, prologue_call_count_alloc);
16555   CHECK_EQ(1, epilogue_call_count_alloc);
16556   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
16557   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
16558 }
16559
16560
16561 THREADED_TEST(AddToJSFunctionResultCache) {
16562   i::FLAG_stress_compaction = false;
16563   i::FLAG_allow_natives_syntax = true;
16564   v8::HandleScope scope(CcTest::isolate());
16565
16566   LocalContext context;
16567
16568   const char* code =
16569       "(function() {"
16570       "  var key0 = 'a';"
16571       "  var key1 = 'b';"
16572       "  var r0 = %_GetFromCache(0, key0);"
16573       "  var r1 = %_GetFromCache(0, key1);"
16574       "  var r0_ = %_GetFromCache(0, key0);"
16575       "  if (r0 !== r0_)"
16576       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
16577       "  var r1_ = %_GetFromCache(0, key1);"
16578       "  if (r1 !== r1_)"
16579       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
16580       "  return 'PASSED';"
16581       "})()";
16582   CcTest::heap()->ClearJSFunctionResultCaches();
16583   ExpectString(code, "PASSED");
16584 }
16585
16586
16587 THREADED_TEST(FillJSFunctionResultCache) {
16588   i::FLAG_allow_natives_syntax = true;
16589   LocalContext context;
16590   v8::HandleScope scope(context->GetIsolate());
16591
16592   const char* code =
16593       "(function() {"
16594       "  var k = 'a';"
16595       "  var r = %_GetFromCache(0, k);"
16596       "  for (var i = 0; i < 16; i++) {"
16597       "    %_GetFromCache(0, 'a' + i);"
16598       "  };"
16599       "  if (r === %_GetFromCache(0, k))"
16600       "    return 'FAILED: k0CacheSize is too small';"
16601       "  return 'PASSED';"
16602       "})()";
16603   CcTest::heap()->ClearJSFunctionResultCaches();
16604   ExpectString(code, "PASSED");
16605 }
16606
16607
16608 THREADED_TEST(RoundRobinGetFromCache) {
16609   i::FLAG_allow_natives_syntax = true;
16610   LocalContext context;
16611   v8::HandleScope scope(context->GetIsolate());
16612
16613   const char* code =
16614       "(function() {"
16615       "  var keys = [];"
16616       "  for (var i = 0; i < 16; i++) keys.push(i);"
16617       "  var values = [];"
16618       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
16619       "  for (var i = 0; i < 16; i++) {"
16620       "    var v = %_GetFromCache(0, keys[i]);"
16621       "    if (v.toString() !== values[i].toString())"
16622       "      return 'Wrong value for ' + "
16623       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
16624       "  };"
16625       "  return 'PASSED';"
16626       "})()";
16627   CcTest::heap()->ClearJSFunctionResultCaches();
16628   ExpectString(code, "PASSED");
16629 }
16630
16631
16632 THREADED_TEST(ReverseGetFromCache) {
16633   i::FLAG_allow_natives_syntax = true;
16634   LocalContext context;
16635   v8::HandleScope scope(context->GetIsolate());
16636
16637   const char* code =
16638       "(function() {"
16639       "  var keys = [];"
16640       "  for (var i = 0; i < 16; i++) keys.push(i);"
16641       "  var values = [];"
16642       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
16643       "  for (var i = 15; i >= 16; i--) {"
16644       "    var v = %_GetFromCache(0, keys[i]);"
16645       "    if (v !== values[i])"
16646       "      return 'Wrong value for ' + "
16647       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
16648       "  };"
16649       "  return 'PASSED';"
16650       "})()";
16651   CcTest::heap()->ClearJSFunctionResultCaches();
16652   ExpectString(code, "PASSED");
16653 }
16654
16655
16656 THREADED_TEST(TestEviction) {
16657   i::FLAG_allow_natives_syntax = true;
16658   LocalContext context;
16659   v8::HandleScope scope(context->GetIsolate());
16660
16661   const char* code =
16662       "(function() {"
16663       "  for (var i = 0; i < 2*16; i++) {"
16664       "    %_GetFromCache(0, 'a' + i);"
16665       "  };"
16666       "  return 'PASSED';"
16667       "})()";
16668   CcTest::heap()->ClearJSFunctionResultCaches();
16669   ExpectString(code, "PASSED");
16670 }
16671
16672
16673 THREADED_TEST(TwoByteStringInOneByteCons) {
16674   // See Chromium issue 47824.
16675   LocalContext context;
16676   v8::HandleScope scope(context->GetIsolate());
16677
16678   const char* init_code =
16679       "var str1 = 'abelspendabel';"
16680       "var str2 = str1 + str1 + str1;"
16681       "str2;";
16682   Local<Value> result = CompileRun(init_code);
16683
16684   Local<Value> indexof = CompileRun("str2.indexOf('els')");
16685   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
16686
16687   CHECK(result->IsString());
16688   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
16689   int length = string->length();
16690   CHECK(string->IsOneByteRepresentation());
16691
16692   i::Handle<i::String> flat_string = i::String::Flatten(string);
16693
16694   CHECK(string->IsOneByteRepresentation());
16695   CHECK(flat_string->IsOneByteRepresentation());
16696
16697   // Create external resource.
16698   uint16_t* uc16_buffer = new uint16_t[length + 1];
16699
16700   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
16701   uc16_buffer[length] = 0;
16702
16703   TestResource resource(uc16_buffer);
16704
16705   flat_string->MakeExternal(&resource);
16706
16707   CHECK(flat_string->IsTwoByteRepresentation());
16708
16709   // If the cons string has been short-circuited, skip the following checks.
16710   if (!string.is_identical_to(flat_string)) {
16711     // At this point, we should have a Cons string which is flat and one-byte,
16712     // with a first half that is a two-byte string (although it only contains
16713     // one-byte characters). This is a valid sequence of steps, and it can
16714     // happen in real pages.
16715     CHECK(string->IsOneByteRepresentation());
16716     i::ConsString* cons = i::ConsString::cast(*string);
16717     CHECK_EQ(0, cons->second()->length());
16718     CHECK(cons->first()->IsTwoByteRepresentation());
16719   }
16720
16721   // Check that some string operations work.
16722
16723   // Atom RegExp.
16724   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
16725   CHECK_EQ(6, reresult->Int32Value());
16726
16727   // Nonatom RegExp.
16728   reresult = CompileRun("str2.match(/abe./g).length;");
16729   CHECK_EQ(6, reresult->Int32Value());
16730
16731   reresult = CompileRun("str2.search(/bel/g);");
16732   CHECK_EQ(1, reresult->Int32Value());
16733
16734   reresult = CompileRun("str2.search(/be./g);");
16735   CHECK_EQ(1, reresult->Int32Value());
16736
16737   ExpectTrue("/bel/g.test(str2);");
16738
16739   ExpectTrue("/be./g.test(str2);");
16740
16741   reresult = CompileRun("/bel/g.exec(str2);");
16742   CHECK(!reresult->IsNull());
16743
16744   reresult = CompileRun("/be./g.exec(str2);");
16745   CHECK(!reresult->IsNull());
16746
16747   ExpectString("str2.substring(2, 10);", "elspenda");
16748
16749   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
16750
16751   ExpectString("str2.charAt(2);", "e");
16752
16753   ExpectObject("str2.indexOf('els');", indexof);
16754
16755   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
16756
16757   reresult = CompileRun("str2.charCodeAt(2);");
16758   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
16759 }
16760
16761
16762 TEST(ContainsOnlyOneByte) {
16763   v8::V8::Initialize();
16764   v8::Isolate* isolate = CcTest::isolate();
16765   v8::HandleScope scope(isolate);
16766   // Make a buffer long enough that it won't automatically be converted.
16767   const int length = 512;
16768   // Ensure word aligned assignment.
16769   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
16770   i::SmartArrayPointer<uintptr_t>
16771   aligned_contents(new uintptr_t[aligned_length]);
16772   uint16_t* string_contents =
16773       reinterpret_cast<uint16_t*>(aligned_contents.get());
16774   // Set to contain only one byte.
16775   for (int i = 0; i < length-1; i++) {
16776     string_contents[i] = 0x41;
16777   }
16778   string_contents[length-1] = 0;
16779   // Simple case.
16780   Handle<String> string =
16781       String::NewExternal(isolate,
16782                           new TestResource(string_contents, NULL, false));
16783   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16784   // Counter example.
16785   string = String::NewFromTwoByte(isolate, string_contents);
16786   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
16787   // Test left right and balanced cons strings.
16788   Handle<String> base = String::NewFromUtf8(isolate, "a");
16789   Handle<String> left = base;
16790   Handle<String> right = base;
16791   for (int i = 0; i < 1000; i++) {
16792     left = String::Concat(base, left);
16793     right = String::Concat(right, base);
16794   }
16795   Handle<String> balanced = String::Concat(left, base);
16796   balanced = String::Concat(balanced, right);
16797   Handle<String> cons_strings[] = {left, balanced, right};
16798   Handle<String> two_byte =
16799       String::NewExternal(isolate,
16800                           new TestResource(string_contents, NULL, false));
16801   USE(two_byte); USE(cons_strings);
16802   for (size_t i = 0; i < arraysize(cons_strings); i++) {
16803     // Base assumptions.
16804     string = cons_strings[i];
16805     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
16806     // Test left and right concatentation.
16807     string = String::Concat(two_byte, cons_strings[i]);
16808     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16809     string = String::Concat(cons_strings[i], two_byte);
16810     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16811   }
16812   // Set bits in different positions
16813   // for strings of different lengths and alignments.
16814   for (int alignment = 0; alignment < 7; alignment++) {
16815     for (int size = 2; alignment + size < length; size *= 2) {
16816       int zero_offset = size + alignment;
16817       string_contents[zero_offset] = 0;
16818       for (int i = 0; i < size; i++) {
16819         int shift = 8 + (i % 7);
16820         string_contents[alignment + i] = 1 << shift;
16821         string = String::NewExternal(
16822             isolate,
16823             new TestResource(string_contents + alignment, NULL, false));
16824         CHECK_EQ(size, string->Length());
16825         CHECK(!string->ContainsOnlyOneByte());
16826         string_contents[alignment + i] = 0x41;
16827       }
16828       string_contents[zero_offset] = 0x41;
16829     }
16830   }
16831 }
16832
16833
16834 // Failed access check callback that performs a GC on each invocation.
16835 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
16836                                  v8::AccessType type,
16837                                  Local<v8::Value> data) {
16838   CcTest::heap()->CollectAllGarbage();
16839   CcTest::isolate()->ThrowException(
16840       v8::Exception::Error(v8_str("cross context")));
16841 }
16842
16843
16844 TEST(GCInFailedAccessCheckCallback) {
16845   // Install a failed access check callback that performs a GC on each
16846   // invocation. Then force the callback to be called from va
16847
16848   v8::V8::Initialize();
16849   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
16850
16851   v8::Isolate* isolate = CcTest::isolate();
16852   v8::HandleScope scope(isolate);
16853
16854   // Create an ObjectTemplate for global objects and install access
16855   // check callbacks that will block access.
16856   v8::Handle<v8::ObjectTemplate> global_template =
16857       v8::ObjectTemplate::New(isolate);
16858   global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL,
16859                                            v8::Handle<v8::Value>());
16860
16861   // Create a context and set an x property on it's global object.
16862   LocalContext context0(NULL, global_template);
16863   context0->Global()->Set(v8_str("x"), v8_num(42));
16864   v8::Handle<v8::Object> global0 = context0->Global();
16865
16866   // Create a context with a different security token so that the
16867   // failed access check callback will be called on each access.
16868   LocalContext context1(NULL, global_template);
16869   context1->Global()->Set(v8_str("other"), global0);
16870
16871   v8::TryCatch try_catch(isolate);
16872
16873   // Get property with failed access check.
16874   CHECK(CompileRun("other.x").IsEmpty());
16875   CHECK(try_catch.HasCaught());
16876   try_catch.Reset();
16877
16878   // Get element with failed access check.
16879   CHECK(CompileRun("other[0]").IsEmpty());
16880   CHECK(try_catch.HasCaught());
16881   try_catch.Reset();
16882
16883   // Set property with failed access check.
16884   CHECK(CompileRun("other.x = new Object()").IsEmpty());
16885   CHECK(try_catch.HasCaught());
16886   try_catch.Reset();
16887
16888   // Set element with failed access check.
16889   CHECK(CompileRun("other[0] = new Object()").IsEmpty());
16890   CHECK(try_catch.HasCaught());
16891   try_catch.Reset();
16892
16893   // Get property attribute with failed access check.
16894   CHECK(CompileRun("\'x\' in other").IsEmpty());
16895   CHECK(try_catch.HasCaught());
16896   try_catch.Reset();
16897
16898   // Get property attribute for element with failed access check.
16899   CHECK(CompileRun("0 in other").IsEmpty());
16900   CHECK(try_catch.HasCaught());
16901   try_catch.Reset();
16902
16903   // Delete property.
16904   CHECK(CompileRun("delete other.x").IsEmpty());
16905   CHECK(try_catch.HasCaught());
16906   try_catch.Reset();
16907
16908   // Delete element.
16909   CHECK_EQ(false, global0->Delete(0));
16910
16911   // DefineAccessor.
16912   CHECK_EQ(false,
16913            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
16914
16915   // Define JavaScript accessor.
16916   CHECK(CompileRun(
16917             "Object.prototype.__defineGetter__.call("
16918             "    other, \'x\', function() { return 42; })").IsEmpty());
16919   CHECK(try_catch.HasCaught());
16920   try_catch.Reset();
16921
16922   // LookupAccessor.
16923   CHECK(CompileRun(
16924             "Object.prototype.__lookupGetter__.call("
16925             "    other, \'x\')").IsEmpty());
16926   CHECK(try_catch.HasCaught());
16927   try_catch.Reset();
16928
16929   // HasOwnElement.
16930   CHECK(CompileRun(
16931             "Object.prototype.hasOwnProperty.call("
16932             "other, \'0\')").IsEmpty());
16933   CHECK(try_catch.HasCaught());
16934   try_catch.Reset();
16935
16936   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
16937   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
16938   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
16939
16940   // Reset the failed access check callback so it does not influence
16941   // the other tests.
16942   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
16943 }
16944
16945
16946 TEST(IsolateNewDispose) {
16947   v8::Isolate* current_isolate = CcTest::isolate();
16948   v8::Isolate::CreateParams create_params;
16949   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16950   v8::Isolate* isolate = v8::Isolate::New(create_params);
16951   CHECK(isolate != NULL);
16952   CHECK(current_isolate != isolate);
16953   CHECK(current_isolate == CcTest::isolate());
16954
16955   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16956   last_location = last_message = NULL;
16957   isolate->Dispose();
16958   CHECK(!last_location);
16959   CHECK(!last_message);
16960 }
16961
16962
16963 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
16964   v8::Isolate::CreateParams create_params;
16965   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16966   v8::Isolate* isolate = v8::Isolate::New(create_params);
16967   {
16968     v8::Isolate::Scope i_scope(isolate);
16969     v8::HandleScope scope(isolate);
16970     LocalContext context(isolate);
16971     // Run something in this isolate.
16972     ExpectTrue("true");
16973     v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16974     last_location = last_message = NULL;
16975     // Still entered, should fail.
16976     isolate->Dispose();
16977     CHECK(last_location);
16978     CHECK(last_message);
16979   }
16980   isolate->Dispose();
16981 }
16982
16983
16984 static void BreakArrayGuarantees(const char* script) {
16985   v8::Isolate::CreateParams create_params;
16986   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16987   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
16988   isolate1->Enter();
16989   v8::Persistent<v8::Context> context1;
16990   {
16991     v8::HandleScope scope(isolate1);
16992     context1.Reset(isolate1, Context::New(isolate1));
16993   }
16994
16995   {
16996     v8::HandleScope scope(isolate1);
16997     v8::Local<v8::Context> context =
16998         v8::Local<v8::Context>::New(isolate1, context1);
16999     v8::Context::Scope context_scope(context);
17000     v8::internal::Isolate* i_isolate =
17001         reinterpret_cast<v8::internal::Isolate*>(isolate1);
17002     CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
17003     // Run something in new isolate.
17004     CompileRun(script);
17005     CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
17006   }
17007   isolate1->Exit();
17008   isolate1->Dispose();
17009 }
17010
17011
17012 TEST(VerifyArrayPrototypeGuarantees) {
17013   // Break fast array hole handling by element changes.
17014   BreakArrayGuarantees("[].__proto__[1] = 3;");
17015   BreakArrayGuarantees("Object.prototype[3] = 'three';");
17016   BreakArrayGuarantees("Array.prototype.push(1);");
17017   BreakArrayGuarantees("Array.prototype.unshift(1);");
17018   // Break fast array hole handling by changing length.
17019   BreakArrayGuarantees("Array.prototype.length = 30;");
17020   // Break fast array hole handling by prototype structure changes.
17021   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
17022   // By sending elements to dictionary mode.
17023   BreakArrayGuarantees("Object.freeze(Array.prototype);");
17024   BreakArrayGuarantees("Object.freeze(Object.prototype);");
17025   BreakArrayGuarantees(
17026       "Object.defineProperty(Array.prototype, 0, {"
17027       "  get: function() { return 3; }});");
17028   BreakArrayGuarantees(
17029       "Object.defineProperty(Object.prototype, 0, {"
17030       "  get: function() { return 3; }});");
17031 }
17032
17033
17034 TEST(RunTwoIsolatesOnSingleThread) {
17035   // Run isolate 1.
17036   v8::Isolate::CreateParams create_params;
17037   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17038   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
17039   isolate1->Enter();
17040   v8::Persistent<v8::Context> context1;
17041   {
17042     v8::HandleScope scope(isolate1);
17043     context1.Reset(isolate1, Context::New(isolate1));
17044   }
17045
17046   {
17047     v8::HandleScope scope(isolate1);
17048     v8::Local<v8::Context> context =
17049         v8::Local<v8::Context>::New(isolate1, context1);
17050     v8::Context::Scope context_scope(context);
17051     // Run something in new isolate.
17052     CompileRun("var foo = 'isolate 1';");
17053     ExpectString("function f() { return foo; }; f()", "isolate 1");
17054   }
17055
17056   // Run isolate 2.
17057   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
17058   v8::Persistent<v8::Context> context2;
17059
17060   {
17061     v8::Isolate::Scope iscope(isolate2);
17062     v8::HandleScope scope(isolate2);
17063     context2.Reset(isolate2, Context::New(isolate2));
17064     v8::Local<v8::Context> context =
17065         v8::Local<v8::Context>::New(isolate2, context2);
17066     v8::Context::Scope context_scope(context);
17067
17068     // Run something in new isolate.
17069     CompileRun("var foo = 'isolate 2';");
17070     ExpectString("function f() { return foo; }; f()", "isolate 2");
17071   }
17072
17073   {
17074     v8::HandleScope scope(isolate1);
17075     v8::Local<v8::Context> context =
17076         v8::Local<v8::Context>::New(isolate1, context1);
17077     v8::Context::Scope context_scope(context);
17078     // Now again in isolate 1
17079     ExpectString("function f() { return foo; }; f()", "isolate 1");
17080   }
17081
17082   isolate1->Exit();
17083
17084   // Run some stuff in default isolate.
17085   v8::Persistent<v8::Context> context_default;
17086   {
17087     v8::Isolate* isolate = CcTest::isolate();
17088     v8::Isolate::Scope iscope(isolate);
17089     v8::HandleScope scope(isolate);
17090     context_default.Reset(isolate, Context::New(isolate));
17091   }
17092
17093   {
17094     v8::HandleScope scope(CcTest::isolate());
17095     v8::Local<v8::Context> context =
17096         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
17097     v8::Context::Scope context_scope(context);
17098     // Variables in other isolates should be not available, verify there
17099     // is an exception.
17100     ExpectTrue("function f() {"
17101                "  try {"
17102                "    foo;"
17103                "    return false;"
17104                "  } catch(e) {"
17105                "    return true;"
17106                "  }"
17107                "};"
17108                "var isDefaultIsolate = true;"
17109                "f()");
17110   }
17111
17112   isolate1->Enter();
17113
17114   {
17115     v8::Isolate::Scope iscope(isolate2);
17116     v8::HandleScope scope(isolate2);
17117     v8::Local<v8::Context> context =
17118         v8::Local<v8::Context>::New(isolate2, context2);
17119     v8::Context::Scope context_scope(context);
17120     ExpectString("function f() { return foo; }; f()", "isolate 2");
17121   }
17122
17123   {
17124     v8::HandleScope scope(v8::Isolate::GetCurrent());
17125     v8::Local<v8::Context> context =
17126         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
17127     v8::Context::Scope context_scope(context);
17128     ExpectString("function f() { return foo; }; f()", "isolate 1");
17129   }
17130
17131   {
17132     v8::Isolate::Scope iscope(isolate2);
17133     context2.Reset();
17134   }
17135
17136   context1.Reset();
17137   isolate1->Exit();
17138
17139   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
17140   last_location = last_message = NULL;
17141
17142   isolate1->Dispose();
17143   CHECK(!last_location);
17144   CHECK(!last_message);
17145
17146   isolate2->Dispose();
17147   CHECK(!last_location);
17148   CHECK(!last_message);
17149
17150   // Check that default isolate still runs.
17151   {
17152     v8::HandleScope scope(CcTest::isolate());
17153     v8::Local<v8::Context> context =
17154         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
17155     v8::Context::Scope context_scope(context);
17156     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
17157   }
17158 }
17159
17160
17161 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
17162   v8::Isolate::Scope isolate_scope(isolate);
17163   v8::HandleScope scope(isolate);
17164   LocalContext context(isolate);
17165   i::ScopedVector<char> code(1024);
17166   i::SNPrintF(code, "function fib(n) {"
17167                     "  if (n <= 2) return 1;"
17168                     "  return fib(n-1) + fib(n-2);"
17169                     "}"
17170                     "fib(%d)", limit);
17171   Local<Value> value = CompileRun(code.start());
17172   CHECK(value->IsNumber());
17173   return static_cast<int>(value->NumberValue());
17174 }
17175
17176 class IsolateThread : public v8::base::Thread {
17177  public:
17178   explicit IsolateThread(int fib_limit)
17179       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
17180
17181   void Run() {
17182     v8::Isolate::CreateParams create_params;
17183     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17184     v8::Isolate* isolate = v8::Isolate::New(create_params);
17185     result_ = CalcFibonacci(isolate, fib_limit_);
17186     isolate->Dispose();
17187   }
17188
17189   int result() { return result_; }
17190
17191  private:
17192   int fib_limit_;
17193   int result_;
17194 };
17195
17196
17197 TEST(MultipleIsolatesOnIndividualThreads) {
17198   IsolateThread thread1(21);
17199   IsolateThread thread2(12);
17200
17201   // Compute some fibonacci numbers on 3 threads in 3 isolates.
17202   thread1.Start();
17203   thread2.Start();
17204
17205   int result1 = CalcFibonacci(CcTest::isolate(), 21);
17206   int result2 = CalcFibonacci(CcTest::isolate(), 12);
17207
17208   thread1.Join();
17209   thread2.Join();
17210
17211   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
17212   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
17213   CHECK_EQ(result1, 10946);
17214   CHECK_EQ(result2, 144);
17215   CHECK_EQ(result1, thread1.result());
17216   CHECK_EQ(result2, thread2.result());
17217 }
17218
17219
17220 TEST(IsolateDifferentContexts) {
17221   v8::Isolate::CreateParams create_params;
17222   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17223   v8::Isolate* isolate = v8::Isolate::New(create_params);
17224   Local<v8::Context> context;
17225   {
17226     v8::Isolate::Scope isolate_scope(isolate);
17227     v8::HandleScope handle_scope(isolate);
17228     context = v8::Context::New(isolate);
17229     v8::Context::Scope context_scope(context);
17230     Local<Value> v = CompileRun("2");
17231     CHECK(v->IsNumber());
17232     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
17233   }
17234   {
17235     v8::Isolate::Scope isolate_scope(isolate);
17236     v8::HandleScope handle_scope(isolate);
17237     context = v8::Context::New(isolate);
17238     v8::Context::Scope context_scope(context);
17239     Local<Value> v = CompileRun("22");
17240     CHECK(v->IsNumber());
17241     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
17242   }
17243   isolate->Dispose();
17244 }
17245
17246 class InitDefaultIsolateThread : public v8::base::Thread {
17247  public:
17248   enum TestCase {
17249     SetResourceConstraints,
17250     SetFatalHandler,
17251     SetCounterFunction,
17252     SetCreateHistogramFunction,
17253     SetAddHistogramSampleFunction
17254   };
17255
17256   explicit InitDefaultIsolateThread(TestCase testCase)
17257       : Thread(Options("InitDefaultIsolateThread")),
17258         testCase_(testCase),
17259         result_(false) {}
17260
17261   void Run() {
17262     v8::Isolate::CreateParams create_params;
17263     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17264     switch (testCase_) {
17265       case SetResourceConstraints: {
17266         create_params.constraints.set_max_semi_space_size(1);
17267         create_params.constraints.set_max_old_space_size(4);
17268         break;
17269       }
17270       default:
17271         break;
17272     }
17273     v8::Isolate* isolate = v8::Isolate::New(create_params);
17274     isolate->Enter();
17275     switch (testCase_) {
17276       case SetResourceConstraints:
17277         // Already handled in pre-Isolate-creation block.
17278         break;
17279
17280       case SetFatalHandler:
17281         v8::V8::SetFatalErrorHandler(NULL);
17282         break;
17283
17284       case SetCounterFunction:
17285         CcTest::isolate()->SetCounterFunction(NULL);
17286         break;
17287
17288       case SetCreateHistogramFunction:
17289         CcTest::isolate()->SetCreateHistogramFunction(NULL);
17290         break;
17291
17292       case SetAddHistogramSampleFunction:
17293         CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
17294         break;
17295     }
17296     isolate->Exit();
17297     isolate->Dispose();
17298     result_ = true;
17299   }
17300
17301   bool result() { return result_; }
17302
17303  private:
17304   TestCase testCase_;
17305   bool result_;
17306 };
17307
17308
17309 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
17310   InitDefaultIsolateThread thread(testCase);
17311   thread.Start();
17312   thread.Join();
17313   CHECK_EQ(thread.result(), true);
17314 }
17315
17316
17317 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
17318   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
17319 }
17320
17321
17322 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
17323   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
17324 }
17325
17326
17327 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
17328   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
17329 }
17330
17331
17332 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
17333   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
17334 }
17335
17336
17337 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
17338   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
17339 }
17340
17341
17342 TEST(StringCheckMultipleContexts) {
17343   const char* code =
17344       "(function() { return \"a\".charAt(0); })()";
17345
17346   {
17347     // Run the code twice in the first context to initialize the call IC.
17348     LocalContext context1;
17349     v8::HandleScope scope(context1->GetIsolate());
17350     ExpectString(code, "a");
17351     ExpectString(code, "a");
17352   }
17353
17354   {
17355     // Change the String.prototype in the second context and check
17356     // that the right function gets called.
17357     LocalContext context2;
17358     v8::HandleScope scope(context2->GetIsolate());
17359     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
17360     ExpectString(code, "not a");
17361   }
17362 }
17363
17364
17365 TEST(NumberCheckMultipleContexts) {
17366   const char* code =
17367       "(function() { return (42).toString(); })()";
17368
17369   {
17370     // Run the code twice in the first context to initialize the call IC.
17371     LocalContext context1;
17372     v8::HandleScope scope(context1->GetIsolate());
17373     ExpectString(code, "42");
17374     ExpectString(code, "42");
17375   }
17376
17377   {
17378     // Change the Number.prototype in the second context and check
17379     // that the right function gets called.
17380     LocalContext context2;
17381     v8::HandleScope scope(context2->GetIsolate());
17382     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
17383     ExpectString(code, "not 42");
17384   }
17385 }
17386
17387
17388 TEST(BooleanCheckMultipleContexts) {
17389   const char* code =
17390       "(function() { return true.toString(); })()";
17391
17392   {
17393     // Run the code twice in the first context to initialize the call IC.
17394     LocalContext context1;
17395     v8::HandleScope scope(context1->GetIsolate());
17396     ExpectString(code, "true");
17397     ExpectString(code, "true");
17398   }
17399
17400   {
17401     // Change the Boolean.prototype in the second context and check
17402     // that the right function gets called.
17403     LocalContext context2;
17404     v8::HandleScope scope(context2->GetIsolate());
17405     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
17406     ExpectString(code, "");
17407   }
17408 }
17409
17410
17411 TEST(DontDeleteCellLoadIC) {
17412   const char* function_code =
17413       "function readCell() { while (true) { return cell; } }";
17414
17415   {
17416     // Run the code twice in the first context to initialize the load
17417     // IC for a don't delete cell.
17418     LocalContext context1;
17419     v8::HandleScope scope(context1->GetIsolate());
17420     CompileRun("var cell = \"first\";");
17421     ExpectBoolean("delete cell", false);
17422     CompileRun(function_code);
17423     ExpectString("readCell()", "first");
17424     ExpectString("readCell()", "first");
17425   }
17426
17427   {
17428     // Use a deletable cell in the second context.
17429     LocalContext context2;
17430     v8::HandleScope scope(context2->GetIsolate());
17431     CompileRun("cell = \"second\";");
17432     CompileRun(function_code);
17433     ExpectString("readCell()", "second");
17434     ExpectBoolean("delete cell", true);
17435     ExpectString("(function() {"
17436                  "  try {"
17437                  "    return readCell();"
17438                  "  } catch(e) {"
17439                  "    return e.toString();"
17440                  "  }"
17441                  "})()",
17442                  "ReferenceError: cell is not defined");
17443     CompileRun("cell = \"new_second\";");
17444     CcTest::heap()->CollectAllGarbage();
17445     ExpectString("readCell()", "new_second");
17446     ExpectString("readCell()", "new_second");
17447   }
17448 }
17449
17450
17451 class Visitor42 : public v8::PersistentHandleVisitor {
17452  public:
17453   explicit Visitor42(v8::Persistent<v8::Object>* object)
17454       : counter_(0), object_(object) { }
17455
17456   virtual void VisitPersistentHandle(Persistent<Value>* value,
17457                                      uint16_t class_id) {
17458     if (class_id != 42) return;
17459     CHECK_EQ(42, value->WrapperClassId());
17460     v8::Isolate* isolate = CcTest::isolate();
17461     v8::HandleScope handle_scope(isolate);
17462     v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
17463     v8::Handle<v8::Value> object =
17464         v8::Local<v8::Object>::New(isolate, *object_);
17465     CHECK(handle->IsObject());
17466     CHECK(Handle<Object>::Cast(handle)->Equals(object));
17467     ++counter_;
17468   }
17469
17470   int counter_;
17471   v8::Persistent<v8::Object>* object_;
17472 };
17473
17474
17475 TEST(PersistentHandleVisitor) {
17476   LocalContext context;
17477   v8::Isolate* isolate = context->GetIsolate();
17478   v8::HandleScope scope(isolate);
17479   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
17480   CHECK_EQ(0, object.WrapperClassId());
17481   object.SetWrapperClassId(42);
17482   CHECK_EQ(42, object.WrapperClassId());
17483
17484   Visitor42 visitor(&object);
17485   v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
17486   CHECK_EQ(1, visitor.counter_);
17487
17488   object.Reset();
17489 }
17490
17491
17492 TEST(WrapperClassId) {
17493   LocalContext context;
17494   v8::Isolate* isolate = context->GetIsolate();
17495   v8::HandleScope scope(isolate);
17496   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
17497   CHECK_EQ(0, object.WrapperClassId());
17498   object.SetWrapperClassId(65535);
17499   CHECK_EQ(65535, object.WrapperClassId());
17500   object.Reset();
17501 }
17502
17503
17504 TEST(PersistentHandleInNewSpaceVisitor) {
17505   LocalContext context;
17506   v8::Isolate* isolate = context->GetIsolate();
17507   v8::HandleScope scope(isolate);
17508   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
17509   CHECK_EQ(0, object1.WrapperClassId());
17510   object1.SetWrapperClassId(42);
17511   CHECK_EQ(42, object1.WrapperClassId());
17512
17513   CcTest::heap()->CollectAllGarbage();
17514   CcTest::heap()->CollectAllGarbage();
17515
17516   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
17517   CHECK_EQ(0, object2.WrapperClassId());
17518   object2.SetWrapperClassId(42);
17519   CHECK_EQ(42, object2.WrapperClassId());
17520
17521   Visitor42 visitor(&object2);
17522   v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
17523   CHECK_EQ(1, visitor.counter_);
17524
17525   object1.Reset();
17526   object2.Reset();
17527 }
17528
17529
17530 TEST(RegExp) {
17531   LocalContext context;
17532   v8::HandleScope scope(context->GetIsolate());
17533
17534   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
17535   CHECK(re->IsRegExp());
17536   CHECK(re->GetSource()->Equals(v8_str("foo")));
17537   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17538
17539   re = v8::RegExp::New(v8_str("bar"),
17540                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17541                                                       v8::RegExp::kGlobal));
17542   CHECK(re->IsRegExp());
17543   CHECK(re->GetSource()->Equals(v8_str("bar")));
17544   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
17545            static_cast<int>(re->GetFlags()));
17546
17547   re = v8::RegExp::New(v8_str("baz"),
17548                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17549                                                       v8::RegExp::kMultiline));
17550   CHECK(re->IsRegExp());
17551   CHECK(re->GetSource()->Equals(v8_str("baz")));
17552   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
17553            static_cast<int>(re->GetFlags()));
17554
17555   re = CompileRun("/quux/").As<v8::RegExp>();
17556   CHECK(re->IsRegExp());
17557   CHECK(re->GetSource()->Equals(v8_str("quux")));
17558   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17559
17560   re = CompileRun("/quux/gm").As<v8::RegExp>();
17561   CHECK(re->IsRegExp());
17562   CHECK(re->GetSource()->Equals(v8_str("quux")));
17563   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
17564            static_cast<int>(re->GetFlags()));
17565
17566   // Override the RegExp constructor and check the API constructor
17567   // still works.
17568   CompileRun("RegExp = function() {}");
17569
17570   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
17571   CHECK(re->IsRegExp());
17572   CHECK(re->GetSource()->Equals(v8_str("foobar")));
17573   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17574
17575   re = v8::RegExp::New(v8_str("foobarbaz"),
17576                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17577                                                       v8::RegExp::kMultiline));
17578   CHECK(re->IsRegExp());
17579   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
17580   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
17581            static_cast<int>(re->GetFlags()));
17582
17583   context->Global()->Set(v8_str("re"), re);
17584   ExpectTrue("re.test('FoobarbaZ')");
17585
17586   // RegExps are objects on which you can set properties.
17587   re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
17588   v8::Handle<v8::Value> value(CompileRun("re.property"));
17589   CHECK_EQ(32, value->Int32Value());
17590
17591   v8::TryCatch try_catch(context->GetIsolate());
17592   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
17593   CHECK(re.IsEmpty());
17594   CHECK(try_catch.HasCaught());
17595   context->Global()->Set(v8_str("ex"), try_catch.Exception());
17596   ExpectTrue("ex instanceof SyntaxError");
17597 }
17598
17599
17600 THREADED_TEST(Equals) {
17601   LocalContext localContext;
17602   v8::HandleScope handleScope(localContext->GetIsolate());
17603
17604   v8::Handle<v8::Object> globalProxy = localContext->Global();
17605   v8::Handle<Value> global = globalProxy->GetPrototype();
17606
17607   CHECK(global->StrictEquals(global));
17608   CHECK(!global->StrictEquals(globalProxy));
17609   CHECK(!globalProxy->StrictEquals(global));
17610   CHECK(globalProxy->StrictEquals(globalProxy));
17611
17612   CHECK(global->Equals(global));
17613   CHECK(!global->Equals(globalProxy));
17614   CHECK(!globalProxy->Equals(global));
17615   CHECK(globalProxy->Equals(globalProxy));
17616 }
17617
17618
17619 static void Getter(v8::Local<v8::Name> property,
17620                    const v8::PropertyCallbackInfo<v8::Value>& info) {
17621   info.GetReturnValue().Set(v8_str("42!"));
17622 }
17623
17624
17625 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
17626   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
17627   result->Set(0, v8_str("universalAnswer"));
17628   info.GetReturnValue().Set(result);
17629 }
17630
17631
17632 TEST(NamedEnumeratorAndForIn) {
17633   LocalContext context;
17634   v8::Isolate* isolate = context->GetIsolate();
17635   v8::HandleScope handle_scope(isolate);
17636   v8::Context::Scope context_scope(context.local());
17637
17638   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
17639   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
17640                                                          NULL, Enumerator));
17641   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
17642   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
17643         "var result = []; for (var k in o) result.push(k); result"));
17644   CHECK_EQ(1u, result->Length());
17645   CHECK(v8_str("universalAnswer")->Equals(result->Get(0)));
17646 }
17647
17648
17649 TEST(DefinePropertyPostDetach) {
17650   LocalContext context;
17651   v8::HandleScope scope(context->GetIsolate());
17652   v8::Handle<v8::Object> proxy = context->Global();
17653   v8::Handle<v8::Function> define_property =
17654       CompileRun("(function() {"
17655                  "  Object.defineProperty("
17656                  "    this,"
17657                  "    1,"
17658                  "    { configurable: true, enumerable: true, value: 3 });"
17659                  "})").As<Function>();
17660   context->DetachGlobal();
17661   define_property->Call(proxy, 0, NULL);
17662 }
17663
17664
17665 static void InstallContextId(v8::Handle<Context> context, int id) {
17666   Context::Scope scope(context);
17667   CompileRun("Object.prototype").As<Object>()->
17668       Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
17669 }
17670
17671
17672 static void CheckContextId(v8::Handle<Object> object, int expected) {
17673   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
17674 }
17675
17676
17677 THREADED_TEST(CreationContext) {
17678   v8::Isolate* isolate = CcTest::isolate();
17679   HandleScope handle_scope(isolate);
17680   Handle<Context> context1 = Context::New(isolate);
17681   InstallContextId(context1, 1);
17682   Handle<Context> context2 = Context::New(isolate);
17683   InstallContextId(context2, 2);
17684   Handle<Context> context3 = Context::New(isolate);
17685   InstallContextId(context3, 3);
17686
17687   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
17688
17689   Local<Object> object1;
17690   Local<Function> func1;
17691   {
17692     Context::Scope scope(context1);
17693     object1 = Object::New(isolate);
17694     func1 = tmpl->GetFunction();
17695   }
17696
17697   Local<Object> object2;
17698   Local<Function> func2;
17699   {
17700     Context::Scope scope(context2);
17701     object2 = Object::New(isolate);
17702     func2 = tmpl->GetFunction();
17703   }
17704
17705   Local<Object> instance1;
17706   Local<Object> instance2;
17707
17708   {
17709     Context::Scope scope(context3);
17710     instance1 = func1->NewInstance();
17711     instance2 = func2->NewInstance();
17712   }
17713
17714   {
17715     Handle<Context> other_context = Context::New(isolate);
17716     Context::Scope scope(other_context);
17717     CHECK(object1->CreationContext() == context1);
17718     CheckContextId(object1, 1);
17719     CHECK(func1->CreationContext() == context1);
17720     CheckContextId(func1, 1);
17721     CHECK(instance1->CreationContext() == context1);
17722     CheckContextId(instance1, 1);
17723     CHECK(object2->CreationContext() == context2);
17724     CheckContextId(object2, 2);
17725     CHECK(func2->CreationContext() == context2);
17726     CheckContextId(func2, 2);
17727     CHECK(instance2->CreationContext() == context2);
17728     CheckContextId(instance2, 2);
17729   }
17730
17731   {
17732     Context::Scope scope(context1);
17733     CHECK(object1->CreationContext() == context1);
17734     CheckContextId(object1, 1);
17735     CHECK(func1->CreationContext() == context1);
17736     CheckContextId(func1, 1);
17737     CHECK(instance1->CreationContext() == context1);
17738     CheckContextId(instance1, 1);
17739     CHECK(object2->CreationContext() == context2);
17740     CheckContextId(object2, 2);
17741     CHECK(func2->CreationContext() == context2);
17742     CheckContextId(func2, 2);
17743     CHECK(instance2->CreationContext() == context2);
17744     CheckContextId(instance2, 2);
17745   }
17746
17747   {
17748     Context::Scope scope(context2);
17749     CHECK(object1->CreationContext() == context1);
17750     CheckContextId(object1, 1);
17751     CHECK(func1->CreationContext() == context1);
17752     CheckContextId(func1, 1);
17753     CHECK(instance1->CreationContext() == context1);
17754     CheckContextId(instance1, 1);
17755     CHECK(object2->CreationContext() == context2);
17756     CheckContextId(object2, 2);
17757     CHECK(func2->CreationContext() == context2);
17758     CheckContextId(func2, 2);
17759     CHECK(instance2->CreationContext() == context2);
17760     CheckContextId(instance2, 2);
17761   }
17762 }
17763
17764
17765 THREADED_TEST(CreationContextOfJsFunction) {
17766   HandleScope handle_scope(CcTest::isolate());
17767   Handle<Context> context = Context::New(CcTest::isolate());
17768   InstallContextId(context, 1);
17769
17770   Local<Object> function;
17771   {
17772     Context::Scope scope(context);
17773     function = CompileRun("function foo() {}; foo").As<Object>();
17774   }
17775
17776   Handle<Context> other_context = Context::New(CcTest::isolate());
17777   Context::Scope scope(other_context);
17778   CHECK(function->CreationContext() == context);
17779   CheckContextId(function, 1);
17780 }
17781
17782
17783 void HasOwnPropertyIndexedPropertyGetter(
17784     uint32_t index,
17785     const v8::PropertyCallbackInfo<v8::Value>& info) {
17786   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
17787 }
17788
17789
17790 void HasOwnPropertyNamedPropertyGetter(
17791     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
17792   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
17793 }
17794
17795
17796 void HasOwnPropertyIndexedPropertyQuery(
17797     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17798   if (index == 42) info.GetReturnValue().Set(1);
17799 }
17800
17801
17802 void HasOwnPropertyNamedPropertyQuery(
17803     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17804   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
17805 }
17806
17807
17808 void HasOwnPropertyNamedPropertyQuery2(
17809     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17810   if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
17811 }
17812
17813
17814 void HasOwnPropertyAccessorGetter(
17815     Local<String> property,
17816     const v8::PropertyCallbackInfo<v8::Value>& info) {
17817   info.GetReturnValue().Set(v8_str("yes"));
17818 }
17819
17820
17821 TEST(HasOwnProperty) {
17822   LocalContext env;
17823   v8::Isolate* isolate = env->GetIsolate();
17824   v8::HandleScope scope(isolate);
17825   { // Check normal properties and defined getters.
17826     Handle<Value> value = CompileRun(
17827         "function Foo() {"
17828         "    this.foo = 11;"
17829         "    this.__defineGetter__('baz', function() { return 1; });"
17830         "};"
17831         "function Bar() { "
17832         "    this.bar = 13;"
17833         "    this.__defineGetter__('bla', function() { return 2; });"
17834         "};"
17835         "Bar.prototype = new Foo();"
17836         "new Bar();");
17837     CHECK(value->IsObject());
17838     Handle<Object> object = value->ToObject(isolate);
17839     CHECK(object->Has(v8_str("foo")));
17840     CHECK(!object->HasOwnProperty(v8_str("foo")));
17841     CHECK(object->HasOwnProperty(v8_str("bar")));
17842     CHECK(object->Has(v8_str("baz")));
17843     CHECK(!object->HasOwnProperty(v8_str("baz")));
17844     CHECK(object->HasOwnProperty(v8_str("bla")));
17845   }
17846   { // Check named getter interceptors.
17847     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17848     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17849         HasOwnPropertyNamedPropertyGetter));
17850     Handle<Object> instance = templ->NewInstance();
17851     CHECK(!instance->HasOwnProperty(v8_str("42")));
17852     CHECK(instance->HasOwnProperty(v8_str("foo")));
17853     CHECK(!instance->HasOwnProperty(v8_str("bar")));
17854   }
17855   { // Check indexed getter interceptors.
17856     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17857     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17858         HasOwnPropertyIndexedPropertyGetter));
17859     Handle<Object> instance = templ->NewInstance();
17860     CHECK(instance->HasOwnProperty(v8_str("42")));
17861     CHECK(!instance->HasOwnProperty(v8_str("43")));
17862     CHECK(!instance->HasOwnProperty(v8_str("foo")));
17863   }
17864   { // Check named query interceptors.
17865     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17866     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17867         0, 0, HasOwnPropertyNamedPropertyQuery));
17868     Handle<Object> instance = templ->NewInstance();
17869     CHECK(instance->HasOwnProperty(v8_str("foo")));
17870     CHECK(!instance->HasOwnProperty(v8_str("bar")));
17871   }
17872   { // Check indexed query interceptors.
17873     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17874     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17875         0, 0, HasOwnPropertyIndexedPropertyQuery));
17876     Handle<Object> instance = templ->NewInstance();
17877     CHECK(instance->HasOwnProperty(v8_str("42")));
17878     CHECK(!instance->HasOwnProperty(v8_str("41")));
17879   }
17880   { // Check callbacks.
17881     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17882     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
17883     Handle<Object> instance = templ->NewInstance();
17884     CHECK(instance->HasOwnProperty(v8_str("foo")));
17885     CHECK(!instance->HasOwnProperty(v8_str("bar")));
17886   }
17887   { // Check that query wins on disagreement.
17888     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17889     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17890         HasOwnPropertyNamedPropertyGetter, 0,
17891         HasOwnPropertyNamedPropertyQuery2));
17892     Handle<Object> instance = templ->NewInstance();
17893     CHECK(!instance->HasOwnProperty(v8_str("foo")));
17894     CHECK(instance->HasOwnProperty(v8_str("bar")));
17895   }
17896 }
17897
17898
17899 TEST(IndexedInterceptorWithStringProto) {
17900   v8::Isolate* isolate = CcTest::isolate();
17901   v8::HandleScope scope(isolate);
17902   Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17903   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17904       NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
17905   LocalContext context;
17906   context->Global()->Set(v8_str("obj"), templ->NewInstance());
17907   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
17908   // These should be intercepted.
17909   CHECK(CompileRun("42 in obj")->BooleanValue());
17910   CHECK(CompileRun("'42' in obj")->BooleanValue());
17911   // These should fall through to the String prototype.
17912   CHECK(CompileRun("0 in obj")->BooleanValue());
17913   CHECK(CompileRun("'0' in obj")->BooleanValue());
17914   // And these should both fail.
17915   CHECK(!CompileRun("32 in obj")->BooleanValue());
17916   CHECK(!CompileRun("'32' in obj")->BooleanValue());
17917 }
17918
17919
17920 void CheckCodeGenerationAllowed() {
17921   Handle<Value> result = CompileRun("eval('42')");
17922   CHECK_EQ(42, result->Int32Value());
17923   result = CompileRun("(function(e) { return e('42'); })(eval)");
17924   CHECK_EQ(42, result->Int32Value());
17925   result = CompileRun("var f = new Function('return 42'); f()");
17926   CHECK_EQ(42, result->Int32Value());
17927 }
17928
17929
17930 void CheckCodeGenerationDisallowed() {
17931   TryCatch try_catch(CcTest::isolate());
17932
17933   Handle<Value> result = CompileRun("eval('42')");
17934   CHECK(result.IsEmpty());
17935   CHECK(try_catch.HasCaught());
17936   try_catch.Reset();
17937
17938   result = CompileRun("(function(e) { return e('42'); })(eval)");
17939   CHECK(result.IsEmpty());
17940   CHECK(try_catch.HasCaught());
17941   try_catch.Reset();
17942
17943   result = CompileRun("var f = new Function('return 42'); f()");
17944   CHECK(result.IsEmpty());
17945   CHECK(try_catch.HasCaught());
17946 }
17947
17948
17949 bool CodeGenerationAllowed(Local<Context> context) {
17950   ApiTestFuzzer::Fuzz();
17951   return true;
17952 }
17953
17954
17955 bool CodeGenerationDisallowed(Local<Context> context) {
17956   ApiTestFuzzer::Fuzz();
17957   return false;
17958 }
17959
17960
17961 THREADED_TEST(AllowCodeGenFromStrings) {
17962   LocalContext context;
17963   v8::HandleScope scope(context->GetIsolate());
17964
17965   // eval and the Function constructor allowed by default.
17966   CHECK(context->IsCodeGenerationFromStringsAllowed());
17967   CheckCodeGenerationAllowed();
17968
17969   // Disallow eval and the Function constructor.
17970   context->AllowCodeGenerationFromStrings(false);
17971   CHECK(!context->IsCodeGenerationFromStringsAllowed());
17972   CheckCodeGenerationDisallowed();
17973
17974   // Allow again.
17975   context->AllowCodeGenerationFromStrings(true);
17976   CheckCodeGenerationAllowed();
17977
17978   // Disallow but setting a global callback that will allow the calls.
17979   context->AllowCodeGenerationFromStrings(false);
17980   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
17981   CHECK(!context->IsCodeGenerationFromStringsAllowed());
17982   CheckCodeGenerationAllowed();
17983
17984   // Set a callback that disallows the code generation.
17985   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
17986   CHECK(!context->IsCodeGenerationFromStringsAllowed());
17987   CheckCodeGenerationDisallowed();
17988 }
17989
17990
17991 TEST(SetErrorMessageForCodeGenFromStrings) {
17992   LocalContext context;
17993   v8::HandleScope scope(context->GetIsolate());
17994   TryCatch try_catch(context->GetIsolate());
17995
17996   Handle<String> message = v8_str("Message") ;
17997   Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
17998   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
17999   context->AllowCodeGenerationFromStrings(false);
18000   context->SetErrorMessageForCodeGenerationFromStrings(message);
18001   Handle<Value> result = CompileRun("eval('42')");
18002   CHECK(result.IsEmpty());
18003   CHECK(try_catch.HasCaught());
18004   Handle<String> actual_message = try_catch.Message()->Get();
18005   CHECK(expected_message->Equals(actual_message));
18006 }
18007
18008
18009 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
18010 }
18011
18012
18013 THREADED_TEST(CallAPIFunctionOnNonObject) {
18014   LocalContext context;
18015   v8::Isolate* isolate = context->GetIsolate();
18016   v8::HandleScope scope(isolate);
18017   Handle<FunctionTemplate> templ =
18018       v8::FunctionTemplate::New(isolate, NonObjectThis);
18019   Handle<Function> function = templ->GetFunction();
18020   context->Global()->Set(v8_str("f"), function);
18021   TryCatch try_catch(isolate);
18022   CompileRun("f.call(2)");
18023 }
18024
18025
18026 // Regression test for issue 1470.
18027 THREADED_TEST(ReadOnlyIndexedProperties) {
18028   v8::Isolate* isolate = CcTest::isolate();
18029   v8::HandleScope scope(isolate);
18030   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18031
18032   LocalContext context;
18033   Local<v8::Object> obj = templ->NewInstance();
18034   context->Global()->Set(v8_str("obj"), obj);
18035   obj->ForceSet(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
18036   obj->Set(v8_str("1"), v8_str("foobar"));
18037   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("1"))));
18038   obj->ForceSet(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
18039   obj->Set(v8_num(2), v8_str("foobar"));
18040   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_num(2))));
18041
18042   // Test non-smi case.
18043   obj->ForceSet(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
18044   obj->Set(v8_str("2000000000"), v8_str("foobar"));
18045   CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("2000000000"))));
18046 }
18047
18048
18049 static int CountLiveMapsInMapCache(i::Context* context) {
18050   i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
18051   int length = map_cache->length();
18052   int count = 0;
18053   for (int i = 0; i < length; i++) {
18054     i::Object* value = map_cache->get(i);
18055     if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
18056   }
18057   return count;
18058 }
18059
18060
18061 THREADED_TEST(Regress1516) {
18062   LocalContext context;
18063   v8::HandleScope scope(context->GetIsolate());
18064
18065   // Object with 20 properties is not a common case, so it should be removed
18066   // from the cache after GC.
18067   { v8::HandleScope temp_scope(context->GetIsolate());
18068     CompileRun(
18069         "({"
18070         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
18071         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
18072         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
18073         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
18074         "})");
18075   }
18076
18077   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
18078   CHECK_LE(1, elements);
18079
18080   CcTest::heap()->CollectAllGarbage();
18081
18082   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
18083 }
18084
18085
18086 THREADED_TEST(Regress93759) {
18087   v8::Isolate* isolate = CcTest::isolate();
18088   HandleScope scope(isolate);
18089
18090   // Template for object with security check.
18091   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
18092   no_proto_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
18093
18094   // Templates for objects with hidden prototypes and possibly security check.
18095   Local<FunctionTemplate> hidden_proto_template =
18096       v8::FunctionTemplate::New(isolate);
18097   hidden_proto_template->SetHiddenPrototype(true);
18098
18099   Local<FunctionTemplate> protected_hidden_proto_template =
18100       v8::FunctionTemplate::New(isolate);
18101   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
18102       AccessAlwaysBlocked, NULL);
18103   protected_hidden_proto_template->SetHiddenPrototype(true);
18104
18105   // Context for "foreign" objects used in test.
18106   Local<Context> context = v8::Context::New(isolate);
18107   context->Enter();
18108
18109   // Plain object, no security check.
18110   Local<Object> simple_object = Object::New(isolate);
18111
18112   // Object with explicit security check.
18113   Local<Object> protected_object = no_proto_template->NewInstance();
18114
18115   // JSGlobalProxy object, always have security check.
18116   Local<Object> proxy_object = context->Global();
18117
18118   // Global object, the  prototype of proxy_object. No security checks.
18119   Local<Object> global_object = proxy_object->GetPrototype()->ToObject(isolate);
18120
18121   // Hidden prototype without security check.
18122   Local<Object> hidden_prototype =
18123       hidden_proto_template->GetFunction()->NewInstance();
18124   Local<Object> object_with_hidden =
18125     Object::New(isolate);
18126   object_with_hidden->SetPrototype(hidden_prototype);
18127
18128   // Hidden prototype with security check on the hidden prototype.
18129   Local<Object> protected_hidden_prototype =
18130       protected_hidden_proto_template->GetFunction()->NewInstance();
18131   Local<Object> object_with_protected_hidden =
18132     Object::New(isolate);
18133   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
18134
18135   context->Exit();
18136
18137   // Template for object for second context. Values to test are put on it as
18138   // properties.
18139   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
18140   global_template->Set(v8_str("simple"), simple_object);
18141   global_template->Set(v8_str("protected"), protected_object);
18142   global_template->Set(v8_str("global"), global_object);
18143   global_template->Set(v8_str("proxy"), proxy_object);
18144   global_template->Set(v8_str("hidden"), object_with_hidden);
18145   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
18146
18147   LocalContext context2(NULL, global_template);
18148
18149   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
18150   CHECK(result1->Equals(simple_object->GetPrototype()));
18151
18152   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
18153   CHECK(result2.IsEmpty());
18154
18155   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
18156   CHECK(result3->Equals(global_object->GetPrototype()));
18157
18158   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
18159   CHECK(result4.IsEmpty());
18160
18161   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
18162   CHECK(result5->Equals(
18163       object_with_hidden->GetPrototype()->ToObject(isolate)->GetPrototype()));
18164
18165   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
18166   CHECK(result6.IsEmpty());
18167 }
18168
18169
18170 static void TestReceiver(Local<Value> expected_result,
18171                          Local<Value> expected_receiver,
18172                          const char* code) {
18173   Local<Value> result = CompileRun(code);
18174   CHECK(result->IsObject());
18175   CHECK(expected_receiver->Equals(result.As<v8::Object>()->Get(1)));
18176   CHECK(expected_result->Equals(result.As<v8::Object>()->Get(0)));
18177 }
18178
18179
18180 THREADED_TEST(ForeignFunctionReceiver) {
18181   v8::Isolate* isolate = CcTest::isolate();
18182   HandleScope scope(isolate);
18183
18184   // Create two contexts with different "id" properties ('i' and 'o').
18185   // Call a function both from its own context and from a the foreign
18186   // context, and see what "this" is bound to (returning both "this"
18187   // and "this.id" for comparison).
18188
18189   Local<Context> foreign_context = v8::Context::New(isolate);
18190   foreign_context->Enter();
18191   Local<Value> foreign_function =
18192     CompileRun("function func() { return { 0: this.id, "
18193                "                           1: this, "
18194                "                           toString: function() { "
18195                "                               return this[0];"
18196                "                           }"
18197                "                         };"
18198                "}"
18199                "var id = 'i';"
18200                "func;");
18201   CHECK(foreign_function->IsFunction());
18202   foreign_context->Exit();
18203
18204   LocalContext context;
18205
18206   Local<String> password = v8_str("Password");
18207   // Don't get hit by security checks when accessing foreign_context's
18208   // global receiver (aka. global proxy).
18209   context->SetSecurityToken(password);
18210   foreign_context->SetSecurityToken(password);
18211
18212   Local<String> i = v8_str("i");
18213   Local<String> o = v8_str("o");
18214   Local<String> id = v8_str("id");
18215
18216   CompileRun("function ownfunc() { return { 0: this.id, "
18217              "                              1: this, "
18218              "                              toString: function() { "
18219              "                                  return this[0];"
18220              "                              }"
18221              "                             };"
18222              "}"
18223              "var id = 'o';"
18224              "ownfunc");
18225   context->Global()->Set(v8_str("func"), foreign_function);
18226
18227   // Sanity check the contexts.
18228   CHECK(i->Equals(foreign_context->Global()->Get(id)));
18229   CHECK(o->Equals(context->Global()->Get(id)));
18230
18231   // Checking local function's receiver.
18232   // Calling function using its call/apply methods.
18233   TestReceiver(o, context->Global(), "ownfunc.call()");
18234   TestReceiver(o, context->Global(), "ownfunc.apply()");
18235   // Making calls through built-in functions.
18236   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
18237   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
18238   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
18239   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
18240   // Calling with environment record as base.
18241   TestReceiver(o, context->Global(), "ownfunc()");
18242   // Calling with no base.
18243   TestReceiver(o, context->Global(), "(1,ownfunc)()");
18244
18245   // Checking foreign function return value.
18246   // Calling function using its call/apply methods.
18247   TestReceiver(i, foreign_context->Global(), "func.call()");
18248   TestReceiver(i, foreign_context->Global(), "func.apply()");
18249   // Calling function using another context's call/apply methods.
18250   TestReceiver(i, foreign_context->Global(),
18251                "Function.prototype.call.call(func)");
18252   TestReceiver(i, foreign_context->Global(),
18253                "Function.prototype.call.apply(func)");
18254   TestReceiver(i, foreign_context->Global(),
18255                "Function.prototype.apply.call(func)");
18256   TestReceiver(i, foreign_context->Global(),
18257                "Function.prototype.apply.apply(func)");
18258   // Making calls through built-in functions.
18259   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
18260   // ToString(func()) is func()[0], i.e., the returned this.id.
18261   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
18262   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
18263   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
18264
18265   // Calling with environment record as base.
18266   TestReceiver(i, foreign_context->Global(), "func()");
18267   // Calling with no base.
18268   TestReceiver(i, foreign_context->Global(), "(1,func)()");
18269 }
18270
18271
18272 uint8_t callback_fired = 0;
18273
18274
18275 void CallCompletedCallback1() {
18276   v8::base::OS::Print("Firing callback 1.\n");
18277   callback_fired ^= 1;  // Toggle first bit.
18278 }
18279
18280
18281 void CallCompletedCallback2() {
18282   v8::base::OS::Print("Firing callback 2.\n");
18283   callback_fired ^= 2;  // Toggle second bit.
18284 }
18285
18286
18287 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
18288   int32_t level = args[0]->Int32Value();
18289   if (level < 3) {
18290     level++;
18291     v8::base::OS::Print("Entering recursion level %d.\n", level);
18292     char script[64];
18293     i::Vector<char> script_vector(script, sizeof(script));
18294     i::SNPrintF(script_vector, "recursion(%d)", level);
18295     CompileRun(script_vector.start());
18296     v8::base::OS::Print("Leaving recursion level %d.\n", level);
18297     CHECK_EQ(0, callback_fired);
18298   } else {
18299     v8::base::OS::Print("Recursion ends.\n");
18300     CHECK_EQ(0, callback_fired);
18301   }
18302 }
18303
18304
18305 TEST(CallCompletedCallback) {
18306   LocalContext env;
18307   v8::HandleScope scope(env->GetIsolate());
18308   v8::Handle<v8::FunctionTemplate> recursive_runtime =
18309       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
18310   env->Global()->Set(v8_str("recursion"),
18311                      recursive_runtime->GetFunction());
18312   // Adding the same callback a second time has no effect.
18313   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
18314   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
18315   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
18316   v8::base::OS::Print("--- Script (1) ---\n");
18317   Local<Script> script = v8::Script::Compile(
18318       v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
18319   script->Run();
18320   CHECK_EQ(3, callback_fired);
18321
18322   v8::base::OS::Print("\n--- Script (2) ---\n");
18323   callback_fired = 0;
18324   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
18325   script->Run();
18326   CHECK_EQ(2, callback_fired);
18327
18328   v8::base::OS::Print("\n--- Function ---\n");
18329   callback_fired = 0;
18330   Local<Function> recursive_function =
18331       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
18332   v8::Handle<Value> args[] = { v8_num(0) };
18333   recursive_function->Call(env->Global(), 1, args);
18334   CHECK_EQ(2, callback_fired);
18335 }
18336
18337
18338 void CallCompletedCallbackNoException() {
18339   v8::HandleScope scope(CcTest::isolate());
18340   CompileRun("1+1;");
18341 }
18342
18343
18344 void CallCompletedCallbackException() {
18345   v8::HandleScope scope(CcTest::isolate());
18346   CompileRun("throw 'second exception';");
18347 }
18348
18349
18350 TEST(CallCompletedCallbackOneException) {
18351   LocalContext env;
18352   v8::HandleScope scope(env->GetIsolate());
18353   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
18354   CompileRun("throw 'exception';");
18355 }
18356
18357
18358 TEST(CallCompletedCallbackTwoExceptions) {
18359   LocalContext env;
18360   v8::HandleScope scope(env->GetIsolate());
18361   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
18362   CompileRun("throw 'first exception';");
18363 }
18364
18365
18366 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
18367   v8::HandleScope scope(info.GetIsolate());
18368   CompileRun("ext1Calls++;");
18369 }
18370
18371
18372 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
18373   v8::HandleScope scope(info.GetIsolate());
18374   CompileRun("ext2Calls++;");
18375 }
18376
18377
18378 void* g_passed_to_three = NULL;
18379
18380
18381 static void MicrotaskThree(void* data) {
18382   g_passed_to_three = data;
18383 }
18384
18385
18386 TEST(EnqueueMicrotask) {
18387   LocalContext env;
18388   v8::HandleScope scope(env->GetIsolate());
18389   CompileRun(
18390       "var ext1Calls = 0;"
18391       "var ext2Calls = 0;");
18392   CompileRun("1+1;");
18393   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
18394   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18395
18396   env->GetIsolate()->EnqueueMicrotask(
18397       Function::New(env->GetIsolate(), MicrotaskOne));
18398   CompileRun("1+1;");
18399   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18400   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18401
18402   env->GetIsolate()->EnqueueMicrotask(
18403       Function::New(env->GetIsolate(), MicrotaskOne));
18404   env->GetIsolate()->EnqueueMicrotask(
18405       Function::New(env->GetIsolate(), MicrotaskTwo));
18406   CompileRun("1+1;");
18407   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18408   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18409
18410   env->GetIsolate()->EnqueueMicrotask(
18411       Function::New(env->GetIsolate(), MicrotaskTwo));
18412   CompileRun("1+1;");
18413   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18414   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18415
18416   CompileRun("1+1;");
18417   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18418   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18419
18420   g_passed_to_three = NULL;
18421   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
18422   CompileRun("1+1;");
18423   CHECK(!g_passed_to_three);
18424   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18425   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18426
18427   int dummy;
18428   env->GetIsolate()->EnqueueMicrotask(
18429       Function::New(env->GetIsolate(), MicrotaskOne));
18430   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
18431   env->GetIsolate()->EnqueueMicrotask(
18432       Function::New(env->GetIsolate(), MicrotaskTwo));
18433   CompileRun("1+1;");
18434   CHECK_EQ(&dummy, g_passed_to_three);
18435   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
18436   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18437   g_passed_to_three = NULL;
18438 }
18439
18440
18441 static void MicrotaskExceptionOne(
18442     const v8::FunctionCallbackInfo<Value>& info) {
18443   v8::HandleScope scope(info.GetIsolate());
18444   CompileRun("exception1Calls++;");
18445   info.GetIsolate()->ThrowException(
18446       v8::Exception::Error(v8_str("first")));
18447 }
18448
18449
18450 static void MicrotaskExceptionTwo(
18451     const v8::FunctionCallbackInfo<Value>& info) {
18452   v8::HandleScope scope(info.GetIsolate());
18453   CompileRun("exception2Calls++;");
18454   info.GetIsolate()->ThrowException(
18455       v8::Exception::Error(v8_str("second")));
18456 }
18457
18458
18459 TEST(RunMicrotasksIgnoresThrownExceptions) {
18460   LocalContext env;
18461   v8::Isolate* isolate = env->GetIsolate();
18462   v8::HandleScope scope(isolate);
18463   CompileRun(
18464       "var exception1Calls = 0;"
18465       "var exception2Calls = 0;");
18466   isolate->EnqueueMicrotask(
18467       Function::New(isolate, MicrotaskExceptionOne));
18468   isolate->EnqueueMicrotask(
18469       Function::New(isolate, MicrotaskExceptionTwo));
18470   TryCatch try_catch(isolate);
18471   CompileRun("1+1;");
18472   CHECK(!try_catch.HasCaught());
18473   CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
18474   CHECK_EQ(1, CompileRun("exception2Calls")->Int32Value());
18475 }
18476
18477
18478 TEST(SetAutorunMicrotasks) {
18479   LocalContext env;
18480   v8::HandleScope scope(env->GetIsolate());
18481   CompileRun(
18482       "var ext1Calls = 0;"
18483       "var ext2Calls = 0;");
18484   CompileRun("1+1;");
18485   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
18486   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18487
18488   env->GetIsolate()->EnqueueMicrotask(
18489       Function::New(env->GetIsolate(), MicrotaskOne));
18490   CompileRun("1+1;");
18491   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18492   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18493
18494   env->GetIsolate()->SetAutorunMicrotasks(false);
18495   env->GetIsolate()->EnqueueMicrotask(
18496       Function::New(env->GetIsolate(), MicrotaskOne));
18497   env->GetIsolate()->EnqueueMicrotask(
18498       Function::New(env->GetIsolate(), MicrotaskTwo));
18499   CompileRun("1+1;");
18500   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18501   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18502
18503   env->GetIsolate()->RunMicrotasks();
18504   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18505   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18506
18507   env->GetIsolate()->EnqueueMicrotask(
18508       Function::New(env->GetIsolate(), MicrotaskTwo));
18509   CompileRun("1+1;");
18510   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18511   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18512
18513   env->GetIsolate()->RunMicrotasks();
18514   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18515   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18516
18517   env->GetIsolate()->SetAutorunMicrotasks(true);
18518   env->GetIsolate()->EnqueueMicrotask(
18519       Function::New(env->GetIsolate(), MicrotaskTwo));
18520   CompileRun("1+1;");
18521   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18522   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18523
18524   env->GetIsolate()->EnqueueMicrotask(
18525       Function::New(env->GetIsolate(), MicrotaskTwo));
18526   {
18527     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
18528     CompileRun("1+1;");
18529     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18530     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18531   }
18532
18533   CompileRun("1+1;");
18534   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18535   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value());
18536 }
18537
18538
18539 TEST(RunMicrotasksWithoutEnteringContext) {
18540   v8::Isolate* isolate = CcTest::isolate();
18541   HandleScope handle_scope(isolate);
18542   isolate->SetAutorunMicrotasks(false);
18543   Handle<Context> context = Context::New(isolate);
18544   {
18545     Context::Scope context_scope(context);
18546     CompileRun("var ext1Calls = 0;");
18547     isolate->EnqueueMicrotask(Function::New(isolate, MicrotaskOne));
18548   }
18549   isolate->RunMicrotasks();
18550   {
18551     Context::Scope context_scope(context);
18552     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18553   }
18554   isolate->SetAutorunMicrotasks(true);
18555 }
18556
18557
18558 static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
18559   v8::DebugEvent event = event_details.GetEvent();
18560   if (event != v8::Break) return;
18561   Handle<Object> exec_state = event_details.GetExecutionState();
18562   Handle<Value> break_id = exec_state->Get(v8_str("break_id"));
18563   CompileRun("function f(id) { new FrameDetails(id, 0); }");
18564   Handle<Function> fun =
18565       Handle<Function>::Cast(CcTest::global()->Get(v8_str("f")));
18566   fun->Call(CcTest::global(), 1, &break_id);
18567 }
18568
18569
18570 TEST(Regress385349) {
18571   i::FLAG_allow_natives_syntax = true;
18572   v8::Isolate* isolate = CcTest::isolate();
18573   HandleScope handle_scope(isolate);
18574   isolate->SetAutorunMicrotasks(false);
18575   Handle<Context> context = Context::New(isolate);
18576   v8::Debug::SetDebugEventListener(DebugEventInObserver);
18577   {
18578     Context::Scope context_scope(context);
18579     CompileRun("var obj = {};"
18580                "Object.observe(obj, function(changes) { debugger; });"
18581                "obj.a = 0;");
18582   }
18583   isolate->RunMicrotasks();
18584   isolate->SetAutorunMicrotasks(true);
18585   v8::Debug::SetDebugEventListener(NULL);
18586 }
18587
18588
18589 #ifdef ENABLE_DISASSEMBLER
18590 static int probes_counter = 0;
18591 static int misses_counter = 0;
18592 static int updates_counter = 0;
18593
18594
18595 static int* LookupCounter(const char* name) {
18596   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
18597     return &probes_counter;
18598   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
18599     return &misses_counter;
18600   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
18601     return &updates_counter;
18602   }
18603   return NULL;
18604 }
18605
18606
18607 static const char* kMegamorphicTestProgram =
18608     "function ClassA() { };"
18609     "function ClassB() { };"
18610     "ClassA.prototype.foo = function() { };"
18611     "ClassB.prototype.foo = function() { };"
18612     "function fooify(obj) { obj.foo(); };"
18613     "var a = new ClassA();"
18614     "var b = new ClassB();"
18615     "for (var i = 0; i < 10000; i++) {"
18616     "  fooify(a);"
18617     "  fooify(b);"
18618     "}";
18619 #endif
18620
18621
18622 static void StubCacheHelper(bool primary) {
18623 #ifdef ENABLE_DISASSEMBLER
18624   i::FLAG_native_code_counters = true;
18625   if (primary) {
18626     i::FLAG_test_primary_stub_cache = true;
18627   } else {
18628     i::FLAG_test_secondary_stub_cache = true;
18629   }
18630   i::FLAG_crankshaft = false;
18631   LocalContext env;
18632   env->GetIsolate()->SetCounterFunction(LookupCounter);
18633   v8::HandleScope scope(env->GetIsolate());
18634   int initial_probes = probes_counter;
18635   int initial_misses = misses_counter;
18636   int initial_updates = updates_counter;
18637   CompileRun(kMegamorphicTestProgram);
18638   int probes = probes_counter - initial_probes;
18639   int misses = misses_counter - initial_misses;
18640   int updates = updates_counter - initial_updates;
18641   CHECK_LT(updates, 10);
18642   CHECK_LT(misses, 10);
18643   // TODO(verwaest): Update this test to overflow the degree of polymorphism
18644   // before megamorphism. The number of probes will only work once we teach the
18645   // serializer to embed references to counters in the stubs, given that the
18646   // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
18647   CHECK_GE(probes, 0);
18648 #endif
18649 }
18650
18651
18652 TEST(SecondaryStubCache) {
18653   StubCacheHelper(true);
18654 }
18655
18656
18657 TEST(PrimaryStubCache) {
18658   StubCacheHelper(false);
18659 }
18660
18661
18662 #ifdef DEBUG
18663 static int cow_arrays_created_runtime = 0;
18664
18665
18666 static int* LookupCounterCOWArrays(const char* name) {
18667   if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
18668     return &cow_arrays_created_runtime;
18669   }
18670   return NULL;
18671 }
18672 #endif
18673
18674
18675 TEST(CheckCOWArraysCreatedRuntimeCounter) {
18676 #ifdef DEBUG
18677   i::FLAG_native_code_counters = true;
18678   LocalContext env;
18679   env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
18680   v8::HandleScope scope(env->GetIsolate());
18681   int initial_cow_arrays = cow_arrays_created_runtime;
18682   CompileRun("var o = [1, 2, 3];");
18683   CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
18684   CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
18685   CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
18686   CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
18687   CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
18688 #endif
18689 }
18690
18691
18692 TEST(StaticGetters) {
18693   LocalContext context;
18694   i::Factory* factory = CcTest::i_isolate()->factory();
18695   v8::Isolate* isolate = CcTest::isolate();
18696   v8::HandleScope scope(isolate);
18697   i::Handle<i::Object> undefined_value = factory->undefined_value();
18698   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
18699   i::Handle<i::Object> null_value = factory->null_value();
18700   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
18701   i::Handle<i::Object> true_value = factory->true_value();
18702   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
18703   i::Handle<i::Object> false_value = factory->false_value();
18704   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
18705 }
18706
18707
18708 UNINITIALIZED_TEST(IsolateEmbedderData) {
18709   CcTest::DisableAutomaticDispose();
18710   v8::Isolate::CreateParams create_params;
18711   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18712   v8::Isolate* isolate = v8::Isolate::New(create_params);
18713   isolate->Enter();
18714   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
18715   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18716     CHECK(!isolate->GetData(slot));
18717     CHECK(!i_isolate->GetData(slot));
18718   }
18719   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18720     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
18721     isolate->SetData(slot, data);
18722   }
18723   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18724     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
18725     CHECK_EQ(data, isolate->GetData(slot));
18726     CHECK_EQ(data, i_isolate->GetData(slot));
18727   }
18728   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18729     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
18730     isolate->SetData(slot, data);
18731   }
18732   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18733     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
18734     CHECK_EQ(data, isolate->GetData(slot));
18735     CHECK_EQ(data, i_isolate->GetData(slot));
18736   }
18737   isolate->Exit();
18738   isolate->Dispose();
18739 }
18740
18741
18742 TEST(StringEmpty) {
18743   LocalContext context;
18744   i::Factory* factory = CcTest::i_isolate()->factory();
18745   v8::Isolate* isolate = CcTest::isolate();
18746   v8::HandleScope scope(isolate);
18747   i::Handle<i::Object> empty_string = factory->empty_string();
18748   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
18749 }
18750
18751
18752 static int instance_checked_getter_count = 0;
18753 static void InstanceCheckedGetter(
18754     Local<String> name,
18755     const v8::PropertyCallbackInfo<v8::Value>& info) {
18756   CHECK(name->Equals(v8_str("foo")));
18757   instance_checked_getter_count++;
18758   info.GetReturnValue().Set(v8_num(11));
18759 }
18760
18761
18762 static int instance_checked_setter_count = 0;
18763 static void InstanceCheckedSetter(Local<String> name,
18764                       Local<Value> value,
18765                       const v8::PropertyCallbackInfo<void>& info) {
18766   CHECK(name->Equals(v8_str("foo")));
18767   CHECK(value->Equals(v8_num(23)));
18768   instance_checked_setter_count++;
18769 }
18770
18771
18772 static void CheckInstanceCheckedResult(int getters, int setters,
18773                                        bool expects_callbacks,
18774                                        TryCatch* try_catch) {
18775   if (expects_callbacks) {
18776     CHECK(!try_catch->HasCaught());
18777     CHECK_EQ(getters, instance_checked_getter_count);
18778     CHECK_EQ(setters, instance_checked_setter_count);
18779   } else {
18780     CHECK(try_catch->HasCaught());
18781     CHECK_EQ(0, instance_checked_getter_count);
18782     CHECK_EQ(0, instance_checked_setter_count);
18783   }
18784   try_catch->Reset();
18785 }
18786
18787
18788 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
18789   instance_checked_getter_count = 0;
18790   instance_checked_setter_count = 0;
18791   TryCatch try_catch(CcTest::isolate());
18792
18793   // Test path through generic runtime code.
18794   CompileRun("obj.foo");
18795   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
18796   CompileRun("obj.foo = 23");
18797   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
18798
18799   // Test path through generated LoadIC and StoredIC.
18800   CompileRun("function test_get(o) { o.foo; }"
18801              "test_get(obj);");
18802   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
18803   CompileRun("test_get(obj);");
18804   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
18805   CompileRun("test_get(obj);");
18806   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
18807   CompileRun("function test_set(o) { o.foo = 23; }"
18808              "test_set(obj);");
18809   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
18810   CompileRun("test_set(obj);");
18811   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
18812   CompileRun("test_set(obj);");
18813   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
18814
18815   // Test path through optimized code.
18816   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
18817              "test_get(obj);");
18818   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
18819   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
18820              "test_set(obj);");
18821   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
18822
18823   // Cleanup so that closures start out fresh in next check.
18824   CompileRun("%DeoptimizeFunction(test_get);"
18825              "%ClearFunctionTypeFeedback(test_get);"
18826              "%DeoptimizeFunction(test_set);"
18827              "%ClearFunctionTypeFeedback(test_set);");
18828 }
18829
18830
18831 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
18832   v8::internal::FLAG_allow_natives_syntax = true;
18833   LocalContext context;
18834   v8::HandleScope scope(context->GetIsolate());
18835
18836   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18837   Local<ObjectTemplate> inst = templ->InstanceTemplate();
18838   inst->SetAccessor(v8_str("foo"),
18839                     InstanceCheckedGetter, InstanceCheckedSetter,
18840                     Handle<Value>(),
18841                     v8::DEFAULT,
18842                     v8::None,
18843                     v8::AccessorSignature::New(context->GetIsolate(), templ));
18844   context->Global()->Set(v8_str("f"), templ->GetFunction());
18845
18846   printf("Testing positive ...\n");
18847   CompileRun("var obj = new f();");
18848   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18849   CheckInstanceCheckedAccessors(true);
18850
18851   printf("Testing negative ...\n");
18852   CompileRun("var obj = {};"
18853              "obj.__proto__ = new f();");
18854   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18855   CheckInstanceCheckedAccessors(false);
18856 }
18857
18858
18859 static void EmptyInterceptorGetter(
18860     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
18861
18862
18863 static void EmptyInterceptorSetter(
18864     Local<String> name, Local<Value> value,
18865     const v8::PropertyCallbackInfo<v8::Value>& info) {}
18866
18867
18868 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
18869   v8::internal::FLAG_allow_natives_syntax = true;
18870   LocalContext context;
18871   v8::HandleScope scope(context->GetIsolate());
18872
18873   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18874   Local<ObjectTemplate> inst = templ->InstanceTemplate();
18875   templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
18876                                                      EmptyInterceptorSetter);
18877   inst->SetAccessor(v8_str("foo"),
18878                     InstanceCheckedGetter, InstanceCheckedSetter,
18879                     Handle<Value>(),
18880                     v8::DEFAULT,
18881                     v8::None,
18882                     v8::AccessorSignature::New(context->GetIsolate(), templ));
18883   context->Global()->Set(v8_str("f"), templ->GetFunction());
18884
18885   printf("Testing positive ...\n");
18886   CompileRun("var obj = new f();");
18887   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18888   CheckInstanceCheckedAccessors(true);
18889
18890   printf("Testing negative ...\n");
18891   CompileRun("var obj = {};"
18892              "obj.__proto__ = new f();");
18893   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18894   CheckInstanceCheckedAccessors(false);
18895 }
18896
18897
18898 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
18899   v8::internal::FLAG_allow_natives_syntax = true;
18900   LocalContext context;
18901   v8::HandleScope scope(context->GetIsolate());
18902
18903   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18904   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
18905   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
18906                      InstanceCheckedSetter, Handle<Value>(), v8::DEFAULT,
18907                      v8::None,
18908                      v8::AccessorSignature::New(context->GetIsolate(), templ));
18909   context->Global()->Set(v8_str("f"), templ->GetFunction());
18910
18911   printf("Testing positive ...\n");
18912   CompileRun("var obj = new f();");
18913   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18914   CheckInstanceCheckedAccessors(true);
18915
18916   printf("Testing negative ...\n");
18917   CompileRun("var obj = {};"
18918              "obj.__proto__ = new f();");
18919   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18920   CheckInstanceCheckedAccessors(false);
18921
18922   printf("Testing positive with modified prototype chain ...\n");
18923   CompileRun("var obj = new f();"
18924              "var pro = {};"
18925              "pro.__proto__ = obj.__proto__;"
18926              "obj.__proto__ = pro;");
18927   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18928   CheckInstanceCheckedAccessors(true);
18929 }
18930
18931
18932 TEST(TryFinallyMessage) {
18933   LocalContext context;
18934   v8::HandleScope scope(context->GetIsolate());
18935   {
18936     // Test that the original error message is not lost if there is a
18937     // recursive call into Javascript is done in the finally block, e.g. to
18938     // initialize an IC. (crbug.com/129171)
18939     TryCatch try_catch(context->GetIsolate());
18940     const char* trigger_ic =
18941         "try {                      \n"
18942         "  throw new Error('test'); \n"
18943         "} finally {                \n"
18944         "  var x = 0;               \n"
18945         "  x++;                     \n"  // Trigger an IC initialization here.
18946         "}                          \n";
18947     CompileRun(trigger_ic);
18948     CHECK(try_catch.HasCaught());
18949     Local<Message> message = try_catch.Message();
18950     CHECK(!message.IsEmpty());
18951     CHECK_EQ(2, message->GetLineNumber());
18952   }
18953
18954   {
18955     // Test that the original exception message is indeed overwritten if
18956     // a new error is thrown in the finally block.
18957     TryCatch try_catch(context->GetIsolate());
18958     const char* throw_again =
18959         "try {                       \n"
18960         "  throw new Error('test');  \n"
18961         "} finally {                 \n"
18962         "  var x = 0;                \n"
18963         "  x++;                      \n"
18964         "  throw new Error('again'); \n"  // This is the new uncaught error.
18965         "}                           \n";
18966     CompileRun(throw_again);
18967     CHECK(try_catch.HasCaught());
18968     Local<Message> message = try_catch.Message();
18969     CHECK(!message.IsEmpty());
18970     CHECK_EQ(6, message->GetLineNumber());
18971   }
18972 }
18973
18974
18975 static void Helper137002(bool do_store,
18976                          bool polymorphic,
18977                          bool remove_accessor,
18978                          bool interceptor) {
18979   LocalContext context;
18980   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
18981   if (interceptor) {
18982     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
18983                                                             FooSetInterceptor));
18984   } else {
18985     templ->SetAccessor(v8_str("foo"),
18986                        GetterWhichReturns42,
18987                        SetterWhichSetsYOnThisTo23);
18988   }
18989   context->Global()->Set(v8_str("obj"), templ->NewInstance());
18990
18991   // Turn monomorphic on slow object with native accessor, then turn
18992   // polymorphic, finally optimize to create negative lookup and fail.
18993   CompileRun(do_store ?
18994              "function f(x) { x.foo = void 0; }" :
18995              "function f(x) { return x.foo; }");
18996   CompileRun("obj.y = void 0;");
18997   if (!interceptor) {
18998     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
18999   }
19000   CompileRun("obj.__proto__ = null;"
19001              "f(obj); f(obj); f(obj);");
19002   if (polymorphic) {
19003     CompileRun("f({});");
19004   }
19005   CompileRun("obj.y = void 0;"
19006              "%OptimizeFunctionOnNextCall(f);");
19007   if (remove_accessor) {
19008     CompileRun("delete obj.foo;");
19009   }
19010   CompileRun("var result = f(obj);");
19011   if (do_store) {
19012     CompileRun("result = obj.y;");
19013   }
19014   if (remove_accessor && !interceptor) {
19015     CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
19016   } else {
19017     CHECK_EQ(do_store ? 23 : 42,
19018              context->Global()->Get(v8_str("result"))->Int32Value());
19019   }
19020 }
19021
19022
19023 THREADED_TEST(Regress137002a) {
19024   i::FLAG_allow_natives_syntax = true;
19025   i::FLAG_compilation_cache = false;
19026   v8::HandleScope scope(CcTest::isolate());
19027   for (int i = 0; i < 16; i++) {
19028     Helper137002(i & 8, i & 4, i & 2, i & 1);
19029   }
19030 }
19031
19032
19033 THREADED_TEST(Regress137002b) {
19034   i::FLAG_allow_natives_syntax = true;
19035   LocalContext context;
19036   v8::Isolate* isolate = context->GetIsolate();
19037   v8::HandleScope scope(isolate);
19038   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19039   templ->SetAccessor(v8_str("foo"),
19040                      GetterWhichReturns42,
19041                      SetterWhichSetsYOnThisTo23);
19042   context->Global()->Set(v8_str("obj"), templ->NewInstance());
19043
19044   // Turn monomorphic on slow object with native accessor, then just
19045   // delete the property and fail.
19046   CompileRun("function load(x) { return x.foo; }"
19047              "function store(x) { x.foo = void 0; }"
19048              "function keyed_load(x, key) { return x[key]; }"
19049              // Second version of function has a different source (add void 0)
19050              // so that it does not share code with the first version.  This
19051              // ensures that the ICs are monomorphic.
19052              "function load2(x) { void 0; return x.foo; }"
19053              "function store2(x) { void 0; x.foo = void 0; }"
19054              "function keyed_load2(x, key) { void 0; return x[key]; }"
19055
19056              "obj.y = void 0;"
19057              "obj.__proto__ = null;"
19058              "var subobj = {};"
19059              "subobj.y = void 0;"
19060              "subobj.__proto__ = obj;"
19061              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
19062
19063              // Make the ICs monomorphic.
19064              "load(obj); load(obj);"
19065              "load2(subobj); load2(subobj);"
19066              "store(obj); store(obj);"
19067              "store2(subobj); store2(subobj);"
19068              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
19069              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
19070
19071              // Actually test the shiny new ICs and better not crash. This
19072              // serves as a regression test for issue 142088 as well.
19073              "load(obj);"
19074              "load2(subobj);"
19075              "store(obj);"
19076              "store2(subobj);"
19077              "keyed_load(obj, 'foo');"
19078              "keyed_load2(subobj, 'foo');"
19079
19080              // Delete the accessor.  It better not be called any more now.
19081              "delete obj.foo;"
19082              "obj.y = void 0;"
19083              "subobj.y = void 0;"
19084
19085              "var load_result = load(obj);"
19086              "var load_result2 = load2(subobj);"
19087              "var keyed_load_result = keyed_load(obj, 'foo');"
19088              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
19089              "store(obj);"
19090              "store2(subobj);"
19091              "var y_from_obj = obj.y;"
19092              "var y_from_subobj = subobj.y;");
19093   CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
19094   CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
19095   CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
19096   CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
19097   CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
19098   CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
19099 }
19100
19101
19102 THREADED_TEST(Regress142088) {
19103   i::FLAG_allow_natives_syntax = true;
19104   LocalContext context;
19105   v8::Isolate* isolate = context->GetIsolate();
19106   v8::HandleScope scope(isolate);
19107   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19108   templ->SetAccessor(v8_str("foo"),
19109                      GetterWhichReturns42,
19110                      SetterWhichSetsYOnThisTo23);
19111   context->Global()->Set(v8_str("obj"), templ->NewInstance());
19112
19113   CompileRun("function load(x) { return x.foo; }"
19114              "var o = Object.create(obj);"
19115              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
19116              "load(o); load(o); load(o); load(o);");
19117 }
19118
19119
19120 THREADED_TEST(Regress137496) {
19121   i::FLAG_expose_gc = true;
19122   LocalContext context;
19123   v8::HandleScope scope(context->GetIsolate());
19124
19125   // Compile a try-finally clause where the finally block causes a GC
19126   // while there still is a message pending for external reporting.
19127   TryCatch try_catch(context->GetIsolate());
19128   try_catch.SetVerbose(true);
19129   CompileRun("try { throw new Error(); } finally { gc(); }");
19130   CHECK(try_catch.HasCaught());
19131 }
19132
19133
19134 THREADED_TEST(Regress157124) {
19135   LocalContext context;
19136   v8::Isolate* isolate = context->GetIsolate();
19137   v8::HandleScope scope(isolate);
19138   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19139   Local<Object> obj = templ->NewInstance();
19140   obj->GetIdentityHash();
19141   obj->DeleteHiddenValue(v8_str("Bug"));
19142 }
19143
19144
19145 THREADED_TEST(Regress2535) {
19146   LocalContext context;
19147   v8::HandleScope scope(context->GetIsolate());
19148   Local<Value> set_value = CompileRun("new Set();");
19149   Local<Object> set_object(Local<Object>::Cast(set_value));
19150   CHECK_EQ(0, set_object->InternalFieldCount());
19151   Local<Value> map_value = CompileRun("new Map();");
19152   Local<Object> map_object(Local<Object>::Cast(map_value));
19153   CHECK_EQ(0, map_object->InternalFieldCount());
19154 }
19155
19156
19157 THREADED_TEST(Regress2746) {
19158   LocalContext context;
19159   v8::Isolate* isolate = context->GetIsolate();
19160   v8::HandleScope scope(isolate);
19161   Local<Object> obj = Object::New(isolate);
19162   Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
19163   obj->SetHiddenValue(key, v8::Undefined(isolate));
19164   Local<Value> value = obj->GetHiddenValue(key);
19165   CHECK(!value.IsEmpty());
19166   CHECK(value->IsUndefined());
19167 }
19168
19169
19170 THREADED_TEST(Regress260106) {
19171   LocalContext context;
19172   v8::Isolate* isolate = context->GetIsolate();
19173   v8::HandleScope scope(isolate);
19174   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
19175                                                         DummyCallHandler);
19176   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
19177   Local<Function> function = templ->GetFunction();
19178   CHECK(!function.IsEmpty());
19179   CHECK(function->IsFunction());
19180 }
19181
19182
19183 THREADED_TEST(JSONParseObject) {
19184   LocalContext context;
19185   HandleScope scope(context->GetIsolate());
19186   Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
19187   Handle<Object> global = context->Global();
19188   global->Set(v8_str("obj"), obj);
19189   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
19190 }
19191
19192
19193 THREADED_TEST(JSONParseNumber) {
19194   LocalContext context;
19195   HandleScope scope(context->GetIsolate());
19196   Local<Value> obj = v8::JSON::Parse(v8_str("42"));
19197   Handle<Object> global = context->Global();
19198   global->Set(v8_str("obj"), obj);
19199   ExpectString("JSON.stringify(obj)", "42");
19200 }
19201
19202
19203 #if V8_OS_POSIX && !V8_OS_NACL
19204 class ThreadInterruptTest {
19205  public:
19206   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
19207   ~ThreadInterruptTest() {}
19208
19209   void RunTest() {
19210     InterruptThread i_thread(this);
19211     i_thread.Start();
19212
19213     sem_.Wait();
19214     CHECK_EQ(kExpectedValue, sem_value_);
19215   }
19216
19217  private:
19218   static const int kExpectedValue = 1;
19219
19220   class InterruptThread : public v8::base::Thread {
19221    public:
19222     explicit InterruptThread(ThreadInterruptTest* test)
19223         : Thread(Options("InterruptThread")), test_(test) {}
19224
19225     virtual void Run() {
19226       struct sigaction action;
19227
19228       // Ensure that we'll enter waiting condition
19229       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
19230
19231       // Setup signal handler
19232       memset(&action, 0, sizeof(action));
19233       action.sa_handler = SignalHandler;
19234       sigaction(SIGCHLD, &action, NULL);
19235
19236       // Send signal
19237       kill(getpid(), SIGCHLD);
19238
19239       // Ensure that if wait has returned because of error
19240       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
19241
19242       // Set value and signal semaphore
19243       test_->sem_value_ = 1;
19244       test_->sem_.Signal();
19245     }
19246
19247     static void SignalHandler(int signal) {
19248     }
19249
19250    private:
19251      ThreadInterruptTest* test_;
19252   };
19253
19254   v8::base::Semaphore sem_;
19255   volatile int sem_value_;
19256 };
19257
19258
19259 THREADED_TEST(SemaphoreInterruption) {
19260   ThreadInterruptTest().RunTest();
19261 }
19262
19263
19264 #endif  // V8_OS_POSIX
19265
19266
19267 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19268   CHECK(false);
19269 }
19270
19271
19272 TEST(JSONStringifyAccessCheck) {
19273   v8::V8::Initialize();
19274   v8::Isolate* isolate = CcTest::isolate();
19275   v8::HandleScope scope(isolate);
19276
19277   // Create an ObjectTemplate for global objects and install access
19278   // check callbacks that will block access.
19279   v8::Handle<v8::ObjectTemplate> global_template =
19280       v8::ObjectTemplate::New(isolate);
19281   global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
19282
19283   // Create a context and set an x property on it's global object.
19284   LocalContext context0(NULL, global_template);
19285   v8::Handle<v8::Object> global0 = context0->Global();
19286   global0->Set(v8_str("x"), v8_num(42));
19287   ExpectString("JSON.stringify(this)", "{\"x\":42}");
19288
19289   for (int i = 0; i < 2; i++) {
19290     if (i == 1) {
19291       // Install a toJSON function on the second run.
19292       v8::Handle<v8::FunctionTemplate> toJSON =
19293           v8::FunctionTemplate::New(isolate, UnreachableCallback);
19294
19295       global0->Set(v8_str("toJSON"), toJSON->GetFunction());
19296     }
19297     // Create a context with a different security token so that the
19298     // failed access check callback will be called on each access.
19299     LocalContext context1(NULL, global_template);
19300     context1->Global()->Set(v8_str("other"), global0);
19301
19302     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
19303     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
19304     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
19305   }
19306 }
19307
19308
19309 bool access_check_fail_thrown = false;
19310 bool catch_callback_called = false;
19311
19312
19313 // Failed access check callback that performs a GC on each invocation.
19314 void FailedAccessCheckThrows(Local<v8::Object> target,
19315                              v8::AccessType type,
19316                              Local<v8::Value> data) {
19317   access_check_fail_thrown = true;
19318   i::PrintF("Access check failed. Error thrown.\n");
19319   CcTest::isolate()->ThrowException(
19320       v8::Exception::Error(v8_str("cross context")));
19321 }
19322
19323
19324 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19325   for (int i = 0; i < args.Length(); i++) {
19326     i::PrintF("%s\n", *String::Utf8Value(args[i]));
19327   }
19328   catch_callback_called = true;
19329 }
19330
19331
19332 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19333   args[0]->ToObject(args.GetIsolate())->HasOwnProperty(
19334       args[1]->ToString(args.GetIsolate()));
19335 }
19336
19337
19338 void CheckCorrectThrow(const char* script) {
19339   // Test that the script, when wrapped into a try-catch, triggers the catch
19340   // clause due to failed access check throwing an exception.
19341   // The subsequent try-catch should run without any exception.
19342   access_check_fail_thrown = false;
19343   catch_callback_called = false;
19344   i::ScopedVector<char> source(1024);
19345   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
19346   CompileRun(source.start());
19347   CHECK(access_check_fail_thrown);
19348   CHECK(catch_callback_called);
19349
19350   access_check_fail_thrown = false;
19351   catch_callback_called = false;
19352   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
19353   CHECK(!access_check_fail_thrown);
19354   CHECK(!catch_callback_called);
19355 }
19356
19357
19358 TEST(AccessCheckThrows) {
19359   i::FLAG_allow_natives_syntax = true;
19360   i::FLAG_turbo_try_catch = true;
19361   v8::V8::Initialize();
19362   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
19363   v8::Isolate* isolate = CcTest::isolate();
19364   v8::HandleScope scope(isolate);
19365
19366   // Create an ObjectTemplate for global objects and install access
19367   // check callbacks that will block access.
19368   v8::Handle<v8::ObjectTemplate> global_template =
19369       v8::ObjectTemplate::New(isolate);
19370   global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
19371
19372   // Create a context and set an x property on it's global object.
19373   LocalContext context0(NULL, global_template);
19374   v8::Handle<v8::Object> global0 = context0->Global();
19375
19376   // Create a context with a different security token so that the
19377   // failed access check callback will be called on each access.
19378   LocalContext context1(NULL, global_template);
19379   context1->Global()->Set(v8_str("other"), global0);
19380
19381   v8::Handle<v8::FunctionTemplate> catcher_fun =
19382       v8::FunctionTemplate::New(isolate, CatcherCallback);
19383   context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
19384
19385   v8::Handle<v8::FunctionTemplate> has_own_property_fun =
19386       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
19387   context1->Global()->Set(v8_str("has_own_property"),
19388                           has_own_property_fun->GetFunction());
19389
19390   {
19391     v8::TryCatch try_catch(isolate);
19392     access_check_fail_thrown = false;
19393     CompileRun("other.x;");
19394     CHECK(access_check_fail_thrown);
19395     CHECK(try_catch.HasCaught());
19396   }
19397
19398   CheckCorrectThrow("other.x");
19399   CheckCorrectThrow("other[1]");
19400   CheckCorrectThrow("JSON.stringify(other)");
19401   CheckCorrectThrow("has_own_property(other, 'x')");
19402   CheckCorrectThrow("%GetProperty(other, 'x')");
19403   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
19404   CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
19405   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
19406   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
19407   CheckCorrectThrow("%HasOwnProperty(other, 'x')");
19408   CheckCorrectThrow("%HasProperty(other, 'x')");
19409   CheckCorrectThrow("%HasElement(other, 1)");
19410   CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
19411   CheckCorrectThrow("%GetPropertyNames(other)");
19412   // PROPERTY_ATTRIBUTES_NONE = 0
19413   CheckCorrectThrow("%GetOwnPropertyNames(other, 0)");
19414   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
19415                         "other, 'x', null, null, 1)");
19416
19417   // Reset the failed access check callback so it does not influence
19418   // the other tests.
19419   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19420 }
19421
19422
19423 class RequestInterruptTestBase {
19424  public:
19425   RequestInterruptTestBase()
19426       : env_(),
19427         isolate_(env_->GetIsolate()),
19428         sem_(0),
19429         warmup_(20000),
19430         should_continue_(true) {
19431   }
19432
19433   virtual ~RequestInterruptTestBase() { }
19434
19435   virtual void StartInterruptThread() = 0;
19436
19437   virtual void TestBody() = 0;
19438
19439   void RunTest() {
19440     StartInterruptThread();
19441
19442     v8::HandleScope handle_scope(isolate_);
19443
19444     TestBody();
19445
19446     // Verify we arrived here because interruptor was called
19447     // not due to a bug causing us to exit the loop too early.
19448     CHECK(!should_continue());
19449   }
19450
19451   void WakeUpInterruptor() {
19452     sem_.Signal();
19453   }
19454
19455   bool should_continue() const { return should_continue_; }
19456
19457   bool ShouldContinue() {
19458     if (warmup_ > 0) {
19459       if (--warmup_ == 0) {
19460         WakeUpInterruptor();
19461       }
19462     }
19463
19464     return should_continue_;
19465   }
19466
19467   static void ShouldContinueCallback(
19468       const v8::FunctionCallbackInfo<Value>& info) {
19469     RequestInterruptTestBase* test =
19470         reinterpret_cast<RequestInterruptTestBase*>(
19471             info.Data().As<v8::External>()->Value());
19472     info.GetReturnValue().Set(test->ShouldContinue());
19473   }
19474
19475   LocalContext env_;
19476   v8::Isolate* isolate_;
19477   v8::base::Semaphore sem_;
19478   int warmup_;
19479   bool should_continue_;
19480 };
19481
19482
19483 class RequestInterruptTestBaseWithSimpleInterrupt
19484     : public RequestInterruptTestBase {
19485  public:
19486   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
19487
19488   virtual void StartInterruptThread() {
19489     i_thread.Start();
19490   }
19491
19492  private:
19493   class InterruptThread : public v8::base::Thread {
19494    public:
19495     explicit InterruptThread(RequestInterruptTestBase* test)
19496         : Thread(Options("RequestInterruptTest")), test_(test) {}
19497
19498     virtual void Run() {
19499       test_->sem_.Wait();
19500       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
19501     }
19502
19503     static void OnInterrupt(v8::Isolate* isolate, void* data) {
19504       reinterpret_cast<RequestInterruptTestBase*>(data)->
19505           should_continue_ = false;
19506     }
19507
19508    private:
19509      RequestInterruptTestBase* test_;
19510   };
19511
19512   InterruptThread i_thread;
19513 };
19514
19515
19516 class RequestInterruptTestWithFunctionCall
19517     : public RequestInterruptTestBaseWithSimpleInterrupt {
19518  public:
19519   virtual void TestBody() {
19520     Local<Function> func = Function::New(
19521         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
19522     env_->Global()->Set(v8_str("ShouldContinue"), func);
19523
19524     CompileRun("while (ShouldContinue()) { }");
19525   }
19526 };
19527
19528
19529 class RequestInterruptTestWithMethodCall
19530     : public RequestInterruptTestBaseWithSimpleInterrupt {
19531  public:
19532   virtual void TestBody() {
19533     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19534     v8::Local<v8::Template> proto = t->PrototypeTemplate();
19535     proto->Set(v8_str("shouldContinue"), Function::New(
19536         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19537     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19538
19539     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
19540   }
19541 };
19542
19543
19544 class RequestInterruptTestWithAccessor
19545     : public RequestInterruptTestBaseWithSimpleInterrupt {
19546  public:
19547   virtual void TestBody() {
19548     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19549     v8::Local<v8::Template> proto = t->PrototypeTemplate();
19550     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
19551         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19552     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19553
19554     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
19555   }
19556 };
19557
19558
19559 class RequestInterruptTestWithNativeAccessor
19560     : public RequestInterruptTestBaseWithSimpleInterrupt {
19561  public:
19562   virtual void TestBody() {
19563     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19564     t->InstanceTemplate()->SetNativeDataProperty(
19565         v8_str("shouldContinue"),
19566         &ShouldContinueNativeGetter,
19567         NULL,
19568         v8::External::New(isolate_, this));
19569     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19570
19571     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
19572   }
19573
19574  private:
19575   static void ShouldContinueNativeGetter(
19576       Local<String> property,
19577       const v8::PropertyCallbackInfo<v8::Value>& info) {
19578     RequestInterruptTestBase* test =
19579         reinterpret_cast<RequestInterruptTestBase*>(
19580             info.Data().As<v8::External>()->Value());
19581     info.GetReturnValue().Set(test->ShouldContinue());
19582   }
19583 };
19584
19585
19586 class RequestInterruptTestWithMethodCallAndInterceptor
19587     : public RequestInterruptTestBaseWithSimpleInterrupt {
19588  public:
19589   virtual void TestBody() {
19590     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19591     v8::Local<v8::Template> proto = t->PrototypeTemplate();
19592     proto->Set(v8_str("shouldContinue"), Function::New(
19593         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19594     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
19595     instance_template->SetHandler(
19596         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
19597
19598     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19599
19600     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
19601   }
19602
19603  private:
19604   static void EmptyInterceptor(
19605       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
19606 };
19607
19608
19609 class RequestInterruptTestWithMathAbs
19610     : public RequestInterruptTestBaseWithSimpleInterrupt {
19611  public:
19612   virtual void TestBody() {
19613     env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
19614         isolate_,
19615         WakeUpInterruptorCallback,
19616         v8::External::New(isolate_, this)));
19617
19618     env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
19619         isolate_,
19620         ShouldContinueCallback,
19621         v8::External::New(isolate_, this)));
19622
19623     i::FLAG_allow_natives_syntax = true;
19624     CompileRun("function loopish(o) {"
19625                "  var pre = 10;"
19626                "  while (o.abs(1) > 0) {"
19627                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
19628                "    if (pre > 0) {"
19629                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
19630                "    }"
19631                "  }"
19632                "}"
19633                "var i = 50;"
19634                "var obj = {abs: function () { return i-- }, x: null};"
19635                "delete obj.x;"
19636                "loopish(obj);"
19637                "%OptimizeFunctionOnNextCall(loopish);"
19638                "loopish(Math);");
19639
19640     i::FLAG_allow_natives_syntax = false;
19641   }
19642
19643  private:
19644   static void WakeUpInterruptorCallback(
19645       const v8::FunctionCallbackInfo<Value>& info) {
19646     if (!info[0]->BooleanValue()) return;
19647
19648     RequestInterruptTestBase* test =
19649         reinterpret_cast<RequestInterruptTestBase*>(
19650             info.Data().As<v8::External>()->Value());
19651     test->WakeUpInterruptor();
19652   }
19653
19654   static void ShouldContinueCallback(
19655       const v8::FunctionCallbackInfo<Value>& info) {
19656     RequestInterruptTestBase* test =
19657         reinterpret_cast<RequestInterruptTestBase*>(
19658             info.Data().As<v8::External>()->Value());
19659     info.GetReturnValue().Set(test->should_continue());
19660   }
19661 };
19662
19663
19664 TEST(RequestInterruptTestWithFunctionCall) {
19665   RequestInterruptTestWithFunctionCall().RunTest();
19666 }
19667
19668
19669 TEST(RequestInterruptTestWithMethodCall) {
19670   RequestInterruptTestWithMethodCall().RunTest();
19671 }
19672
19673
19674 TEST(RequestInterruptTestWithAccessor) {
19675   RequestInterruptTestWithAccessor().RunTest();
19676 }
19677
19678
19679 TEST(RequestInterruptTestWithNativeAccessor) {
19680   RequestInterruptTestWithNativeAccessor().RunTest();
19681 }
19682
19683
19684 TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
19685   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
19686 }
19687
19688
19689 TEST(RequestInterruptTestWithMathAbs) {
19690   RequestInterruptTestWithMathAbs().RunTest();
19691 }
19692
19693
19694 class RequestMultipleInterrupts : public RequestInterruptTestBase {
19695  public:
19696   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
19697
19698   virtual void StartInterruptThread() {
19699     i_thread.Start();
19700   }
19701
19702   virtual void TestBody() {
19703     Local<Function> func = Function::New(
19704         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
19705     env_->Global()->Set(v8_str("ShouldContinue"), func);
19706
19707     CompileRun("while (ShouldContinue()) { }");
19708   }
19709
19710  private:
19711   class InterruptThread : public v8::base::Thread {
19712    public:
19713     enum { NUM_INTERRUPTS = 10 };
19714     explicit InterruptThread(RequestMultipleInterrupts* test)
19715         : Thread(Options("RequestInterruptTest")), test_(test) {}
19716
19717     virtual void Run() {
19718       test_->sem_.Wait();
19719       for (int i = 0; i < NUM_INTERRUPTS; i++) {
19720         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
19721       }
19722     }
19723
19724     static void OnInterrupt(v8::Isolate* isolate, void* data) {
19725       RequestMultipleInterrupts* test =
19726           reinterpret_cast<RequestMultipleInterrupts*>(data);
19727       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
19728     }
19729
19730    private:
19731     RequestMultipleInterrupts* test_;
19732   };
19733
19734   InterruptThread i_thread;
19735   int counter_;
19736 };
19737
19738
19739 TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
19740
19741
19742 static bool interrupt_was_called = false;
19743
19744
19745 void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
19746   interrupt_was_called = true;
19747 }
19748
19749
19750 TEST(RequestInterruptSmallScripts) {
19751   LocalContext env;
19752   v8::Isolate* isolate = CcTest::isolate();
19753   v8::HandleScope scope(isolate);
19754
19755   interrupt_was_called = false;
19756   isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
19757   CompileRun("(function(x){return x;})(1);");
19758   CHECK(interrupt_was_called);
19759 }
19760
19761
19762 static Local<Value> function_new_expected_env;
19763 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
19764   CHECK(function_new_expected_env->Equals(info.Data()));
19765   info.GetReturnValue().Set(17);
19766 }
19767
19768
19769 THREADED_TEST(FunctionNew) {
19770   LocalContext env;
19771   v8::Isolate* isolate = env->GetIsolate();
19772   v8::HandleScope scope(isolate);
19773   Local<Object> data = v8::Object::New(isolate);
19774   function_new_expected_env = data;
19775   Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
19776   env->Global()->Set(v8_str("func"), func);
19777   Local<Value> result = CompileRun("func();");
19778   CHECK(v8::Integer::New(isolate, 17)->Equals(result));
19779   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
19780   // Verify function not cached
19781   auto serial_number = handle(i::Smi::cast(v8::Utils::OpenHandle(*func)
19782                                                ->shared()
19783                                                ->get_api_func_data()
19784                                                ->serial_number()),
19785                               i_isolate);
19786   auto cache = i_isolate->function_cache();
19787   CHECK(cache->Lookup(serial_number)->IsTheHole());
19788   // Verify that each Function::New creates a new function instance
19789   Local<Object> data2 = v8::Object::New(isolate);
19790   function_new_expected_env = data2;
19791   Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
19792   CHECK(!func2->IsNull());
19793   CHECK(!func->Equals(func2));
19794   env->Global()->Set(v8_str("func2"), func2);
19795   Local<Value> result2 = CompileRun("func2();");
19796   CHECK(v8::Integer::New(isolate, 17)->Equals(result2));
19797 }
19798
19799
19800 TEST(EscapeableHandleScope) {
19801   HandleScope outer_scope(CcTest::isolate());
19802   LocalContext context;
19803   const int runs = 10;
19804   Local<String> values[runs];
19805   for (int i = 0; i < runs; i++) {
19806     v8::EscapableHandleScope inner_scope(CcTest::isolate());
19807     Local<String> value;
19808     if (i != 0) value = v8_str("escape value");
19809     values[i] = inner_scope.Escape(value);
19810   }
19811   for (int i = 0; i < runs; i++) {
19812     Local<String> expected;
19813     if (i != 0) {
19814       CHECK(v8_str("escape value")->Equals(values[i]));
19815     } else {
19816       CHECK(values[i].IsEmpty());
19817     }
19818   }
19819 }
19820
19821
19822 static void SetterWhichExpectsThisAndHolderToDiffer(
19823     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
19824   CHECK(info.Holder() != info.This());
19825 }
19826
19827
19828 TEST(Regress239669) {
19829   LocalContext context;
19830   v8::Isolate* isolate = context->GetIsolate();
19831   v8::HandleScope scope(isolate);
19832   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19833   templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
19834   context->Global()->Set(v8_str("P"), templ->NewInstance());
19835   CompileRun(
19836       "function C1() {"
19837       "  this.x = 23;"
19838       "};"
19839       "C1.prototype = P;"
19840       "for (var i = 0; i < 4; i++ ) {"
19841       "  new C1();"
19842       "}");
19843 }
19844
19845
19846 class ApiCallOptimizationChecker {
19847  private:
19848   static Local<Object> data;
19849   static Local<Object> receiver;
19850   static Local<Object> holder;
19851   static Local<Object> callee;
19852   static int count;
19853
19854   static void OptimizationCallback(
19855       const v8::FunctionCallbackInfo<v8::Value>& info) {
19856     CHECK(callee == info.Callee());
19857     CHECK(data == info.Data());
19858     CHECK(receiver == info.This());
19859     if (info.Length() == 1) {
19860       CHECK(v8_num(1)->Equals(info[0]));
19861     }
19862     CHECK(holder == info.Holder());
19863     count++;
19864     info.GetReturnValue().Set(v8_str("returned"));
19865   }
19866
19867  public:
19868   enum SignatureType {
19869     kNoSignature,
19870     kSignatureOnReceiver,
19871     kSignatureOnPrototype
19872   };
19873
19874   void RunAll() {
19875     SignatureType signature_types[] =
19876       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
19877     for (unsigned i = 0; i < arraysize(signature_types); i++) {
19878       SignatureType signature_type = signature_types[i];
19879       for (int j = 0; j < 2; j++) {
19880         bool global = j == 0;
19881         int key = signature_type +
19882             arraysize(signature_types) * (global ? 1 : 0);
19883         Run(signature_type, global, key);
19884       }
19885     }
19886   }
19887
19888   void Run(SignatureType signature_type, bool global, int key) {
19889     v8::Isolate* isolate = CcTest::isolate();
19890     v8::HandleScope scope(isolate);
19891     // Build a template for signature checks.
19892     Local<v8::ObjectTemplate> signature_template;
19893     Local<v8::Signature> signature;
19894     {
19895       Local<v8::FunctionTemplate> parent_template =
19896         FunctionTemplate::New(isolate);
19897       parent_template->SetHiddenPrototype(true);
19898       Local<v8::FunctionTemplate> function_template
19899           = FunctionTemplate::New(isolate);
19900       function_template->Inherit(parent_template);
19901       switch (signature_type) {
19902         case kNoSignature:
19903           break;
19904         case kSignatureOnReceiver:
19905           signature = v8::Signature::New(isolate, function_template);
19906           break;
19907         case kSignatureOnPrototype:
19908           signature = v8::Signature::New(isolate, parent_template);
19909           break;
19910       }
19911       signature_template = function_template->InstanceTemplate();
19912     }
19913     // Global object must pass checks.
19914     Local<v8::Context> context =
19915         v8::Context::New(isolate, NULL, signature_template);
19916     v8::Context::Scope context_scope(context);
19917     // Install regular object that can pass signature checks.
19918     Local<Object> function_receiver = signature_template->NewInstance();
19919     context->Global()->Set(v8_str("function_receiver"), function_receiver);
19920     // Get the holder objects.
19921     Local<Object> inner_global =
19922         Local<Object>::Cast(context->Global()->GetPrototype());
19923     // Install functions on hidden prototype object if there is one.
19924     data = Object::New(isolate);
19925     Local<FunctionTemplate> function_template = FunctionTemplate::New(
19926         isolate, OptimizationCallback, data, signature);
19927     Local<Function> function = function_template->GetFunction();
19928     Local<Object> global_holder = inner_global;
19929     Local<Object> function_holder = function_receiver;
19930     if (signature_type == kSignatureOnPrototype) {
19931       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
19932       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
19933     }
19934     global_holder->Set(v8_str("g_f"), function);
19935     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
19936     function_holder->Set(v8_str("f"), function);
19937     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
19938     // Initialize expected values.
19939     callee = function;
19940     count = 0;
19941     if (global) {
19942       receiver = context->Global();
19943       holder = inner_global;
19944     } else {
19945       holder = function_receiver;
19946       // If not using a signature, add something else to the prototype chain
19947       // to test the case that holder != receiver
19948       if (signature_type == kNoSignature) {
19949         receiver = Local<Object>::Cast(CompileRun(
19950             "var receiver_subclass = {};\n"
19951             "receiver_subclass.__proto__ = function_receiver;\n"
19952             "receiver_subclass"));
19953       } else {
19954         receiver = Local<Object>::Cast(CompileRun(
19955           "var receiver_subclass = function_receiver;\n"
19956           "receiver_subclass"));
19957       }
19958     }
19959     // With no signature, the holder is not set.
19960     if (signature_type == kNoSignature) holder = receiver;
19961     // build wrap_function
19962     i::ScopedVector<char> wrap_function(200);
19963     if (global) {
19964       i::SNPrintF(
19965           wrap_function,
19966           "function wrap_f_%d() { var f = g_f; return f(); }\n"
19967           "function wrap_get_%d() { return this.g_acc; }\n"
19968           "function wrap_set_%d() { return this.g_acc = 1; }\n",
19969           key, key, key);
19970     } else {
19971       i::SNPrintF(
19972           wrap_function,
19973           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
19974           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
19975           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
19976           key, key, key);
19977     }
19978     // build source string
19979     i::ScopedVector<char> source(1000);
19980     i::SNPrintF(
19981         source,
19982         "%s\n"  // wrap functions
19983         "function wrap_f() { return wrap_f_%d(); }\n"
19984         "function wrap_get() { return wrap_get_%d(); }\n"
19985         "function wrap_set() { return wrap_set_%d(); }\n"
19986         "check = function(returned) {\n"
19987         "  if (returned !== 'returned') { throw returned; }\n"
19988         "}\n"
19989         "\n"
19990         "check(wrap_f());\n"
19991         "check(wrap_f());\n"
19992         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
19993         "check(wrap_f());\n"
19994         "\n"
19995         "check(wrap_get());\n"
19996         "check(wrap_get());\n"
19997         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
19998         "check(wrap_get());\n"
19999         "\n"
20000         "check = function(returned) {\n"
20001         "  if (returned !== 1) { throw returned; }\n"
20002         "}\n"
20003         "check(wrap_set());\n"
20004         "check(wrap_set());\n"
20005         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
20006         "check(wrap_set());\n",
20007         wrap_function.start(), key, key, key, key, key, key);
20008     v8::TryCatch try_catch(isolate);
20009     CompileRun(source.start());
20010     DCHECK(!try_catch.HasCaught());
20011     CHECK_EQ(9, count);
20012   }
20013 };
20014
20015
20016 Local<Object> ApiCallOptimizationChecker::data;
20017 Local<Object> ApiCallOptimizationChecker::receiver;
20018 Local<Object> ApiCallOptimizationChecker::holder;
20019 Local<Object> ApiCallOptimizationChecker::callee;
20020 int ApiCallOptimizationChecker::count = 0;
20021
20022
20023 TEST(FunctionCallOptimization) {
20024   i::FLAG_allow_natives_syntax = true;
20025   ApiCallOptimizationChecker checker;
20026   checker.RunAll();
20027 }
20028
20029
20030 TEST(FunctionCallOptimizationMultipleArgs) {
20031   i::FLAG_allow_natives_syntax = true;
20032   LocalContext context;
20033   v8::Isolate* isolate = context->GetIsolate();
20034   v8::HandleScope scope(isolate);
20035   Handle<Object> global = context->Global();
20036   Local<v8::Function> function = Function::New(isolate, Returns42);
20037   global->Set(v8_str("x"), function);
20038   CompileRun(
20039       "function x_wrap() {\n"
20040       "  for (var i = 0; i < 5; i++) {\n"
20041       "    x(1,2,3);\n"
20042       "  }\n"
20043       "}\n"
20044       "x_wrap();\n"
20045       "%OptimizeFunctionOnNextCall(x_wrap);"
20046       "x_wrap();\n");
20047 }
20048
20049
20050 static void ReturnsSymbolCallback(
20051     const v8::FunctionCallbackInfo<v8::Value>& info) {
20052   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
20053 }
20054
20055
20056 TEST(ApiCallbackCanReturnSymbols) {
20057   i::FLAG_allow_natives_syntax = true;
20058   LocalContext context;
20059   v8::Isolate* isolate = context->GetIsolate();
20060   v8::HandleScope scope(isolate);
20061   Handle<Object> global = context->Global();
20062   Local<v8::Function> function = Function::New(isolate, ReturnsSymbolCallback);
20063   global->Set(v8_str("x"), function);
20064   CompileRun(
20065       "function x_wrap() {\n"
20066       "  for (var i = 0; i < 5; i++) {\n"
20067       "    x();\n"
20068       "  }\n"
20069       "}\n"
20070       "x_wrap();\n"
20071       "%OptimizeFunctionOnNextCall(x_wrap);"
20072       "x_wrap();\n");
20073 }
20074
20075
20076 TEST(EmptyApiCallback) {
20077   LocalContext context;
20078   auto isolate = context->GetIsolate();
20079   v8::HandleScope scope(isolate);
20080   auto global = context->Global();
20081   auto function = FunctionTemplate::New(isolate)->GetFunction();
20082   global->Set(v8_str("x"), function);
20083
20084   auto result = CompileRun("x()");
20085   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
20086
20087   result = CompileRun("x(1,2,3)");
20088   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
20089
20090   result = CompileRun("7 + x.call(3) + 11");
20091   CHECK(result->IsInt32());
20092   CHECK_EQ(21, result->Int32Value());
20093
20094   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
20095   CHECK(result->IsInt32());
20096   CHECK_EQ(21, result->Int32Value());
20097
20098   result = CompileRun("var y = []; x.call(y)");
20099   CHECK(result->IsArray());
20100
20101   result = CompileRun("x.call(y, 1, 2, 3, 4)");
20102   CHECK(result->IsArray());
20103 }
20104
20105
20106 TEST(SimpleSignatureCheck) {
20107   LocalContext context;
20108   auto isolate = context->GetIsolate();
20109   v8::HandleScope scope(isolate);
20110   auto global = context->Global();
20111   auto sig_obj = FunctionTemplate::New(isolate);
20112   auto sig = v8::Signature::New(isolate, sig_obj);
20113   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20114   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20115   global->Set(v8_str("x"), x->GetFunction());
20116   CompileRun("var s = new sig_obj();");
20117   {
20118     TryCatch try_catch(isolate);
20119     CompileRun("x()");
20120     CHECK(try_catch.HasCaught());
20121   }
20122   {
20123     TryCatch try_catch(isolate);
20124     CompileRun("x.call(1)");
20125     CHECK(try_catch.HasCaught());
20126   }
20127   {
20128     TryCatch try_catch(isolate);
20129     auto result = CompileRun("s.x = x; s.x()");
20130     CHECK(!try_catch.HasCaught());
20131     CHECK_EQ(42, result->Int32Value());
20132   }
20133   {
20134     TryCatch try_catch(isolate);
20135     auto result = CompileRun("x.call(s)");
20136     CHECK(!try_catch.HasCaught());
20137     CHECK_EQ(42, result->Int32Value());
20138   }
20139 }
20140
20141
20142 TEST(ChainSignatureCheck) {
20143   LocalContext context;
20144   auto isolate = context->GetIsolate();
20145   v8::HandleScope scope(isolate);
20146   auto global = context->Global();
20147   auto sig_obj = FunctionTemplate::New(isolate);
20148   auto sig = v8::Signature::New(isolate, sig_obj);
20149   for (int i = 0; i < 4; ++i) {
20150     auto temp = FunctionTemplate::New(isolate);
20151     temp->Inherit(sig_obj);
20152     sig_obj = temp;
20153   }
20154   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20155   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20156   global->Set(v8_str("x"), x->GetFunction());
20157   CompileRun("var s = new sig_obj();");
20158   {
20159     TryCatch try_catch(isolate);
20160     CompileRun("x()");
20161     CHECK(try_catch.HasCaught());
20162   }
20163   {
20164     TryCatch try_catch(isolate);
20165     CompileRun("x.call(1)");
20166     CHECK(try_catch.HasCaught());
20167   }
20168   {
20169     TryCatch try_catch(isolate);
20170     auto result = CompileRun("s.x = x; s.x()");
20171     CHECK(!try_catch.HasCaught());
20172     CHECK_EQ(42, result->Int32Value());
20173   }
20174   {
20175     TryCatch try_catch(isolate);
20176     auto result = CompileRun("x.call(s)");
20177     CHECK(!try_catch.HasCaught());
20178     CHECK_EQ(42, result->Int32Value());
20179   }
20180 }
20181
20182
20183 TEST(PrototypeSignatureCheck) {
20184   LocalContext context;
20185   auto isolate = context->GetIsolate();
20186   v8::HandleScope scope(isolate);
20187   auto global = context->Global();
20188   auto sig_obj = FunctionTemplate::New(isolate);
20189   sig_obj->SetHiddenPrototype(true);
20190   auto sig = v8::Signature::New(isolate, sig_obj);
20191   auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20192   global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20193   global->Set(v8_str("x"), x->GetFunction());
20194   CompileRun("s = {}; s.__proto__ = new sig_obj();");
20195   {
20196     TryCatch try_catch(isolate);
20197     CompileRun("x()");
20198     CHECK(try_catch.HasCaught());
20199   }
20200   {
20201     TryCatch try_catch(isolate);
20202     CompileRun("x.call(1)");
20203     CHECK(try_catch.HasCaught());
20204   }
20205   {
20206     TryCatch try_catch(isolate);
20207     auto result = CompileRun("s.x = x; s.x()");
20208     CHECK(!try_catch.HasCaught());
20209     CHECK_EQ(42, result->Int32Value());
20210   }
20211   {
20212     TryCatch try_catch(isolate);
20213     auto result = CompileRun("x.call(s)");
20214     CHECK(!try_catch.HasCaught());
20215     CHECK_EQ(42, result->Int32Value());
20216   }
20217 }
20218
20219
20220 static const char* last_event_message;
20221 static int last_event_status;
20222 void StoringEventLoggerCallback(const char* message, int status) {
20223     last_event_message = message;
20224     last_event_status = status;
20225 }
20226
20227
20228 TEST(EventLogging) {
20229   v8::Isolate* isolate = CcTest::isolate();
20230   isolate->SetEventLogger(StoringEventLoggerCallback);
20231   v8::internal::HistogramTimer histogramTimer(
20232       "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
20233       reinterpret_cast<v8::internal::Isolate*>(isolate));
20234   histogramTimer.Start();
20235   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
20236   CHECK_EQ(0, last_event_status);
20237   histogramTimer.Stop();
20238   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
20239   CHECK_EQ(1, last_event_status);
20240 }
20241
20242
20243 TEST(Promises) {
20244   LocalContext context;
20245   v8::Isolate* isolate = context->GetIsolate();
20246   v8::HandleScope scope(isolate);
20247   Handle<Object> global = context->Global();
20248
20249   // Creation.
20250   Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
20251   Handle<v8::Promise::Resolver> rr = v8::Promise::Resolver::New(isolate);
20252   Handle<v8::Promise> p = pr->GetPromise();
20253   Handle<v8::Promise> r = rr->GetPromise();
20254   CHECK_EQ(isolate, p->GetIsolate());
20255
20256   // IsPromise predicate.
20257   CHECK(p->IsPromise());
20258   CHECK(r->IsPromise());
20259   Handle<Value> o = v8::Object::New(isolate);
20260   CHECK(!o->IsPromise());
20261
20262   // Resolution and rejection.
20263   pr->Resolve(v8::Integer::New(isolate, 1));
20264   CHECK(p->IsPromise());
20265   rr->Reject(v8::Integer::New(isolate, 2));
20266   CHECK(r->IsPromise());
20267
20268   // Chaining non-pending promises.
20269   CompileRun(
20270       "var x1 = 0;\n"
20271       "var x2 = 0;\n"
20272       "function f1(x) { x1 = x; return x+1 };\n"
20273       "function f2(x) { x2 = x; return x+1 };\n");
20274   Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
20275   Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
20276
20277   p->Chain(f1);
20278   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20279   isolate->RunMicrotasks();
20280   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20281
20282   p->Catch(f2);
20283   isolate->RunMicrotasks();
20284   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20285
20286   r->Catch(f2);
20287   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20288   isolate->RunMicrotasks();
20289   CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
20290
20291   r->Chain(f1);
20292   isolate->RunMicrotasks();
20293   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20294
20295   // Chaining pending promises.
20296   CompileRun("x1 = x2 = 0;");
20297   pr = v8::Promise::Resolver::New(isolate);
20298   rr = v8::Promise::Resolver::New(isolate);
20299
20300   pr->GetPromise()->Chain(f1);
20301   rr->GetPromise()->Catch(f2);
20302   isolate->RunMicrotasks();
20303   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20304   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20305
20306   pr->Resolve(v8::Integer::New(isolate, 1));
20307   rr->Reject(v8::Integer::New(isolate, 2));
20308   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20309   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20310
20311   isolate->RunMicrotasks();
20312   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20313   CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
20314
20315   // Multi-chaining.
20316   CompileRun("x1 = x2 = 0;");
20317   pr = v8::Promise::Resolver::New(isolate);
20318   pr->GetPromise()->Chain(f1)->Chain(f2);
20319   pr->Resolve(v8::Integer::New(isolate, 3));
20320   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20321   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20322   isolate->RunMicrotasks();
20323   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20324   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20325
20326   CompileRun("x1 = x2 = 0;");
20327   rr = v8::Promise::Resolver::New(isolate);
20328   rr->GetPromise()->Catch(f1)->Chain(f2);
20329   rr->Reject(v8::Integer::New(isolate, 3));
20330   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20331   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20332   isolate->RunMicrotasks();
20333   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20334   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20335 }
20336
20337
20338 TEST(PromiseThen) {
20339   LocalContext context;
20340   v8::Isolate* isolate = context->GetIsolate();
20341   v8::HandleScope scope(isolate);
20342   Handle<Object> global = context->Global();
20343
20344   // Creation.
20345   Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
20346   Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
20347   Handle<v8::Promise> p = pr->GetPromise();
20348   Handle<v8::Promise> q = qr->GetPromise();
20349
20350   CHECK(p->IsPromise());
20351   CHECK(q->IsPromise());
20352
20353   pr->Resolve(v8::Integer::New(isolate, 1));
20354   qr->Resolve(p);
20355
20356   // Chaining non-pending promises.
20357   CompileRun(
20358       "var x1 = 0;\n"
20359       "var x2 = 0;\n"
20360       "function f1(x) { x1 = x; return x+1 };\n"
20361       "function f2(x) { x2 = x; return x+1 };\n");
20362   Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
20363   Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
20364
20365   // Chain
20366   q->Chain(f1);
20367   CHECK(global->Get(v8_str("x1"))->IsNumber());
20368   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20369   isolate->RunMicrotasks();
20370   CHECK(!global->Get(v8_str("x1"))->IsNumber());
20371   CHECK(p->Equals(global->Get(v8_str("x1"))));
20372
20373   // Then
20374   CompileRun("x1 = x2 = 0;");
20375   q->Then(f1);
20376   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20377   isolate->RunMicrotasks();
20378   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20379
20380   // Then
20381   CompileRun("x1 = x2 = 0;");
20382   pr = v8::Promise::Resolver::New(isolate);
20383   qr = v8::Promise::Resolver::New(isolate);
20384
20385   qr->Resolve(pr);
20386   qr->GetPromise()->Then(f1)->Then(f2);
20387
20388   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20389   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20390   isolate->RunMicrotasks();
20391   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20392   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20393
20394   pr->Resolve(v8::Integer::New(isolate, 3));
20395
20396   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20397   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20398   isolate->RunMicrotasks();
20399   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20400   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20401 }
20402
20403
20404 TEST(DisallowJavascriptExecutionScope) {
20405   LocalContext context;
20406   v8::Isolate* isolate = context->GetIsolate();
20407   v8::HandleScope scope(isolate);
20408   v8::Isolate::DisallowJavascriptExecutionScope no_js(
20409       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
20410   CompileRun("2+2");
20411 }
20412
20413
20414 TEST(AllowJavascriptExecutionScope) {
20415   LocalContext context;
20416   v8::Isolate* isolate = context->GetIsolate();
20417   v8::HandleScope scope(isolate);
20418   v8::Isolate::DisallowJavascriptExecutionScope no_js(
20419       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
20420   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
20421       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
20422   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
20423     CompileRun("1+1");
20424   }
20425 }
20426
20427
20428 TEST(ThrowOnJavascriptExecution) {
20429   LocalContext context;
20430   v8::Isolate* isolate = context->GetIsolate();
20431   v8::HandleScope scope(isolate);
20432   v8::TryCatch try_catch(isolate);
20433   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
20434       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
20435   CompileRun("1+1");
20436   CHECK(try_catch.HasCaught());
20437 }
20438
20439
20440 TEST(Regress354123) {
20441   LocalContext current;
20442   v8::Isolate* isolate = current->GetIsolate();
20443   v8::HandleScope scope(isolate);
20444
20445   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
20446   templ->SetAccessCheckCallbacks(AccessCounter, NULL);
20447   current->Global()->Set(v8_str("friend"), templ->NewInstance());
20448
20449   // Test access using __proto__ from the prototype chain.
20450   access_count = 0;
20451   CompileRun("friend.__proto__ = {};");
20452   CHECK_EQ(2, access_count);
20453   CompileRun("friend.__proto__;");
20454   CHECK_EQ(4, access_count);
20455
20456   // Test access using __proto__ as a hijacked function (A).
20457   access_count = 0;
20458   CompileRun("var p = Object.prototype;"
20459              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
20460              "f.call(friend, {});");
20461   CHECK_EQ(1, access_count);
20462   CompileRun("var p = Object.prototype;"
20463              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
20464              "f.call(friend);");
20465   CHECK_EQ(2, access_count);
20466
20467   // Test access using __proto__ as a hijacked function (B).
20468   access_count = 0;
20469   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
20470              "f.call(friend, {});");
20471   CHECK_EQ(1, access_count);
20472   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
20473              "f.call(friend);");
20474   CHECK_EQ(2, access_count);
20475
20476   // Test access using Object.setPrototypeOf reflective method.
20477   access_count = 0;
20478   CompileRun("Object.setPrototypeOf(friend, {});");
20479   CHECK_EQ(1, access_count);
20480   CompileRun("Object.getPrototypeOf(friend);");
20481   CHECK_EQ(2, access_count);
20482 }
20483
20484
20485 TEST(CaptureStackTraceForStackOverflow) {
20486   v8::internal::FLAG_stack_size = 150;
20487   LocalContext current;
20488   v8::Isolate* isolate = current->GetIsolate();
20489   v8::HandleScope scope(isolate);
20490   V8::SetCaptureStackTraceForUncaughtExceptions(
20491       true, 10, v8::StackTrace::kDetailed);
20492   v8::TryCatch try_catch(isolate);
20493   CompileRun("(function f(x) { f(x+1); })(0)");
20494   CHECK(try_catch.HasCaught());
20495 }
20496
20497
20498 TEST(ScriptNameAndLineNumber) {
20499   LocalContext env;
20500   v8::Isolate* isolate = env->GetIsolate();
20501   v8::HandleScope scope(isolate);
20502   const char* url = "http://www.foo.com/foo.js";
20503   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
20504   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
20505   Local<Script> script = v8::ScriptCompiler::Compile(
20506       isolate, &script_source);
20507   Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
20508   CHECK(!script_name.IsEmpty());
20509   CHECK(script_name->IsString());
20510   String::Utf8Value utf8_name(script_name);
20511   CHECK_EQ(0, strcmp(url, *utf8_name));
20512   int line_number = script->GetUnboundScript()->GetLineNumber(0);
20513   CHECK_EQ(13, line_number);
20514 }
20515
20516 void CheckMagicComments(Handle<Script> script, const char* expected_source_url,
20517                         const char* expected_source_mapping_url) {
20518   if (expected_source_url != NULL) {
20519     v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
20520     CHECK_EQ(0, strcmp(expected_source_url, *url));
20521   } else {
20522     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
20523   }
20524   if (expected_source_mapping_url != NULL) {
20525     v8::String::Utf8Value url(
20526         script->GetUnboundScript()->GetSourceMappingURL());
20527     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
20528   } else {
20529     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
20530   }
20531 }
20532
20533 void SourceURLHelper(const char* source, const char* expected_source_url,
20534                      const char* expected_source_mapping_url) {
20535   Local<Script> script = v8_compile(source);
20536   CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
20537 }
20538
20539
20540 TEST(ScriptSourceURLAndSourceMappingURL) {
20541   LocalContext env;
20542   v8::Isolate* isolate = env->GetIsolate();
20543   v8::HandleScope scope(isolate);
20544   SourceURLHelper("function foo() {}\n"
20545                   "//# sourceURL=bar1.js\n", "bar1.js", NULL);
20546   SourceURLHelper("function foo() {}\n"
20547                   "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
20548
20549   // Both sourceURL and sourceMappingURL.
20550   SourceURLHelper("function foo() {}\n"
20551                   "//# sourceURL=bar3.js\n"
20552                   "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
20553
20554   // Two source URLs; the first one is ignored.
20555   SourceURLHelper("function foo() {}\n"
20556                   "//# sourceURL=ignoreme.js\n"
20557                   "//# sourceURL=bar5.js\n", "bar5.js", NULL);
20558   SourceURLHelper("function foo() {}\n"
20559                   "//# sourceMappingURL=ignoreme.js\n"
20560                   "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
20561
20562   // SourceURL or sourceMappingURL in the middle of the script.
20563   SourceURLHelper("function foo() {}\n"
20564                   "//# sourceURL=bar7.js\n"
20565                   "function baz() {}\n", "bar7.js", NULL);
20566   SourceURLHelper("function foo() {}\n"
20567                   "//# sourceMappingURL=bar8.js\n"
20568                   "function baz() {}\n", NULL, "bar8.js");
20569
20570   // Too much whitespace.
20571   SourceURLHelper("function foo() {}\n"
20572                   "//#  sourceURL=bar9.js\n"
20573                   "//#  sourceMappingURL=bar10.js\n", NULL, NULL);
20574   SourceURLHelper("function foo() {}\n"
20575                   "//# sourceURL =bar11.js\n"
20576                   "//# sourceMappingURL =bar12.js\n", NULL, NULL);
20577
20578   // Disallowed characters in value.
20579   SourceURLHelper("function foo() {}\n"
20580                   "//# sourceURL=bar13 .js   \n"
20581                   "//# sourceMappingURL=bar14 .js \n",
20582                   NULL, NULL);
20583   SourceURLHelper("function foo() {}\n"
20584                   "//# sourceURL=bar15\t.js   \n"
20585                   "//# sourceMappingURL=bar16\t.js \n",
20586                   NULL, NULL);
20587   SourceURLHelper("function foo() {}\n"
20588                   "//# sourceURL=bar17'.js   \n"
20589                   "//# sourceMappingURL=bar18'.js \n",
20590                   NULL, NULL);
20591   SourceURLHelper("function foo() {}\n"
20592                   "//# sourceURL=bar19\".js   \n"
20593                   "//# sourceMappingURL=bar20\".js \n",
20594                   NULL, NULL);
20595
20596   // Not too much whitespace.
20597   SourceURLHelper("function foo() {}\n"
20598                   "//# sourceURL=  bar21.js   \n"
20599                   "//# sourceMappingURL=  bar22.js \n", "bar21.js", "bar22.js");
20600 }
20601
20602
20603 TEST(GetOwnPropertyDescriptor) {
20604   LocalContext env;
20605   v8::Isolate* isolate = env->GetIsolate();
20606   v8::HandleScope scope(isolate);
20607   CompileRun(
20608     "var x = { value : 13};"
20609     "Object.defineProperty(x, 'p0', {value : 12});"
20610     "Object.defineProperty(x, 'p1', {"
20611     "  set : function(value) { this.value = value; },"
20612     "  get : function() { return this.value; },"
20613     "});");
20614   Local<Object> x = Local<Object>::Cast(env->Global()->Get(v8_str("x")));
20615   Local<Value> desc = x->GetOwnPropertyDescriptor(v8_str("no_prop"));
20616   CHECK(desc->IsUndefined());
20617   desc = x->GetOwnPropertyDescriptor(v8_str("p0"));
20618   CHECK(v8_num(12)->Equals(Local<Object>::Cast(desc)->Get(v8_str("value"))));
20619   desc = x->GetOwnPropertyDescriptor(v8_str("p1"));
20620   Local<Function> set =
20621     Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("set")));
20622   Local<Function> get =
20623     Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("get")));
20624   CHECK(v8_num(13)->Equals(get->Call(x, 0, NULL)));
20625   Handle<Value> args[] = { v8_num(14) };
20626   set->Call(x, 1, args);
20627   CHECK(v8_num(14)->Equals(get->Call(x, 0, NULL)));
20628 }
20629
20630
20631 TEST(Regress411877) {
20632   v8::Isolate* isolate = CcTest::isolate();
20633   v8::HandleScope handle_scope(isolate);
20634   v8::Handle<v8::ObjectTemplate> object_template =
20635       v8::ObjectTemplate::New(isolate);
20636   object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20637
20638   v8::Handle<Context> context = Context::New(isolate);
20639   v8::Context::Scope context_scope(context);
20640
20641   context->Global()->Set(v8_str("o"), object_template->NewInstance());
20642   CompileRun("Object.getOwnPropertyNames(o)");
20643 }
20644
20645
20646 TEST(GetHiddenPropertyTableAfterAccessCheck) {
20647   v8::Isolate* isolate = CcTest::isolate();
20648   v8::HandleScope handle_scope(isolate);
20649   v8::Handle<v8::ObjectTemplate> object_template =
20650       v8::ObjectTemplate::New(isolate);
20651   object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20652
20653   v8::Handle<Context> context = Context::New(isolate);
20654   v8::Context::Scope context_scope(context);
20655
20656   v8::Handle<v8::Object> obj = object_template->NewInstance();
20657   obj->Set(v8_str("key"), v8_str("value"));
20658   obj->Delete(v8_str("key"));
20659
20660   obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
20661 }
20662
20663
20664 TEST(Regress411793) {
20665   v8::Isolate* isolate = CcTest::isolate();
20666   v8::HandleScope handle_scope(isolate);
20667   v8::Handle<v8::ObjectTemplate> object_template =
20668       v8::ObjectTemplate::New(isolate);
20669   object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20670
20671   v8::Handle<Context> context = Context::New(isolate);
20672   v8::Context::Scope context_scope(context);
20673
20674   context->Global()->Set(v8_str("o"), object_template->NewInstance());
20675   CompileRun(
20676       "Object.defineProperty(o, 'key', "
20677       "    { get: function() {}, set: function() {} });");
20678 }
20679
20680 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
20681  public:
20682   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
20683
20684   virtual size_t GetMoreData(const uint8_t** src) {
20685     // Unlike in real use cases, this function will never block.
20686     if (chunks_[index_] == NULL) {
20687       return 0;
20688     }
20689     // Copy the data, since the caller takes ownership of it.
20690     size_t len = strlen(chunks_[index_]);
20691     // We don't need to zero-terminate since we return the length.
20692     uint8_t* copy = new uint8_t[len];
20693     memcpy(copy, chunks_[index_], len);
20694     *src = copy;
20695     ++index_;
20696     return len;
20697   }
20698
20699   // Helper for constructing a string from chunks (the compilation needs it
20700   // too).
20701   static char* FullSourceString(const char** chunks) {
20702     size_t total_len = 0;
20703     for (size_t i = 0; chunks[i] != NULL; ++i) {
20704       total_len += strlen(chunks[i]);
20705     }
20706     char* full_string = new char[total_len + 1];
20707     size_t offset = 0;
20708     for (size_t i = 0; chunks[i] != NULL; ++i) {
20709       size_t len = strlen(chunks[i]);
20710       memcpy(full_string + offset, chunks[i], len);
20711       offset += len;
20712     }
20713     full_string[total_len] = 0;
20714     return full_string;
20715   }
20716
20717  private:
20718   const char** chunks_;
20719   unsigned index_;
20720 };
20721
20722
20723 // Helper function for running streaming tests.
20724 void RunStreamingTest(const char** chunks,
20725                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
20726                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
20727                       bool expected_success = true,
20728                       const char* expected_source_url = NULL,
20729                       const char* expected_source_mapping_url = NULL) {
20730   LocalContext env;
20731   v8::Isolate* isolate = env->GetIsolate();
20732   v8::HandleScope scope(isolate);
20733   v8::TryCatch try_catch(isolate);
20734
20735   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
20736                                             encoding);
20737   v8::ScriptCompiler::ScriptStreamingTask* task =
20738       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
20739
20740   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
20741   // task here in the main thread.
20742   task->Run();
20743   delete task;
20744
20745   // Possible errors are only produced while compiling.
20746   CHECK_EQ(false, try_catch.HasCaught());
20747
20748   v8::ScriptOrigin origin(v8_str("http://foo.com"));
20749   char* full_source = TestSourceStream::FullSourceString(chunks);
20750   v8::Handle<Script> script = v8::ScriptCompiler::Compile(
20751       isolate, &source, v8_str(full_source), origin);
20752   if (expected_success) {
20753     CHECK(!script.IsEmpty());
20754     v8::Handle<Value> result(script->Run());
20755     // All scripts are supposed to return the fixed value 13 when ran.
20756     CHECK_EQ(13, result->Int32Value());
20757     CheckMagicComments(script, expected_source_url,
20758                        expected_source_mapping_url);
20759   } else {
20760     CHECK(script.IsEmpty());
20761     CHECK(try_catch.HasCaught());
20762   }
20763   delete[] full_source;
20764 }
20765
20766
20767 TEST(StreamingSimpleScript) {
20768   // This script is unrealistically small, since no one chunk is enough to fill
20769   // the backing buffer of Scanner, let alone overflow it.
20770   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
20771                           NULL};
20772   RunStreamingTest(chunks);
20773 }
20774
20775
20776 TEST(StreamingBiggerScript) {
20777   const char* chunk1 =
20778       "function foo() {\n"
20779       "  // Make this chunk sufficiently long so that it will overflow the\n"
20780       "  // backing buffer of the Scanner.\n"
20781       "  var i = 0;\n"
20782       "  var result = 0;\n"
20783       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20784       "  result = 0;\n"
20785       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20786       "  result = 0;\n"
20787       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20788       "  result = 0;\n"
20789       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20790       "  return result;\n"
20791       "}\n";
20792   const char* chunks[] = {chunk1, "foo(); ", NULL};
20793   RunStreamingTest(chunks);
20794 }
20795
20796
20797 TEST(StreamingScriptWithParseError) {
20798   // Test that parse errors from streamed scripts are propagated correctly.
20799   {
20800     char chunk1[] =
20801         "  // This will result in a parse error.\n"
20802         "  var if else then foo";
20803     char chunk2[] = "  13\n";
20804     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20805
20806     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
20807                      false);
20808   }
20809   // Test that the next script succeeds normally.
20810   {
20811     char chunk1[] =
20812         "  // This will be parsed successfully.\n"
20813         "  function foo() { return ";
20814     char chunk2[] = "  13; }\n";
20815     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20816
20817     RunStreamingTest(chunks);
20818   }
20819 }
20820
20821
20822 TEST(StreamingUtf8Script) {
20823   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
20824   // don't like it.
20825   const char* chunk1 =
20826       "function foo() {\n"
20827       "  // This function will contain an UTF-8 character which is not in\n"
20828       "  // ASCII.\n"
20829       "  var foob\xec\x92\x81r = 13;\n"
20830       "  return foob\xec\x92\x81r;\n"
20831       "}\n";
20832   const char* chunks[] = {chunk1, "foo(); ", NULL};
20833   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20834 }
20835
20836
20837 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
20838   // A sanity check to prove that the approach of splitting UTF-8
20839   // characters is correct. Here is an UTF-8 character which will take three
20840   // bytes.
20841   const char* reference = "\xec\x92\x81";
20842   CHECK(3u == strlen(reference));  // NOLINT - no CHECK_EQ for unsigned.
20843
20844   char chunk1[] =
20845       "function foo() {\n"
20846       "  // This function will contain an UTF-8 character which is not in\n"
20847       "  // ASCII.\n"
20848       "  var foob";
20849   char chunk2[] =
20850       "XXXr = 13;\n"
20851       "  return foob\xec\x92\x81r;\n"
20852       "}\n";
20853   for (int i = 0; i < 3; ++i) {
20854     chunk2[i] = reference[i];
20855   }
20856   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20857   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20858 }
20859
20860
20861 TEST(StreamingUtf8ScriptWithSplitCharacters) {
20862   // Stream data where a multi-byte UTF-8 character is split between two data
20863   // chunks.
20864   const char* reference = "\xec\x92\x81";
20865   char chunk1[] =
20866       "function foo() {\n"
20867       "  // This function will contain an UTF-8 character which is not in\n"
20868       "  // ASCII.\n"
20869       "  var foobX";
20870   char chunk2[] =
20871       "XXr = 13;\n"
20872       "  return foob\xec\x92\x81r;\n"
20873       "}\n";
20874   chunk1[strlen(chunk1) - 1] = reference[0];
20875   chunk2[0] = reference[1];
20876   chunk2[1] = reference[2];
20877   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20878   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20879 }
20880
20881
20882 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
20883   // Tests edge cases which should still be decoded correctly.
20884
20885   // Case 1: a chunk contains only bytes for a split character (and no other
20886   // data). This kind of a chunk would be exceptionally small, but we should
20887   // still decode it correctly.
20888   const char* reference = "\xec\x92\x81";
20889   // The small chunk is at the beginning of the split character
20890   {
20891     char chunk1[] =
20892         "function foo() {\n"
20893         "  // This function will contain an UTF-8 character which is not in\n"
20894         "  // ASCII.\n"
20895         "  var foob";
20896     char chunk2[] = "XX";
20897     char chunk3[] =
20898         "Xr = 13;\n"
20899         "  return foob\xec\x92\x81r;\n"
20900         "}\n";
20901     chunk2[0] = reference[0];
20902     chunk2[1] = reference[1];
20903     chunk3[0] = reference[2];
20904     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20905     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20906   }
20907   // The small chunk is at the end of a character
20908   {
20909     char chunk1[] =
20910         "function foo() {\n"
20911         "  // This function will contain an UTF-8 character which is not in\n"
20912         "  // ASCII.\n"
20913         "  var foobX";
20914     char chunk2[] = "XX";
20915     char chunk3[] =
20916         "r = 13;\n"
20917         "  return foob\xec\x92\x81r;\n"
20918         "}\n";
20919     chunk1[strlen(chunk1) - 1] = reference[0];
20920     chunk2[0] = reference[1];
20921     chunk2[1] = reference[2];
20922     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20923     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20924   }
20925   // Case 2: the script ends with a multi-byte character. Make sure that it's
20926   // decoded correctly and not just ignored.
20927   {
20928     char chunk1[] =
20929         "var foob\xec\x92\x81 = 13;\n"
20930         "foob\xec\x92\x81";
20931     const char* chunks[] = {chunk1, NULL};
20932     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20933   }
20934 }
20935
20936
20937 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
20938   // Test cases where a UTF-8 character is split over several chunks. Those
20939   // cases are not supported (the embedder should give the data in big enough
20940   // chunks), but we shouldn't crash, just produce a parse error.
20941   const char* reference = "\xec\x92\x81";
20942   char chunk1[] =
20943       "function foo() {\n"
20944       "  // This function will contain an UTF-8 character which is not in\n"
20945       "  // ASCII.\n"
20946       "  var foobX";
20947   char chunk2[] = "X";
20948   char chunk3[] =
20949       "Xr = 13;\n"
20950       "  return foob\xec\x92\x81r;\n"
20951       "}\n";
20952   chunk1[strlen(chunk1) - 1] = reference[0];
20953   chunk2[0] = reference[1];
20954   chunk3[0] = reference[2];
20955   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20956
20957   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
20958 }
20959
20960
20961 TEST(StreamingProducesParserCache) {
20962   i::FLAG_min_preparse_length = 0;
20963   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
20964                           NULL};
20965
20966   LocalContext env;
20967   v8::Isolate* isolate = env->GetIsolate();
20968   v8::HandleScope scope(isolate);
20969
20970   v8::ScriptCompiler::StreamedSource source(
20971       new TestSourceStream(chunks),
20972       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
20973   v8::ScriptCompiler::ScriptStreamingTask* task =
20974       v8::ScriptCompiler::StartStreamingScript(
20975           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
20976
20977   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
20978   // task here in the main thread.
20979   task->Run();
20980   delete task;
20981
20982   const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
20983   CHECK(cached_data != NULL);
20984   CHECK(cached_data->data != NULL);
20985   CHECK(!cached_data->rejected);
20986   CHECK_GT(cached_data->length, 0);
20987 }
20988
20989
20990 TEST(StreamingWithDebuggingDoesNotProduceParserCache) {
20991   // If the debugger is active, we should just not produce parser cache at
20992   // all. This is a regeression test: We used to produce a parser cache without
20993   // any data in it (just headers).
20994   i::FLAG_min_preparse_length = 0;
20995   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
20996                           NULL};
20997
20998   LocalContext env;
20999   v8::Isolate* isolate = env->GetIsolate();
21000   v8::HandleScope scope(isolate);
21001
21002   // Make the debugger active by setting a breakpoint.
21003   CompileRun("function break_here() { }");
21004   i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(
21005       v8::Utils::OpenHandle(*env->Global()->Get(v8_str("break_here"))));
21006   EnableDebugger();
21007   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
21008   int position = 0;
21009   debug->SetBreakPoint(func, i::Handle<i::Object>(v8::internal::Smi::FromInt(1),
21010                                                   CcTest::i_isolate()),
21011                        &position);
21012
21013   v8::ScriptCompiler::StreamedSource source(
21014       new TestSourceStream(chunks),
21015       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
21016   v8::ScriptCompiler::ScriptStreamingTask* task =
21017       v8::ScriptCompiler::StartStreamingScript(
21018           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
21019
21020   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
21021   // task here in the main thread.
21022   task->Run();
21023   delete task;
21024
21025   // Check that we got no cached data.
21026   CHECK(source.GetCachedData() == NULL);
21027   DisableDebugger();
21028 }
21029
21030
21031 TEST(StreamingScriptWithInvalidUtf8) {
21032   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
21033   // chunk don't produce a crash.
21034   const char* reference = "\xec\x92\x81\x80\x80";
21035   char chunk1[] =
21036       "function foo() {\n"
21037       "  // This function will contain an UTF-8 character which is not in\n"
21038       "  // ASCII.\n"
21039       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
21040   char chunk2[] =
21041       "r = 13;\n"
21042       "  return foob\xec\x92\x81\x80\x80r;\n"
21043       "}\n";
21044   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
21045
21046   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21047   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
21048 }
21049
21050
21051 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
21052   // Regression test: Stream data where there are several multi-byte UTF-8
21053   // characters in a sequence and one of them is split between two data chunks.
21054   const char* reference = "\xec\x92\x81";
21055   char chunk1[] =
21056       "function foo() {\n"
21057       "  // This function will contain an UTF-8 character which is not in\n"
21058       "  // ASCII.\n"
21059       "  var foob\xec\x92\x81X";
21060   char chunk2[] =
21061       "XXr = 13;\n"
21062       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
21063       "}\n";
21064   chunk1[strlen(chunk1) - 1] = reference[0];
21065   chunk2[0] = reference[1];
21066   chunk2[1] = reference[2];
21067   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21068   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21069 }
21070
21071
21072 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
21073   // Another regression test, similar to the previous one. The difference is
21074   // that the split character is not the last one in the sequence.
21075   const char* reference = "\xec\x92\x81";
21076   char chunk1[] =
21077       "function foo() {\n"
21078       "  // This function will contain an UTF-8 character which is not in\n"
21079       "  // ASCII.\n"
21080       "  var foobX";
21081   char chunk2[] =
21082       "XX\xec\x92\x81r = 13;\n"
21083       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
21084       "}\n";
21085   chunk1[strlen(chunk1) - 1] = reference[0];
21086   chunk2[0] = reference[1];
21087   chunk2[1] = reference[2];
21088   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
21089   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
21090 }
21091
21092
21093 TEST(StreamingWithHarmonyScopes) {
21094   // Don't use RunStreamingTest here so that both scripts get to use the same
21095   // LocalContext and HandleScope.
21096   LocalContext env;
21097   v8::Isolate* isolate = env->GetIsolate();
21098   v8::HandleScope scope(isolate);
21099
21100   // First, run a script with a let variable.
21101   CompileRun("\"use strict\"; let x = 1;");
21102
21103   // Then stream a script which (erroneously) tries to introduce the same
21104   // variable again.
21105   const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
21106
21107   v8::TryCatch try_catch(isolate);
21108   v8::ScriptCompiler::StreamedSource source(
21109       new TestSourceStream(chunks),
21110       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
21111   v8::ScriptCompiler::ScriptStreamingTask* task =
21112       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
21113   task->Run();
21114   delete task;
21115
21116   // Parsing should succeed (the script will be parsed and compiled in a context
21117   // independent way, so the error is not detected).
21118   CHECK_EQ(false, try_catch.HasCaught());
21119
21120   v8::ScriptOrigin origin(v8_str("http://foo.com"));
21121   char* full_source = TestSourceStream::FullSourceString(chunks);
21122   v8::Handle<Script> script = v8::ScriptCompiler::Compile(
21123       isolate, &source, v8_str(full_source), origin);
21124   CHECK(!script.IsEmpty());
21125   CHECK_EQ(false, try_catch.HasCaught());
21126
21127   // Running the script exposes the error.
21128   v8::Handle<Value> result(script->Run());
21129   CHECK(result.IsEmpty());
21130   CHECK(try_catch.HasCaught());
21131   delete[] full_source;
21132 }
21133
21134
21135 TEST(CodeCache) {
21136   v8::Isolate::CreateParams create_params;
21137   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
21138
21139   const char* source = "Math.sqrt(4)";
21140   const char* origin = "code cache test";
21141   v8::ScriptCompiler::CachedData* cache;
21142
21143   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
21144   {
21145     v8::Isolate::Scope iscope(isolate1);
21146     v8::HandleScope scope(isolate1);
21147     v8::Local<v8::Context> context = v8::Context::New(isolate1);
21148     v8::Context::Scope cscope(context);
21149     v8::Local<v8::String> source_string = v8_str(source);
21150     v8::ScriptOrigin script_origin(v8_str(origin));
21151     v8::ScriptCompiler::Source source(source_string, script_origin);
21152     v8::ScriptCompiler::CompileOptions option =
21153         v8::ScriptCompiler::kProduceCodeCache;
21154     v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
21155     int length = source.GetCachedData()->length;
21156     uint8_t* cache_data = new uint8_t[length];
21157     memcpy(cache_data, source.GetCachedData()->data, length);
21158     cache = new v8::ScriptCompiler::CachedData(
21159         cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
21160   }
21161   isolate1->Dispose();
21162
21163   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
21164   {
21165     v8::Isolate::Scope iscope(isolate2);
21166     v8::HandleScope scope(isolate2);
21167     v8::Local<v8::Context> context = v8::Context::New(isolate2);
21168     v8::Context::Scope cscope(context);
21169     v8::Local<v8::String> source_string = v8_str(source);
21170     v8::ScriptOrigin script_origin(v8_str(origin));
21171     v8::ScriptCompiler::Source source(source_string, script_origin, cache);
21172     v8::ScriptCompiler::CompileOptions option =
21173         v8::ScriptCompiler::kConsumeCodeCache;
21174     v8::Local<v8::Script> script;
21175     {
21176       i::DisallowCompilation no_compile(
21177           reinterpret_cast<i::Isolate*>(isolate2));
21178       script = v8::ScriptCompiler::Compile(context, &source, option)
21179                    .ToLocalChecked();
21180     }
21181     CHECK_EQ(2, script->Run()->ToInt32(isolate2)->Int32Value());
21182   }
21183   isolate2->Dispose();
21184 }
21185
21186
21187 void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
21188   const char* garbage = "garbage garbage garbage garbage garbage garbage";
21189   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
21190   int length = 16;
21191   v8::ScriptCompiler::CachedData* cached_data =
21192       new v8::ScriptCompiler::CachedData(data, length);
21193   DCHECK(!cached_data->rejected);
21194   v8::ScriptOrigin origin(v8_str("origin"));
21195   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
21196   v8::Handle<v8::Script> script =
21197       v8::ScriptCompiler::Compile(CcTest::isolate(), &source, option);
21198   CHECK(cached_data->rejected);
21199   CHECK_EQ(42, script->Run()->Int32Value());
21200 }
21201
21202
21203 TEST(InvalidCacheData) {
21204   v8::V8::Initialize();
21205   v8::HandleScope scope(CcTest::isolate());
21206   LocalContext context;
21207   TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
21208   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
21209 }
21210
21211
21212 TEST(ParserCacheRejectedGracefully) {
21213   i::FLAG_min_preparse_length = 0;
21214   v8::V8::Initialize();
21215   v8::HandleScope scope(CcTest::isolate());
21216   LocalContext context;
21217   // Produce valid cached data.
21218   v8::ScriptOrigin origin(v8_str("origin"));
21219   v8::Local<v8::String> source_str = v8_str("function foo() {}");
21220   v8::ScriptCompiler::Source source(source_str, origin);
21221   v8::Handle<v8::Script> script = v8::ScriptCompiler::Compile(
21222       CcTest::isolate(), &source, v8::ScriptCompiler::kProduceParserCache);
21223   CHECK(!script.IsEmpty());
21224   const v8::ScriptCompiler::CachedData* original_cached_data =
21225       source.GetCachedData();
21226   CHECK(original_cached_data != NULL);
21227   CHECK(original_cached_data->data != NULL);
21228   CHECK(!original_cached_data->rejected);
21229   CHECK_GT(original_cached_data->length, 0);
21230   // Recompiling the same script with it won't reject the data.
21231   {
21232     v8::ScriptCompiler::Source source_with_cached_data(
21233         source_str, origin,
21234         new v8::ScriptCompiler::CachedData(original_cached_data->data,
21235                                            original_cached_data->length));
21236     v8::Handle<v8::Script> script =
21237         v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
21238                                     v8::ScriptCompiler::kConsumeParserCache);
21239     CHECK(!script.IsEmpty());
21240     const v8::ScriptCompiler::CachedData* new_cached_data =
21241         source_with_cached_data.GetCachedData();
21242     CHECK(new_cached_data != NULL);
21243     CHECK(!new_cached_data->rejected);
21244   }
21245   // Compile an incompatible script with the cached data. The new script doesn't
21246   // have the same starting position for the function as the old one, so the old
21247   // cached data will be incompatible with it and will be rejected.
21248   {
21249     v8::Local<v8::String> incompatible_source_str =
21250         v8_str("   function foo() {}");
21251     v8::ScriptCompiler::Source source_with_cached_data(
21252         incompatible_source_str, origin,
21253         new v8::ScriptCompiler::CachedData(original_cached_data->data,
21254                                            original_cached_data->length));
21255     v8::Handle<v8::Script> script =
21256         v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
21257                                     v8::ScriptCompiler::kConsumeParserCache);
21258     CHECK(!script.IsEmpty());
21259     const v8::ScriptCompiler::CachedData* new_cached_data =
21260         source_with_cached_data.GetCachedData();
21261     CHECK(new_cached_data != NULL);
21262     CHECK(new_cached_data->rejected);
21263   }
21264 }
21265
21266
21267 TEST(StringConcatOverflow) {
21268   v8::V8::Initialize();
21269   v8::HandleScope scope(CcTest::isolate());
21270   RandomLengthOneByteResource* r =
21271       new RandomLengthOneByteResource(i::String::kMaxLength);
21272   v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), r);
21273   CHECK(!str.IsEmpty());
21274   v8::TryCatch try_catch(CcTest::isolate());
21275   v8::Local<v8::String> result = v8::String::Concat(str, str);
21276   CHECK(result.IsEmpty());
21277   CHECK(!try_catch.HasCaught());
21278 }
21279
21280
21281 TEST(TurboAsmDisablesNeuter) {
21282   v8::V8::Initialize();
21283   v8::HandleScope scope(CcTest::isolate());
21284   LocalContext context;
21285 #if V8_TURBOFAN_TARGET
21286   bool should_be_neuterable = !i::FLAG_turbo_asm;
21287 #else
21288   bool should_be_neuterable = true;
21289 #endif
21290   const char* load =
21291       "function Module(stdlib, foreign, heap) {"
21292       "  'use asm';"
21293       "  var MEM32 = new stdlib.Int32Array(heap);"
21294       "  function load() { return MEM32[0]; }"
21295       "  return { load: load };"
21296       "}"
21297       "var buffer = new ArrayBuffer(4);"
21298       "Module(this, {}, buffer).load();"
21299       "buffer";
21300
21301   i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
21302   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
21303   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
21304
21305   const char* store =
21306       "function Module(stdlib, foreign, heap) {"
21307       "  'use asm';"
21308       "  var MEM32 = new stdlib.Int32Array(heap);"
21309       "  function store() { MEM32[0] = 0; }"
21310       "  return { store: store };"
21311       "}"
21312       "var buffer = new ArrayBuffer(4);"
21313       "Module(this, {}, buffer).store();"
21314       "buffer";
21315
21316   i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
21317   result = CompileRun(store).As<v8::ArrayBuffer>();
21318   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
21319 }
21320
21321
21322 TEST(GetPrototypeAccessControl) {
21323   i::FLAG_allow_natives_syntax = true;
21324   v8::Isolate* isolate = CcTest::isolate();
21325   v8::HandleScope handle_scope(isolate);
21326   LocalContext env;
21327
21328   v8::Handle<v8::ObjectTemplate> obj_template =
21329       v8::ObjectTemplate::New(isolate);
21330   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
21331
21332   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
21333
21334   {
21335     v8::TryCatch try_catch(isolate);
21336     CompileRun(
21337         "function f() { %_GetPrototype(prohibited); }"
21338         "%OptimizeFunctionOnNextCall(f);"
21339         "f();");
21340     CHECK(try_catch.HasCaught());
21341   }
21342 }
21343
21344
21345 TEST(GetPrototypeHidden) {
21346   i::FLAG_allow_natives_syntax = true;
21347   v8::Isolate* isolate = CcTest::isolate();
21348   v8::HandleScope handle_scope(isolate);
21349   LocalContext env;
21350
21351   Handle<FunctionTemplate> t = FunctionTemplate::New(isolate);
21352   t->SetHiddenPrototype(true);
21353   Handle<Object> proto = t->GetFunction()->NewInstance();
21354   Handle<Object> object = Object::New(isolate);
21355   Handle<Object> proto2 = Object::New(isolate);
21356   object->SetPrototype(proto);
21357   proto->SetPrototype(proto2);
21358
21359   env->Global()->Set(v8_str("object"), object);
21360   env->Global()->Set(v8_str("proto"), proto);
21361   env->Global()->Set(v8_str("proto2"), proto2);
21362
21363   v8::Handle<v8::Value> result = CompileRun("%_GetPrototype(object)");
21364   CHECK(result->Equals(proto2));
21365
21366   result = CompileRun(
21367       "function f() { return %_GetPrototype(object); }"
21368       "%OptimizeFunctionOnNextCall(f);"
21369       "f()");
21370   CHECK(result->Equals(proto2));
21371 }
21372
21373
21374 TEST(ClassPrototypeCreationContext) {
21375   v8::Isolate* isolate = CcTest::isolate();
21376   v8::HandleScope handle_scope(isolate);
21377   LocalContext env;
21378
21379   Handle<Object> result = Handle<Object>::Cast(
21380       CompileRun("'use strict'; class Example { }; Example.prototype"));
21381   CHECK(env.local() == result->CreationContext());
21382 }
21383
21384
21385 TEST(SimpleStreamingScriptWithSourceURL) {
21386   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
21387                           "//# sourceURL=bar2.js\n", NULL};
21388   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
21389                    "bar2.js");
21390 }
21391
21392
21393 TEST(StreamingScriptWithSplitSourceURL) {
21394   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
21395                           "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
21396   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
21397                    "bar2.js");
21398 }
21399
21400
21401 TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
21402   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
21403                           " sourceMappingURL=bar2.js\n", "foo();", NULL};
21404   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
21405                    "bar2.js");
21406 }
21407
21408
21409 TEST(NewStringRangeError) {
21410   v8::Isolate* isolate = CcTest::isolate();
21411   v8::HandleScope handle_scope(isolate);
21412   const int length = i::String::kMaxLength + 1;
21413   const int buffer_size = length * sizeof(uint16_t);
21414   void* buffer = malloc(buffer_size);
21415   if (buffer == NULL) return;
21416   memset(buffer, 'A', buffer_size);
21417   {
21418     v8::TryCatch try_catch(isolate);
21419     char* data = reinterpret_cast<char*>(buffer);
21420     CHECK(v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString,
21421                                   length).IsEmpty());
21422     CHECK(!try_catch.HasCaught());
21423   }
21424   {
21425     v8::TryCatch try_catch(isolate);
21426     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
21427     CHECK(v8::String::NewFromOneByte(isolate, data, v8::String::kNormalString,
21428                                      length).IsEmpty());
21429     CHECK(!try_catch.HasCaught());
21430   }
21431   {
21432     v8::TryCatch try_catch(isolate);
21433     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
21434     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString,
21435                                      length).IsEmpty());
21436     CHECK(!try_catch.HasCaught());
21437   }
21438   free(buffer);
21439 }
21440
21441
21442 TEST(SealHandleScope) {
21443   v8::Isolate* isolate = CcTest::isolate();
21444   v8::HandleScope handle_scope(isolate);
21445   LocalContext env;
21446
21447   v8::SealHandleScope seal(isolate);
21448
21449   // Should fail
21450   v8::Local<v8::Object> obj = v8::Object::New(isolate);
21451
21452   USE(obj);
21453 }
21454
21455
21456 TEST(SealHandleScopeNested) {
21457   v8::Isolate* isolate = CcTest::isolate();
21458   v8::HandleScope handle_scope(isolate);
21459   LocalContext env;
21460
21461   v8::SealHandleScope seal(isolate);
21462
21463   {
21464     v8::HandleScope handle_scope(isolate);
21465
21466     // Should work
21467     v8::Local<v8::Object> obj = v8::Object::New(isolate);
21468
21469     USE(obj);
21470   }
21471 }
21472
21473
21474 static bool access_was_called = false;
21475
21476
21477 static bool AccessAlwaysAllowedWithFlag(Local<v8::Object> global,
21478                                         Local<Value> name, v8::AccessType type,
21479                                         Local<Value> data) {
21480   access_was_called = true;
21481   return true;
21482 }
21483
21484
21485 static bool AccessAlwaysBlockedWithFlag(Local<v8::Object> global,
21486                                         Local<Value> name, v8::AccessType type,
21487                                         Local<Value> data) {
21488   access_was_called = true;
21489   return false;
21490 }
21491
21492
21493 TEST(StrongModeAccessCheckAllowed) {
21494   i::FLAG_strong_mode = true;
21495   v8::Isolate* isolate = CcTest::isolate();
21496   v8::HandleScope handle_scope(isolate);
21497   v8::Handle<Value> value;
21498   access_was_called = false;
21499
21500   v8::Handle<v8::ObjectTemplate> obj_template =
21501       v8::ObjectTemplate::New(isolate);
21502
21503   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
21504   obj_template->SetAccessCheckCallbacks(AccessAlwaysAllowedWithFlag, NULL);
21505
21506   // Create an environment
21507   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
21508   context0->Enter();
21509   v8::Handle<v8::Object> global0 = context0->Global();
21510   global0->Set(v8_str("object"), obj_template->NewInstance());
21511   {
21512     v8::TryCatch try_catch(isolate);
21513     value = CompileRun("'use strong'; object.x");
21514     CHECK(!try_catch.HasCaught());
21515     CHECK(!access_was_called);
21516     CHECK_EQ(42, value->Int32Value());
21517   }
21518   {
21519     v8::TryCatch try_catch(isolate);
21520     value = CompileRun("'use strong'; object.foo");
21521     CHECK(try_catch.HasCaught());
21522     CHECK(!access_was_called);
21523   }
21524   {
21525     v8::TryCatch try_catch(isolate);
21526     value = CompileRun("'use strong'; object[10]");
21527     CHECK(try_catch.HasCaught());
21528     CHECK(!access_was_called);
21529   }
21530
21531   // Create an environment
21532   v8::Local<Context> context1 = Context::New(isolate);
21533   context1->Enter();
21534   v8::Handle<v8::Object> global1 = context1->Global();
21535   global1->Set(v8_str("object"), obj_template->NewInstance());
21536   {
21537     v8::TryCatch try_catch(isolate);
21538     value = CompileRun("'use strong'; object.x");
21539     CHECK(!try_catch.HasCaught());
21540     CHECK(access_was_called);
21541     CHECK_EQ(42, value->Int32Value());
21542   }
21543   access_was_called = false;
21544   {
21545     v8::TryCatch try_catch(isolate);
21546     value = CompileRun("'use strong'; object.foo");
21547     CHECK(try_catch.HasCaught());
21548     CHECK(access_was_called);
21549   }
21550   access_was_called = false;
21551   {
21552     v8::TryCatch try_catch(isolate);
21553     value = CompileRun("'use strong'; object[10]");
21554     CHECK(try_catch.HasCaught());
21555     CHECK(access_was_called);
21556   }
21557
21558   context1->Exit();
21559   context0->Exit();
21560 }
21561
21562
21563 TEST(StrongModeAccessCheckBlocked) {
21564   i::FLAG_strong_mode = true;
21565   v8::Isolate* isolate = CcTest::isolate();
21566   v8::HandleScope handle_scope(isolate);
21567   v8::Handle<Value> value;
21568   access_was_called = false;
21569
21570   v8::Handle<v8::ObjectTemplate> obj_template =
21571       v8::ObjectTemplate::New(isolate);
21572
21573   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
21574   obj_template->SetAccessCheckCallbacks(AccessAlwaysBlockedWithFlag, NULL);
21575
21576   // Create an environment
21577   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
21578   context0->Enter();
21579   v8::Handle<v8::Object> global0 = context0->Global();
21580   global0->Set(v8_str("object"), obj_template->NewInstance());
21581   {
21582     v8::TryCatch try_catch(isolate);
21583     value = CompileRun("'use strong'; object.x");
21584     CHECK(!try_catch.HasCaught());
21585     CHECK(!access_was_called);
21586     CHECK_EQ(42, value->Int32Value());
21587   }
21588   {
21589     v8::TryCatch try_catch(isolate);
21590     value = CompileRun("'use strong'; object.foo");
21591     CHECK(try_catch.HasCaught());
21592     CHECK(!access_was_called);
21593   }
21594   {
21595     v8::TryCatch try_catch(isolate);
21596     value = CompileRun("'use strong'; object[10]");
21597     CHECK(try_catch.HasCaught());
21598     CHECK(!access_was_called);
21599   }
21600
21601   // Create an environment
21602   v8::Local<Context> context1 = Context::New(isolate);
21603   context1->Enter();
21604   v8::Handle<v8::Object> global1 = context1->Global();
21605   global1->Set(v8_str("object"), obj_template->NewInstance());
21606   {
21607     v8::TryCatch try_catch(isolate);
21608     value = CompileRun("'use strong'; object.x");
21609     CHECK(try_catch.HasCaught());
21610     CHECK(access_was_called);
21611   }
21612   access_was_called = false;
21613   {
21614     v8::TryCatch try_catch(isolate);
21615     value = CompileRun("'use strong'; object.foo");
21616     CHECK(try_catch.HasCaught());
21617     CHECK(access_was_called);
21618   }
21619   access_was_called = false;
21620   {
21621     v8::TryCatch try_catch(isolate);
21622     value = CompileRun("'use strong'; object[10]");
21623     CHECK(try_catch.HasCaught());
21624     CHECK(access_was_called);
21625   }
21626
21627   context1->Exit();
21628   context0->Exit();
21629 }
21630
21631
21632 TEST(StrongModeArityCallFromApi) {
21633   i::FLAG_strong_mode = true;
21634   LocalContext env;
21635   v8::Isolate* isolate = env->GetIsolate();
21636   v8::HandleScope scope(isolate);
21637   Local<Function> fun;
21638   {
21639     v8::TryCatch try_catch(isolate);
21640     fun = Local<Function>::Cast(CompileRun(
21641         "function f(x) { 'use strong'; }"
21642         "f"));
21643
21644     CHECK(!try_catch.HasCaught());
21645   }
21646
21647   {
21648     v8::TryCatch try_catch(isolate);
21649     fun->Call(v8::Undefined(isolate), 0, nullptr);
21650     CHECK(try_catch.HasCaught());
21651   }
21652
21653   {
21654     v8::TryCatch try_catch(isolate);
21655     v8::Handle<Value> args[] = {v8_num(42)};
21656     fun->Call(v8::Undefined(isolate), arraysize(args), args);
21657     CHECK(!try_catch.HasCaught());
21658   }
21659
21660   {
21661     v8::TryCatch try_catch(isolate);
21662     v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
21663     fun->Call(v8::Undefined(isolate), arraysize(args), args);
21664     CHECK(!try_catch.HasCaught());
21665   }
21666 }
21667
21668
21669 TEST(StrongModeArityCallFromApi2) {
21670   i::FLAG_strong_mode = true;
21671   LocalContext env;
21672   v8::Isolate* isolate = env->GetIsolate();
21673   v8::HandleScope scope(isolate);
21674   Local<Function> fun;
21675   {
21676     v8::TryCatch try_catch(isolate);
21677     fun = Local<Function>::Cast(CompileRun(
21678         "'use strong';"
21679         "function f(x) {}"
21680         "f"));
21681
21682     CHECK(!try_catch.HasCaught());
21683   }
21684
21685   {
21686     v8::TryCatch try_catch(isolate);
21687     fun->Call(v8::Undefined(isolate), 0, nullptr);
21688     CHECK(try_catch.HasCaught());
21689   }
21690
21691   {
21692     v8::TryCatch try_catch(isolate);
21693     v8::Handle<Value> args[] = {v8_num(42)};
21694     fun->Call(v8::Undefined(isolate), arraysize(args), args);
21695     CHECK(!try_catch.HasCaught());
21696   }
21697
21698   {
21699     v8::TryCatch try_catch(isolate);
21700     v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
21701     fun->Call(v8::Undefined(isolate), arraysize(args), args);
21702     CHECK(!try_catch.HasCaught());
21703   }
21704 }
21705
21706
21707 TEST(StrongObjectDelete) {
21708   i::FLAG_strong_mode = true;
21709   LocalContext env;
21710   v8::Isolate* isolate = env->GetIsolate();
21711   v8::HandleScope scope(isolate);
21712   Local<Object> obj;
21713   {
21714     v8::TryCatch try_catch;
21715     obj = Local<Object>::Cast(CompileRun(
21716         "'use strong';"
21717         "({});"));
21718     CHECK(!try_catch.HasCaught());
21719   }
21720   obj->ForceSet(v8_str("foo"), v8_num(1), v8::None);
21721   obj->ForceSet(v8_str("2"), v8_num(1), v8::None);
21722   CHECK(obj->HasOwnProperty(v8_str("foo")));
21723   CHECK(obj->HasOwnProperty(v8_str("2")));
21724   CHECK(!obj->Delete(v8_str("foo")));
21725   CHECK(!obj->Delete(2));
21726 }
21727
21728
21729 static void ExtrasExportsTestRuntimeFunction(
21730     const v8::FunctionCallbackInfo<v8::Value>& args) {
21731   CHECK_EQ(3, args[0]->Int32Value());
21732   args.GetReturnValue().Set(v8_num(7));
21733 }
21734
21735
21736 TEST(ExtrasExportsObject) {
21737   v8::Isolate* isolate = CcTest::isolate();
21738   v8::HandleScope handle_scope(isolate);
21739   LocalContext env;
21740
21741   // standalone.gypi ensures we include the test-extra.js file, which should
21742   // export the tested functions.
21743   v8::Local<v8::Object> exports = env->GetExtrasExportsObject();
21744
21745   auto func =
21746       exports->Get(v8_str("testExtraShouldReturnFive")).As<v8::Function>();
21747   auto undefined = v8::Undefined(isolate);
21748   auto result = func->Call(undefined, 0, {}).As<v8::Number>();
21749   CHECK_EQ(5, result->Int32Value());
21750
21751   v8::Handle<v8::FunctionTemplate> runtimeFunction =
21752       v8::FunctionTemplate::New(isolate, ExtrasExportsTestRuntimeFunction);
21753   exports->Set(v8_str("runtime"), runtimeFunction->GetFunction());
21754   func =
21755       exports->Get(v8_str("testExtraShouldCallToRuntime")).As<v8::Function>();
21756   result = func->Call(undefined, 0, {}).As<v8::Number>();
21757   CHECK_EQ(7, result->Int32Value());
21758 }
21759
21760
21761 TEST(Map) {
21762   v8::Isolate* isolate = CcTest::isolate();
21763   v8::HandleScope handle_scope(isolate);
21764   LocalContext env;
21765
21766   v8::Local<v8::Map> map = v8::Map::New(isolate);
21767   CHECK(map->IsObject());
21768   CHECK(map->IsMap());
21769   CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
21770   CHECK_EQ(0U, map->Size());
21771
21772   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
21773   CHECK(val->IsMap());
21774   map = v8::Local<v8::Map>::Cast(val);
21775   CHECK_EQ(2U, map->Size());
21776
21777   v8::Local<v8::Array> contents = map->AsArray();
21778   CHECK_EQ(4U, contents->Length());
21779   CHECK_EQ(1, contents->Get(0).As<v8::Int32>()->Value());
21780   CHECK_EQ(2, contents->Get(1).As<v8::Int32>()->Value());
21781   CHECK_EQ(3, contents->Get(2).As<v8::Int32>()->Value());
21782   CHECK_EQ(4, contents->Get(3).As<v8::Int32>()->Value());
21783
21784   map = v8::Map::FromArray(env.local(), contents).ToLocalChecked();
21785   CHECK_EQ(2U, map->Size());
21786
21787   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
21788   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
21789
21790   CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
21791   CHECK(!map->Has(env.local(), map).FromJust());
21792
21793   CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
21794                   .ToLocalChecked()
21795                   ->Int32Value());
21796   CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
21797                   .ToLocalChecked()
21798                   ->Int32Value());
21799
21800   CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
21801             .ToLocalChecked()
21802             ->IsUndefined());
21803
21804   CHECK(!map->Set(env.local(), map, map).IsEmpty());
21805   CHECK_EQ(3U, map->Size());
21806   CHECK(map->Has(env.local(), map).FromJust());
21807
21808   CHECK(map->Delete(env.local(), map).FromJust());
21809   CHECK_EQ(2U, map->Size());
21810   CHECK(!map->Has(env.local(), map).FromJust());
21811   CHECK(!map->Delete(env.local(), map).FromJust());
21812
21813   map->Clear();
21814   CHECK_EQ(0U, map->Size());
21815 }
21816
21817
21818 TEST(MapFromArrayOddLength) {
21819   v8::Isolate* isolate = CcTest::isolate();
21820   v8::HandleScope handle_scope(isolate);
21821   LocalContext env;
21822   // Odd lengths result in a null MaybeLocal.
21823   Local<v8::Array> contents = v8::Array::New(isolate, 41);
21824   CHECK(v8::Map::FromArray(env.local(), contents).IsEmpty());
21825 }
21826
21827
21828 TEST(Set) {
21829   v8::Isolate* isolate = CcTest::isolate();
21830   v8::HandleScope handle_scope(isolate);
21831   LocalContext env;
21832
21833   v8::Local<v8::Set> set = v8::Set::New(isolate);
21834   CHECK(set->IsObject());
21835   CHECK(set->IsSet());
21836   CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
21837   CHECK_EQ(0U, set->Size());
21838
21839   v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
21840   CHECK(val->IsSet());
21841   set = v8::Local<v8::Set>::Cast(val);
21842   CHECK_EQ(2U, set->Size());
21843
21844   v8::Local<v8::Array> keys = set->AsArray();
21845   CHECK_EQ(2U, keys->Length());
21846   CHECK_EQ(1, keys->Get(0).As<v8::Int32>()->Value());
21847   CHECK_EQ(2, keys->Get(1).As<v8::Int32>()->Value());
21848
21849   set = v8::Set::FromArray(env.local(), keys).ToLocalChecked();
21850   CHECK_EQ(2U, set->Size());
21851
21852   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
21853   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
21854
21855   CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
21856   CHECK(!set->Has(env.local(), set).FromJust());
21857
21858   CHECK(!set->Add(env.local(), set).IsEmpty());
21859   CHECK_EQ(3U, set->Size());
21860   CHECK(set->Has(env.local(), set).FromJust());
21861
21862   CHECK(set->Delete(env.local(), set).FromJust());
21863   CHECK_EQ(2U, set->Size());
21864   CHECK(!set->Has(env.local(), set).FromJust());
21865   CHECK(!set->Delete(env.local(), set).FromJust());
21866
21867   set->Clear();
21868   CHECK_EQ(0U, set->Size());
21869 }
21870
21871
21872 TEST(CompatibleReceiverCheckOnCachedICHandler) {
21873   v8::Isolate* isolate = CcTest::isolate();
21874   v8::HandleScope scope(isolate);
21875   v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
21876   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
21877   auto returns_42 =
21878       v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
21879   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
21880   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
21881   child->Inherit(parent);
21882   LocalContext env;
21883   env->Global()->Set(v8_str("Child"), child->GetFunction());
21884
21885   // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
21886   CompileRun(
21887       "var real = new Child();\n"
21888       "for (var i = 0; i < 3; ++i) {\n"
21889       "  real.age;\n"
21890       "}\n");
21891
21892   // Check that the cached stub is never used.
21893   ExpectInt32(
21894       "var fake = Object.create(Child.prototype);\n"
21895       "var result = 0;\n"
21896       "function test(d) {\n"
21897       "  if (d == 3) return;\n"
21898       "  try {\n"
21899       "    fake.age;\n"
21900       "    result = 1;\n"
21901       "  } catch (e) {\n"
21902       "  }\n"
21903       "  test(d+1);\n"
21904       "}\n"
21905       "test(0);\n"
21906       "result;\n",
21907       0);
21908 }
21909
21910
21911 static int nb_uncaught_exception_callback_calls = 0;
21912
21913
21914 bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
21915   ++nb_uncaught_exception_callback_calls;
21916   return false;
21917 }
21918
21919
21920 TEST(AbortOnUncaughtExceptionNoAbort) {
21921   v8::Isolate* isolate = CcTest::isolate();
21922   v8::HandleScope handle_scope(isolate);
21923   v8::Handle<v8::ObjectTemplate> global_template =
21924       v8::ObjectTemplate::New(isolate);
21925   LocalContext env(NULL, global_template);
21926
21927   i::FLAG_abort_on_uncaught_exception = true;
21928   isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
21929
21930   CompileRun("function boom() { throw new Error(\"boom\") }");
21931
21932   v8::Local<v8::Object> global_object = env->Global();
21933   v8::Local<v8::Function> foo =
21934       v8::Local<v8::Function>::Cast(global_object->Get(v8_str("boom")));
21935
21936   foo->Call(global_object, 0, NULL);
21937
21938   CHECK_EQ(1, nb_uncaught_exception_callback_calls);
21939 }